@joint/core 4.2.0-alpha.1 → 4.2.0-beta.2
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 +2499 -853
- package/dist/joint.min.js +2 -3
- package/dist/joint.nowrap.js +2499 -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 +12 -9
- 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/dist/joint.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! JointJS v4.2.0-
|
|
1
|
+
/*! JointJS v4.2.0-beta.2 (2025-11-04) - JavaScript diagramming library
|
|
2
2
|
|
|
3
3
|
This Source Code Form is subject to the terms of the Mozilla Public
|
|
4
4
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
@@ -12520,7 +12520,9 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
12520
12520
|
defaultTheme: 'default',
|
|
12521
12521
|
// The maximum delay required for two consecutive touchend events to be interpreted
|
|
12522
12522
|
// as a double-tap.
|
|
12523
|
-
doubleTapInterval: 300
|
|
12523
|
+
doubleTapInterval: 300,
|
|
12524
|
+
// Name of the attribute used to store the layer id on the cell model.
|
|
12525
|
+
layerAttribute: 'layer'
|
|
12524
12526
|
};
|
|
12525
12527
|
|
|
12526
12528
|
// TODO: should not read config outside the mvc package
|
|
@@ -14450,16 +14452,12 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
14450
14452
|
var Model = function (attributes, options) {
|
|
14451
14453
|
var attrs = attributes || {};
|
|
14452
14454
|
options || (options = {});
|
|
14455
|
+
this.eventPrefix = options.eventPrefix || '';
|
|
14453
14456
|
this.preinitialize.apply(this, arguments);
|
|
14454
14457
|
this.cid = uniqueId(this.cidPrefix);
|
|
14455
14458
|
this.attributes = {};
|
|
14456
14459
|
if (options.collection) this.collection = options.collection;
|
|
14457
|
-
|
|
14458
|
-
|
|
14459
|
-
// Just _.defaults would work fine, but the additional _.extends
|
|
14460
|
-
// is in there for historical reasons. See #3843.
|
|
14461
|
-
attrs = defaults(assign({}, attributeDefaults, attrs), attributeDefaults);
|
|
14462
|
-
this.set(attrs, options);
|
|
14460
|
+
this._setDefaults(attrs, options);
|
|
14463
14461
|
this.changed = {};
|
|
14464
14462
|
this.initialize.apply(this, arguments);
|
|
14465
14463
|
};
|
|
@@ -14548,14 +14546,14 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
14548
14546
|
if (this.idAttribute in attrs) {
|
|
14549
14547
|
var prevId = this.id;
|
|
14550
14548
|
this.id = this.get(this.idAttribute);
|
|
14551
|
-
this.trigger('changeId', this, prevId, options);
|
|
14549
|
+
this.trigger(this.eventPrefix + 'changeId', this, prevId, options);
|
|
14552
14550
|
}
|
|
14553
14551
|
|
|
14554
14552
|
// Trigger all relevant attribute changes.
|
|
14555
14553
|
if (!silent) {
|
|
14556
14554
|
if (changes.length) this._pending = options;
|
|
14557
14555
|
for (var i = 0; i < changes.length; i++) {
|
|
14558
|
-
this.trigger('change:' + changes[i], this, current[changes[i]], options);
|
|
14556
|
+
this.trigger(this.eventPrefix + 'change:' + changes[i], this, current[changes[i]], options);
|
|
14559
14557
|
}
|
|
14560
14558
|
}
|
|
14561
14559
|
|
|
@@ -14566,7 +14564,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
14566
14564
|
while (this._pending) {
|
|
14567
14565
|
options = this._pending;
|
|
14568
14566
|
this._pending = false;
|
|
14569
|
-
this.trigger('change', this, options);
|
|
14567
|
+
this.trigger(this.eventPrefix + 'change', this, options);
|
|
14570
14568
|
}
|
|
14571
14569
|
}
|
|
14572
14570
|
this._pending = false;
|
|
@@ -14645,6 +14643,13 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
14645
14643
|
validationError: error
|
|
14646
14644
|
}));
|
|
14647
14645
|
return false;
|
|
14646
|
+
},
|
|
14647
|
+
_setDefaults: function (ctorAttributes, options) {
|
|
14648
|
+
const attributeDefaults = result(this, 'defaults');
|
|
14649
|
+
// Just _.defaults would work fine, but the additional _.extends
|
|
14650
|
+
// is in there for historical reasons. See #3843.
|
|
14651
|
+
const attributes = defaults(assign({}, attributeDefaults, ctorAttributes), attributeDefaults);
|
|
14652
|
+
this.set(attributes, options);
|
|
14648
14653
|
}
|
|
14649
14654
|
});
|
|
14650
14655
|
|
|
@@ -15564,6 +15569,30 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
15564
15569
|
assign(attributesNS, offsetAttributesNS);
|
|
15565
15570
|
const attributes = attributesNS;
|
|
15566
15571
|
|
|
15572
|
+
// Internal tags to identify objects as specific JointJS types.
|
|
15573
|
+
// Used instead of `instanceof` for performance and cross-frame safety.
|
|
15574
|
+
|
|
15575
|
+
// dia.Cell
|
|
15576
|
+
const CELL_MARKER = Symbol('joint.cellMarker');
|
|
15577
|
+
|
|
15578
|
+
// dia.CellCollection
|
|
15579
|
+
const CELL_COLLECTION_MARKER = Symbol('joint.cellCollectionMarker');
|
|
15580
|
+
|
|
15581
|
+
// dia.GraphLayer
|
|
15582
|
+
const GRAPH_LAYER_MARKER = Symbol('joint.graphLayerMarker');
|
|
15583
|
+
|
|
15584
|
+
// dia.GraphLayerCollection
|
|
15585
|
+
const GRAPH_LAYER_COLLECTION_MARKER = Symbol('joint.graphLayerCollectionMarker');
|
|
15586
|
+
|
|
15587
|
+
// dia.CellView
|
|
15588
|
+
const CELL_VIEW_MARKER = Symbol('joint.cellViewMarker');
|
|
15589
|
+
|
|
15590
|
+
// dia.LayerView
|
|
15591
|
+
const LAYER_VIEW_MARKER = Symbol('joint.layerViewMarker');
|
|
15592
|
+
|
|
15593
|
+
// dia.GraphLayerView
|
|
15594
|
+
const GRAPH_LAYER_VIEW_MARKER = Symbol('joint.graphLayerViewMarker');
|
|
15595
|
+
|
|
15567
15596
|
// Cell base model.
|
|
15568
15597
|
// --------------------------
|
|
15569
15598
|
|
|
@@ -15584,35 +15613,18 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
15584
15613
|
}
|
|
15585
15614
|
}
|
|
15586
15615
|
const Cell = Model.extend({
|
|
15587
|
-
|
|
15588
|
-
//
|
|
15589
|
-
|
|
15590
|
-
|
|
15591
|
-
|
|
15592
|
-
if (
|
|
15593
|
-
// Check to support an older version
|
|
15594
|
-
this.preinitialize.apply(this, arguments);
|
|
15595
|
-
}
|
|
15596
|
-
this.cid = uniqueId('c');
|
|
15597
|
-
this.attributes = {};
|
|
15598
|
-
if (options && options.collection) this.collection = options.collection;
|
|
15599
|
-
if (options && options.parse) attrs = this.parse(attrs, options) || {};
|
|
15600
|
-
if (defaults = result(this, 'defaults')) {
|
|
15601
|
-
//<custom code>
|
|
15602
|
-
// Replaced the call to _.defaults with util.merge.
|
|
15616
|
+
cidPrefix: 'c',
|
|
15617
|
+
// Default attributes are merged deeply instead of shallowly.
|
|
15618
|
+
_setDefaults: function (ctorAttributes, options) {
|
|
15619
|
+
let attributes;
|
|
15620
|
+
const attributeDefaults = result(this, 'defaults');
|
|
15621
|
+
if (attributeDefaults) {
|
|
15603
15622
|
const customizer = options && options.mergeArrays === true ? false : config$3.cellDefaultsMergeStrategy || attributesMerger;
|
|
15604
|
-
|
|
15605
|
-
|
|
15606
|
-
|
|
15607
|
-
this.set(attrs, options);
|
|
15608
|
-
this.changed = {};
|
|
15609
|
-
if (options && options.portLayoutNamespace) {
|
|
15610
|
-
this.portLayoutNamespace = options.portLayoutNamespace;
|
|
15611
|
-
}
|
|
15612
|
-
if (options && options.portLabelLayoutNamespace) {
|
|
15613
|
-
this.portLabelLayoutNamespace = options.portLabelLayoutNamespace;
|
|
15623
|
+
attributes = merge({}, attributeDefaults, ctorAttributes, customizer);
|
|
15624
|
+
} else {
|
|
15625
|
+
attributes = ctorAttributes;
|
|
15614
15626
|
}
|
|
15615
|
-
this.
|
|
15627
|
+
this.set(attributes, options);
|
|
15616
15628
|
},
|
|
15617
15629
|
translate: function (dx, dy, opt) {
|
|
15618
15630
|
throw new Error('Must define a translate() method.');
|
|
@@ -15652,9 +15664,9 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
15652
15664
|
}
|
|
15653
15665
|
return finalAttributes;
|
|
15654
15666
|
},
|
|
15655
|
-
initialize: function (
|
|
15667
|
+
initialize: function (attributes) {
|
|
15656
15668
|
const idAttribute = this.getIdAttribute();
|
|
15657
|
-
if (!
|
|
15669
|
+
if (!attributes || attributes[idAttribute] === undefined) {
|
|
15658
15670
|
this.set(idAttribute, this.generateId(), {
|
|
15659
15671
|
silent: true
|
|
15660
15672
|
});
|
|
@@ -15725,39 +15737,24 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
15725
15737
|
this.ports = ports;
|
|
15726
15738
|
},
|
|
15727
15739
|
remove: function (opt = {}) {
|
|
15728
|
-
// Store the graph in a variable because `this.graph` won't be accessible
|
|
15729
|
-
// after `this.trigger('remove', ...)` down below.
|
|
15730
15740
|
const {
|
|
15731
15741
|
graph,
|
|
15732
15742
|
collection
|
|
15733
15743
|
} = this;
|
|
15734
|
-
|
|
15744
|
+
// If the cell is part of a graph, remove it using the graph API.
|
|
15745
|
+
// To make sure the cell is removed in a batch operation.
|
|
15746
|
+
if (graph) {
|
|
15747
|
+
graph.removeCell(this, opt);
|
|
15748
|
+
} else {
|
|
15735
15749
|
// The collection is a common mvc collection (not the graph collection).
|
|
15736
15750
|
if (collection) collection.remove(this, opt);
|
|
15737
|
-
return this;
|
|
15738
|
-
}
|
|
15739
|
-
graph.startBatch('remove');
|
|
15740
|
-
|
|
15741
|
-
// First, unembed this cell from its parent cell if there is one.
|
|
15742
|
-
const parentCell = this.getParentCell();
|
|
15743
|
-
if (parentCell) {
|
|
15744
|
-
parentCell.unembed(this, opt);
|
|
15745
15751
|
}
|
|
15746
|
-
|
|
15747
|
-
// Remove also all the cells, which were embedded into this cell
|
|
15748
|
-
const embeddedCells = this.getEmbeddedCells();
|
|
15749
|
-
for (let i = 0, n = embeddedCells.length; i < n; i++) {
|
|
15750
|
-
const embed = embeddedCells[i];
|
|
15751
|
-
if (embed) {
|
|
15752
|
-
embed.remove(opt);
|
|
15753
|
-
}
|
|
15754
|
-
}
|
|
15755
|
-
this.trigger('remove', this, graph.attributes.cells, opt);
|
|
15756
|
-
graph.stopBatch('remove');
|
|
15757
15752
|
return this;
|
|
15758
15753
|
},
|
|
15759
15754
|
toFront: function (opt) {
|
|
15760
|
-
|
|
15755
|
+
const {
|
|
15756
|
+
graph
|
|
15757
|
+
} = this;
|
|
15761
15758
|
if (graph) {
|
|
15762
15759
|
opt = defaults(opt || {}, {
|
|
15763
15760
|
foregroundEmbeds: true
|
|
@@ -15774,10 +15771,11 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
15774
15771
|
cells = [this];
|
|
15775
15772
|
}
|
|
15776
15773
|
const sortedCells = opt.foregroundEmbeds ? cells : sortBy(cells, cell => cell.z());
|
|
15777
|
-
const
|
|
15774
|
+
const layerId = graph.getCellLayerId(this);
|
|
15775
|
+
const maxZ = graph.maxZIndex(layerId);
|
|
15778
15776
|
let z = maxZ - cells.length + 1;
|
|
15779
|
-
const
|
|
15780
|
-
let shouldUpdate =
|
|
15777
|
+
const layerCells = graph.getLayer(layerId).cellCollection.toArray();
|
|
15778
|
+
let shouldUpdate = layerCells.indexOf(sortedCells[0]) !== layerCells.length - cells.length;
|
|
15781
15779
|
if (!shouldUpdate) {
|
|
15782
15780
|
shouldUpdate = sortedCells.some(function (cell, index) {
|
|
15783
15781
|
return cell.z() !== z + index;
|
|
@@ -15795,7 +15793,9 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
15795
15793
|
return this;
|
|
15796
15794
|
},
|
|
15797
15795
|
toBack: function (opt) {
|
|
15798
|
-
|
|
15796
|
+
const {
|
|
15797
|
+
graph
|
|
15798
|
+
} = this;
|
|
15799
15799
|
if (graph) {
|
|
15800
15800
|
opt = defaults(opt || {}, {
|
|
15801
15801
|
foregroundEmbeds: true
|
|
@@ -15812,9 +15812,10 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
15812
15812
|
cells = [this];
|
|
15813
15813
|
}
|
|
15814
15814
|
const sortedCells = opt.foregroundEmbeds ? cells : sortBy(cells, cell => cell.z());
|
|
15815
|
-
|
|
15816
|
-
|
|
15817
|
-
|
|
15815
|
+
const layerId = graph.getCellLayerId(this);
|
|
15816
|
+
let z = graph.minZIndex(layerId);
|
|
15817
|
+
const layerCells = graph.getLayer(layerId).cellCollection.toArray();
|
|
15818
|
+
let shouldUpdate = layerCells.indexOf(sortedCells[0]) !== 0;
|
|
15818
15819
|
if (!shouldUpdate) {
|
|
15819
15820
|
shouldUpdate = sortedCells.some(function (cell, index) {
|
|
15820
15821
|
return cell.z() !== z + index;
|
|
@@ -16177,41 +16178,42 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
16177
16178
|
opt = assign(defaults, opt);
|
|
16178
16179
|
var firstFrameTime = 0;
|
|
16179
16180
|
var interpolatingFunction;
|
|
16181
|
+
const transitionKey = Array.isArray(path) ? path.join(delim) : path;
|
|
16180
16182
|
var setter = function (runtime) {
|
|
16181
16183
|
var id, progress, propertyValue;
|
|
16182
16184
|
firstFrameTime = firstFrameTime || runtime;
|
|
16183
16185
|
runtime -= firstFrameTime;
|
|
16184
16186
|
progress = runtime / opt.duration;
|
|
16185
16187
|
if (progress < 1) {
|
|
16186
|
-
this._transitionIds[
|
|
16188
|
+
this._transitionIds[transitionKey] = id = nextFrame(setter);
|
|
16187
16189
|
} else {
|
|
16188
16190
|
progress = 1;
|
|
16189
|
-
delete this._transitionIds[
|
|
16191
|
+
delete this._transitionIds[transitionKey];
|
|
16190
16192
|
}
|
|
16191
16193
|
propertyValue = interpolatingFunction(opt.timingFunction(progress));
|
|
16192
16194
|
opt.transitionId = id;
|
|
16193
16195
|
this.prop(path, propertyValue, opt);
|
|
16194
|
-
if (!id) this.trigger('transition:end', this,
|
|
16196
|
+
if (!id) this.trigger('transition:end', this, transitionKey);
|
|
16195
16197
|
}.bind(this);
|
|
16196
16198
|
const {
|
|
16197
16199
|
_scheduledTransitionIds
|
|
16198
16200
|
} = this;
|
|
16199
16201
|
let initialId;
|
|
16200
16202
|
var initiator = callback => {
|
|
16201
|
-
if (_scheduledTransitionIds[
|
|
16202
|
-
_scheduledTransitionIds[
|
|
16203
|
-
if (_scheduledTransitionIds[
|
|
16204
|
-
delete _scheduledTransitionIds[
|
|
16203
|
+
if (_scheduledTransitionIds[transitionKey]) {
|
|
16204
|
+
_scheduledTransitionIds[transitionKey] = without(_scheduledTransitionIds[transitionKey], initialId);
|
|
16205
|
+
if (_scheduledTransitionIds[transitionKey].length === 0) {
|
|
16206
|
+
delete _scheduledTransitionIds[transitionKey];
|
|
16205
16207
|
}
|
|
16206
16208
|
}
|
|
16207
16209
|
this.stopPendingTransitions(path, delim);
|
|
16208
16210
|
interpolatingFunction = opt.valueFunction(getByPath(this.attributes, path, delim), value);
|
|
16209
|
-
this._transitionIds[
|
|
16210
|
-
this.trigger('transition:start', this,
|
|
16211
|
+
this._transitionIds[transitionKey] = nextFrame(callback);
|
|
16212
|
+
this.trigger('transition:start', this, transitionKey);
|
|
16211
16213
|
};
|
|
16212
16214
|
initialId = setTimeout(initiator, opt.delay, setter);
|
|
16213
|
-
_scheduledTransitionIds[
|
|
16214
|
-
_scheduledTransitionIds[
|
|
16215
|
+
_scheduledTransitionIds[transitionKey] || (_scheduledTransitionIds[transitionKey] = []);
|
|
16216
|
+
_scheduledTransitionIds[transitionKey].push(initialId);
|
|
16215
16217
|
return initialId;
|
|
16216
16218
|
},
|
|
16217
16219
|
getTransitions: function () {
|
|
@@ -16223,7 +16225,8 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
16223
16225
|
} = this;
|
|
16224
16226
|
let transitions = Object.keys(_scheduledTransitionIds);
|
|
16225
16227
|
if (path) {
|
|
16226
|
-
|
|
16228
|
+
// Ensure all path segments are strings for `isEqual` comparison, since it strictly compares values
|
|
16229
|
+
const pathArray = Array.isArray(path) ? path.map(item => String(item)) : path.split(delim);
|
|
16227
16230
|
transitions = transitions.filter(key => {
|
|
16228
16231
|
return isEqual(pathArray, key.split(delim).slice(0, pathArray.length));
|
|
16229
16232
|
});
|
|
@@ -16243,7 +16246,8 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
16243
16246
|
} = this;
|
|
16244
16247
|
let transitions = Object.keys(_transitionIds);
|
|
16245
16248
|
if (path) {
|
|
16246
|
-
|
|
16249
|
+
// Ensure all path segments are strings for `isEqual` comparison, since it strictly compares values
|
|
16250
|
+
const pathArray = Array.isArray(path) ? path.map(item => String(item)) : path.split(delim);
|
|
16247
16251
|
transitions = transitions.filter(key => {
|
|
16248
16252
|
return isEqual(pathArray, key.split(delim).slice(0, pathArray.length));
|
|
16249
16253
|
});
|
|
@@ -16261,7 +16265,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
16261
16265
|
this.stopPendingTransitions(path, delim);
|
|
16262
16266
|
return this;
|
|
16263
16267
|
},
|
|
16264
|
-
// A
|
|
16268
|
+
// A shortcut making it easy to create constructs like the following:
|
|
16265
16269
|
// `var el = (new joint.shapes.standard.Rectangle()).addTo(graph)`.
|
|
16266
16270
|
addTo: function (graph, opt) {
|
|
16267
16271
|
graph.addCell(this, opt);
|
|
@@ -16343,6 +16347,29 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
16343
16347
|
.getPointRotatedAroundCenter(this.angle(), x, y)
|
|
16344
16348
|
// Transform the absolute position into relative
|
|
16345
16349
|
.difference(this.position());
|
|
16350
|
+
},
|
|
16351
|
+
layer: function (layerId, opt) {
|
|
16352
|
+
const layerAttribute = config$3.layerAttribute;
|
|
16353
|
+
|
|
16354
|
+
// Getter:
|
|
16355
|
+
|
|
16356
|
+
// If `undefined` return the current layer ID
|
|
16357
|
+
if (layerId === undefined) {
|
|
16358
|
+
return this.get(layerAttribute) || null;
|
|
16359
|
+
}
|
|
16360
|
+
|
|
16361
|
+
// Setter:
|
|
16362
|
+
|
|
16363
|
+
// If strictly `null` unset the layer
|
|
16364
|
+
if (layerId === null) {
|
|
16365
|
+
return this.unset(layerAttribute, opt);
|
|
16366
|
+
}
|
|
16367
|
+
|
|
16368
|
+
// Otherwise set the layer ID
|
|
16369
|
+
if (!isString(layerId)) {
|
|
16370
|
+
throw new Error('dia.Cell: Layer id must be a string.');
|
|
16371
|
+
}
|
|
16372
|
+
return this.set(layerAttribute, layerId, opt);
|
|
16346
16373
|
}
|
|
16347
16374
|
}, {
|
|
16348
16375
|
getAttributeDefinition: function (attrName) {
|
|
@@ -16367,6 +16394,9 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
16367
16394
|
return Cell;
|
|
16368
16395
|
}
|
|
16369
16396
|
});
|
|
16397
|
+
Object.defineProperty(Cell.prototype, CELL_MARKER, {
|
|
16398
|
+
value: true
|
|
16399
|
+
});
|
|
16370
16400
|
|
|
16371
16401
|
const wrapWith = function (object, methods, wrapper) {
|
|
16372
16402
|
if (isString(wrapper)) {
|
|
@@ -17397,7 +17427,17 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
17397
17427
|
}
|
|
17398
17428
|
};
|
|
17399
17429
|
const elementPortPrototype = {
|
|
17400
|
-
_initializePorts: function () {
|
|
17430
|
+
_initializePorts: function (options) {
|
|
17431
|
+
if (options) {
|
|
17432
|
+
// Override port layout namespaces if provided in options
|
|
17433
|
+
if (options.portLayoutNamespace) {
|
|
17434
|
+
this.portLayoutNamespace = options.portLayoutNamespace;
|
|
17435
|
+
}
|
|
17436
|
+
// Override port label layout namespaces if provided in options
|
|
17437
|
+
if (options.portLabelLayoutNamespace) {
|
|
17438
|
+
this.portLabelLayoutNamespace = options.portLabelLayoutNamespace;
|
|
17439
|
+
}
|
|
17440
|
+
}
|
|
17401
17441
|
this._createPortData();
|
|
17402
17442
|
this.on('change:ports', function () {
|
|
17403
17443
|
this._processRemovedPort();
|
|
@@ -18079,8 +18119,8 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
18079
18119
|
},
|
|
18080
18120
|
angle: 0
|
|
18081
18121
|
},
|
|
18082
|
-
initialize: function () {
|
|
18083
|
-
this._initializePorts();
|
|
18122
|
+
initialize: function (attributes, options) {
|
|
18123
|
+
this._initializePorts(options);
|
|
18084
18124
|
Cell.prototype.initialize.apply(this, arguments);
|
|
18085
18125
|
},
|
|
18086
18126
|
/**
|
|
@@ -21621,7 +21661,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
21621
21661
|
for (i = 0; i < toAdd.length; i++) {
|
|
21622
21662
|
if (at != null) options.index = at + i;
|
|
21623
21663
|
model = toAdd[i];
|
|
21624
|
-
model.trigger('add', model, this, options);
|
|
21664
|
+
model.trigger(model.eventPrefix + 'add', model, this, options);
|
|
21625
21665
|
}
|
|
21626
21666
|
if (sort || orderChanged) this.trigger('sort', this, options);
|
|
21627
21667
|
if (toAdd.length || toRemove.length || toMerge.length) {
|
|
@@ -21684,7 +21724,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
21684
21724
|
// properties, or an attributes object that is transformed through modelId.
|
|
21685
21725
|
get: function (obj) {
|
|
21686
21726
|
if (obj == null) return void 0;
|
|
21687
|
-
return this._byId
|
|
21727
|
+
return this._byId.get(obj) || this._byId.get(this.modelId(this._isModel(obj) ? obj.attributes : obj, obj.idAttribute)) || obj.cid && this._byId.get(obj.cid);
|
|
21688
21728
|
},
|
|
21689
21729
|
// Returns `true` if the model is in the collection.
|
|
21690
21730
|
has: function (obj) {
|
|
@@ -21723,7 +21763,8 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
21723
21763
|
},
|
|
21724
21764
|
// Define how to uniquely identify models in the collection.
|
|
21725
21765
|
modelId: function (attrs, idAttribute) {
|
|
21726
|
-
|
|
21766
|
+
var _this$model$prototype;
|
|
21767
|
+
return attrs[idAttribute || ((_this$model$prototype = this.model.prototype) === null || _this$model$prototype === void 0 ? void 0 : _this$model$prototype.idAttribute) || 'id'];
|
|
21727
21768
|
},
|
|
21728
21769
|
// Get an iterator of all models in this collection.
|
|
21729
21770
|
values: function () {
|
|
@@ -21780,17 +21821,17 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
21780
21821
|
_reset: function () {
|
|
21781
21822
|
this.length = 0;
|
|
21782
21823
|
this.models = [];
|
|
21783
|
-
this._byId =
|
|
21824
|
+
this._byId = new Map();
|
|
21784
21825
|
},
|
|
21785
21826
|
// Prepare a hash of attributes (or other model) to be added to this
|
|
21786
21827
|
// collection.
|
|
21787
21828
|
_prepareModel: function (attrs, options) {
|
|
21788
21829
|
if (this._isModel(attrs)) {
|
|
21789
|
-
if (!attrs.collection) attrs.collection = this;
|
|
21830
|
+
if (!options.dry && !attrs.collection) attrs.collection = this;
|
|
21790
21831
|
return attrs;
|
|
21791
21832
|
}
|
|
21792
21833
|
options = options ? clone$1(options) : {};
|
|
21793
|
-
options.collection = this;
|
|
21834
|
+
if (!options.dry) options.collection = this;
|
|
21794
21835
|
var model;
|
|
21795
21836
|
if (this.model.prototype) {
|
|
21796
21837
|
model = new this.model(attrs, options);
|
|
@@ -21814,12 +21855,12 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
21814
21855
|
|
|
21815
21856
|
// Remove references before triggering 'remove' event to prevent an
|
|
21816
21857
|
// infinite loop. #3693
|
|
21817
|
-
|
|
21858
|
+
this._byId.delete(model.cid);
|
|
21818
21859
|
var id = this.modelId(model.attributes, model.idAttribute);
|
|
21819
|
-
if (id != null)
|
|
21860
|
+
if (id != null) this._byId.delete(id);
|
|
21820
21861
|
if (!options.silent) {
|
|
21821
21862
|
options.index = index;
|
|
21822
|
-
model.trigger('remove', model, this, options);
|
|
21863
|
+
model.trigger(model.eventPrefix + 'remove', model, this, options);
|
|
21823
21864
|
}
|
|
21824
21865
|
removed.push(model);
|
|
21825
21866
|
this._removeReference(model, options);
|
|
@@ -21834,17 +21875,17 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
21834
21875
|
},
|
|
21835
21876
|
// Internal method to create a model's ties to a collection.
|
|
21836
21877
|
_addReference: function (model, options) {
|
|
21837
|
-
this._byId
|
|
21878
|
+
this._byId.set(model.cid, model);
|
|
21838
21879
|
var id = this.modelId(model.attributes, model.idAttribute);
|
|
21839
|
-
if (id != null) this._byId
|
|
21880
|
+
if (id != null) this._byId.set(id, model);
|
|
21840
21881
|
model.on('all', this._onModelEvent, this);
|
|
21841
21882
|
},
|
|
21842
21883
|
// Internal method to sever a model's ties to a collection.
|
|
21843
21884
|
_removeReference: function (model, options) {
|
|
21844
|
-
|
|
21885
|
+
this._byId.delete(model.cid);
|
|
21845
21886
|
var id = this.modelId(model.attributes, model.idAttribute);
|
|
21846
|
-
if (id != null)
|
|
21847
|
-
if (this === model.collection) delete model.collection;
|
|
21887
|
+
if (id != null) this._byId.delete(id);
|
|
21888
|
+
if (!options.dry && this === model.collection) delete model.collection;
|
|
21848
21889
|
model.off('all', this._onModelEvent, this);
|
|
21849
21890
|
},
|
|
21850
21891
|
// Internal method called every time a model in the set fires an event.
|
|
@@ -21853,12 +21894,12 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
21853
21894
|
// in other collections are ignored.
|
|
21854
21895
|
_onModelEvent: function (event, model, collection, options) {
|
|
21855
21896
|
if (model) {
|
|
21856
|
-
if ((event === 'add' || event === 'remove') && collection !== this) return;
|
|
21897
|
+
if ((event === model.eventPrefix + 'add' || event === model.eventPrefix + 'remove') && collection !== this) return;
|
|
21857
21898
|
if (event === 'changeId') {
|
|
21858
21899
|
var prevId = this.modelId(model.previousAttributes(), model.idAttribute);
|
|
21859
21900
|
var id = this.modelId(model.attributes, model.idAttribute);
|
|
21860
|
-
if (prevId != null)
|
|
21861
|
-
if (id != null) this._byId
|
|
21901
|
+
if (prevId != null) this._byId.delete(prevId);
|
|
21902
|
+
if (id != null) this._byId.set(id, model);
|
|
21862
21903
|
}
|
|
21863
21904
|
}
|
|
21864
21905
|
this.trigger.apply(this, arguments);
|
|
@@ -26684,21 +26725,181 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
26684
26725
|
topRight: topRight
|
|
26685
26726
|
};
|
|
26686
26727
|
|
|
26687
|
-
|
|
26688
|
-
|
|
26689
|
-
|
|
26690
|
-
|
|
26691
|
-
|
|
26692
|
-
|
|
26693
|
-
|
|
26694
|
-
|
|
26695
|
-
|
|
26728
|
+
/**
|
|
26729
|
+
* @class GraphLayersController
|
|
26730
|
+
* @description Coordinates interactions between the graph and its layers.
|
|
26731
|
+
* Automatically moves cells between layers when the layer attribute changes.
|
|
26732
|
+
*/
|
|
26733
|
+
class GraphLayersController extends Listener {
|
|
26734
|
+
constructor(options) {
|
|
26735
|
+
super(options);
|
|
26736
|
+
|
|
26737
|
+
// Make sure there are no arguments passed to the callbacks.
|
|
26738
|
+
// See the `mvc.Listener` documentation for more details.
|
|
26739
|
+
this.callbackArguments = [];
|
|
26740
|
+
const graph = options.graph;
|
|
26741
|
+
if (!graph) {
|
|
26742
|
+
throw new Error('GraphLayersController: "graph" option is required.');
|
|
26743
|
+
}
|
|
26744
|
+
this.graph = graph;
|
|
26745
|
+
this.layerCollection = graph.layerCollection;
|
|
26746
|
+
this.startListening();
|
|
26747
|
+
}
|
|
26748
|
+
startListening() {
|
|
26749
|
+
// Handle all events from the layer collection and its inner cell collections.
|
|
26750
|
+
this.listenTo(this.layerCollection, 'all', this.onLayerCollectionEvent);
|
|
26751
|
+
}
|
|
26752
|
+
|
|
26753
|
+
/**
|
|
26754
|
+
* @description When a cell changes its layer attribute,
|
|
26755
|
+
* move the cell to the target layer.
|
|
26756
|
+
*/
|
|
26757
|
+
onCellChange(cell, options) {
|
|
26758
|
+
if (!cell.hasChanged(config$3.layerAttribute)) return;
|
|
26759
|
+
// Move the cell to the appropriate layer
|
|
26760
|
+
const targetLayerId = this.graph.getCellLayerId(cell);
|
|
26761
|
+
this.layerCollection.moveCellBetweenLayers(cell, targetLayerId, options);
|
|
26762
|
+
}
|
|
26763
|
+
|
|
26764
|
+
/**
|
|
26765
|
+
* @description When a cell is removed from a layer,
|
|
26766
|
+
* also remove its embeds and connected links from the graph.
|
|
26767
|
+
* Note: an embedded cell might come from a different layer,
|
|
26768
|
+
* so we can not use the layer's cell collection to remove it.
|
|
26769
|
+
*/
|
|
26770
|
+
onCellRemove(cell, options) {
|
|
26771
|
+
// If the cell is being moved from one layer to another,
|
|
26772
|
+
// no further action is needed.
|
|
26773
|
+
if (options.fromLayer) return;
|
|
26774
|
+
|
|
26775
|
+
// When replacing a cell, we do not want to remove its embeds or
|
|
26776
|
+
// unembed it from its parent.
|
|
26777
|
+
if (options.replace) return;
|
|
26778
|
+
|
|
26779
|
+
// First, unembed this cell from its parent cell if there is one.
|
|
26780
|
+
const parentCell = cell.getParentCell();
|
|
26781
|
+
if (parentCell) {
|
|
26782
|
+
parentCell.unembed(cell, options);
|
|
26783
|
+
}
|
|
26784
|
+
|
|
26785
|
+
// Remove also all the cells, which were embedded into this cell
|
|
26786
|
+
const embeddedCells = cell.getEmbeddedCells();
|
|
26787
|
+
for (let i = 0, n = embeddedCells.length; i < n; i++) {
|
|
26788
|
+
const embed = embeddedCells[i];
|
|
26789
|
+
if (embed) {
|
|
26790
|
+
this.layerCollection.removeCell(embed, options);
|
|
26791
|
+
}
|
|
26792
|
+
}
|
|
26793
|
+
|
|
26794
|
+
// When not clearing the whole graph or replacing the cell,
|
|
26795
|
+
// we don't want to remove the connected links.
|
|
26796
|
+
if (!options.clear) {
|
|
26797
|
+
// Applications might provide a `disconnectLinks` option set to `true` in order to
|
|
26798
|
+
// disconnect links when a cell is removed rather then removing them. The default
|
|
26799
|
+
// is to remove all the associated links.
|
|
26800
|
+
if (options.disconnectLinks) {
|
|
26801
|
+
this.graph.disconnectLinks(cell, options);
|
|
26802
|
+
} else {
|
|
26803
|
+
this.graph.removeLinks(cell, options);
|
|
26804
|
+
}
|
|
26805
|
+
}
|
|
26806
|
+
}
|
|
26807
|
+
onLayerCollectionEvent(eventName, model) {
|
|
26808
|
+
if (!model) return;
|
|
26809
|
+
if (model[CELL_MARKER]) {
|
|
26810
|
+
// First handle cell-specific cases that require custom processing,
|
|
26811
|
+
// then forward the event to the graph.
|
|
26812
|
+
// For example, when a cell is removed from a layer, its embeds and
|
|
26813
|
+
// connected links must be removed as well. Listeners on the graph
|
|
26814
|
+
// should receive removal notifications in the following order:
|
|
26815
|
+
// embeds → links → cell.
|
|
26816
|
+
switch (eventName) {
|
|
26817
|
+
case 'change':
|
|
26818
|
+
/* ('change', cell, options) */
|
|
26819
|
+
this.onCellChange.call(this, model, arguments[2]);
|
|
26820
|
+
break;
|
|
26821
|
+
case 'remove':
|
|
26822
|
+
/* ('remove', cell, collection, options) */
|
|
26823
|
+
// When a cell is removed from a layer,
|
|
26824
|
+
// ensure it is also removed from the graph.
|
|
26825
|
+
this.onCellRemove.call(this, model, arguments[3]);
|
|
26826
|
+
break;
|
|
26827
|
+
}
|
|
26828
|
+
// Notify the graph about cell events.
|
|
26829
|
+
this.forwardCellEvent.apply(this, arguments);
|
|
26830
|
+
return;
|
|
26831
|
+
}
|
|
26832
|
+
if (model[CELL_COLLECTION_MARKER]) {
|
|
26833
|
+
this.forwardCellCollectionEvent.apply(this, arguments);
|
|
26834
|
+
return;
|
|
26835
|
+
}
|
|
26836
|
+
if (model[GRAPH_LAYER_MARKER]) {
|
|
26837
|
+
this.forwardLayerEvent.apply(this, arguments);
|
|
26838
|
+
return;
|
|
26839
|
+
}
|
|
26840
|
+
if (model[GRAPH_LAYER_COLLECTION_MARKER]) {
|
|
26841
|
+
this.forwardLayerCollectionEvent.apply(this, arguments);
|
|
26842
|
+
return;
|
|
26843
|
+
}
|
|
26844
|
+
}
|
|
26845
|
+
forwardLayerEvent() {
|
|
26846
|
+
// Note: the layer event prefix is `layer:`
|
|
26847
|
+
this.graph.trigger.apply(this.graph, arguments);
|
|
26848
|
+
}
|
|
26849
|
+
forwardCellEvent(eventName, cell) {
|
|
26850
|
+
var _arguments$;
|
|
26851
|
+
// Moving a cell from one layer to another is an internal operation
|
|
26852
|
+
// that should not be exposed at the graph level.
|
|
26853
|
+
// The single `move` event is triggered instead.
|
|
26854
|
+
if ((eventName === 'remove' || eventName === 'add') && (_arguments$ = arguments[3]) !== null && _arguments$ !== void 0 && _arguments$.fromLayer) return;
|
|
26855
|
+
this.graph.trigger.apply(this.graph, arguments);
|
|
26856
|
+
}
|
|
26857
|
+
forwardCellCollectionEvent(eventName) {
|
|
26858
|
+
// Do not forward `layer:remove` or `layer:sort` events to the graph
|
|
26859
|
+
if (eventName !== 'sort') return;
|
|
26860
|
+
// Backwards compatibility:
|
|
26861
|
+
// Trigger 'sort' event for cell collection 'sort' events
|
|
26862
|
+
this.graph.trigger.apply(this.graph, arguments);
|
|
26863
|
+
}
|
|
26864
|
+
forwardLayerCollectionEvent(eventName) {
|
|
26865
|
+
if (eventName === 'reset') {
|
|
26866
|
+
// Currently, there is no need to forward `layers:reset` event.
|
|
26867
|
+
// The graph `fromJSON()` triggers a single `reset` event after
|
|
26868
|
+
// resetting cells, layers and attributes.
|
|
26869
|
+
return;
|
|
26870
|
+
}
|
|
26871
|
+
// Forward layer collection events with `layers:` prefix.
|
|
26872
|
+
// For example `layers:reset` event when the layer collection is reset
|
|
26873
|
+
arguments[0] = 'layers:' + arguments[0];
|
|
26874
|
+
this.graph.trigger.apply(this.graph, arguments);
|
|
26875
|
+
}
|
|
26876
|
+
}
|
|
26877
|
+
|
|
26878
|
+
/**
|
|
26879
|
+
* @class CellCollection
|
|
26880
|
+
* @description A CellCollection is a collection of cells which supports z-index management.
|
|
26881
|
+
* Additionally, it facilitates creating cell models from JSON using cellNamespace
|
|
26882
|
+
* and stores a reference to the graph when the cell model has been added.
|
|
26883
|
+
*/
|
|
26884
|
+
class CellCollection extends Collection {
|
|
26885
|
+
[CELL_COLLECTION_MARKER] = true;
|
|
26886
|
+
initialize(_models, opt) {
|
|
26887
|
+
this.layer = opt.layer;
|
|
26888
|
+
}
|
|
26889
|
+
|
|
26890
|
+
// Method for checking whether an object should be considered a model for
|
|
26891
|
+
// the purposes of adding to the collection.
|
|
26892
|
+
_isModel(model) {
|
|
26893
|
+
return Boolean(model[CELL_MARKER]);
|
|
26894
|
+
}
|
|
26895
|
+
|
|
26896
|
+
// Overriding the default `model` method to create cell models
|
|
26897
|
+
// based on their `type` attribute and the `cellNamespace` option.
|
|
26898
|
+
model(attrs, opt) {
|
|
26899
|
+
const namespace = this.cellNamespace;
|
|
26900
|
+
if (!namespace) {
|
|
26901
|
+
throw new Error('dia.CellCollection: cellNamespace is required to instantiate a Cell from JSON.');
|
|
26696
26902
|
}
|
|
26697
|
-
this.graph = opt.graph;
|
|
26698
|
-
},
|
|
26699
|
-
model: function (attrs, opt) {
|
|
26700
|
-
const collection = opt.collection;
|
|
26701
|
-
const namespace = collection.cellNamespace;
|
|
26702
26903
|
const {
|
|
26703
26904
|
type
|
|
26704
26905
|
} = attrs;
|
|
@@ -26709,56 +26910,474 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
26709
26910
|
throw new Error(`dia.Graph: Could not find cell constructor for type: '${type}'. Make sure to add the constructor to 'cellNamespace'.`);
|
|
26710
26911
|
}
|
|
26711
26912
|
return new ModelClass(attrs, opt);
|
|
26712
|
-
}
|
|
26713
|
-
|
|
26714
|
-
|
|
26913
|
+
}
|
|
26914
|
+
|
|
26915
|
+
// Override to set graph reference
|
|
26916
|
+
_addReference(model, options) {
|
|
26917
|
+
super._addReference(model, options);
|
|
26918
|
+
|
|
26715
26919
|
// If not in `dry` mode and the model does not have a graph reference yet,
|
|
26716
26920
|
// set the reference.
|
|
26717
26921
|
if (!options.dry && !model.graph) {
|
|
26718
|
-
model.graph = this.graph;
|
|
26922
|
+
model.graph = this.layer.graph;
|
|
26719
26923
|
}
|
|
26720
|
-
}
|
|
26721
|
-
|
|
26722
|
-
|
|
26924
|
+
}
|
|
26925
|
+
|
|
26926
|
+
// Override to remove graph reference
|
|
26927
|
+
_removeReference(model, options) {
|
|
26928
|
+
super._removeReference(model, options);
|
|
26929
|
+
|
|
26723
26930
|
// If not in `dry` mode and the model has a reference to this exact graph,
|
|
26724
26931
|
// remove the reference.
|
|
26725
|
-
|
|
26932
|
+
// Note: graph reference is removed from the layer after the `remove` event is fired.
|
|
26933
|
+
// Due to this, event handlers can still access the graph during the `remove` event.
|
|
26934
|
+
if (!options.dry && model.graph === this.layer.graph) {
|
|
26726
26935
|
model.graph = null;
|
|
26727
26936
|
}
|
|
26728
|
-
}
|
|
26937
|
+
}
|
|
26938
|
+
|
|
26939
|
+
// remove graph reference additionally
|
|
26940
|
+
_removeReferenceFast(model, options) {
|
|
26941
|
+
model.off('all', this._onModelEvent, this);
|
|
26942
|
+
if (!options.dry) {
|
|
26943
|
+
// If not in `dry` mode and the model has a reference
|
|
26944
|
+
// to this exact graph/collection, remove the reference.
|
|
26945
|
+
if (this === model.collection) {
|
|
26946
|
+
delete model.collection;
|
|
26947
|
+
}
|
|
26948
|
+
if (model.graph === this.layer.graph) {
|
|
26949
|
+
model.graph = null;
|
|
26950
|
+
}
|
|
26951
|
+
}
|
|
26952
|
+
}
|
|
26953
|
+
|
|
26729
26954
|
// `comparator` makes it easy to sort cells based on their `z` index.
|
|
26730
|
-
comparator
|
|
26955
|
+
comparator(model) {
|
|
26731
26956
|
return model.get('z') || 0;
|
|
26732
26957
|
}
|
|
26733
|
-
});
|
|
26734
|
-
const Graph = Model.extend({
|
|
26735
|
-
initialize: function (attrs, opt) {
|
|
26736
|
-
opt = opt || {};
|
|
26737
26958
|
|
|
26738
|
-
|
|
26739
|
-
|
|
26740
|
-
|
|
26741
|
-
|
|
26742
|
-
|
|
26743
|
-
|
|
26744
|
-
|
|
26959
|
+
// This method overrides base mvc.Collection implementation
|
|
26960
|
+
// in a way that improves performance of resetting large collections.
|
|
26961
|
+
// For layers specifically, there is an option where we put references
|
|
26962
|
+
// from the main collection in order to improve performance when
|
|
26963
|
+
// there is only one layer
|
|
26964
|
+
reset(models, options) {
|
|
26965
|
+
options = assign({}, {
|
|
26966
|
+
add: true,
|
|
26967
|
+
remove: false,
|
|
26968
|
+
merge: false
|
|
26969
|
+
}, options);
|
|
26970
|
+
for (let i = 0; i < this.models.length; i++) {
|
|
26971
|
+
this._removeReferenceFast(this.models[i], options);
|
|
26972
|
+
}
|
|
26973
|
+
options.previousModels = this.models;
|
|
26974
|
+
this._reset();
|
|
26975
|
+
for (let i = 0; i < models.length; i++) {
|
|
26976
|
+
const model = this._prepareModel(models[i], options);
|
|
26977
|
+
if (model) {
|
|
26978
|
+
this.models.push(model);
|
|
26979
|
+
this._addReference(model, options);
|
|
26980
|
+
}
|
|
26981
|
+
}
|
|
26982
|
+
this.length = this.models.length;
|
|
26983
|
+
const sort = this.comparator && options.sort !== false;
|
|
26984
|
+
if (sort) {
|
|
26985
|
+
this.sort({
|
|
26986
|
+
silent: true
|
|
26987
|
+
});
|
|
26988
|
+
}
|
|
26989
|
+
if (!options.silent) {
|
|
26990
|
+
this.trigger('reset', this, options);
|
|
26991
|
+
}
|
|
26992
|
+
return this.models;
|
|
26993
|
+
}
|
|
26994
|
+
minZIndex() {
|
|
26995
|
+
var _this$first;
|
|
26996
|
+
return ((_this$first = this.first()) === null || _this$first === void 0 ? void 0 : _this$first.get('z')) || 0;
|
|
26997
|
+
}
|
|
26998
|
+
maxZIndex() {
|
|
26999
|
+
var _this$last;
|
|
27000
|
+
return ((_this$last = this.last()) === null || _this$last === void 0 ? void 0 : _this$last.get('z')) || 0;
|
|
27001
|
+
}
|
|
27002
|
+
}
|
|
27003
|
+
|
|
27004
|
+
const DEFAULT_GRAPH_LAYER_TYPE = 'GraphLayer';
|
|
27005
|
+
|
|
27006
|
+
/**
|
|
27007
|
+
* @class GraphLayer
|
|
27008
|
+
* @description A GraphLayer is a model representing a single layer in a dia.Graph.
|
|
27009
|
+
*/
|
|
27010
|
+
class GraphLayer extends Model {
|
|
27011
|
+
[GRAPH_LAYER_MARKER] = true;
|
|
27012
|
+
preinitialize() {
|
|
27013
|
+
// This allows for propagating events from the inner `cellCollection` collection
|
|
27014
|
+
// without any prefix and therefore distinguish them from the events
|
|
27015
|
+
// fired by the GraphLayer model itself.
|
|
27016
|
+
this.eventPrefix = 'layer:';
|
|
27017
|
+
}
|
|
27018
|
+
defaults() {
|
|
27019
|
+
return {
|
|
27020
|
+
type: DEFAULT_GRAPH_LAYER_TYPE
|
|
27021
|
+
};
|
|
27022
|
+
}
|
|
27023
|
+
initialize(attrs, options = {}) {
|
|
27024
|
+
super.initialize(attrs, options);
|
|
27025
|
+
this.cellCollection = new CellCollection([], {
|
|
27026
|
+
layer: this
|
|
26745
27027
|
});
|
|
26746
|
-
Model.prototype.set.call(this, 'cells', cells);
|
|
26747
27028
|
|
|
26748
|
-
//
|
|
26749
|
-
|
|
26750
|
-
|
|
27029
|
+
// Forward all events from the inner `cellCollection` collection
|
|
27030
|
+
this.cellCollection.on('all', this.trigger, this);
|
|
27031
|
+
// Listen to cell changes to manage z-index sorting
|
|
27032
|
+
this.cellCollection.on('change', this.onCellChange, this);
|
|
27033
|
+
}
|
|
27034
|
+
onCellChange(cell, opt) {
|
|
27035
|
+
if (opt.sort === false || !cell.hasChanged('z')) return;
|
|
27036
|
+
this.cellCollection.sort();
|
|
27037
|
+
}
|
|
27038
|
+
|
|
27039
|
+
/**
|
|
27040
|
+
* @public
|
|
27041
|
+
* @description Returns all cells in this layer.
|
|
27042
|
+
*/
|
|
27043
|
+
getCells() {
|
|
27044
|
+
return this.cellCollection.toArray();
|
|
27045
|
+
}
|
|
27046
|
+
}
|
|
26751
27047
|
|
|
26752
|
-
|
|
26753
|
-
|
|
26754
|
-
|
|
27048
|
+
/**
|
|
27049
|
+
* @class GraphLayerCollection
|
|
27050
|
+
* @description A collection of layers used in dia.Graph. It facilitates creating layers from JSON using layerNamespace.
|
|
27051
|
+
*/
|
|
27052
|
+
const GraphLayerCollection = Collection.extend({
|
|
27053
|
+
defaultLayerNamespace: {
|
|
27054
|
+
GraphLayer
|
|
27055
|
+
},
|
|
27056
|
+
/**
|
|
27057
|
+
* @override
|
|
27058
|
+
* @description Initializes the collection and sets up the layer and cell namespaces.
|
|
27059
|
+
*/
|
|
27060
|
+
initialize: function (_models, options = {}) {
|
|
27061
|
+
const {
|
|
27062
|
+
layerNamespace,
|
|
27063
|
+
cellNamespace,
|
|
27064
|
+
graph
|
|
27065
|
+
} = options;
|
|
26755
27066
|
|
|
26756
|
-
//
|
|
26757
|
-
//
|
|
26758
|
-
|
|
26759
|
-
|
|
26760
|
-
//
|
|
27067
|
+
// Initialize the namespace that holds all available layer classes.
|
|
27068
|
+
// Custom namespaces are merged with the default ones.
|
|
27069
|
+
this.layerNamespace = assign({}, this.defaultLayerNamespace, layerNamespace);
|
|
27070
|
+
|
|
27071
|
+
// Initialize the namespace for all cell model classes, if provided.
|
|
27072
|
+
if (cellNamespace) {
|
|
27073
|
+
this.cellNamespace = cellNamespace;
|
|
27074
|
+
} else {
|
|
27075
|
+
/* eslint-disable no-undef */
|
|
27076
|
+
this.cellNamespace = typeof joint !== 'undefined' && has(joint, 'shapes') ? joint.shapes : null;
|
|
27077
|
+
/* eslint-enable no-undef */
|
|
27078
|
+
}
|
|
27079
|
+
this.graph = graph;
|
|
27080
|
+
},
|
|
27081
|
+
/**
|
|
27082
|
+
* @override
|
|
27083
|
+
* @description Overrides the default `model` method
|
|
27084
|
+
* to create layer models based on their `type` attribute.
|
|
27085
|
+
*/
|
|
27086
|
+
model: function (attrs, opt) {
|
|
27087
|
+
const collection = opt.collection;
|
|
27088
|
+
const namespace = collection.layerNamespace;
|
|
27089
|
+
const {
|
|
27090
|
+
type
|
|
27091
|
+
} = attrs;
|
|
27092
|
+
|
|
27093
|
+
// Find the model class based on the `type` attribute in the cell namespace
|
|
27094
|
+
const GraphLayerClass = getByPath(namespace, type, '.');
|
|
27095
|
+
if (!GraphLayerClass) {
|
|
27096
|
+
throw new Error(`dia.Graph: Could not find layer constructor for type: '${type}'. Make sure to add the constructor to 'layerNamespace'.`);
|
|
27097
|
+
}
|
|
27098
|
+
return new GraphLayerClass(attrs, opt);
|
|
27099
|
+
},
|
|
27100
|
+
// Override to set graph reference
|
|
27101
|
+
_addReference(layer, options) {
|
|
27102
|
+
Collection.prototype._addReference.call(this, layer, options);
|
|
27103
|
+
|
|
27104
|
+
// assign graph and cellNamespace references
|
|
27105
|
+
// to the added layer
|
|
27106
|
+
layer.graph = this.graph;
|
|
27107
|
+
layer.cellCollection.cellNamespace = this.cellNamespace;
|
|
27108
|
+
},
|
|
27109
|
+
// Override to remove graph reference
|
|
27110
|
+
_removeReference(layer, options) {
|
|
27111
|
+
Collection.prototype._removeReference.call(this, layer, options);
|
|
27112
|
+
|
|
27113
|
+
// remove graph and cellNamespace references
|
|
27114
|
+
// from the removed layer
|
|
27115
|
+
layer.graph = null;
|
|
27116
|
+
layer.cellCollection.cellNamespace = null;
|
|
27117
|
+
},
|
|
27118
|
+
/**
|
|
27119
|
+
* @override
|
|
27120
|
+
* @description Overrides the default `_prepareModel` method
|
|
27121
|
+
* to set default layer type if missing.
|
|
27122
|
+
*/
|
|
27123
|
+
_prepareModel: function (attrs, options) {
|
|
27124
|
+
if (!attrs[GRAPH_LAYER_MARKER]) {
|
|
27125
|
+
// Add a mandatory `type` attribute if missing
|
|
27126
|
+
if (!attrs.type) {
|
|
27127
|
+
const preparedAttributes = clone$1(attrs);
|
|
27128
|
+
preparedAttributes.type = DEFAULT_GRAPH_LAYER_TYPE;
|
|
27129
|
+
arguments[0] = preparedAttributes;
|
|
27130
|
+
}
|
|
27131
|
+
}
|
|
27132
|
+
return Collection.prototype._prepareModel.apply(this, arguments);
|
|
27133
|
+
},
|
|
27134
|
+
/**
|
|
27135
|
+
* @override
|
|
27136
|
+
* @description Add an assertion to prevent direct resetting of the collection.
|
|
27137
|
+
*/
|
|
27138
|
+
reset(models, options) {
|
|
27139
|
+
this._assertInternalCall(options);
|
|
27140
|
+
return Collection.prototype.reset.apply(this, arguments);
|
|
27141
|
+
},
|
|
27142
|
+
/**
|
|
27143
|
+
* @override
|
|
27144
|
+
* @description Add an assertion to prevent direct addition of layers.
|
|
27145
|
+
*/
|
|
27146
|
+
add(models, options) {
|
|
27147
|
+
this._assertInternalCall(options);
|
|
27148
|
+
return Collection.prototype.add.apply(this, arguments);
|
|
27149
|
+
},
|
|
27150
|
+
/**
|
|
27151
|
+
* @override
|
|
27152
|
+
* @description Add an assertion to prevent direct removal of layers.
|
|
27153
|
+
*/
|
|
27154
|
+
remove(models, options) {
|
|
27155
|
+
this._assertInternalCall(options);
|
|
27156
|
+
return Collection.prototype.remove.apply(this, arguments);
|
|
27157
|
+
},
|
|
27158
|
+
/**
|
|
27159
|
+
* @override
|
|
27160
|
+
* @description Overrides the default `_onModelEvent` method
|
|
27161
|
+
* to distinguish between events coming from different model types.
|
|
27162
|
+
*/
|
|
27163
|
+
_onModelEvent(_, model) {
|
|
27164
|
+
if (model && model[CELL_MARKER]) {
|
|
27165
|
+
// Do not filter cell `add` and `remove` events
|
|
27166
|
+
// See `mvc.Collection` for more details
|
|
27167
|
+
this.trigger.apply(this, arguments);
|
|
27168
|
+
return;
|
|
27169
|
+
}
|
|
26761
27170
|
|
|
27171
|
+
// For other events, use the default behavior
|
|
27172
|
+
Collection.prototype._onModelEvent.apply(this, arguments);
|
|
27173
|
+
},
|
|
27174
|
+
/**
|
|
27175
|
+
* @protected
|
|
27176
|
+
* @description Asserts that the collection manipulation
|
|
27177
|
+
* is done via internal graph methods. Otherwise, it throws an error.
|
|
27178
|
+
* This is a temporary measure until layers API is stabilized.
|
|
27179
|
+
*/
|
|
27180
|
+
_assertInternalCall(options) {
|
|
27181
|
+
if (options && !options.graph && !options.silent) {
|
|
27182
|
+
throw new Error('dia.GraphLayerCollection: direct manipulation of the collection is not supported, use graph methods instead.');
|
|
27183
|
+
}
|
|
27184
|
+
},
|
|
27185
|
+
/**
|
|
27186
|
+
* @public
|
|
27187
|
+
* @description Inserts a layer before another layer or at the end if `beforeLayerId` is null.
|
|
27188
|
+
*/
|
|
27189
|
+
insert(layerInit, beforeLayerId = null, options = {}) {
|
|
27190
|
+
const id = layerInit.id;
|
|
27191
|
+
if (id === beforeLayerId) {
|
|
27192
|
+
// Inserting before itself is a no-op
|
|
27193
|
+
return;
|
|
27194
|
+
}
|
|
27195
|
+
if (beforeLayerId && !this.has(beforeLayerId)) {
|
|
27196
|
+
throw new Error(`dia.GraphLayerCollection: Layer "${beforeLayerId}" does not exist`);
|
|
27197
|
+
}
|
|
27198
|
+
|
|
27199
|
+
// See if the layer is already in the collection
|
|
27200
|
+
let currentIndex = -1;
|
|
27201
|
+
if (this.has(id)) {
|
|
27202
|
+
currentIndex = this.findIndex(l => l.id === id);
|
|
27203
|
+
if (currentIndex === this.length - 1 && !beforeLayerId) {
|
|
27204
|
+
// The layer is already at the end
|
|
27205
|
+
return;
|
|
27206
|
+
}
|
|
27207
|
+
// Remove the layer from its current position
|
|
27208
|
+
this.remove(id, {
|
|
27209
|
+
silent: true
|
|
27210
|
+
});
|
|
27211
|
+
}
|
|
27212
|
+
|
|
27213
|
+
// At what index to insert the layer?
|
|
27214
|
+
let insertAt;
|
|
27215
|
+
if (!beforeLayerId) {
|
|
27216
|
+
insertAt = this.length;
|
|
27217
|
+
} else {
|
|
27218
|
+
insertAt = this.findIndex(l => l.id === beforeLayerId);
|
|
27219
|
+
}
|
|
27220
|
+
if (currentIndex !== -1) {
|
|
27221
|
+
// Re-insert the layer at the new position.
|
|
27222
|
+
this.add(layerInit, {
|
|
27223
|
+
at: insertAt,
|
|
27224
|
+
silent: true
|
|
27225
|
+
});
|
|
27226
|
+
// Trigger `sort` event manually
|
|
27227
|
+
// since we are not using collection sorting workflow
|
|
27228
|
+
this.trigger('sort', this, options);
|
|
27229
|
+
} else {
|
|
27230
|
+
// Add to the collection and trigger an event
|
|
27231
|
+
// when new layer has been added
|
|
27232
|
+
this.add(layerInit, {
|
|
27233
|
+
...options,
|
|
27234
|
+
at: insertAt
|
|
27235
|
+
});
|
|
27236
|
+
}
|
|
27237
|
+
},
|
|
27238
|
+
/**
|
|
27239
|
+
* @public
|
|
27240
|
+
* @description Finds and returns a cell by its id from all layers.
|
|
27241
|
+
*/
|
|
27242
|
+
getCell(cellRef) {
|
|
27243
|
+
// TODO: should we create a map of cells for faster lookup?
|
|
27244
|
+
for (const layer of this.models) {
|
|
27245
|
+
const cell = layer.cellCollection.get(cellRef);
|
|
27246
|
+
if (cell) {
|
|
27247
|
+
return cell;
|
|
27248
|
+
}
|
|
27249
|
+
}
|
|
27250
|
+
// Backward compatibility: return undefined if cell is not found
|
|
27251
|
+
return undefined;
|
|
27252
|
+
},
|
|
27253
|
+
/**
|
|
27254
|
+
* @public
|
|
27255
|
+
* @description Returns all cells in all layers in the correct order.
|
|
27256
|
+
*/
|
|
27257
|
+
getCells() {
|
|
27258
|
+
const layers = this.models;
|
|
27259
|
+
if (layers.length === 1) {
|
|
27260
|
+
// Single layer:
|
|
27261
|
+
// Fast path, just return the copy of the only layer's cells
|
|
27262
|
+
return layers[0].getCells();
|
|
27263
|
+
}
|
|
27264
|
+
// Multiple layers:
|
|
27265
|
+
// Each layer has its models sorted already, so we can just concatenate
|
|
27266
|
+
// them in the order of layers.
|
|
27267
|
+
const cells = [];
|
|
27268
|
+
for (const layer of layers) {
|
|
27269
|
+
Array.prototype.push.apply(cells, layer.cellCollection.models);
|
|
27270
|
+
}
|
|
27271
|
+
return cells;
|
|
27272
|
+
},
|
|
27273
|
+
/**
|
|
27274
|
+
* @public
|
|
27275
|
+
* @description Removes a cell from its current layer.
|
|
27276
|
+
*/
|
|
27277
|
+
removeCell(cell, options = {}) {
|
|
27278
|
+
var _cell$collection;
|
|
27279
|
+
const cellCollection = (_cell$collection = cell.collection) === null || _cell$collection === void 0 || (_cell$collection = _cell$collection.layer) === null || _cell$collection === void 0 ? void 0 : _cell$collection.cellCollection;
|
|
27280
|
+
if (!cellCollection) return;
|
|
27281
|
+
cellCollection.remove(cell, options);
|
|
27282
|
+
},
|
|
27283
|
+
/**
|
|
27284
|
+
* @public
|
|
27285
|
+
* @description Move a cell from its current layer to a target layer.
|
|
27286
|
+
*/
|
|
27287
|
+
moveCellBetweenLayers(cell, targetLayerId, options = {}) {
|
|
27288
|
+
var _cell$collection2;
|
|
27289
|
+
const sourceLayer = (_cell$collection2 = cell.collection) === null || _cell$collection2 === void 0 ? void 0 : _cell$collection2.layer;
|
|
27290
|
+
if (!sourceLayer) {
|
|
27291
|
+
throw new Error('dia.GraphLayerCollection: cannot move a cell that is not part of any layer.');
|
|
27292
|
+
}
|
|
27293
|
+
const targetLayer = this.get(targetLayerId);
|
|
27294
|
+
if (!targetLayer) {
|
|
27295
|
+
throw new Error(`dia.GraphLayerCollection: cannot move cell to layer '${targetLayerId}' because such layer does not exist.`);
|
|
27296
|
+
}
|
|
27297
|
+
if (sourceLayer === targetLayer) {
|
|
27298
|
+
// 1. The provided cell is already in the target layer
|
|
27299
|
+
// 2. Implicit default layer vs. explicit default (or vice versa)
|
|
27300
|
+
// No follow-up action needed
|
|
27301
|
+
return;
|
|
27302
|
+
}
|
|
27303
|
+
const moveOptions = {
|
|
27304
|
+
...options,
|
|
27305
|
+
fromLayer: sourceLayer.id,
|
|
27306
|
+
toLayer: targetLayer.id
|
|
27307
|
+
};
|
|
27308
|
+
// Move the cell between the two layer collections
|
|
27309
|
+
sourceLayer.cellCollection.remove(cell, moveOptions);
|
|
27310
|
+
targetLayer.cellCollection.add(cell, moveOptions);
|
|
27311
|
+
// Trigger a single `move` event to ease distinguishing layer moves
|
|
27312
|
+
// from add/remove operations
|
|
27313
|
+
cell.trigger('move', cell, moveOptions);
|
|
27314
|
+
},
|
|
27315
|
+
/**
|
|
27316
|
+
* @public
|
|
27317
|
+
* @description Adds a cell to the specified layer.
|
|
27318
|
+
*/
|
|
27319
|
+
addCellToLayer(cell, layerId, options = {}) {
|
|
27320
|
+
const targetLayer = this.get(layerId);
|
|
27321
|
+
if (!targetLayer) {
|
|
27322
|
+
throw new Error(`dia.GraphLayerCollection: layer "${layerId}" does not exist.`);
|
|
27323
|
+
}
|
|
27324
|
+
const addOptions = {
|
|
27325
|
+
...options,
|
|
27326
|
+
toLayer: targetLayer.id
|
|
27327
|
+
};
|
|
27328
|
+
// Add the cell to the target layer collection
|
|
27329
|
+
targetLayer.cellCollection.add(cell, addOptions);
|
|
27330
|
+
}
|
|
27331
|
+
});
|
|
27332
|
+
Object.defineProperty(GraphLayerCollection.prototype, GRAPH_LAYER_COLLECTION_MARKER, {
|
|
27333
|
+
value: true
|
|
27334
|
+
});
|
|
27335
|
+
|
|
27336
|
+
/**
|
|
27337
|
+
* @class GraphTopologyIndex
|
|
27338
|
+
* @description Maintains an index of the graph topology (adjacency list)
|
|
27339
|
+
* for fast graph queries.
|
|
27340
|
+
*/
|
|
27341
|
+
class GraphTopologyIndex extends Listener {
|
|
27342
|
+
constructor(options) {
|
|
27343
|
+
super(options);
|
|
27344
|
+
|
|
27345
|
+
// Make sure there are no arguments passed to the callbacks.
|
|
27346
|
+
// See the `mvc.Listener` documentation for more details.
|
|
27347
|
+
this.callbackArguments = [];
|
|
27348
|
+
this.layerCollection = options.layerCollection;
|
|
27349
|
+
if (!this.layerCollection) {
|
|
27350
|
+
throw new Error('GraphTopologyIndex: "layerCollection" option is required.');
|
|
27351
|
+
}
|
|
27352
|
+
this.initializeIndex();
|
|
27353
|
+
this.startListening();
|
|
27354
|
+
}
|
|
27355
|
+
|
|
27356
|
+
/**
|
|
27357
|
+
* @public
|
|
27358
|
+
* @description Start listening to graph and layer collection events
|
|
27359
|
+
* to maintain the topology index.
|
|
27360
|
+
*/
|
|
27361
|
+
startListening() {
|
|
27362
|
+
this.listenTo(this.layerCollection.graph, {
|
|
27363
|
+
'add': this._restructureOnAdd,
|
|
27364
|
+
'remove': this._restructureOnRemove,
|
|
27365
|
+
'reset': this._restructureOnReset
|
|
27366
|
+
});
|
|
27367
|
+
// Listening to the collection instead of the graph
|
|
27368
|
+
// to avoid reacting to graph attribute change events
|
|
27369
|
+
// e.g. graph.set('source', ...);
|
|
27370
|
+
this.listenTo(this.layerCollection, {
|
|
27371
|
+
'change:source': this._restructureOnChangeSource,
|
|
27372
|
+
'change:target': this._restructureOnChangeTarget
|
|
27373
|
+
});
|
|
27374
|
+
}
|
|
27375
|
+
|
|
27376
|
+
/**
|
|
27377
|
+
* @protected
|
|
27378
|
+
* @description Initialize the internal data structures.
|
|
27379
|
+
*/
|
|
27380
|
+
initializeIndex() {
|
|
26762
27381
|
// Outgoing edges per node. Note that we use a hash-table for the list
|
|
26763
27382
|
// of outgoing edges for a faster lookup.
|
|
26764
27383
|
// [nodeId] -> Object [edgeId] -> true
|
|
@@ -26774,21 +27393,27 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
26774
27393
|
// having to go through the whole cells array.
|
|
26775
27394
|
// [edgeId] -> true
|
|
26776
27395
|
this._edges = {};
|
|
26777
|
-
|
|
26778
|
-
|
|
26779
|
-
|
|
26780
|
-
|
|
26781
|
-
|
|
26782
|
-
|
|
26783
|
-
|
|
26784
|
-
|
|
26785
|
-
|
|
26786
|
-
this.
|
|
26787
|
-
}
|
|
26788
|
-
|
|
27396
|
+
}
|
|
27397
|
+
|
|
27398
|
+
/**
|
|
27399
|
+
* @protected
|
|
27400
|
+
* @description Restructure the topology index on graph reset.
|
|
27401
|
+
* E.g. when fromJSON or resetCells is called.
|
|
27402
|
+
*/
|
|
27403
|
+
_restructureOnReset() {
|
|
27404
|
+
this.initializeIndex();
|
|
27405
|
+
this.layerCollection.getCells().forEach(this._restructureOnAdd, this);
|
|
27406
|
+
}
|
|
27407
|
+
|
|
27408
|
+
/**
|
|
27409
|
+
* @protected
|
|
27410
|
+
* @description Restructure the topology index on cell addition.
|
|
27411
|
+
* @param {dia.Cell} cell - The cell being added.
|
|
27412
|
+
*/
|
|
27413
|
+
_restructureOnAdd(cell) {
|
|
26789
27414
|
if (cell.isLink()) {
|
|
26790
27415
|
this._edges[cell.id] = true;
|
|
26791
|
-
|
|
27416
|
+
const {
|
|
26792
27417
|
source,
|
|
26793
27418
|
target
|
|
26794
27419
|
} = cell.attributes;
|
|
@@ -26801,11 +27426,17 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
26801
27426
|
} else {
|
|
26802
27427
|
this._nodes[cell.id] = true;
|
|
26803
27428
|
}
|
|
26804
|
-
}
|
|
26805
|
-
|
|
27429
|
+
}
|
|
27430
|
+
|
|
27431
|
+
/**
|
|
27432
|
+
* @protected
|
|
27433
|
+
* @description Restructure the topology index on cell removal.
|
|
27434
|
+
* @param {dia.Cell} cell - The cell being removed.
|
|
27435
|
+
*/
|
|
27436
|
+
_restructureOnRemove(cell) {
|
|
26806
27437
|
if (cell.isLink()) {
|
|
26807
27438
|
delete this._edges[cell.id];
|
|
26808
|
-
|
|
27439
|
+
const {
|
|
26809
27440
|
source,
|
|
26810
27441
|
target
|
|
26811
27442
|
} = cell.attributes;
|
|
@@ -26818,89 +27449,222 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
26818
27449
|
} else {
|
|
26819
27450
|
delete this._nodes[cell.id];
|
|
26820
27451
|
}
|
|
26821
|
-
}
|
|
26822
|
-
|
|
26823
|
-
|
|
26824
|
-
|
|
26825
|
-
|
|
26826
|
-
|
|
26827
|
-
|
|
26828
|
-
|
|
26829
|
-
|
|
26830
|
-
},
|
|
26831
|
-
_restructureOnChangeSource: function (link) {
|
|
26832
|
-
var prevSource = link.previous('source');
|
|
27452
|
+
}
|
|
27453
|
+
|
|
27454
|
+
/**
|
|
27455
|
+
* @protected
|
|
27456
|
+
* @description Restructure the topology index on link source change.
|
|
27457
|
+
* @param {dia.Link} link - The link being changed.
|
|
27458
|
+
*/
|
|
27459
|
+
_restructureOnChangeSource(link) {
|
|
27460
|
+
const prevSource = link.previous('source');
|
|
26833
27461
|
if (prevSource.id && this._out[prevSource.id]) {
|
|
26834
27462
|
delete this._out[prevSource.id][link.id];
|
|
26835
27463
|
}
|
|
26836
|
-
|
|
27464
|
+
const source = link.attributes.source;
|
|
26837
27465
|
if (source.id) {
|
|
26838
27466
|
(this._out[source.id] || (this._out[source.id] = {}))[link.id] = true;
|
|
26839
27467
|
}
|
|
26840
|
-
}
|
|
26841
|
-
|
|
26842
|
-
|
|
27468
|
+
}
|
|
27469
|
+
|
|
27470
|
+
/**
|
|
27471
|
+
* @protected
|
|
27472
|
+
* @description Restructure the topology index on link target change.
|
|
27473
|
+
* @param {dia.Link} link - The link being changed.
|
|
27474
|
+
*/
|
|
27475
|
+
_restructureOnChangeTarget(link) {
|
|
27476
|
+
const prevTarget = link.previous('target');
|
|
26843
27477
|
if (prevTarget.id && this._in[prevTarget.id]) {
|
|
26844
27478
|
delete this._in[prevTarget.id][link.id];
|
|
26845
27479
|
}
|
|
26846
|
-
|
|
27480
|
+
const target = link.get('target');
|
|
26847
27481
|
if (target.id) {
|
|
26848
27482
|
(this._in[target.id] || (this._in[target.id] = {}))[link.id] = true;
|
|
26849
27483
|
}
|
|
26850
|
-
}
|
|
26851
|
-
|
|
26852
|
-
|
|
26853
|
-
|
|
26854
|
-
|
|
26855
|
-
|
|
26856
|
-
|
|
26857
|
-
|
|
26858
|
-
|
|
26859
|
-
return this.
|
|
27484
|
+
}
|
|
27485
|
+
|
|
27486
|
+
/**
|
|
27487
|
+
* @public
|
|
27488
|
+
* @description Get all outbound edges for the node. Time complexity: O(1).
|
|
27489
|
+
* @param {string} nodeId - The id of the node.
|
|
27490
|
+
* @returns {Object} - An object of the form: [edgeId] -> true.
|
|
27491
|
+
*/
|
|
27492
|
+
getOutboundEdges(nodeId) {
|
|
27493
|
+
return this._out[nodeId] || {};
|
|
27494
|
+
}
|
|
27495
|
+
|
|
27496
|
+
/**
|
|
27497
|
+
* @public
|
|
27498
|
+
* @description Get all inbound edges for the node. Time complexity: O(1).
|
|
27499
|
+
* @param {string} nodeId - The id of the node.
|
|
27500
|
+
* @returns {Object} - An object of the form: [edgeId] -> true.
|
|
27501
|
+
*/
|
|
27502
|
+
getInboundEdges(nodeId) {
|
|
27503
|
+
return this._in[nodeId] || {};
|
|
27504
|
+
}
|
|
27505
|
+
|
|
27506
|
+
/**
|
|
27507
|
+
* @public
|
|
27508
|
+
* @description Get all sink nodes (leafs) in the graph. Time complexity: O(|V|).
|
|
27509
|
+
* @returns {string[]} - Array of node ids.
|
|
27510
|
+
*/
|
|
27511
|
+
getSinkNodes() {
|
|
27512
|
+
const sinks = [];
|
|
27513
|
+
for (const nodeId in this._nodes) {
|
|
27514
|
+
if (!this._out[nodeId] || isEmpty(this._out[nodeId])) {
|
|
27515
|
+
sinks.push(nodeId);
|
|
27516
|
+
}
|
|
27517
|
+
}
|
|
27518
|
+
return sinks;
|
|
27519
|
+
}
|
|
27520
|
+
|
|
27521
|
+
/**
|
|
27522
|
+
* @public
|
|
27523
|
+
* @description Get all source nodes (roots) in the graph. Time complexity: O(|V|).
|
|
27524
|
+
* @returns {string[]} - Array of node ids.
|
|
27525
|
+
*/
|
|
27526
|
+
getSourceNodes() {
|
|
27527
|
+
const sources = [];
|
|
27528
|
+
for (const nodeId in this._nodes) {
|
|
27529
|
+
if (!this._in[nodeId] || isEmpty(this._in[nodeId])) {
|
|
27530
|
+
sources.push(nodeId);
|
|
27531
|
+
}
|
|
27532
|
+
}
|
|
27533
|
+
return sources;
|
|
27534
|
+
}
|
|
27535
|
+
|
|
27536
|
+
/**
|
|
27537
|
+
* @public
|
|
27538
|
+
* @description Return `true` if `nodeId` is a source node (root). Time complexity: O(1).
|
|
27539
|
+
* @param {string} nodeId - The id of the node to check.
|
|
27540
|
+
* @returns {boolean}
|
|
27541
|
+
*/
|
|
27542
|
+
isSourceNode(nodeId) {
|
|
27543
|
+
return !this._in[nodeId] || isEmpty(this._in[nodeId]);
|
|
27544
|
+
}
|
|
27545
|
+
|
|
27546
|
+
/**
|
|
27547
|
+
* @public
|
|
27548
|
+
* @description Return `true` if `nodeId` is a sink node (leaf). Time complexity: O(1).
|
|
27549
|
+
* @param {string} nodeId - The id of the node to check.
|
|
27550
|
+
* @returns {boolean}
|
|
27551
|
+
*/
|
|
27552
|
+
isSinkNode(nodeId) {
|
|
27553
|
+
return !this._out[nodeId] || isEmpty(this._out[nodeId]);
|
|
27554
|
+
}
|
|
27555
|
+
}
|
|
27556
|
+
|
|
27557
|
+
// The ID of the default graph layer.
|
|
27558
|
+
const DEFAULT_LAYER_ID = 'cells';
|
|
27559
|
+
const Graph = Model.extend({
|
|
27560
|
+
/**
|
|
27561
|
+
* @todo Remove in v5.0.0
|
|
27562
|
+
* @description In legacy mode, the information about layers is not
|
|
27563
|
+
* exported into JSON.
|
|
27564
|
+
*/
|
|
27565
|
+
legacyMode: true,
|
|
27566
|
+
/**
|
|
27567
|
+
* @protected
|
|
27568
|
+
* @description The ID of the default layer.
|
|
27569
|
+
*/
|
|
27570
|
+
defaultLayerId: DEFAULT_LAYER_ID,
|
|
27571
|
+
initialize: function (attrs, options = {}) {
|
|
27572
|
+
const layerCollection = this.layerCollection = new GraphLayerCollection([], {
|
|
27573
|
+
layerNamespace: options.layerNamespace,
|
|
27574
|
+
cellNamespace: options.cellNamespace,
|
|
27575
|
+
graph: this,
|
|
27576
|
+
/** @deprecated use cellNamespace instead */
|
|
27577
|
+
model: options.cellModel
|
|
27578
|
+
});
|
|
27579
|
+
|
|
27580
|
+
// The default setup includes a single default layer.
|
|
27581
|
+
layerCollection.add({
|
|
27582
|
+
id: DEFAULT_LAYER_ID
|
|
27583
|
+
}, {
|
|
27584
|
+
graph: this.cid
|
|
27585
|
+
});
|
|
27586
|
+
|
|
27587
|
+
/**
|
|
27588
|
+
* @todo Remove in v5.0.0
|
|
27589
|
+
* @description Retain legacy 'cells' collection in attributes for backward compatibility.
|
|
27590
|
+
* Applicable only when the default layer setup is used.
|
|
27591
|
+
*/
|
|
27592
|
+
this.attributes.cells = this.getLayer(DEFAULT_LAYER_ID).cellCollection;
|
|
27593
|
+
|
|
27594
|
+
// Controller that manages communication between the graph and its layers.
|
|
27595
|
+
this.layersController = new GraphLayersController({
|
|
27596
|
+
graph: this
|
|
27597
|
+
});
|
|
27598
|
+
|
|
27599
|
+
// `Graph` keeps an internal data structure (an adjacency list)
|
|
27600
|
+
// for fast graph queries. All changes that affect the structure of the graph
|
|
27601
|
+
// must be reflected in the `al` object. This object provides fast answers to
|
|
27602
|
+
// questions such as "what are the neighbors of this node" or "what
|
|
27603
|
+
// are the sibling links of this link".
|
|
27604
|
+
this.topologyIndex = new GraphTopologyIndex({
|
|
27605
|
+
layerCollection
|
|
27606
|
+
});
|
|
27607
|
+
this._batches = {};
|
|
26860
27608
|
},
|
|
26861
27609
|
toJSON: function (opt = {}) {
|
|
26862
|
-
|
|
26863
|
-
|
|
26864
|
-
|
|
26865
|
-
|
|
27610
|
+
const {
|
|
27611
|
+
layerCollection
|
|
27612
|
+
} = this;
|
|
27613
|
+
// Get the graph model attributes as a base JSON.
|
|
27614
|
+
const json = Model.prototype.toJSON.apply(this, arguments);
|
|
27615
|
+
|
|
27616
|
+
// Add `cells` array holding all the cells in the graph.
|
|
27617
|
+
json.cells = this.getCells().map(cell => cell.toJSON(opt.cellAttributes));
|
|
27618
|
+
if (this.legacyMode) {
|
|
27619
|
+
// Backwards compatibility for legacy setup
|
|
27620
|
+
// with single default layer 'cells'.
|
|
27621
|
+
// In this case, we do not need to export layers.
|
|
27622
|
+
return json;
|
|
27623
|
+
}
|
|
27624
|
+
|
|
27625
|
+
// Add `layers` array holding all the layers in the graph.
|
|
27626
|
+
json.layers = layerCollection.toJSON();
|
|
27627
|
+
|
|
27628
|
+
// Add `defaultLayer` property indicating the default layer ID.
|
|
27629
|
+
json.defaultLayer = this.defaultLayerId;
|
|
26866
27630
|
return json;
|
|
26867
27631
|
},
|
|
26868
27632
|
fromJSON: function (json, opt) {
|
|
26869
|
-
|
|
27633
|
+
const {
|
|
27634
|
+
cells,
|
|
27635
|
+
layers,
|
|
27636
|
+
defaultLayer,
|
|
27637
|
+
...attributes
|
|
27638
|
+
} = json;
|
|
27639
|
+
if (!cells) {
|
|
26870
27640
|
throw new Error('Graph JSON must contain cells array.');
|
|
26871
27641
|
}
|
|
26872
|
-
return this.set(json, opt);
|
|
26873
|
-
},
|
|
26874
|
-
set: function (key, val, opt) {
|
|
26875
|
-
var attrs;
|
|
26876
27642
|
|
|
26877
|
-
//
|
|
26878
|
-
|
|
26879
|
-
|
|
26880
|
-
|
|
26881
|
-
}
|
|
26882
|
-
|
|
27643
|
+
// The `fromJSON` should trigger a single 'reset' event at the end.
|
|
27644
|
+
// Set all attributes silently for now.
|
|
27645
|
+
this.set(attributes, {
|
|
27646
|
+
silent: true
|
|
27647
|
+
});
|
|
27648
|
+
if (layers) {
|
|
27649
|
+
// Reset the layers collection
|
|
27650
|
+
// (`layers:reset` is not forwarded to the graph).
|
|
27651
|
+
this._resetLayers(layers, defaultLayer, opt);
|
|
26883
27652
|
}
|
|
26884
|
-
|
|
26885
|
-
|
|
26886
|
-
|
|
26887
|
-
this.resetCells(attrs.cells, opt);
|
|
26888
|
-
attrs = omit(attrs, 'cells');
|
|
27653
|
+
if (cells) {
|
|
27654
|
+
// Reset the cells collection and trigger the 'reset' event.
|
|
27655
|
+
this.resetCells(cells, opt);
|
|
26889
27656
|
}
|
|
26890
|
-
|
|
26891
|
-
// The rest of the attributes are applied via original set method.
|
|
26892
|
-
return Model.prototype.set.call(this, attrs, opt);
|
|
27657
|
+
return this;
|
|
26893
27658
|
},
|
|
27659
|
+
/** @deprecated */
|
|
26894
27660
|
clear: function (opt) {
|
|
26895
27661
|
opt = assign({}, opt, {
|
|
26896
27662
|
clear: true
|
|
26897
27663
|
});
|
|
26898
|
-
|
|
26899
|
-
if (
|
|
27664
|
+
const cells = this.getCells();
|
|
27665
|
+
if (cells.length === 0) return this;
|
|
26900
27666
|
this.startBatch('clear', opt);
|
|
26901
|
-
|
|
26902
|
-
// The elements come after the links.
|
|
26903
|
-
var cells = collection.sortBy(function (cell) {
|
|
27667
|
+
const sortedCells = sortBy(cells, cell => {
|
|
26904
27668
|
return cell.isLink() ? 1 : 2;
|
|
26905
27669
|
});
|
|
26906
27670
|
do {
|
|
@@ -26908,43 +27672,56 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
26908
27672
|
// Note that all the links are removed first, so it's
|
|
26909
27673
|
// safe to remove the elements without removing the connected
|
|
26910
27674
|
// links first.
|
|
26911
|
-
|
|
26912
|
-
} while (
|
|
27675
|
+
this.layerCollection.removeCell(sortedCells.shift(), opt);
|
|
27676
|
+
} while (sortedCells.length > 0);
|
|
26913
27677
|
this.stopBatch('clear');
|
|
26914
27678
|
return this;
|
|
26915
27679
|
},
|
|
26916
|
-
_prepareCell: function (
|
|
26917
|
-
let
|
|
26918
|
-
if (
|
|
26919
|
-
|
|
27680
|
+
_prepareCell: function (cellInit, opt) {
|
|
27681
|
+
let cellAttributes;
|
|
27682
|
+
if (cellInit[CELL_MARKER]) {
|
|
27683
|
+
cellAttributes = cellInit.attributes;
|
|
26920
27684
|
} else {
|
|
26921
|
-
|
|
27685
|
+
cellAttributes = cellInit;
|
|
26922
27686
|
}
|
|
26923
|
-
if (!isString(
|
|
27687
|
+
if (!isString(cellAttributes.type)) {
|
|
26924
27688
|
throw new TypeError('dia.Graph: cell type must be a string.');
|
|
26925
27689
|
}
|
|
26926
|
-
|
|
27690
|
+
|
|
27691
|
+
// Backward compatibility: prior v4.2, z-index was not set during reset.
|
|
27692
|
+
if (opt && opt.ensureZIndex) {
|
|
27693
|
+
if (cellAttributes.z === undefined) {
|
|
27694
|
+
const layerId = cellAttributes[config$3.layerAttribute] || this.defaultLayerId;
|
|
27695
|
+
const zIndex = this.maxZIndex(layerId) + 1;
|
|
27696
|
+
if (cellInit[CELL_MARKER]) {
|
|
27697
|
+
// Set with event in case there is a listener
|
|
27698
|
+
// directly on the cell instance
|
|
27699
|
+
// (the cell is not part of graph yet)
|
|
27700
|
+
cellInit.set('z', zIndex, opt);
|
|
27701
|
+
} else {
|
|
27702
|
+
cellAttributes.z = zIndex;
|
|
27703
|
+
}
|
|
27704
|
+
}
|
|
27705
|
+
}
|
|
27706
|
+
return cellInit;
|
|
26927
27707
|
},
|
|
26928
|
-
minZIndex: function () {
|
|
26929
|
-
|
|
26930
|
-
return
|
|
27708
|
+
minZIndex: function (layerId = this.defaultLayerId) {
|
|
27709
|
+
const layer = this.getLayer(layerId);
|
|
27710
|
+
return layer.cellCollection.minZIndex();
|
|
26931
27711
|
},
|
|
26932
|
-
maxZIndex: function () {
|
|
26933
|
-
|
|
26934
|
-
return
|
|
27712
|
+
maxZIndex: function (layerId = this.defaultLayerId) {
|
|
27713
|
+
const layer = this.getLayer(layerId);
|
|
27714
|
+
return layer.cellCollection.maxZIndex();
|
|
26935
27715
|
},
|
|
26936
|
-
addCell: function (
|
|
26937
|
-
if (Array.isArray(
|
|
26938
|
-
return this.addCells(
|
|
27716
|
+
addCell: function (cellInit, options) {
|
|
27717
|
+
if (Array.isArray(cellInit)) {
|
|
27718
|
+
return this.addCells(cellInit, options);
|
|
26939
27719
|
}
|
|
26940
|
-
|
|
26941
|
-
|
|
26942
|
-
|
|
26943
|
-
|
|
26944
|
-
|
|
26945
|
-
cell.z = this.maxZIndex() + 1;
|
|
26946
|
-
}
|
|
26947
|
-
this.get('cells').add(this._prepareCell(cell, opt), opt || {});
|
|
27720
|
+
this._prepareCell(cellInit, {
|
|
27721
|
+
...options,
|
|
27722
|
+
ensureZIndex: true
|
|
27723
|
+
});
|
|
27724
|
+
this.layerCollection.addCellToLayer(cellInit, this.getCellLayerId(cellInit), options);
|
|
26948
27725
|
return this;
|
|
26949
27726
|
},
|
|
26950
27727
|
addCells: function (cells, opt) {
|
|
@@ -26952,50 +27729,278 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
26952
27729
|
cells = flattenDeep(cells);
|
|
26953
27730
|
opt.maxPosition = opt.position = cells.length - 1;
|
|
26954
27731
|
this.startBatch('add', opt);
|
|
26955
|
-
cells.forEach(
|
|
27732
|
+
cells.forEach(cell => {
|
|
26956
27733
|
this.addCell(cell, opt);
|
|
26957
27734
|
opt.position--;
|
|
26958
|
-
}
|
|
27735
|
+
});
|
|
26959
27736
|
this.stopBatch('add', opt);
|
|
26960
27737
|
return this;
|
|
26961
27738
|
},
|
|
26962
|
-
|
|
26963
|
-
|
|
26964
|
-
|
|
26965
|
-
|
|
26966
|
-
|
|
26967
|
-
|
|
26968
|
-
|
|
26969
|
-
|
|
27739
|
+
/**
|
|
27740
|
+
* @public
|
|
27741
|
+
* @description Reset the cells in the graph.
|
|
27742
|
+
* Useful for bulk operations and optimizations.
|
|
27743
|
+
*/
|
|
27744
|
+
resetCells: function (cellInits, options) {
|
|
27745
|
+
const {
|
|
27746
|
+
layerCollection
|
|
27747
|
+
} = this;
|
|
27748
|
+
// Note: `cellInits` is always an array and `options` is always an object.
|
|
27749
|
+
// See `wrappers.cells` at the end of this file.
|
|
27750
|
+
|
|
27751
|
+
// When resetting cells, do not set z-index if not provided.
|
|
27752
|
+
const prepareOptions = {
|
|
27753
|
+
...options,
|
|
27754
|
+
ensureZIndex: false
|
|
27755
|
+
};
|
|
27756
|
+
|
|
27757
|
+
// Initialize a map of layer IDs to arrays of cells
|
|
27758
|
+
const layerCellsMap = layerCollection.reduce((map, layer) => {
|
|
27759
|
+
map[layer.id] = [];
|
|
27760
|
+
return map;
|
|
27761
|
+
}, {});
|
|
27762
|
+
|
|
27763
|
+
// Distribute cells into their respective layers
|
|
27764
|
+
for (let i = 0; i < cellInits.length; i++) {
|
|
27765
|
+
const cellInit = cellInits[i];
|
|
27766
|
+
const layerId = this.getCellLayerId(cellInit);
|
|
27767
|
+
if (layerId in layerCellsMap) {
|
|
27768
|
+
this._prepareCell(cellInit, prepareOptions);
|
|
27769
|
+
layerCellsMap[layerId].push(cellInit);
|
|
27770
|
+
} else {
|
|
27771
|
+
throw new Error(`dia.Graph: Layer "${layerId}" does not exist.`);
|
|
27772
|
+
}
|
|
27773
|
+
}
|
|
27774
|
+
|
|
27775
|
+
// Reset each layer's cell collection with the corresponding cells.
|
|
27776
|
+
layerCollection.each(layer => {
|
|
27777
|
+
layer.cellCollection.reset(layerCellsMap[layer.id], options);
|
|
27778
|
+
});
|
|
27779
|
+
|
|
27780
|
+
// Trigger a single `reset` event on the graph
|
|
27781
|
+
// (while multiple `reset` events are triggered on layers).
|
|
27782
|
+
// Backwards compatibility: use default layer collection
|
|
27783
|
+
// The `collection` parameter is retained for backwards compatibility,
|
|
27784
|
+
// and it is subject to removal in future releases.
|
|
27785
|
+
this.trigger('reset', this.getDefaultLayer().cellCollection, options);
|
|
26970
27786
|
return this;
|
|
26971
27787
|
},
|
|
26972
|
-
|
|
26973
|
-
|
|
26974
|
-
|
|
26975
|
-
|
|
26976
|
-
|
|
27788
|
+
/**
|
|
27789
|
+
* @public
|
|
27790
|
+
* @description Get the layer ID in which the cell resides.
|
|
27791
|
+
* Cells without an explicit layer are assigned to the default layer.
|
|
27792
|
+
* @param {dia.Cell | Object} cellInit - Cell model or attributes.
|
|
27793
|
+
* @returns {string} - The layer ID.
|
|
27794
|
+
*/
|
|
27795
|
+
getCellLayerId: function (cellInit) {
|
|
27796
|
+
if (!cellInit) {
|
|
27797
|
+
throw new Error('dia.Graph: No cell provided.');
|
|
27798
|
+
}
|
|
27799
|
+
const cellAttributes = cellInit[CELL_MARKER] ? cellInit.attributes : cellInit;
|
|
27800
|
+
return cellAttributes[config$3.layerAttribute] || this.defaultLayerId;
|
|
27801
|
+
},
|
|
27802
|
+
/**
|
|
27803
|
+
* @protected
|
|
27804
|
+
* @description Reset the layers in the graph.
|
|
27805
|
+
* It assumes the existing cells have been removed beforehand
|
|
27806
|
+
* or can be discarded.
|
|
27807
|
+
*/
|
|
27808
|
+
_resetLayers: function (layers, defaultLayerId, options = {}) {
|
|
27809
|
+
if (!Array.isArray(layers) || layers.length === 0) {
|
|
27810
|
+
throw new Error('dia.Graph: At least one layer must be defined.');
|
|
27811
|
+
}
|
|
27812
|
+
|
|
27813
|
+
// Resetting layers disables legacy mode
|
|
27814
|
+
this.legacyMode = false;
|
|
27815
|
+
this.layerCollection.reset(layers, {
|
|
27816
|
+
...options,
|
|
27817
|
+
graph: this.cid
|
|
27818
|
+
});
|
|
27819
|
+
|
|
27820
|
+
// If no default layer is specified, use the first layer as default
|
|
27821
|
+
if (defaultLayerId) {
|
|
27822
|
+
// The default layer must be one of the defined layers
|
|
27823
|
+
if (!this.hasLayer(defaultLayerId)) {
|
|
27824
|
+
throw new Error(`dia.Graph: default layer "${defaultLayerId}" does not exist.`);
|
|
27825
|
+
}
|
|
27826
|
+
this.defaultLayerId = defaultLayerId;
|
|
27827
|
+
} else {
|
|
27828
|
+
this.defaultLayerId = this.layerCollection.at(0).id;
|
|
26977
27829
|
}
|
|
26978
27830
|
return this;
|
|
26979
27831
|
},
|
|
26980
|
-
|
|
26981
|
-
|
|
26982
|
-
|
|
26983
|
-
|
|
26984
|
-
|
|
26985
|
-
|
|
26986
|
-
|
|
26987
|
-
|
|
27832
|
+
/**
|
|
27833
|
+
* @public
|
|
27834
|
+
* @description Remove multiple cells from the graph.
|
|
27835
|
+
* @param {Array<dia.Cell | dia.Cell.ID>} cellRefs - Array of cell references (models or IDs) to remove.
|
|
27836
|
+
* @param {Object} [options] - Removal options. See {@link dia.Graph#removeCell}.
|
|
27837
|
+
*/
|
|
27838
|
+
removeCells: function (cellRefs, options) {
|
|
27839
|
+
if (!cellRefs.length) return this;
|
|
27840
|
+
// Remove multiple cells in a single batch
|
|
27841
|
+
this.startBatch('remove');
|
|
27842
|
+
for (const cellRef of cellRefs) {
|
|
27843
|
+
if (!cellRef) continue;
|
|
27844
|
+
let cell;
|
|
27845
|
+
if (cellRef[CELL_MARKER]) {
|
|
27846
|
+
cell = cellRef;
|
|
26988
27847
|
} else {
|
|
26989
|
-
this.
|
|
27848
|
+
cell = this.getCell(cellRef);
|
|
27849
|
+
if (!cell) {
|
|
27850
|
+
// The cell might have been already removed (embedded cell, connected link, etc.)
|
|
27851
|
+
continue;
|
|
27852
|
+
}
|
|
26990
27853
|
}
|
|
27854
|
+
this.layerCollection.removeCell(cell, options);
|
|
26991
27855
|
}
|
|
26992
|
-
|
|
26993
|
-
|
|
26994
|
-
|
|
26995
|
-
|
|
26996
|
-
|
|
26997
|
-
|
|
26998
|
-
|
|
27856
|
+
this.stopBatch('remove');
|
|
27857
|
+
return this;
|
|
27858
|
+
},
|
|
27859
|
+
/**
|
|
27860
|
+
* @protected
|
|
27861
|
+
* @description Replace an existing cell with a new cell.
|
|
27862
|
+
*/
|
|
27863
|
+
_replaceCell: function (currentCell, newCellInit, opt = {}) {
|
|
27864
|
+
const batchName = 'replace-cell';
|
|
27865
|
+
const replaceOptions = {
|
|
27866
|
+
...opt,
|
|
27867
|
+
replace: true
|
|
27868
|
+
};
|
|
27869
|
+
this.startBatch(batchName, opt);
|
|
27870
|
+
// 1. Remove the cell without removing connected links or embedded cells.
|
|
27871
|
+
this.layerCollection.removeCell(currentCell, replaceOptions);
|
|
27872
|
+
const newCellInitAttributes = newCellInit[CELL_MARKER] ? newCellInit.attributes : newCellInit;
|
|
27873
|
+
// 2. Combine the current cell attributes with the new cell attributes
|
|
27874
|
+
const replacementCellAttributes = Object.assign({}, currentCell.attributes, newCellInitAttributes);
|
|
27875
|
+
let replacement;
|
|
27876
|
+
if (newCellInit[CELL_MARKER]) {
|
|
27877
|
+
// If the new cell is a model, set the merged attributes on the model
|
|
27878
|
+
newCellInit.set(replacementCellAttributes, replaceOptions);
|
|
27879
|
+
replacement = newCellInit;
|
|
27880
|
+
} else {
|
|
27881
|
+
replacement = replacementCellAttributes;
|
|
27882
|
+
}
|
|
27883
|
+
|
|
27884
|
+
// 3. Add the replacement cell
|
|
27885
|
+
this.addCell(replacement, replaceOptions);
|
|
27886
|
+
this.stopBatch(batchName);
|
|
27887
|
+
},
|
|
27888
|
+
/**
|
|
27889
|
+
* @protected
|
|
27890
|
+
* @description Synchronize a single graph cell with the provided cell (model or attributes).
|
|
27891
|
+
* If the cell with the same `id` exists, it is updated. If the cell does not exist, it is added.
|
|
27892
|
+
* If the existing cell type is different from the incoming cell type, the existing cell is replaced.
|
|
27893
|
+
*/
|
|
27894
|
+
_syncCell: function (cellInit, opt = {}) {
|
|
27895
|
+
const cellAttributes = cellInit[CELL_MARKER] ? cellInit.attributes : cellInit;
|
|
27896
|
+
const currentCell = this.getCell(cellInit.id);
|
|
27897
|
+
if (currentCell) {
|
|
27898
|
+
// `cellInit` is either a model or attributes object
|
|
27899
|
+
if ('type' in cellAttributes && currentCell.get('type') !== cellAttributes.type) {
|
|
27900
|
+
// Replace the cell if the type has changed
|
|
27901
|
+
this._replaceCell(currentCell, cellInit, opt);
|
|
27902
|
+
} else {
|
|
27903
|
+
// Update existing cell
|
|
27904
|
+
// Note: the existing cell attributes are not removed,
|
|
27905
|
+
// if they're missing in `cellAttributes`.
|
|
27906
|
+
currentCell.set(cellAttributes, opt);
|
|
27907
|
+
}
|
|
27908
|
+
} else {
|
|
27909
|
+
// The cell does not exist yet, add it
|
|
27910
|
+
this.addCell(cellInit, opt);
|
|
27911
|
+
}
|
|
27912
|
+
},
|
|
27913
|
+
/**
|
|
27914
|
+
* @public
|
|
27915
|
+
* @description Synchronize the graph cells with the provided array of cells (models or attributes).
|
|
27916
|
+
*/
|
|
27917
|
+
syncCells: function (cellInits, opt = {}) {
|
|
27918
|
+
const batchName = 'sync-cells';
|
|
27919
|
+
const {
|
|
27920
|
+
remove = false,
|
|
27921
|
+
...setOpt
|
|
27922
|
+
} = opt;
|
|
27923
|
+
let currentCells, newCellsMap;
|
|
27924
|
+
if (remove) {
|
|
27925
|
+
// We need to track existing cells to remove the missing ones later
|
|
27926
|
+
currentCells = this.getCells();
|
|
27927
|
+
newCellsMap = new Map();
|
|
27928
|
+
}
|
|
27929
|
+
|
|
27930
|
+
// Observe changes to the graph cells
|
|
27931
|
+
let changeObserver, changedLayers;
|
|
27932
|
+
const shouldSort = opt.sort !== false;
|
|
27933
|
+
if (shouldSort) {
|
|
27934
|
+
changeObserver = new Listener();
|
|
27935
|
+
changedLayers = new Set();
|
|
27936
|
+
changeObserver.listenTo(this, {
|
|
27937
|
+
'add': cell => {
|
|
27938
|
+
changedLayers.add(this.getCellLayerId(cell));
|
|
27939
|
+
},
|
|
27940
|
+
'change': cell => {
|
|
27941
|
+
if (cell.hasChanged(config$3.layerAttribute) || cell.hasChanged('z')) {
|
|
27942
|
+
changedLayers.add(this.getCellLayerId(cell));
|
|
27943
|
+
}
|
|
27944
|
+
}
|
|
27945
|
+
});
|
|
27946
|
+
}
|
|
27947
|
+
this.startBatch(batchName, opt);
|
|
27948
|
+
|
|
27949
|
+
// Prevent multiple sorts during sync
|
|
27950
|
+
setOpt.sort = false;
|
|
27951
|
+
|
|
27952
|
+
// Add or update incoming cells
|
|
27953
|
+
for (const cellInit of cellInits) {
|
|
27954
|
+
if (remove) {
|
|
27955
|
+
// only track existence
|
|
27956
|
+
newCellsMap.set(cellInit.id, true);
|
|
27957
|
+
}
|
|
27958
|
+
this._syncCell(cellInit, setOpt);
|
|
27959
|
+
}
|
|
27960
|
+
if (remove) {
|
|
27961
|
+
// Remove cells not present in the incoming array
|
|
27962
|
+
for (const cell of currentCells) {
|
|
27963
|
+
if (!newCellsMap.has(cell.id)) {
|
|
27964
|
+
this.layerCollection.removeCell(cell, setOpt);
|
|
27965
|
+
}
|
|
27966
|
+
}
|
|
27967
|
+
}
|
|
27968
|
+
if (shouldSort) {
|
|
27969
|
+
// Sort layers that had changes affecting z-index or layer
|
|
27970
|
+
changeObserver.stopListening();
|
|
27971
|
+
for (const layerId of changedLayers) {
|
|
27972
|
+
this.getLayer(layerId).cellCollection.sort(opt);
|
|
27973
|
+
}
|
|
27974
|
+
}
|
|
27975
|
+
this.stopBatch(batchName);
|
|
27976
|
+
},
|
|
27977
|
+
/**
|
|
27978
|
+
* @public
|
|
27979
|
+
* @description Remove a cell from the graph.
|
|
27980
|
+
* @param {dia.Cell} cell
|
|
27981
|
+
* @param {Object} [options]
|
|
27982
|
+
* @param {boolean} [options.disconnectLinks=false] - If `true`, the connected links are
|
|
27983
|
+
* disconnected instead of removed.
|
|
27984
|
+
* @param {boolean} [options.clear=false] - If `true`, the connected links
|
|
27985
|
+
* are kept. @internal
|
|
27986
|
+
* @param {boolean} [options.replace=false] - If `true`, the connected links and
|
|
27987
|
+
* embedded cells are kept. @internal
|
|
27988
|
+
* @throws Will throw an error if no cell is provided
|
|
27989
|
+
* @throws Will throw an error if the ID of the cell to remove
|
|
27990
|
+
* does not exist in the graph
|
|
27991
|
+
**/
|
|
27992
|
+
removeCell: function (cellRef, options) {
|
|
27993
|
+
if (!cellRef) {
|
|
27994
|
+
throw new Error('dia.Graph: no cell provided.');
|
|
27995
|
+
}
|
|
27996
|
+
const cell = cellRef[CELL_MARKER] ? cellRef : this.getCell(cellRef);
|
|
27997
|
+
if (!cell) {
|
|
27998
|
+
throw new Error('dia.Graph: cell to remove does not exist in the graph.');
|
|
27999
|
+
}
|
|
28000
|
+
if (cell.graph !== this) return;
|
|
28001
|
+
this.startBatch('remove');
|
|
28002
|
+
cell.collection.remove(cell, options);
|
|
28003
|
+
this.stopBatch('remove');
|
|
26999
28004
|
},
|
|
27000
28005
|
transferCellEmbeds: function (sourceCell, targetCell, opt = {}) {
|
|
27001
28006
|
const batchName = 'transfer-embeds';
|
|
@@ -27025,24 +28030,249 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
27025
28030
|
});
|
|
27026
28031
|
this.stopBatch(batchName);
|
|
27027
28032
|
},
|
|
27028
|
-
|
|
27029
|
-
|
|
27030
|
-
|
|
28033
|
+
/**
|
|
28034
|
+
* @private
|
|
28035
|
+
* Helper method for addLayer and moveLayer methods
|
|
28036
|
+
*/
|
|
28037
|
+
_getBeforeLayerIdFromOptions(options, layer = null) {
|
|
28038
|
+
let {
|
|
28039
|
+
before = null,
|
|
28040
|
+
index
|
|
28041
|
+
} = options;
|
|
28042
|
+
if (before && index !== undefined) {
|
|
28043
|
+
throw new Error('dia.Graph: Options "before" and "index" are mutually exclusive.');
|
|
28044
|
+
}
|
|
28045
|
+
let computedBefore;
|
|
28046
|
+
if (index !== undefined) {
|
|
28047
|
+
const layersArray = this.getLayers();
|
|
28048
|
+
if (index >= layersArray.length) {
|
|
28049
|
+
// If index is greater than the number of layers,
|
|
28050
|
+
// return before as null (move to the end).
|
|
28051
|
+
computedBefore = null;
|
|
28052
|
+
} else if (index < 0) {
|
|
28053
|
+
// If index is negative, move to the beginning.
|
|
28054
|
+
computedBefore = layersArray[0].id;
|
|
28055
|
+
} else {
|
|
28056
|
+
var _layersArray$index;
|
|
28057
|
+
const originalIndex = layersArray.indexOf(layer);
|
|
28058
|
+
if (originalIndex !== -1 && index > originalIndex) {
|
|
28059
|
+
// If moving a layer upwards in the stack, we need to adjust the index
|
|
28060
|
+
// to account for the layer being removed from its original position.
|
|
28061
|
+
index += 1;
|
|
28062
|
+
}
|
|
28063
|
+
// Otherwise, get the layer ID at the specified index.
|
|
28064
|
+
computedBefore = ((_layersArray$index = layersArray[index]) === null || _layersArray$index === void 0 ? void 0 : _layersArray$index.id) || null;
|
|
28065
|
+
}
|
|
28066
|
+
} else {
|
|
28067
|
+
computedBefore = before;
|
|
28068
|
+
}
|
|
28069
|
+
return computedBefore;
|
|
28070
|
+
},
|
|
28071
|
+
/**
|
|
28072
|
+
* @public
|
|
28073
|
+
* Adds a new layer to the graph.
|
|
28074
|
+
* @param {GraphLayer | GraphLayerJSON} layerInit
|
|
28075
|
+
* @param {*} options
|
|
28076
|
+
* @param {string | null} [options.before] - ID of the layer
|
|
28077
|
+
* before which to insert the new layer. If `null`, the layer is added at the end.
|
|
28078
|
+
* @param {number} [options.index] - Zero-based index to which to add the layer.
|
|
28079
|
+
* @throws Will throw an error if the layer to add is invalid
|
|
28080
|
+
* @throws Will throw an error if a layer with the same ID already exists
|
|
28081
|
+
* @throws Will throw if `before` reference is invalid
|
|
28082
|
+
*/
|
|
28083
|
+
addLayer(layerInit, options = {}) {
|
|
28084
|
+
if (!layerInit || !layerInit.id) {
|
|
28085
|
+
throw new Error('dia.Graph: Layer to add is invalid.');
|
|
28086
|
+
}
|
|
28087
|
+
if (this.hasLayer(layerInit.id)) {
|
|
28088
|
+
throw new Error(`dia.Graph: Layer "${layerInit.id}" already exists.`);
|
|
28089
|
+
}
|
|
28090
|
+
const {
|
|
28091
|
+
before = null,
|
|
28092
|
+
index,
|
|
28093
|
+
...insertOptions
|
|
28094
|
+
} = options;
|
|
28095
|
+
insertOptions.graph = this.cid;
|
|
28096
|
+
|
|
28097
|
+
// Adding a new layer disables legacy mode
|
|
28098
|
+
this.legacyMode = false;
|
|
28099
|
+
const beforeId = this._getBeforeLayerIdFromOptions({
|
|
28100
|
+
before,
|
|
28101
|
+
index
|
|
28102
|
+
});
|
|
28103
|
+
this.layerCollection.insert(layerInit, beforeId, insertOptions);
|
|
28104
|
+
},
|
|
28105
|
+
/**
|
|
28106
|
+
* @public
|
|
28107
|
+
* Moves an existing layer to a new position in the layer stack.
|
|
28108
|
+
* @param {string | GraphLayer} layerRef - ID or reference of the layer to move.
|
|
28109
|
+
* @param {*} options
|
|
28110
|
+
* @param {string | null} [options.before] - ID of the layer
|
|
28111
|
+
* before which to insert the moved layer. If `null`, the layer is moved to the end.
|
|
28112
|
+
* @param {number} [options.index] - Zero-based index to which to move the layer.
|
|
28113
|
+
* @throws Will throw an error if the layer to move does not exist
|
|
28114
|
+
* @throws Will throw an error if `before` reference is invalid
|
|
28115
|
+
* @throws Will throw an error if both `before` and `index` options are provided
|
|
28116
|
+
*/
|
|
28117
|
+
moveLayer(layerRef, options = {}) {
|
|
28118
|
+
if (!layerRef || !this.hasLayer(layerRef)) {
|
|
28119
|
+
throw new Error('dia.Graph: Layer to move does not exist.');
|
|
28120
|
+
}
|
|
28121
|
+
const layer = this.getLayer(layerRef);
|
|
28122
|
+
const {
|
|
28123
|
+
before = null,
|
|
28124
|
+
index,
|
|
28125
|
+
...insertOptions
|
|
28126
|
+
} = options;
|
|
28127
|
+
insertOptions.graph = this.cid;
|
|
28128
|
+
|
|
28129
|
+
// Moving a layer disables legacy mode
|
|
28130
|
+
this.legacyMode = false;
|
|
28131
|
+
const beforeId = this._getBeforeLayerIdFromOptions({
|
|
28132
|
+
before,
|
|
28133
|
+
index
|
|
28134
|
+
}, layer);
|
|
28135
|
+
this.layerCollection.insert(layer, beforeId, insertOptions);
|
|
28136
|
+
},
|
|
28137
|
+
/**
|
|
28138
|
+
* @public
|
|
28139
|
+
* Removes an existing layer from the graph.
|
|
28140
|
+
* @param {string | GraphLayer} layerRef - ID or reference of the layer to remove.
|
|
28141
|
+
* @param {*} options
|
|
28142
|
+
* @throws Will throw an error if no layer is provided
|
|
28143
|
+
* @throws Will throw an error if the layer to remove does not exist
|
|
28144
|
+
*/
|
|
28145
|
+
removeLayer(layerRef, options = {}) {
|
|
28146
|
+
if (!layerRef) {
|
|
28147
|
+
throw new Error('dia.Graph: No layer provided.');
|
|
28148
|
+
}
|
|
28149
|
+
|
|
28150
|
+
// The layer must exist
|
|
28151
|
+
const layerId = layerRef.id ? layerRef.id : layerRef;
|
|
28152
|
+
const layer = this.getLayer(layerId);
|
|
28153
|
+
|
|
28154
|
+
// Prevent removing the default layer
|
|
28155
|
+
// Note: if there is only one layer, it is also the default layer.
|
|
28156
|
+
const {
|
|
28157
|
+
id: defaultLayerId
|
|
28158
|
+
} = this.getDefaultLayer();
|
|
28159
|
+
if (layerId === defaultLayerId) {
|
|
28160
|
+
throw new Error('dia.Graph: default layer cannot be removed.');
|
|
28161
|
+
}
|
|
28162
|
+
|
|
28163
|
+
// A layer with cells cannot be removed
|
|
28164
|
+
if (layer.cellCollection.length > 0) {
|
|
28165
|
+
throw new Error(`dia.Graph: Layer "${layerId}" cannot be removed because it is not empty.`);
|
|
28166
|
+
}
|
|
28167
|
+
this.layerCollection.remove(layerId, {
|
|
28168
|
+
...options,
|
|
28169
|
+
graph: this.cid
|
|
28170
|
+
});
|
|
28171
|
+
},
|
|
28172
|
+
getDefaultLayer() {
|
|
28173
|
+
return this.layerCollection.get(this.defaultLayerId);
|
|
28174
|
+
},
|
|
28175
|
+
setDefaultLayer(layerRef, options = {}) {
|
|
28176
|
+
if (!layerRef) {
|
|
28177
|
+
throw new Error('dia.Graph: No default layer ID provided.');
|
|
28178
|
+
}
|
|
28179
|
+
|
|
28180
|
+
// Make sure the layer exists
|
|
28181
|
+
const defaultLayerId = layerRef.id ? layerRef.id : layerRef;
|
|
28182
|
+
const defaultLayer = this.getLayer(defaultLayerId);
|
|
28183
|
+
|
|
28184
|
+
// If the default layer is not changing, do nothing
|
|
28185
|
+
const currentDefaultLayerId = this.defaultLayerId;
|
|
28186
|
+
if (defaultLayerId === currentDefaultLayerId) {
|
|
28187
|
+
// The default layer stays the same
|
|
28188
|
+
return;
|
|
28189
|
+
}
|
|
28190
|
+
|
|
28191
|
+
// Get all cells that belong to the current default layer implicitly
|
|
28192
|
+
const implicitLayerCells = this.getImplicitLayerCells();
|
|
28193
|
+
|
|
28194
|
+
// Set the new default layer ID
|
|
28195
|
+
this.defaultLayerId = defaultLayerId;
|
|
28196
|
+
const batchName = 'default-layer-change';
|
|
28197
|
+
this.startBatch(batchName, options);
|
|
28198
|
+
if (implicitLayerCells.length > 0) {
|
|
28199
|
+
// Reassign any cells lacking an explicit layer to the new default layer.
|
|
28200
|
+
// Do not sort yet, wait until all cells are moved.
|
|
28201
|
+
const moveOptions = {
|
|
28202
|
+
...options,
|
|
28203
|
+
sort: false
|
|
28204
|
+
};
|
|
28205
|
+
for (const cell of implicitLayerCells) {
|
|
28206
|
+
this.layerCollection.moveCellBetweenLayers(cell, defaultLayerId, moveOptions);
|
|
28207
|
+
}
|
|
28208
|
+
// Now sort the new default layer
|
|
28209
|
+
if (options.sort !== false) {
|
|
28210
|
+
defaultLayer.cellCollection.sort(options);
|
|
28211
|
+
}
|
|
28212
|
+
}
|
|
28213
|
+
|
|
28214
|
+
// Pretend to trigger the event on the layer itself.
|
|
28215
|
+
// It will bubble up as `layer:default` event on the graph.
|
|
28216
|
+
defaultLayer.trigger(defaultLayer.eventPrefix + 'default', defaultLayer, {
|
|
28217
|
+
...options,
|
|
28218
|
+
previousDefaultLayerId: currentDefaultLayerId
|
|
28219
|
+
});
|
|
28220
|
+
this.stopBatch(batchName, options);
|
|
28221
|
+
},
|
|
28222
|
+
/**
|
|
28223
|
+
* @protected
|
|
28224
|
+
* @description Get all cells that do not have an explicit layer assigned.
|
|
28225
|
+
* These cells belong to the default layer implicitly.
|
|
28226
|
+
* @return {Array<dia.Cell>} Array of cells without an explicit layer.
|
|
28227
|
+
*/
|
|
28228
|
+
getImplicitLayerCells() {
|
|
28229
|
+
return this.getDefaultLayer().cellCollection.filter(cell => {
|
|
28230
|
+
return cell.get(config$3.layerAttribute) == null;
|
|
28231
|
+
});
|
|
28232
|
+
},
|
|
28233
|
+
getLayer(layerId) {
|
|
28234
|
+
if (!this.hasLayer(layerId)) {
|
|
28235
|
+
throw new Error(`dia.Graph: Layer "${layerId}" does not exist.`);
|
|
28236
|
+
}
|
|
28237
|
+
return this.layerCollection.get(layerId);
|
|
28238
|
+
},
|
|
28239
|
+
hasLayer(layerRef) {
|
|
28240
|
+
return this.layerCollection.has(layerRef);
|
|
28241
|
+
},
|
|
28242
|
+
getLayers() {
|
|
28243
|
+
return this.layerCollection.toArray();
|
|
28244
|
+
},
|
|
28245
|
+
getCell: function (cellRef) {
|
|
28246
|
+
return this.layerCollection.getCell(cellRef);
|
|
27031
28247
|
},
|
|
27032
28248
|
getCells: function () {
|
|
27033
|
-
return this.
|
|
28249
|
+
return this.layerCollection.getCells();
|
|
27034
28250
|
},
|
|
27035
28251
|
getElements: function () {
|
|
27036
|
-
return this.
|
|
28252
|
+
return this.getCells().filter(cell => cell.isElement());
|
|
27037
28253
|
},
|
|
27038
28254
|
getLinks: function () {
|
|
27039
|
-
return this.
|
|
28255
|
+
return this.getCells().filter(cell => cell.isLink());
|
|
27040
28256
|
},
|
|
27041
|
-
getFirstCell: function () {
|
|
27042
|
-
|
|
28257
|
+
getFirstCell: function (layerId) {
|
|
28258
|
+
let layer;
|
|
28259
|
+
if (!layerId) {
|
|
28260
|
+
// Get the first cell from the bottom-most layer
|
|
28261
|
+
layer = this.getLayers().at(0);
|
|
28262
|
+
} else {
|
|
28263
|
+
layer = this.getLayer(layerId);
|
|
28264
|
+
}
|
|
28265
|
+
return layer.cellCollection.models.at(0);
|
|
27043
28266
|
},
|
|
27044
|
-
getLastCell: function () {
|
|
27045
|
-
|
|
28267
|
+
getLastCell: function (layerId) {
|
|
28268
|
+
let layer;
|
|
28269
|
+
if (!layerId) {
|
|
28270
|
+
// Get the last cell from the top-most layer
|
|
28271
|
+
layer = this.getLayers().at(-1);
|
|
28272
|
+
} else {
|
|
28273
|
+
layer = this.getLayer(layerId);
|
|
28274
|
+
}
|
|
28275
|
+
return layer.cellCollection.models.at(-1);
|
|
27046
28276
|
},
|
|
27047
28277
|
// Get all inbound and outbound links connected to the cell `model`.
|
|
27048
28278
|
getConnectedLinks: function (model, opt) {
|
|
@@ -27066,12 +28296,13 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
27066
28296
|
addInbounds(this, model);
|
|
27067
28297
|
}
|
|
27068
28298
|
function addOutbounds(graph, model) {
|
|
27069
|
-
forIn(graph.getOutboundEdges(model.id), function (_, edge) {
|
|
28299
|
+
forIn(graph.topologyIndex.getOutboundEdges(model.id), function (_, edge) {
|
|
27070
28300
|
// skip links that were already added
|
|
27071
28301
|
// (those must be self-loop links)
|
|
27072
28302
|
// (because they are inbound and outbound edges of the same two elements)
|
|
27073
28303
|
if (edges[edge]) return;
|
|
27074
28304
|
var link = graph.getCell(edge);
|
|
28305
|
+
if (!link) return;
|
|
27075
28306
|
links.push(link);
|
|
27076
28307
|
edges[edge] = true;
|
|
27077
28308
|
if (indirect) {
|
|
@@ -27090,12 +28321,13 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
27090
28321
|
}
|
|
27091
28322
|
}
|
|
27092
28323
|
function addInbounds(graph, model) {
|
|
27093
|
-
forIn(graph.getInboundEdges(model.id), function (_, edge) {
|
|
28324
|
+
forIn(graph.topologyIndex.getInboundEdges(model.id), function (_, edge) {
|
|
27094
28325
|
// skip links that were already added
|
|
27095
28326
|
// (those must be self-loop links)
|
|
27096
28327
|
// (because they are inbound and outbound edges of the same two elements)
|
|
27097
28328
|
if (edges[edge]) return;
|
|
27098
28329
|
var link = graph.getCell(edge);
|
|
28330
|
+
if (!link) return;
|
|
27099
28331
|
links.push(link);
|
|
27100
28332
|
edges[edge] = true;
|
|
27101
28333
|
if (indirect) {
|
|
@@ -27130,7 +28362,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
27130
28362
|
embeddedCells.forEach(function (cell) {
|
|
27131
28363
|
if (cell.isLink()) return;
|
|
27132
28364
|
if (outbound) {
|
|
27133
|
-
forIn(this.getOutboundEdges(cell.id), function (exists, edge) {
|
|
28365
|
+
forIn(this.topologyIndex.getOutboundEdges(cell.id), function (exists, edge) {
|
|
27134
28366
|
if (!edges[edge]) {
|
|
27135
28367
|
var edgeCell = this.getCell(edge);
|
|
27136
28368
|
var {
|
|
@@ -27150,7 +28382,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
27150
28382
|
}.bind(this));
|
|
27151
28383
|
}
|
|
27152
28384
|
if (inbound) {
|
|
27153
|
-
forIn(this.getInboundEdges(cell.id), function (exists, edge) {
|
|
28385
|
+
forIn(this.topologyIndex.getInboundEdges(cell.id), function (exists, edge) {
|
|
27154
28386
|
if (!edges[edge]) {
|
|
27155
28387
|
var edgeCell = this.getCell(edge);
|
|
27156
28388
|
var {
|
|
@@ -27429,31 +28661,19 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
27429
28661
|
},
|
|
27430
28662
|
// Get all the roots of the graph. Time complexity: O(|V|).
|
|
27431
28663
|
getSources: function () {
|
|
27432
|
-
|
|
27433
|
-
forIn(this._nodes, function (exists, node) {
|
|
27434
|
-
if (!this._in[node] || isEmpty(this._in[node])) {
|
|
27435
|
-
sources.push(this.getCell(node));
|
|
27436
|
-
}
|
|
27437
|
-
}.bind(this));
|
|
27438
|
-
return sources;
|
|
28664
|
+
return this.topologyIndex.getSourceNodes().map(nodeId => this.getCell(nodeId));
|
|
27439
28665
|
},
|
|
27440
28666
|
// Get all the leafs of the graph. Time complexity: O(|V|).
|
|
27441
28667
|
getSinks: function () {
|
|
27442
|
-
|
|
27443
|
-
forIn(this._nodes, function (exists, node) {
|
|
27444
|
-
if (!this._out[node] || isEmpty(this._out[node])) {
|
|
27445
|
-
sinks.push(this.getCell(node));
|
|
27446
|
-
}
|
|
27447
|
-
}.bind(this));
|
|
27448
|
-
return sinks;
|
|
28668
|
+
return this.topologyIndex.getSinkNodes().map(nodeId => this.getCell(nodeId));
|
|
27449
28669
|
},
|
|
27450
28670
|
// Return `true` if `element` is a root. Time complexity: O(1).
|
|
27451
28671
|
isSource: function (element) {
|
|
27452
|
-
return
|
|
28672
|
+
return this.topologyIndex.isSourceNode(element.id);
|
|
27453
28673
|
},
|
|
27454
28674
|
// Return `true` if `element` is a leaf. Time complexity: O(1).
|
|
27455
28675
|
isSink: function (element) {
|
|
27456
|
-
return
|
|
28676
|
+
return this.topologyIndex.isSinkNode(element.id);
|
|
27457
28677
|
},
|
|
27458
28678
|
// Return `true` is `elementB` is a successor of `elementA`. Return `false` otherwise.
|
|
27459
28679
|
isSuccessor: function (elementA, elementB) {
|
|
@@ -27524,8 +28744,10 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
27524
28744
|
});
|
|
27525
28745
|
},
|
|
27526
28746
|
// Remove links connected to the cell `model` completely.
|
|
27527
|
-
removeLinks: function (
|
|
27528
|
-
|
|
28747
|
+
removeLinks: function (cell, opt) {
|
|
28748
|
+
this.getConnectedLinks(cell).forEach(link => {
|
|
28749
|
+
this.layerCollection.removeCell(link, opt);
|
|
28750
|
+
});
|
|
27529
28751
|
},
|
|
27530
28752
|
// Find all cells at given point
|
|
27531
28753
|
|
|
@@ -27716,85 +28938,6 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
27716
28938
|
});
|
|
27717
28939
|
wrapWith(Graph.prototype, ['resetCells', 'addCells', 'removeCells'], wrappers.cells);
|
|
27718
28940
|
|
|
27719
|
-
const LayersNames = {
|
|
27720
|
-
GRID: 'grid',
|
|
27721
|
-
CELLS: 'cells',
|
|
27722
|
-
BACK: 'back',
|
|
27723
|
-
FRONT: 'front',
|
|
27724
|
-
TOOLS: 'tools',
|
|
27725
|
-
LABELS: 'labels'
|
|
27726
|
-
};
|
|
27727
|
-
const PaperLayer = View.extend({
|
|
27728
|
-
tagName: 'g',
|
|
27729
|
-
svgElement: true,
|
|
27730
|
-
pivotNodes: null,
|
|
27731
|
-
defaultTheme: null,
|
|
27732
|
-
options: {
|
|
27733
|
-
name: ''
|
|
27734
|
-
},
|
|
27735
|
-
className: function () {
|
|
27736
|
-
const {
|
|
27737
|
-
name
|
|
27738
|
-
} = this.options;
|
|
27739
|
-
if (!name) return null;
|
|
27740
|
-
return addClassNamePrefix(`${name}-layer`);
|
|
27741
|
-
},
|
|
27742
|
-
init: function () {
|
|
27743
|
-
this.pivotNodes = {};
|
|
27744
|
-
},
|
|
27745
|
-
insertSortedNode: function (node, z) {
|
|
27746
|
-
this.el.insertBefore(node, this.insertPivot(z));
|
|
27747
|
-
},
|
|
27748
|
-
insertNode: function (node) {
|
|
27749
|
-
const {
|
|
27750
|
-
el
|
|
27751
|
-
} = this;
|
|
27752
|
-
if (node.parentNode !== el) {
|
|
27753
|
-
el.appendChild(node);
|
|
27754
|
-
}
|
|
27755
|
-
},
|
|
27756
|
-
insertPivot: function (z) {
|
|
27757
|
-
const {
|
|
27758
|
-
el,
|
|
27759
|
-
pivotNodes
|
|
27760
|
-
} = this;
|
|
27761
|
-
z = +z;
|
|
27762
|
-
z || (z = 0);
|
|
27763
|
-
let pivotNode = pivotNodes[z];
|
|
27764
|
-
if (pivotNode) return pivotNode;
|
|
27765
|
-
pivotNode = pivotNodes[z] = document.createComment('z-index:' + (z + 1));
|
|
27766
|
-
let neighborZ = -Infinity;
|
|
27767
|
-
for (let currentZ in pivotNodes) {
|
|
27768
|
-
currentZ = +currentZ;
|
|
27769
|
-
if (currentZ < z && currentZ > neighborZ) {
|
|
27770
|
-
neighborZ = currentZ;
|
|
27771
|
-
if (neighborZ === z - 1) continue;
|
|
27772
|
-
}
|
|
27773
|
-
}
|
|
27774
|
-
if (neighborZ !== -Infinity) {
|
|
27775
|
-
const neighborPivot = pivotNodes[neighborZ];
|
|
27776
|
-
// Insert After
|
|
27777
|
-
el.insertBefore(pivotNode, neighborPivot.nextSibling);
|
|
27778
|
-
} else {
|
|
27779
|
-
// First Child
|
|
27780
|
-
el.insertBefore(pivotNode, el.firstChild);
|
|
27781
|
-
}
|
|
27782
|
-
return pivotNode;
|
|
27783
|
-
},
|
|
27784
|
-
removePivots: function () {
|
|
27785
|
-
const {
|
|
27786
|
-
el,
|
|
27787
|
-
pivotNodes
|
|
27788
|
-
} = this;
|
|
27789
|
-
for (let z in pivotNodes) el.removeChild(pivotNodes[z]);
|
|
27790
|
-
this.pivotNodes = {};
|
|
27791
|
-
},
|
|
27792
|
-
isEmpty: function () {
|
|
27793
|
-
// Check if the layer has any child elements (pivot comments are not counted).
|
|
27794
|
-
return this.el.children.length === 0;
|
|
27795
|
-
}
|
|
27796
|
-
});
|
|
27797
|
-
|
|
27798
28941
|
const calcAttributesList = ['transform', 'x', 'y', 'cx', 'cy', 'dx', 'dy', 'x1', 'y1', 'x2', 'y2', 'points', 'd', 'r', 'rx', 'ry', 'width', 'height', 'stroke-width', 'font-size'];
|
|
27799
28942
|
const positiveValueList = ['r', 'rx', 'ry', 'width', 'height', 'stroke-width', 'font-size'];
|
|
27800
28943
|
const calcAttributes = calcAttributesList.reduce((acc, attrName) => {
|
|
@@ -29036,7 +30179,6 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
29036
30179
|
// Internal tag to identify this object as a cell view instance.
|
|
29037
30180
|
// Used instead of `instanceof` for performance and cross-frame safety.
|
|
29038
30181
|
|
|
29039
|
-
const CELL_VIEW_MARKER = Symbol('joint.cellViewMarker');
|
|
29040
30182
|
Object.defineProperty(CellView.prototype, CELL_VIEW_MARKER, {
|
|
29041
30183
|
value: true
|
|
29042
30184
|
});
|
|
@@ -31844,6 +32986,231 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
31844
32986
|
}
|
|
31845
32987
|
});
|
|
31846
32988
|
|
|
32989
|
+
const LayerView = View.extend({
|
|
32990
|
+
tagName: 'g',
|
|
32991
|
+
svgElement: true,
|
|
32992
|
+
pivotNodes: null,
|
|
32993
|
+
defaultTheme: null,
|
|
32994
|
+
UPDATE_PRIORITY: 4,
|
|
32995
|
+
options: {
|
|
32996
|
+
id: ''
|
|
32997
|
+
},
|
|
32998
|
+
paper: null,
|
|
32999
|
+
init: function () {
|
|
33000
|
+
this.pivotNodes = {};
|
|
33001
|
+
this.id = this.options.id || this.cid;
|
|
33002
|
+
},
|
|
33003
|
+
setPaperReference: function (paper) {
|
|
33004
|
+
this.paper = paper;
|
|
33005
|
+
this.afterPaperReferenceSet(paper);
|
|
33006
|
+
},
|
|
33007
|
+
unsetPaperReference: function () {
|
|
33008
|
+
this.beforePaperReferenceUnset();
|
|
33009
|
+
this.paper = null;
|
|
33010
|
+
},
|
|
33011
|
+
assertPaperReference() {
|
|
33012
|
+
if (!this.paper) {
|
|
33013
|
+
throw new Error('LayerView: paper reference is not set.');
|
|
33014
|
+
}
|
|
33015
|
+
},
|
|
33016
|
+
afterPaperReferenceSet: function () {
|
|
33017
|
+
// Can be overridden in subclasses.
|
|
33018
|
+
},
|
|
33019
|
+
beforePaperReferenceUnset: function () {
|
|
33020
|
+
// Can be overridden in subclasses.
|
|
33021
|
+
},
|
|
33022
|
+
// prevents id to be set on the DOM element
|
|
33023
|
+
_setAttributes: function (attrs) {
|
|
33024
|
+
const newAttrs = clone$1(attrs);
|
|
33025
|
+
delete newAttrs.id;
|
|
33026
|
+
View.prototype._setAttributes.call(this, newAttrs);
|
|
33027
|
+
},
|
|
33028
|
+
className: function () {
|
|
33029
|
+
const {
|
|
33030
|
+
id
|
|
33031
|
+
} = this.options;
|
|
33032
|
+
return addClassNamePrefix(`${id}-layer`);
|
|
33033
|
+
},
|
|
33034
|
+
insertSortedNode: function (node, z) {
|
|
33035
|
+
this.el.insertBefore(node, this.insertPivot(z));
|
|
33036
|
+
},
|
|
33037
|
+
insertNode: function (node) {
|
|
33038
|
+
const {
|
|
33039
|
+
el
|
|
33040
|
+
} = this;
|
|
33041
|
+
if (node.parentNode !== el) {
|
|
33042
|
+
el.appendChild(node);
|
|
33043
|
+
}
|
|
33044
|
+
},
|
|
33045
|
+
insertPivot: function (z) {
|
|
33046
|
+
const {
|
|
33047
|
+
el,
|
|
33048
|
+
pivotNodes
|
|
33049
|
+
} = this;
|
|
33050
|
+
z = +z;
|
|
33051
|
+
z || (z = 0);
|
|
33052
|
+
let pivotNode = pivotNodes[z];
|
|
33053
|
+
if (pivotNode) return pivotNode;
|
|
33054
|
+
pivotNode = pivotNodes[z] = document.createComment('z-index:' + (z + 1));
|
|
33055
|
+
let neighborZ = -Infinity;
|
|
33056
|
+
for (let currentZ in pivotNodes) {
|
|
33057
|
+
currentZ = +currentZ;
|
|
33058
|
+
if (currentZ < z && currentZ > neighborZ) {
|
|
33059
|
+
neighborZ = currentZ;
|
|
33060
|
+
if (neighborZ === z - 1) continue;
|
|
33061
|
+
}
|
|
33062
|
+
}
|
|
33063
|
+
if (neighborZ !== -Infinity) {
|
|
33064
|
+
const neighborPivot = pivotNodes[neighborZ];
|
|
33065
|
+
// Insert After
|
|
33066
|
+
el.insertBefore(pivotNode, neighborPivot.nextSibling);
|
|
33067
|
+
} else {
|
|
33068
|
+
// First Child
|
|
33069
|
+
el.insertBefore(pivotNode, el.firstChild);
|
|
33070
|
+
}
|
|
33071
|
+
return pivotNode;
|
|
33072
|
+
},
|
|
33073
|
+
removePivots: function () {
|
|
33074
|
+
const {
|
|
33075
|
+
el,
|
|
33076
|
+
pivotNodes
|
|
33077
|
+
} = this;
|
|
33078
|
+
for (let z in pivotNodes) el.removeChild(pivotNodes[z]);
|
|
33079
|
+
this.pivotNodes = {};
|
|
33080
|
+
},
|
|
33081
|
+
isEmpty: function () {
|
|
33082
|
+
// Check if the layer has any child elements (pivot comments are not counted).
|
|
33083
|
+
return this.el.children.length === 0;
|
|
33084
|
+
},
|
|
33085
|
+
reset: function () {
|
|
33086
|
+
this.removePivots();
|
|
33087
|
+
}
|
|
33088
|
+
});
|
|
33089
|
+
Object.defineProperty(LayerView.prototype, LAYER_VIEW_MARKER, {
|
|
33090
|
+
value: true
|
|
33091
|
+
});
|
|
33092
|
+
|
|
33093
|
+
/**
|
|
33094
|
+
* @class GraphLayerView
|
|
33095
|
+
* @description A GraphLayerView is responsible for managing the rendering of cell views inside a layer.
|
|
33096
|
+
* It listens to the corresponding GraphLayer model and updates the DOM accordingly.
|
|
33097
|
+
* It uses dia.Paper sorting options to sort cell views in the DOM based on their `z` attribute.
|
|
33098
|
+
*/
|
|
33099
|
+
const GraphLayerView = LayerView.extend({
|
|
33100
|
+
SORT_DELAYING_BATCHES: ['add', 'to-front', 'to-back'],
|
|
33101
|
+
style: {
|
|
33102
|
+
webkitUserSelect: 'none',
|
|
33103
|
+
userSelect: 'none'
|
|
33104
|
+
},
|
|
33105
|
+
graph: null,
|
|
33106
|
+
init() {
|
|
33107
|
+
LayerView.prototype.init.apply(this, arguments);
|
|
33108
|
+
this.graph = this.model.graph;
|
|
33109
|
+
},
|
|
33110
|
+
className: function () {
|
|
33111
|
+
const {
|
|
33112
|
+
id
|
|
33113
|
+
} = this.options;
|
|
33114
|
+
return [addClassNamePrefix(`${id}-layer`), addClassNamePrefix('cells')].join(' ');
|
|
33115
|
+
},
|
|
33116
|
+
afterPaperReferenceSet(paper) {
|
|
33117
|
+
this.listenTo(this.model, 'sort', this.onCellCollectionSort);
|
|
33118
|
+
this.listenTo(this.model, 'change', this.onCellChange);
|
|
33119
|
+
this.listenTo(this.model, 'move', this.onCellMove);
|
|
33120
|
+
this.listenTo(this.graph, 'batch:stop', this.onGraphBatchStop);
|
|
33121
|
+
},
|
|
33122
|
+
beforePaperReferenceUnset() {
|
|
33123
|
+
this.stopListening(this.model);
|
|
33124
|
+
this.stopListening(this.graph);
|
|
33125
|
+
},
|
|
33126
|
+
onCellCollectionSort() {
|
|
33127
|
+
if (this.graph.hasActiveBatch(this.SORT_DELAYING_BATCHES)) return;
|
|
33128
|
+
this.sort();
|
|
33129
|
+
},
|
|
33130
|
+
onCellMove(cell, opt = {}) {
|
|
33131
|
+
// When a cell is moved from one layer to another,
|
|
33132
|
+
// request insertion of its view in the new layer.
|
|
33133
|
+
this.paper.requestCellViewInsertion(cell, opt);
|
|
33134
|
+
},
|
|
33135
|
+
onCellChange(cell, opt) {
|
|
33136
|
+
if (!cell.hasChanged('z')) return;
|
|
33137
|
+
// Re-insert the cell view to maintain correct z-ordering
|
|
33138
|
+
if (this.paper.options.sorting === sortingTypes.APPROX) {
|
|
33139
|
+
this.paper.requestCellViewInsertion(cell, opt);
|
|
33140
|
+
}
|
|
33141
|
+
},
|
|
33142
|
+
onGraphBatchStop(data) {
|
|
33143
|
+
const name = data && data.batchName;
|
|
33144
|
+
const sortDelayingBatches = this.SORT_DELAYING_BATCHES;
|
|
33145
|
+
// After certain batches, sorting may be required
|
|
33146
|
+
if (sortDelayingBatches.includes(name) && !this.graph.hasActiveBatch(sortDelayingBatches)) {
|
|
33147
|
+
this.sort();
|
|
33148
|
+
}
|
|
33149
|
+
},
|
|
33150
|
+
sort() {
|
|
33151
|
+
this.assertPaperReference();
|
|
33152
|
+
const {
|
|
33153
|
+
paper
|
|
33154
|
+
} = this;
|
|
33155
|
+
if (!paper.isExactSorting()) {
|
|
33156
|
+
// noop
|
|
33157
|
+
return;
|
|
33158
|
+
}
|
|
33159
|
+
if (paper.isFrozen()) {
|
|
33160
|
+
// sort views once unfrozen
|
|
33161
|
+
paper._updates.sort = true;
|
|
33162
|
+
return;
|
|
33163
|
+
}
|
|
33164
|
+
this.sortExact();
|
|
33165
|
+
},
|
|
33166
|
+
sortExact() {
|
|
33167
|
+
// Run insertion sort algorithm in order to efficiently sort DOM elements according to their
|
|
33168
|
+
// associated model `z` attribute.
|
|
33169
|
+
const cellNodes = Array.from(this.el.children).filter(node => node.getAttribute('model-id'));
|
|
33170
|
+
const cellCollection = this.model.cellCollection;
|
|
33171
|
+
sortElements(cellNodes, function (a, b) {
|
|
33172
|
+
const cellA = cellCollection.get(a.getAttribute('model-id'));
|
|
33173
|
+
const cellB = cellCollection.get(b.getAttribute('model-id'));
|
|
33174
|
+
const zA = cellA.attributes.z || 0;
|
|
33175
|
+
const zB = cellB.attributes.z || 0;
|
|
33176
|
+
return zA === zB ? 0 : zA < zB ? -1 : 1;
|
|
33177
|
+
});
|
|
33178
|
+
},
|
|
33179
|
+
insertCellView(cellView) {
|
|
33180
|
+
this.assertPaperReference();
|
|
33181
|
+
const {
|
|
33182
|
+
paper
|
|
33183
|
+
} = this;
|
|
33184
|
+
const {
|
|
33185
|
+
el,
|
|
33186
|
+
model
|
|
33187
|
+
} = cellView;
|
|
33188
|
+
switch (paper.options.sorting) {
|
|
33189
|
+
case sortingTypes.APPROX:
|
|
33190
|
+
this.insertSortedNode(el, model.get('z'));
|
|
33191
|
+
break;
|
|
33192
|
+
case sortingTypes.EXACT:
|
|
33193
|
+
default:
|
|
33194
|
+
this.insertNode(el);
|
|
33195
|
+
break;
|
|
33196
|
+
}
|
|
33197
|
+
}
|
|
33198
|
+
});
|
|
33199
|
+
Object.defineProperty(GraphLayerView.prototype, GRAPH_LAYER_VIEW_MARKER, {
|
|
33200
|
+
value: true
|
|
33201
|
+
});
|
|
33202
|
+
|
|
33203
|
+
/**
|
|
33204
|
+
* @class LegacyGraphLayerView
|
|
33205
|
+
* @description A legacy GraphLayerView with an additional class name for backward compatibility.
|
|
33206
|
+
*/
|
|
33207
|
+
const LegacyGraphLayerView = GraphLayerView.extend({
|
|
33208
|
+
className: function () {
|
|
33209
|
+
const className = GraphLayerView.prototype.className.apply(this, arguments);
|
|
33210
|
+
return className + ' ' + addClassNamePrefix('viewport');
|
|
33211
|
+
}
|
|
33212
|
+
});
|
|
33213
|
+
|
|
31847
33214
|
/**
|
|
31848
33215
|
* Deque implementation for managing a double-ended queue.
|
|
31849
33216
|
* This implementation uses a doubly linked list for efficient operations.
|
|
@@ -31966,23 +33333,24 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
31966
33333
|
}
|
|
31967
33334
|
}
|
|
31968
33335
|
|
|
31969
|
-
const
|
|
33336
|
+
const GridLayerView = LayerView.extend({
|
|
31970
33337
|
style: {
|
|
31971
33338
|
'pointer-events': 'none'
|
|
31972
33339
|
},
|
|
31973
33340
|
_gridCache: null,
|
|
31974
33341
|
_gridSettings: null,
|
|
31975
33342
|
init() {
|
|
31976
|
-
|
|
31977
|
-
|
|
31978
|
-
options: {
|
|
31979
|
-
paper
|
|
31980
|
-
}
|
|
31981
|
-
} = this;
|
|
33343
|
+
LayerView.prototype.init.apply(this, arguments);
|
|
33344
|
+
this.paper = this.options.paper;
|
|
31982
33345
|
this._gridCache = null;
|
|
31983
33346
|
this._gridSettings = [];
|
|
33347
|
+
},
|
|
33348
|
+
afterPaperReferenceSet(paper) {
|
|
31984
33349
|
this.listenTo(paper, 'transform resize', this.updateGrid);
|
|
31985
33350
|
},
|
|
33351
|
+
beforePaperReferenceUnset(paper) {
|
|
33352
|
+
this.stopListening(paper);
|
|
33353
|
+
},
|
|
31986
33354
|
setGrid(drawGrid) {
|
|
31987
33355
|
this._gridSettings = this.getGridSettings(drawGrid);
|
|
31988
33356
|
this.renderGrid();
|
|
@@ -32007,9 +33375,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32007
33375
|
},
|
|
32008
33376
|
renderGrid() {
|
|
32009
33377
|
const {
|
|
32010
|
-
|
|
32011
|
-
paper
|
|
32012
|
-
}
|
|
33378
|
+
paper
|
|
32013
33379
|
} = this;
|
|
32014
33380
|
const {
|
|
32015
33381
|
_gridSettings: gridSettings
|
|
@@ -32054,9 +33420,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32054
33420
|
const {
|
|
32055
33421
|
_gridCache: grid,
|
|
32056
33422
|
_gridSettings: gridSettings,
|
|
32057
|
-
|
|
32058
|
-
paper
|
|
32059
|
-
}
|
|
33423
|
+
paper
|
|
32060
33424
|
} = this;
|
|
32061
33425
|
if (!grid) return;
|
|
32062
33426
|
const {
|
|
@@ -32090,7 +33454,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32090
33454
|
});
|
|
32091
33455
|
},
|
|
32092
33456
|
_getPatternId(index) {
|
|
32093
|
-
return `pattern_${this.
|
|
33457
|
+
return `pattern_${this.paper.cid}_${index}`;
|
|
32094
33458
|
},
|
|
32095
33459
|
_getGridRefs() {
|
|
32096
33460
|
let {
|
|
@@ -32125,27 +33489,27 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32125
33489
|
return grid;
|
|
32126
33490
|
},
|
|
32127
33491
|
_resolveDrawGridOption(opt) {
|
|
32128
|
-
|
|
33492
|
+
const namespace = this.options.patterns;
|
|
32129
33493
|
if (isString(opt) && Array.isArray(namespace[opt])) {
|
|
32130
33494
|
return namespace[opt].map(function (item) {
|
|
32131
33495
|
return assign({}, item);
|
|
32132
33496
|
});
|
|
32133
33497
|
}
|
|
32134
|
-
|
|
33498
|
+
const options = opt || {
|
|
32135
33499
|
args: [{}]
|
|
32136
33500
|
};
|
|
32137
|
-
|
|
32138
|
-
|
|
33501
|
+
const isArray = Array.isArray(options);
|
|
33502
|
+
let name = options.name;
|
|
32139
33503
|
if (!isArray && !name && !options.markup) {
|
|
32140
33504
|
name = 'dot';
|
|
32141
33505
|
}
|
|
32142
33506
|
if (name && Array.isArray(namespace[name])) {
|
|
32143
|
-
|
|
33507
|
+
const pattern = namespace[name].map(function (item) {
|
|
32144
33508
|
return assign({}, item);
|
|
32145
33509
|
});
|
|
32146
|
-
|
|
33510
|
+
const args = Array.isArray(options.args) ? options.args : [options.args || {}];
|
|
32147
33511
|
defaults(args[0], omit(opt, 'args'));
|
|
32148
|
-
for (
|
|
33512
|
+
for (let i = 0; i < args.length; i++) {
|
|
32149
33513
|
if (pattern[i]) {
|
|
32150
33514
|
assign(pattern[i], args[i]);
|
|
32151
33515
|
}
|
|
@@ -32162,6 +33526,15 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32162
33526
|
}
|
|
32163
33527
|
});
|
|
32164
33528
|
|
|
33529
|
+
const paperLayers = {
|
|
33530
|
+
GRID: 'grid',
|
|
33531
|
+
BACK: 'back',
|
|
33532
|
+
/** @deprecated */
|
|
33533
|
+
CELLS: 'cells',
|
|
33534
|
+
FRONT: 'front',
|
|
33535
|
+
TOOLS: 'tools',
|
|
33536
|
+
LABELS: 'labels'
|
|
33537
|
+
};
|
|
32165
33538
|
const sortingTypes = {
|
|
32166
33539
|
NONE: 'sorting-none',
|
|
32167
33540
|
APPROX: 'sorting-approximate',
|
|
@@ -32194,18 +33567,205 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32194
33567
|
}
|
|
32195
33568
|
}
|
|
32196
33569
|
};
|
|
32197
|
-
const
|
|
32198
|
-
|
|
32199
|
-
|
|
32200
|
-
|
|
33570
|
+
const gridPatterns = {
|
|
33571
|
+
dot: [{
|
|
33572
|
+
color: '#AAAAAA',
|
|
33573
|
+
thickness: 1,
|
|
33574
|
+
markup: 'rect',
|
|
33575
|
+
render: function (el, opt) {
|
|
33576
|
+
V(el).attr({
|
|
33577
|
+
width: opt.thickness,
|
|
33578
|
+
height: opt.thickness,
|
|
33579
|
+
fill: opt.color
|
|
33580
|
+
});
|
|
33581
|
+
}
|
|
33582
|
+
}],
|
|
33583
|
+
fixedDot: [{
|
|
33584
|
+
color: '#AAAAAA',
|
|
33585
|
+
thickness: 1,
|
|
33586
|
+
markup: 'rect',
|
|
33587
|
+
render: function (el, opt) {
|
|
33588
|
+
V(el).attr({
|
|
33589
|
+
fill: opt.color
|
|
33590
|
+
});
|
|
33591
|
+
},
|
|
33592
|
+
update: function (el, opt, paper) {
|
|
33593
|
+
const {
|
|
33594
|
+
sx,
|
|
33595
|
+
sy
|
|
33596
|
+
} = paper.scale();
|
|
33597
|
+
const width = sx <= 1 ? opt.thickness : opt.thickness / sx;
|
|
33598
|
+
const height = sy <= 1 ? opt.thickness : opt.thickness / sy;
|
|
33599
|
+
V(el).attr({
|
|
33600
|
+
width,
|
|
33601
|
+
height
|
|
33602
|
+
});
|
|
33603
|
+
}
|
|
33604
|
+
}],
|
|
33605
|
+
mesh: [{
|
|
33606
|
+
color: '#AAAAAA',
|
|
33607
|
+
thickness: 1,
|
|
33608
|
+
markup: 'path',
|
|
33609
|
+
render: function (el, opt) {
|
|
33610
|
+
var d;
|
|
33611
|
+
var width = opt.width;
|
|
33612
|
+
var height = opt.height;
|
|
33613
|
+
var thickness = opt.thickness;
|
|
33614
|
+
if (width - thickness >= 0 && height - thickness >= 0) {
|
|
33615
|
+
d = ['M', width, 0, 'H0 M0 0 V0', height].join(' ');
|
|
33616
|
+
} else {
|
|
33617
|
+
d = 'M 0 0 0 0';
|
|
33618
|
+
}
|
|
33619
|
+
V(el).attr({
|
|
33620
|
+
'd': d,
|
|
33621
|
+
stroke: opt.color,
|
|
33622
|
+
'stroke-width': opt.thickness
|
|
33623
|
+
});
|
|
33624
|
+
}
|
|
33625
|
+
}],
|
|
33626
|
+
doubleMesh: [{
|
|
33627
|
+
color: '#AAAAAA',
|
|
33628
|
+
thickness: 1,
|
|
33629
|
+
markup: 'path',
|
|
33630
|
+
render: function (el, opt) {
|
|
33631
|
+
var d;
|
|
33632
|
+
var width = opt.width;
|
|
33633
|
+
var height = opt.height;
|
|
33634
|
+
var thickness = opt.thickness;
|
|
33635
|
+
if (width - thickness >= 0 && height - thickness >= 0) {
|
|
33636
|
+
d = ['M', width, 0, 'H0 M0 0 V0', height].join(' ');
|
|
33637
|
+
} else {
|
|
33638
|
+
d = 'M 0 0 0 0';
|
|
33639
|
+
}
|
|
33640
|
+
V(el).attr({
|
|
33641
|
+
'd': d,
|
|
33642
|
+
stroke: opt.color,
|
|
33643
|
+
'stroke-width': opt.thickness
|
|
33644
|
+
});
|
|
33645
|
+
}
|
|
33646
|
+
}, {
|
|
33647
|
+
color: '#000000',
|
|
33648
|
+
thickness: 3,
|
|
33649
|
+
scaleFactor: 4,
|
|
33650
|
+
markup: 'path',
|
|
33651
|
+
render: function (el, opt) {
|
|
33652
|
+
var d;
|
|
33653
|
+
var width = opt.width;
|
|
33654
|
+
var height = opt.height;
|
|
33655
|
+
var thickness = opt.thickness;
|
|
33656
|
+
if (width - thickness >= 0 && height - thickness >= 0) {
|
|
33657
|
+
d = ['M', width, 0, 'H0 M0 0 V0', height].join(' ');
|
|
33658
|
+
} else {
|
|
33659
|
+
d = 'M 0 0 0 0';
|
|
33660
|
+
}
|
|
33661
|
+
V(el).attr({
|
|
33662
|
+
'd': d,
|
|
33663
|
+
stroke: opt.color,
|
|
33664
|
+
'stroke-width': opt.thickness
|
|
33665
|
+
});
|
|
33666
|
+
}
|
|
33667
|
+
}]
|
|
33668
|
+
};
|
|
33669
|
+
const backgroundPatterns = {
|
|
33670
|
+
flipXy: function (img) {
|
|
33671
|
+
// d b
|
|
33672
|
+
// q p
|
|
33673
|
+
|
|
33674
|
+
var canvas = document.createElement('canvas');
|
|
33675
|
+
var imgWidth = img.width;
|
|
33676
|
+
var imgHeight = img.height;
|
|
33677
|
+
canvas.width = 2 * imgWidth;
|
|
33678
|
+
canvas.height = 2 * imgHeight;
|
|
33679
|
+
var ctx = canvas.getContext('2d');
|
|
33680
|
+
// top-left image
|
|
33681
|
+
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
33682
|
+
// xy-flipped bottom-right image
|
|
33683
|
+
ctx.setTransform(-1, 0, 0, -1, canvas.width, canvas.height);
|
|
33684
|
+
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
33685
|
+
// x-flipped top-right image
|
|
33686
|
+
ctx.setTransform(-1, 0, 0, 1, canvas.width, 0);
|
|
33687
|
+
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
33688
|
+
// y-flipped bottom-left image
|
|
33689
|
+
ctx.setTransform(1, 0, 0, -1, 0, canvas.height);
|
|
33690
|
+
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
33691
|
+
return canvas;
|
|
33692
|
+
},
|
|
33693
|
+
flipX: function (img) {
|
|
33694
|
+
// d b
|
|
33695
|
+
// d b
|
|
33696
|
+
|
|
33697
|
+
var canvas = document.createElement('canvas');
|
|
33698
|
+
var imgWidth = img.width;
|
|
33699
|
+
var imgHeight = img.height;
|
|
33700
|
+
canvas.width = imgWidth * 2;
|
|
33701
|
+
canvas.height = imgHeight;
|
|
33702
|
+
var ctx = canvas.getContext('2d');
|
|
33703
|
+
// left image
|
|
33704
|
+
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
33705
|
+
// flipped right image
|
|
33706
|
+
ctx.translate(2 * imgWidth, 0);
|
|
33707
|
+
ctx.scale(-1, 1);
|
|
33708
|
+
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
33709
|
+
return canvas;
|
|
33710
|
+
},
|
|
33711
|
+
flipY: function (img) {
|
|
33712
|
+
// d d
|
|
33713
|
+
// q q
|
|
33714
|
+
|
|
33715
|
+
var canvas = document.createElement('canvas');
|
|
33716
|
+
var imgWidth = img.width;
|
|
33717
|
+
var imgHeight = img.height;
|
|
33718
|
+
canvas.width = imgWidth;
|
|
33719
|
+
canvas.height = imgHeight * 2;
|
|
33720
|
+
var ctx = canvas.getContext('2d');
|
|
33721
|
+
// top image
|
|
33722
|
+
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
33723
|
+
// flipped bottom image
|
|
33724
|
+
ctx.translate(0, 2 * imgHeight);
|
|
33725
|
+
ctx.scale(1, -1);
|
|
33726
|
+
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
33727
|
+
return canvas;
|
|
33728
|
+
},
|
|
33729
|
+
watermark: function (img, opt) {
|
|
33730
|
+
// d
|
|
33731
|
+
// d
|
|
33732
|
+
|
|
33733
|
+
opt = opt || {};
|
|
33734
|
+
var imgWidth = img.width;
|
|
33735
|
+
var imgHeight = img.height;
|
|
33736
|
+
var canvas = document.createElement('canvas');
|
|
33737
|
+
canvas.width = imgWidth * 3;
|
|
33738
|
+
canvas.height = imgHeight * 3;
|
|
33739
|
+
var ctx = canvas.getContext('2d');
|
|
33740
|
+
var angle = isNumber(opt.watermarkAngle) ? -opt.watermarkAngle : -20;
|
|
33741
|
+
var radians = toRad(angle);
|
|
33742
|
+
var stepX = canvas.width / 4;
|
|
33743
|
+
var stepY = canvas.height / 4;
|
|
33744
|
+
for (var i = 0; i < 4; i++) {
|
|
33745
|
+
for (var j = 0; j < 4; j++) {
|
|
33746
|
+
if ((i + j) % 2 > 0) {
|
|
33747
|
+
// reset the current transformations
|
|
33748
|
+
ctx.setTransform(1, 0, 0, 1, (2 * i - 1) * stepX, (2 * j - 1) * stepY);
|
|
33749
|
+
ctx.rotate(radians);
|
|
33750
|
+
ctx.drawImage(img, -imgWidth / 2, -imgHeight / 2, imgWidth, imgHeight);
|
|
33751
|
+
}
|
|
33752
|
+
}
|
|
33753
|
+
}
|
|
33754
|
+
return canvas;
|
|
33755
|
+
}
|
|
33756
|
+
};
|
|
33757
|
+
const implicitLayers = [{
|
|
33758
|
+
id: paperLayers.GRID,
|
|
33759
|
+
type: 'GridLayerView',
|
|
33760
|
+
patterns: gridPatterns
|
|
32201
33761
|
}, {
|
|
32202
|
-
|
|
33762
|
+
id: paperLayers.BACK
|
|
32203
33763
|
}, {
|
|
32204
|
-
|
|
33764
|
+
id: paperLayers.LABELS
|
|
32205
33765
|
}, {
|
|
32206
|
-
|
|
33766
|
+
id: paperLayers.FRONT
|
|
32207
33767
|
}, {
|
|
32208
|
-
|
|
33768
|
+
id: paperLayers.TOOLS
|
|
32209
33769
|
}];
|
|
32210
33770
|
const CELL_VIEW_PLACEHOLDER_MARKER = Symbol('joint.cellViewPlaceholderMarker');
|
|
32211
33771
|
const Paper = View.extend({
|
|
@@ -32275,7 +33835,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32275
33835
|
// Do not create hard dependency on the joint.shapes.standard namespace (by importing the standard.Link model directly)
|
|
32276
33836
|
const {
|
|
32277
33837
|
cellNamespace
|
|
32278
|
-
} = this.model.
|
|
33838
|
+
} = this.model.layerCollection;
|
|
32279
33839
|
const ctor = getByPath(cellNamespace, ['standard', 'Link']);
|
|
32280
33840
|
if (!ctor) throw new Error('dia.Paper: no default link model found. Use `options.defaultLink` to specify a default link model.');
|
|
32281
33841
|
return new ctor();
|
|
@@ -32361,12 +33921,24 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32361
33921
|
viewManagement: false,
|
|
32362
33922
|
// no docs yet
|
|
32363
33923
|
onViewUpdate: function (view, flag, priority, opt, paper) {
|
|
32364
|
-
|
|
32365
|
-
|
|
32366
|
-
|
|
32367
|
-
|
|
32368
|
-
|
|
32369
|
-
|
|
33924
|
+
if (opt.mounting || opt.isolate) {
|
|
33925
|
+
// Do not update connected links when:
|
|
33926
|
+
// - the view was just mounted (added back to the paper by viewport function)
|
|
33927
|
+
// - the change was marked as `isolate`.
|
|
33928
|
+
return;
|
|
33929
|
+
}
|
|
33930
|
+
// Always update connected links when the view model was replaced with another model
|
|
33931
|
+
// with the same id.
|
|
33932
|
+
// Note: the removal is done in 2 steps: remove the old model, add the new model.
|
|
33933
|
+
// We update connected links on the add step.
|
|
33934
|
+
if (!(opt.replace && opt.add)) {
|
|
33935
|
+
if (flag & (paper.FLAG_INSERT | paper.FLAG_REMOVE)) {
|
|
33936
|
+
// Do not update connected links when:
|
|
33937
|
+
// - the view was just inserted (added to the graph and rendered)
|
|
33938
|
+
// - the view model was just removed from the graph
|
|
33939
|
+
return;
|
|
33940
|
+
}
|
|
33941
|
+
}
|
|
32370
33942
|
paper.requestConnectedLinksUpdate(view, priority, opt);
|
|
32371
33943
|
},
|
|
32372
33944
|
// no docs yet
|
|
@@ -32383,6 +33955,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32383
33955
|
// Default namespaces
|
|
32384
33956
|
|
|
32385
33957
|
cellViewNamespace: null,
|
|
33958
|
+
layerViewNamespace: null,
|
|
32386
33959
|
routerNamespace: null,
|
|
32387
33960
|
connectorNamespace: null,
|
|
32388
33961
|
highlighterNamespace: highlighters,
|
|
@@ -32430,10 +34003,11 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32430
34003
|
}
|
|
32431
34004
|
`,
|
|
32432
34005
|
svg: null,
|
|
32433
|
-
viewport: null,
|
|
32434
34006
|
defs: null,
|
|
32435
34007
|
tools: null,
|
|
32436
34008
|
layers: null,
|
|
34009
|
+
// deprecated, use layers element instead
|
|
34010
|
+
viewport: null,
|
|
32437
34011
|
// For storing the current transformation matrix (CTM) of the paper's viewport.
|
|
32438
34012
|
_viewportMatrix: null,
|
|
32439
34013
|
// For verifying whether the CTM is up-to-date. The viewport transform attribute
|
|
@@ -32443,7 +34017,6 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32443
34017
|
_updates: null,
|
|
32444
34018
|
// Paper Layers
|
|
32445
34019
|
_layers: null,
|
|
32446
|
-
SORT_DELAYING_BATCHES: ['add', 'to-front', 'to-back'],
|
|
32447
34020
|
UPDATE_DELAYING_BATCHES: ['translate'],
|
|
32448
34021
|
// If you interact with these elements,
|
|
32449
34022
|
// the default interaction such as `element move` is prevented.
|
|
@@ -32463,12 +34036,13 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32463
34036
|
// The find buffer is used to extend the area of the search
|
|
32464
34037
|
// to mitigate the differences between the model and view geometry.
|
|
32465
34038
|
DEFAULT_FIND_BUFFER: 200,
|
|
32466
|
-
// Default layer to insert the cell views into.
|
|
32467
|
-
DEFAULT_CELL_LAYER: LayersNames.CELLS,
|
|
32468
|
-
// Update flags
|
|
32469
34039
|
FLAG_INSERT: 1 << 30,
|
|
32470
34040
|
FLAG_REMOVE: 1 << 29,
|
|
32471
34041
|
FLAG_INIT: 1 << 28,
|
|
34042
|
+
// Layers that are always present on the paper (e.g. grid, back, front, tools)
|
|
34043
|
+
implicitLayers,
|
|
34044
|
+
// Reference layer for inserting new graph layers.
|
|
34045
|
+
graphLayerRefId: paperLayers.LABELS,
|
|
32472
34046
|
init: function () {
|
|
32473
34047
|
const {
|
|
32474
34048
|
options
|
|
@@ -32478,6 +34052,12 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32478
34052
|
options.cellViewNamespace = typeof joint !== 'undefined' && has(joint, 'shapes') ? joint.shapes : null;
|
|
32479
34053
|
/* eslint-enable no-undef */
|
|
32480
34054
|
}
|
|
34055
|
+
const defaultLayerViewNamespace = {
|
|
34056
|
+
LayerView,
|
|
34057
|
+
GraphLayerView,
|
|
34058
|
+
GridLayerView
|
|
34059
|
+
};
|
|
34060
|
+
this.layerViewNamespace = defaultsDeep({}, options.layerViewNamespace || {}, defaultLayerViewNamespace);
|
|
32481
34061
|
const model = this.model = options.model || new Graph();
|
|
32482
34062
|
|
|
32483
34063
|
// This property tells us if we need to keep the compatibility
|
|
@@ -32487,18 +34067,17 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32487
34067
|
// Layers (SVGGroups)
|
|
32488
34068
|
this._layers = {
|
|
32489
34069
|
viewsMap: {},
|
|
32490
|
-
namesMap: {},
|
|
32491
34070
|
order: []
|
|
32492
34071
|
};
|
|
32493
|
-
this.cloneOptions();
|
|
32494
|
-
this.render();
|
|
32495
|
-
this._setDimensions();
|
|
32496
|
-
this.startListening();
|
|
32497
34072
|
|
|
32498
34073
|
// Hash of all cell views.
|
|
32499
34074
|
this._views = {};
|
|
32500
34075
|
this._viewPlaceholders = {};
|
|
32501
34076
|
this._idToCid = {};
|
|
34077
|
+
this.cloneOptions();
|
|
34078
|
+
this.render();
|
|
34079
|
+
this._setDimensions();
|
|
34080
|
+
this.startListening();
|
|
32502
34081
|
|
|
32503
34082
|
// Mouse wheel events buffer
|
|
32504
34083
|
this._mw_evt_buffer = {
|
|
@@ -32507,7 +34086,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32507
34086
|
};
|
|
32508
34087
|
|
|
32509
34088
|
// Render existing cells in the graph
|
|
32510
|
-
this.resetViews(model.
|
|
34089
|
+
this.resetViews(model.getCells());
|
|
32511
34090
|
},
|
|
32512
34091
|
_resetUpdates: function () {
|
|
32513
34092
|
if (this._updates && this._updates.id) cancelFrame(this._updates.id);
|
|
@@ -32527,7 +34106,8 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32527
34106
|
},
|
|
32528
34107
|
startListening: function () {
|
|
32529
34108
|
var model = this.model;
|
|
32530
|
-
this.listenTo(model, 'add', this.onCellAdded).listenTo(model, 'remove', this.onCellRemoved).listenTo(model, '
|
|
34109
|
+
this.listenTo(model, 'add', this.onCellAdded).listenTo(model, 'remove', this.onCellRemoved).listenTo(model, 'reset', this.onGraphReset).listenTo(model, 'batch:stop', this.onGraphBatchStop);
|
|
34110
|
+
this.listenTo(model, 'layer:add', this.onGraphLayerAdd).listenTo(model, 'layer:remove', this.onGraphLayerRemove).listenTo(model, 'layers:sort', this.onGraphLayerCollectionSort);
|
|
32531
34111
|
this.on('cell:highlight', this.onCellHighlight).on('cell:unhighlight', this.onCellUnhighlight).on('transform', this.update);
|
|
32532
34112
|
},
|
|
32533
34113
|
onCellAdded: function (cell, _, opt) {
|
|
@@ -32553,22 +34133,15 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32553
34133
|
this.requestViewUpdate(viewLike, this.FLAG_REMOVE, viewLike.UPDATE_PRIORITY, opt);
|
|
32554
34134
|
}
|
|
32555
34135
|
},
|
|
32556
|
-
|
|
32557
|
-
|
|
32558
|
-
|
|
32559
|
-
|
|
32560
|
-
|
|
32561
|
-
|
|
32562
|
-
|
|
32563
|
-
|
|
32564
|
-
|
|
32565
|
-
onGraphReset: function (collection, opt) {
|
|
32566
|
-
this.resetLayers();
|
|
32567
|
-
this.resetViews(collection.models, opt);
|
|
32568
|
-
},
|
|
32569
|
-
onGraphSort: function () {
|
|
32570
|
-
if (this.model.hasActiveBatch(this.SORT_DELAYING_BATCHES)) return;
|
|
32571
|
-
this.sortViews();
|
|
34136
|
+
onGraphReset: function (_collection, opt) {
|
|
34137
|
+
// Re-render all graph layer views
|
|
34138
|
+
// but keep the implicit layer views.
|
|
34139
|
+
this.renderGraphLayerViews();
|
|
34140
|
+
this.resetLayerViews();
|
|
34141
|
+
// Backward compatibility: reassign the `cells` property
|
|
34142
|
+
// with the default layer view.
|
|
34143
|
+
this.assertLayerViews();
|
|
34144
|
+
this.resetViews(this.model.getCells(), opt);
|
|
32572
34145
|
},
|
|
32573
34146
|
onGraphBatchStop: function (data) {
|
|
32574
34147
|
if (this.isFrozen() || this.isIdle()) return;
|
|
@@ -32580,10 +34153,92 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32580
34153
|
this.updateViews(data);
|
|
32581
34154
|
}
|
|
32582
34155
|
}
|
|
32583
|
-
|
|
32584
|
-
|
|
32585
|
-
|
|
34156
|
+
},
|
|
34157
|
+
/**
|
|
34158
|
+
* @protected
|
|
34159
|
+
* @description When a new layer is added to the graph, we create a new layer view
|
|
34160
|
+
**/
|
|
34161
|
+
onGraphLayerAdd: function (layer, _, opt) {
|
|
34162
|
+
if (this.hasLayerView(layer.id)) return;
|
|
34163
|
+
const layerView = this.createLayerView({
|
|
34164
|
+
id: layer.id,
|
|
34165
|
+
model: layer
|
|
34166
|
+
});
|
|
34167
|
+
const layers = this.model.getLayers();
|
|
34168
|
+
let before;
|
|
34169
|
+
// Note: There is always at least one graph layer.
|
|
34170
|
+
if (layers[layers.length - 1] === layer) {
|
|
34171
|
+
// This is the last layer, so insert before the labels layer
|
|
34172
|
+
before = paperLayers.LABELS;
|
|
34173
|
+
} else {
|
|
34174
|
+
// There is a layer after the current one, so insert before that one
|
|
34175
|
+
const index = layers.indexOf(layer);
|
|
34176
|
+
before = layers[index + 1].id;
|
|
32586
34177
|
}
|
|
34178
|
+
this.addLayerView(layerView, {
|
|
34179
|
+
before
|
|
34180
|
+
});
|
|
34181
|
+
},
|
|
34182
|
+
/**
|
|
34183
|
+
* @protected
|
|
34184
|
+
* @description When a layer is removed from the graph, we remove the corresponding layer view
|
|
34185
|
+
**/
|
|
34186
|
+
onGraphLayerRemove: function (layer, _, opt) {
|
|
34187
|
+
if (!this.hasLayerView(layer)) return;
|
|
34188
|
+
|
|
34189
|
+
// Request layer removal. Since the UPDATE_PRIORITY is lower
|
|
34190
|
+
// than cells update priority, the cell views will be removed first.
|
|
34191
|
+
this.requestLayerViewRemoval(layer);
|
|
34192
|
+
},
|
|
34193
|
+
/**
|
|
34194
|
+
* @protected
|
|
34195
|
+
* @description When the graph layer collection is sorted,
|
|
34196
|
+
* we reorder all graph layer views.
|
|
34197
|
+
**/
|
|
34198
|
+
onGraphLayerCollectionSort: function (layerCollection) {
|
|
34199
|
+
layerCollection.each(layer => {
|
|
34200
|
+
if (!this.hasLayerView(layer)) return;
|
|
34201
|
+
this.moveLayerView(layer, {
|
|
34202
|
+
before: this.graphLayerRefId
|
|
34203
|
+
});
|
|
34204
|
+
});
|
|
34205
|
+
},
|
|
34206
|
+
/**
|
|
34207
|
+
* @protected
|
|
34208
|
+
* @description Resets all graph layer views.
|
|
34209
|
+
*/
|
|
34210
|
+
renderGraphLayerViews: function () {
|
|
34211
|
+
// Remove all existing graph layer views
|
|
34212
|
+
// Note: we don't use `getGraphLayerViews()` here because
|
|
34213
|
+
// rendered graph layer views could be different from the ones
|
|
34214
|
+
// in the graph layer collection (`onResetGraphLayerCollectionReset`).
|
|
34215
|
+
this.getLayerViews().forEach(layerView => {
|
|
34216
|
+
if (!layerView[GRAPH_LAYER_VIEW_MARKER]) return;
|
|
34217
|
+
this._removeLayerView(layerView);
|
|
34218
|
+
});
|
|
34219
|
+
// Create and insert new graph layer views
|
|
34220
|
+
this.model.getLayers().forEach(layer => {
|
|
34221
|
+
const layerView = this.createLayerView({
|
|
34222
|
+
id: layer.id,
|
|
34223
|
+
model: layer
|
|
34224
|
+
});
|
|
34225
|
+
// Insert the layer view into the paper layers, just before the labels layer.
|
|
34226
|
+
// All cell layers are positioned between the "back" and "labels" layers,
|
|
34227
|
+
// with the default "cells" layer originally occupying this position.
|
|
34228
|
+
this.addLayerView(layerView, {
|
|
34229
|
+
before: this.graphLayerRefId
|
|
34230
|
+
});
|
|
34231
|
+
});
|
|
34232
|
+
},
|
|
34233
|
+
/**
|
|
34234
|
+
* @protected
|
|
34235
|
+
* @description Renders all implicit layer views.
|
|
34236
|
+
*/
|
|
34237
|
+
renderImplicitLayerViews: function () {
|
|
34238
|
+
this.implicitLayers.forEach(layerInit => {
|
|
34239
|
+
const layerView = this.createLayerView(layerInit);
|
|
34240
|
+
this.addLayerView(layerView);
|
|
34241
|
+
});
|
|
32587
34242
|
},
|
|
32588
34243
|
cloneOptions: function () {
|
|
32589
34244
|
const {
|
|
@@ -32678,136 +34333,295 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32678
34333
|
}]
|
|
32679
34334
|
}];
|
|
32680
34335
|
},
|
|
32681
|
-
|
|
32682
|
-
|
|
34336
|
+
/**
|
|
34337
|
+
* @public
|
|
34338
|
+
* @description Checks whether the layer view exists by the given layer id or layer model.
|
|
34339
|
+
* @param {string|dia.GraphLayer} layerRef - Layer id or layer model.
|
|
34340
|
+
* @return {boolean} True if the layer view exists, false otherwise.
|
|
34341
|
+
*/
|
|
34342
|
+
hasLayerView(layerRef) {
|
|
34343
|
+
let layerId;
|
|
34344
|
+
if (isString(layerRef)) {
|
|
34345
|
+
layerId = layerRef;
|
|
34346
|
+
} else if (layerRef) {
|
|
34347
|
+
layerId = layerRef.id;
|
|
34348
|
+
} else {
|
|
34349
|
+
return false;
|
|
34350
|
+
}
|
|
34351
|
+
return layerId in this._layers.viewsMap;
|
|
32683
34352
|
},
|
|
32684
|
-
|
|
32685
|
-
|
|
32686
|
-
|
|
32687
|
-
|
|
32688
|
-
|
|
32689
|
-
|
|
32690
|
-
|
|
32691
|
-
|
|
34353
|
+
/**
|
|
34354
|
+
* @public
|
|
34355
|
+
* @description Returns the layer view by the given layer id or layer model.
|
|
34356
|
+
* @param {string|dia.GraphLayer} layerRef - Layer id or layer model.
|
|
34357
|
+
* @return {dia.LayerView} The layer view.
|
|
34358
|
+
* @throws {Error} if the layer view is not found
|
|
34359
|
+
*/
|
|
34360
|
+
getLayerView(layerRef) {
|
|
34361
|
+
let layerId;
|
|
34362
|
+
if (isString(layerRef)) {
|
|
34363
|
+
layerId = layerRef;
|
|
34364
|
+
} else if (layerRef) {
|
|
34365
|
+
layerId = layerRef.id;
|
|
34366
|
+
} else {
|
|
34367
|
+
throw new Error('dia.Paper: No layer provided.');
|
|
34368
|
+
}
|
|
34369
|
+
const layerView = this._layers.viewsMap[layerId];
|
|
34370
|
+
if (!layerView) {
|
|
34371
|
+
throw new Error(`dia.Paper: Unknown layer view "${layerId}".`);
|
|
34372
|
+
}
|
|
34373
|
+
return layerView;
|
|
32692
34374
|
},
|
|
32693
|
-
|
|
32694
|
-
|
|
34375
|
+
/**
|
|
34376
|
+
* @deprecated use `getLayerView(layerId).el` instead
|
|
34377
|
+
*/
|
|
34378
|
+
getLayerNode(layerId) {
|
|
34379
|
+
return this.getLayerView(layerId).el;
|
|
32695
34380
|
},
|
|
32696
|
-
|
|
32697
|
-
|
|
34381
|
+
/**
|
|
34382
|
+
* @protected
|
|
34383
|
+
* @description Removes the given layer view from the paper.
|
|
34384
|
+
* It does not check whether the layer view is empty.
|
|
34385
|
+
* @param {dia.LayerView} layerView - The layer view to remove.
|
|
34386
|
+
*/
|
|
34387
|
+
_removeLayerView(layerView) {
|
|
34388
|
+
this._unregisterLayerView(layerView);
|
|
32698
34389
|
layerView.remove();
|
|
32699
34390
|
},
|
|
32700
|
-
|
|
32701
|
-
|
|
32702
|
-
|
|
32703
|
-
|
|
32704
|
-
|
|
32705
|
-
|
|
32706
|
-
|
|
32707
|
-
|
|
32708
|
-
|
|
32709
|
-
order.splice(order.indexOf(layerName), 1);
|
|
32710
|
-
delete namesMap[layerView.cid];
|
|
32711
|
-
delete viewsMap[layerName];
|
|
34391
|
+
/**
|
|
34392
|
+
* @protected
|
|
34393
|
+
* @description Removes all layer views from the paper.
|
|
34394
|
+
* It does not check whether the layer views are empty.
|
|
34395
|
+
*/
|
|
34396
|
+
_removeLayerViews: function () {
|
|
34397
|
+
Object.values(this._layers.viewsMap).forEach(layerView => {
|
|
34398
|
+
this._removeLayerView(layerView);
|
|
34399
|
+
});
|
|
32712
34400
|
},
|
|
32713
|
-
|
|
34401
|
+
/**
|
|
34402
|
+
* @protected
|
|
34403
|
+
* @description Unregisters the given layer view from the paper.
|
|
34404
|
+
* @param {dia.LayerView} layerView - The layer view to unregister.
|
|
34405
|
+
*/
|
|
34406
|
+
_unregisterLayerView(layerView) {
|
|
32714
34407
|
const {
|
|
32715
34408
|
_layers: {
|
|
32716
34409
|
viewsMap,
|
|
32717
|
-
namesMap,
|
|
32718
34410
|
order
|
|
32719
34411
|
}
|
|
32720
34412
|
} = this;
|
|
32721
|
-
|
|
32722
|
-
|
|
32723
|
-
|
|
32724
|
-
|
|
32725
|
-
order.
|
|
34413
|
+
const layerId = layerView.id;
|
|
34414
|
+
// Remove the layer id from the order list.
|
|
34415
|
+
const layerIndex = order.indexOf(layerId);
|
|
34416
|
+
if (layerIndex !== -1) {
|
|
34417
|
+
order.splice(layerIndex, 1);
|
|
32726
34418
|
}
|
|
32727
|
-
|
|
32728
|
-
|
|
34419
|
+
// Unlink the layer view from the paper.
|
|
34420
|
+
layerView.unsetPaperReference();
|
|
34421
|
+
// Remove the layer view from the paper's registry.
|
|
34422
|
+
delete viewsMap[layerId];
|
|
32729
34423
|
},
|
|
32730
|
-
|
|
32731
|
-
|
|
32732
|
-
|
|
32733
|
-
|
|
32734
|
-
|
|
32735
|
-
|
|
32736
|
-
|
|
32737
|
-
|
|
32738
|
-
|
|
32739
|
-
|
|
34424
|
+
/**
|
|
34425
|
+
* @protected
|
|
34426
|
+
* @description Registers the given layer view in the paper.
|
|
34427
|
+
* @param {dia.LayerView} layerView - The layer view to register.
|
|
34428
|
+
* @throws {Error} if the layer view is not an instance of dia.LayerView
|
|
34429
|
+
* @throws {Error} if the layer view already exists in the paper
|
|
34430
|
+
*/
|
|
34431
|
+
_registerLayerView(layerView) {
|
|
34432
|
+
if (!layerView || !layerView[LAYER_VIEW_MARKER]) {
|
|
34433
|
+
throw new Error('dia.Paper: The layer view must be an instance of dia.LayerView.');
|
|
32740
34434
|
}
|
|
32741
|
-
if (
|
|
32742
|
-
|
|
34435
|
+
if (this.hasLayerView(layerView.id)) {
|
|
34436
|
+
throw new Error(`dia.Paper: The layer view "${layerView.id}" already exists.`);
|
|
34437
|
+
}
|
|
34438
|
+
// Link the layer view back to the paper.
|
|
34439
|
+
layerView.setPaperReference(this);
|
|
34440
|
+
// Store the layer view in the paper's registry.
|
|
34441
|
+
this._layers.viewsMap[layerView.id] = layerView;
|
|
32743
34442
|
},
|
|
32744
|
-
|
|
34443
|
+
/**
|
|
34444
|
+
* @public
|
|
34445
|
+
* @description Removes the layer view by the given layer id or layer model.
|
|
34446
|
+
* @param {string|dia.GraphLayer} layerRef - Layer id or layer model.
|
|
34447
|
+
* @throws {Error} if the layer view is not empty
|
|
34448
|
+
*/
|
|
34449
|
+
removeLayerView(layerRef) {
|
|
34450
|
+
const layerView = this.getLayerView(layerRef);
|
|
34451
|
+
if (!layerView.isEmpty()) {
|
|
34452
|
+
throw new Error('dia.Paper: The layer view is not empty.');
|
|
34453
|
+
}
|
|
34454
|
+
this._removeLayerView(layerView);
|
|
34455
|
+
},
|
|
34456
|
+
/**
|
|
34457
|
+
* @protected
|
|
34458
|
+
* @description Schedules the layer view removal by the given layer id or layer model.
|
|
34459
|
+
* The actual removal will be performed during the paper update cycle.
|
|
34460
|
+
* @param {string|dia.GraphLayer} layerRef - Layer id or layer model.
|
|
34461
|
+
* @param {Object} [opt] - Update options.
|
|
34462
|
+
*/
|
|
34463
|
+
requestLayerViewRemoval(layerRef, opt) {
|
|
34464
|
+
const layerView = this.getLayerView(layerRef);
|
|
32745
34465
|
const {
|
|
32746
|
-
|
|
32747
|
-
namesMap
|
|
32748
|
-
}
|
|
34466
|
+
FLAG_REMOVE
|
|
32749
34467
|
} = this;
|
|
32750
|
-
|
|
34468
|
+
const {
|
|
34469
|
+
UPDATE_PRIORITY
|
|
34470
|
+
} = layerView;
|
|
34471
|
+
this.requestViewUpdate(layerView, FLAG_REMOVE, UPDATE_PRIORITY, opt);
|
|
32751
34472
|
},
|
|
32752
|
-
|
|
32753
|
-
|
|
32754
|
-
|
|
32755
|
-
|
|
32756
|
-
|
|
34473
|
+
/**
|
|
34474
|
+
* @public
|
|
34475
|
+
* @internal not documented
|
|
34476
|
+
* @description Schedules the cell view insertion into the appropriate layer view.
|
|
34477
|
+
* The actual insertion will be performed during the paper update cycle.
|
|
34478
|
+
* @param {dia.Cell} cell - The cell model whose view should be inserted.
|
|
34479
|
+
* @param {Object} [opt] - Update options.
|
|
34480
|
+
*/
|
|
34481
|
+
requestCellViewInsertion(cell, opt) {
|
|
34482
|
+
const viewLike = this._getCellViewLike(cell);
|
|
34483
|
+
if (!viewLike) return;
|
|
34484
|
+
this.requestViewUpdate(viewLike, this.FLAG_INSERT, viewLike.UPDATE_PRIORITY, opt);
|
|
34485
|
+
},
|
|
34486
|
+
/**
|
|
34487
|
+
* @private
|
|
34488
|
+
* Helper method for addLayerView and moveLayerView methods
|
|
34489
|
+
*/
|
|
34490
|
+
_getBeforeLayerViewFromOptions(layerView, options) {
|
|
34491
|
+
let {
|
|
34492
|
+
before = null,
|
|
34493
|
+
index
|
|
34494
|
+
} = options;
|
|
34495
|
+
if (before && index !== undefined) {
|
|
34496
|
+
throw new Error('dia.Paper: Options "before" and "index" are mutually exclusive.');
|
|
34497
|
+
}
|
|
34498
|
+
let computedBefore;
|
|
34499
|
+
if (index !== undefined) {
|
|
34500
|
+
const {
|
|
34501
|
+
_layers: {
|
|
34502
|
+
order
|
|
34503
|
+
}
|
|
34504
|
+
} = this;
|
|
34505
|
+
if (index >= order.length) {
|
|
34506
|
+
// If index is greater than the number of layers,
|
|
34507
|
+
// return before as null (move to the end).
|
|
34508
|
+
computedBefore = null;
|
|
34509
|
+
} else if (index < 0) {
|
|
34510
|
+
// If index is negative, move to the beginning.
|
|
34511
|
+
computedBefore = order[0];
|
|
32757
34512
|
} else {
|
|
32758
|
-
|
|
34513
|
+
const originalIndex = order.indexOf(layerView.id);
|
|
34514
|
+
if (originalIndex !== -1 && index > originalIndex) {
|
|
34515
|
+
// If moving a layer upwards in the stack, we need to adjust the index
|
|
34516
|
+
// to account for the layer being removed from its original position.
|
|
34517
|
+
index += 1;
|
|
34518
|
+
}
|
|
34519
|
+
// Otherwise, get the layer ID at the specified index.
|
|
34520
|
+
computedBefore = order[index] || null;
|
|
32759
34521
|
}
|
|
34522
|
+
} else {
|
|
34523
|
+
computedBefore = before;
|
|
32760
34524
|
}
|
|
32761
|
-
return
|
|
34525
|
+
return computedBefore ? this.getLayerView(computedBefore) : null;
|
|
32762
34526
|
},
|
|
32763
|
-
|
|
32764
|
-
|
|
34527
|
+
/**
|
|
34528
|
+
* @public
|
|
34529
|
+
* @description Adds the layer view to the paper.
|
|
34530
|
+
* @param {dia.LayerView} layerView - The layer view to add.
|
|
34531
|
+
* @param {Object} [options] - Adding options.
|
|
34532
|
+
* @param {string|dia.GraphLayer} [options.before] - Layer id or layer model before
|
|
34533
|
+
*/
|
|
34534
|
+
addLayerView(layerView, options = {}) {
|
|
34535
|
+
this._registerLayerView(layerView);
|
|
34536
|
+
const beforeLayerView = this._getBeforeLayerViewFromOptions(layerView, options);
|
|
34537
|
+
this.insertLayerView(layerView, beforeLayerView);
|
|
32765
34538
|
},
|
|
32766
|
-
|
|
32767
|
-
|
|
32768
|
-
|
|
32769
|
-
|
|
32770
|
-
|
|
32771
|
-
|
|
34539
|
+
/**
|
|
34540
|
+
* @public
|
|
34541
|
+
* @description Moves the layer view.
|
|
34542
|
+
* @param {Paper.LayerRef} layerRef - The layer view reference to move.
|
|
34543
|
+
* @param {Object} [options] - Moving options.
|
|
34544
|
+
* @param {Paper.LayerRef} [options.before] - Layer id or layer model before
|
|
34545
|
+
* @param {number} [options.index] - Zero-based index to which to move the layer view.
|
|
34546
|
+
*/
|
|
34547
|
+
moveLayerView(layerRef, options = {}) {
|
|
34548
|
+
const layerView = this.getLayerView(layerRef);
|
|
34549
|
+
const beforeLayerView = this._getBeforeLayerViewFromOptions(layerView, options);
|
|
34550
|
+
this.insertLayerView(layerView, beforeLayerView);
|
|
32772
34551
|
},
|
|
32773
|
-
|
|
32774
|
-
|
|
32775
|
-
|
|
32776
|
-
|
|
32777
|
-
|
|
32778
|
-
|
|
32779
|
-
|
|
32780
|
-
|
|
32781
|
-
|
|
32782
|
-
|
|
34552
|
+
/**
|
|
34553
|
+
* @protected
|
|
34554
|
+
* @description Inserts the layer view into the paper.
|
|
34555
|
+
* If the layer view already exists in the paper, it is moved to the new position.
|
|
34556
|
+
* @param {dia.LayerView} layerView - The layer view to insert.
|
|
34557
|
+
* @param {dia.LayerView} [before] - Layer view before
|
|
34558
|
+
* which the layer view should be inserted.
|
|
34559
|
+
*/
|
|
34560
|
+
insertLayerView(layerView, beforeLayerView) {
|
|
34561
|
+
const layerId = layerView.id;
|
|
32783
34562
|
const {
|
|
32784
|
-
|
|
32785
|
-
|
|
32786
|
-
|
|
32787
|
-
|
|
32788
|
-
|
|
32789
|
-
|
|
32790
|
-
|
|
32791
|
-
|
|
34563
|
+
_layers: {
|
|
34564
|
+
order
|
|
34565
|
+
}
|
|
34566
|
+
} = this;
|
|
34567
|
+
const currentLayerIndex = order.indexOf(layerId);
|
|
34568
|
+
|
|
34569
|
+
// Should the layer view be inserted before another layer view?
|
|
34570
|
+
if (beforeLayerView) {
|
|
34571
|
+
const beforeLayerViewId = beforeLayerView.id;
|
|
34572
|
+
if (layerId === beforeLayerViewId) {
|
|
34573
|
+
// The layer view is already in the right place.
|
|
34574
|
+
return;
|
|
34575
|
+
}
|
|
34576
|
+
let beforeLayerPosition = order.indexOf(beforeLayerViewId);
|
|
34577
|
+
// Remove from the `order` list if the layer view is already in the order.
|
|
34578
|
+
if (currentLayerIndex !== -1) {
|
|
34579
|
+
if (currentLayerIndex < beforeLayerPosition) {
|
|
34580
|
+
beforeLayerPosition -= 1;
|
|
34581
|
+
}
|
|
34582
|
+
order.splice(currentLayerIndex, 1);
|
|
34583
|
+
}
|
|
34584
|
+
order.splice(beforeLayerPosition, 0, layerId);
|
|
32792
34585
|
this.layers.insertBefore(layerView.el, beforeLayerView.el);
|
|
34586
|
+
return;
|
|
32793
34587
|
}
|
|
34588
|
+
|
|
34589
|
+
// Remove from the `order` list if the layer view is already in the order.
|
|
34590
|
+
// This is needed for the case when the layer view is inserted in the new position.
|
|
34591
|
+
if (currentLayerIndex !== -1) {
|
|
34592
|
+
order.splice(currentLayerIndex, 1);
|
|
34593
|
+
}
|
|
34594
|
+
order.push(layerId);
|
|
34595
|
+
this.layers.appendChild(layerView.el);
|
|
32794
34596
|
},
|
|
32795
|
-
|
|
32796
|
-
|
|
32797
|
-
|
|
32798
|
-
|
|
32799
|
-
|
|
32800
|
-
|
|
32801
|
-
insertBefore
|
|
32802
|
-
});
|
|
32803
|
-
},
|
|
32804
|
-
getLayerNames() {
|
|
32805
|
-
// Returns a sorted array of layer names.
|
|
34597
|
+
/**
|
|
34598
|
+
* @protected
|
|
34599
|
+
* @description Returns an array of layer view ids in the order they are rendered.
|
|
34600
|
+
* @returns {string[]} An array of layer view ids.
|
|
34601
|
+
*/
|
|
34602
|
+
getLayerViewOrder() {
|
|
32806
34603
|
return this._layers.order.slice();
|
|
32807
34604
|
},
|
|
32808
|
-
|
|
32809
|
-
|
|
32810
|
-
|
|
34605
|
+
/**
|
|
34606
|
+
* @public
|
|
34607
|
+
* @description Returns an array of layer views in the order they are rendered.
|
|
34608
|
+
* @returns {dia.LayerView[]} An array of layer views.
|
|
34609
|
+
*/
|
|
34610
|
+
getLayerViews() {
|
|
34611
|
+
return this.getLayerViewOrder().map(id => this.getLayerView(id));
|
|
34612
|
+
},
|
|
34613
|
+
/**
|
|
34614
|
+
* @public
|
|
34615
|
+
* @description Returns an array of graph layer views in the order they are rendered.
|
|
34616
|
+
* @returns {dia.GraphLayerView[]} An array of graph layer views.
|
|
34617
|
+
*/
|
|
34618
|
+
getGraphLayerViews() {
|
|
34619
|
+
const {
|
|
34620
|
+
_layers: {
|
|
34621
|
+
viewsMap
|
|
34622
|
+
}
|
|
34623
|
+
} = this;
|
|
34624
|
+
return this.model.getLayers().map(layer => viewsMap[layer.id]);
|
|
32811
34625
|
},
|
|
32812
34626
|
render: function () {
|
|
32813
34627
|
this.renderChildren();
|
|
@@ -32827,7 +34641,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32827
34641
|
this.svg = svg;
|
|
32828
34642
|
this.defs = defs;
|
|
32829
34643
|
this.layers = layers;
|
|
32830
|
-
this.
|
|
34644
|
+
this.renderLayerViews();
|
|
32831
34645
|
V.ensureId(svg);
|
|
32832
34646
|
this.addStylesheet(stylesheet);
|
|
32833
34647
|
if (options.background) {
|
|
@@ -32842,60 +34656,79 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
32842
34656
|
if (!css) return;
|
|
32843
34657
|
V(this.svg).prepend(V.createSVGStyle(css));
|
|
32844
34658
|
},
|
|
32845
|
-
|
|
32846
|
-
|
|
32847
|
-
|
|
32848
|
-
|
|
32849
|
-
|
|
32850
|
-
|
|
32851
|
-
|
|
32852
|
-
|
|
32853
|
-
|
|
32854
|
-
|
|
32855
|
-
|
|
32856
|
-
|
|
34659
|
+
/**
|
|
34660
|
+
* @protected
|
|
34661
|
+
* @description Creates a layer view instance based on the provided options.
|
|
34662
|
+
* It finds the appropriate layer view constructor from the paper's
|
|
34663
|
+
* `layerViewNamespace` and instantiates it.
|
|
34664
|
+
* @param {*} options See `dia.LayerView` options.
|
|
34665
|
+
* @returns {dia.LayerView}
|
|
34666
|
+
*/
|
|
34667
|
+
createLayerView(options) {
|
|
34668
|
+
if (options == null) {
|
|
34669
|
+
throw new Error('dia.Paper: Layer view options are required.');
|
|
34670
|
+
}
|
|
34671
|
+
if (options.id == null) {
|
|
34672
|
+
throw new Error('dia.Paper: Layer view id is required.');
|
|
34673
|
+
}
|
|
34674
|
+
const viewOptions = clone$1(options);
|
|
34675
|
+
let viewConstructor;
|
|
34676
|
+
if (viewOptions.model) {
|
|
34677
|
+
const modelType = viewOptions.model.get('type') || viewOptions.model.constructor.name;
|
|
34678
|
+
const type = modelType + 'View';
|
|
34679
|
+
|
|
34680
|
+
// For backward compatibility we use the LegacyGraphLayerView for the default `cells` layer.
|
|
34681
|
+
if (this.model.layersController.legacyMode) {
|
|
34682
|
+
viewConstructor = LegacyGraphLayerView;
|
|
34683
|
+
} else {
|
|
34684
|
+
viewConstructor = this.layerViewNamespace[type] || LayerView;
|
|
34685
|
+
}
|
|
34686
|
+
} else {
|
|
34687
|
+
// Paper layers
|
|
34688
|
+
const type = viewOptions.type;
|
|
34689
|
+
viewConstructor = this.layerViewNamespace[type] || LayerView;
|
|
32857
34690
|
}
|
|
34691
|
+
return new viewConstructor(viewOptions);
|
|
32858
34692
|
},
|
|
32859
|
-
|
|
32860
|
-
|
|
32861
|
-
|
|
32862
|
-
|
|
34693
|
+
/**
|
|
34694
|
+
* @protected
|
|
34695
|
+
* @description Renders all paper layer views and graph layer views.
|
|
34696
|
+
*/
|
|
34697
|
+
renderLayerViews: function () {
|
|
34698
|
+
this._removeLayerViews();
|
|
34699
|
+
// Render the paper layers.
|
|
34700
|
+
this.renderImplicitLayerViews();
|
|
34701
|
+
// Render the layers.
|
|
34702
|
+
this.renderGraphLayerViews();
|
|
34703
|
+
// Ensure that essential layer views are present.
|
|
34704
|
+
this.assertLayerViews();
|
|
32863
34705
|
},
|
|
32864
|
-
|
|
32865
|
-
|
|
32866
|
-
|
|
32867
|
-
|
|
32868
|
-
|
|
32869
|
-
|
|
32870
|
-
|
|
32871
|
-
const
|
|
32872
|
-
const
|
|
34706
|
+
/**
|
|
34707
|
+
* @protected
|
|
34708
|
+
* @description Ensures that essential layer views are present on the paper.
|
|
34709
|
+
* @throws {Error} if any of the essential layer views is missing
|
|
34710
|
+
*/
|
|
34711
|
+
assertLayerViews: function () {
|
|
34712
|
+
// Throws an exception if essential layer views are missing.
|
|
34713
|
+
const cellsLayerView = this.getLayerView(this.model.getDefaultLayer().id);
|
|
34714
|
+
const toolsLayerView = this.getLayerView(paperLayers.TOOLS);
|
|
34715
|
+
const labelsLayerView = this.getLayerView(paperLayers.LABELS);
|
|
34716
|
+
|
|
32873
34717
|
// backwards compatibility
|
|
32874
34718
|
this.tools = toolsLayerView.el;
|
|
32875
34719
|
this.cells = this.viewport = cellsLayerView.el;
|
|
32876
|
-
//
|
|
32877
|
-
|
|
34720
|
+
// Backwards compatibility: same as `LegacyGraphLayerView` we keep
|
|
34721
|
+
// the `viewport` class on the labels layer.
|
|
32878
34722
|
labelsLayerView.vel.addClass(addClassNamePrefix('viewport'));
|
|
32879
|
-
cellsLayerView.el.style.webkitUserSelect = 'none';
|
|
32880
|
-
cellsLayerView.el.style.userSelect = 'none';
|
|
32881
34723
|
labelsLayerView.el.style.webkitUserSelect = 'none';
|
|
32882
34724
|
labelsLayerView.el.style.userSelect = 'none';
|
|
32883
34725
|
},
|
|
32884
|
-
|
|
32885
|
-
|
|
32886
|
-
|
|
32887
|
-
|
|
32888
|
-
|
|
32889
|
-
|
|
32890
|
-
Object.values(viewsMap).forEach(layerView => this._removeLayer(layerView));
|
|
32891
|
-
},
|
|
32892
|
-
resetLayers: function () {
|
|
32893
|
-
const {
|
|
32894
|
-
_layers: {
|
|
32895
|
-
viewsMap
|
|
32896
|
-
}
|
|
32897
|
-
} = this;
|
|
32898
|
-
Object.values(viewsMap).forEach(layerView => layerView.removePivots());
|
|
34726
|
+
/**
|
|
34727
|
+
* @protected
|
|
34728
|
+
* @description Resets all layer views.
|
|
34729
|
+
*/
|
|
34730
|
+
resetLayerViews: function () {
|
|
34731
|
+
this.getLayerViews().forEach(layerView => layerView.reset());
|
|
32899
34732
|
},
|
|
32900
34733
|
update: function () {
|
|
32901
34734
|
if (this._background) {
|
|
@@ -33011,26 +34844,25 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
33011
34844
|
return this;
|
|
33012
34845
|
},
|
|
33013
34846
|
clientMatrix: function () {
|
|
33014
|
-
return V.createSVGMatrix(this.
|
|
34847
|
+
return V.createSVGMatrix(this.layers.getScreenCTM());
|
|
33015
34848
|
},
|
|
33016
34849
|
requestConnectedLinksUpdate: function (view, priority, opt) {
|
|
33017
|
-
if (view
|
|
33018
|
-
|
|
33019
|
-
|
|
33020
|
-
|
|
33021
|
-
|
|
33022
|
-
|
|
33023
|
-
|
|
33024
|
-
|
|
33025
|
-
|
|
33026
|
-
|
|
33027
|
-
|
|
33028
|
-
|
|
33029
|
-
}
|
|
34850
|
+
if (!view || !view[CELL_VIEW_MARKER]) return;
|
|
34851
|
+
var model = view.model;
|
|
34852
|
+
var links = this.model.getConnectedLinks(model);
|
|
34853
|
+
for (var j = 0, n = links.length; j < n; j++) {
|
|
34854
|
+
var link = links[j];
|
|
34855
|
+
var linkView = this._getCellViewLike(link);
|
|
34856
|
+
if (!linkView) continue;
|
|
34857
|
+
// We do not have to update placeholder views.
|
|
34858
|
+
// They will be updated on initial render.
|
|
34859
|
+
if (linkView[CELL_VIEW_PLACEHOLDER_MARKER]) continue;
|
|
34860
|
+
var nextPriority = Math.max(priority + 1, linkView.UPDATE_PRIORITY);
|
|
34861
|
+
this.scheduleViewUpdate(linkView, linkView.getFlag(LinkView.Flags.UPDATE), nextPriority, opt);
|
|
33030
34862
|
}
|
|
33031
34863
|
},
|
|
33032
34864
|
forcePostponedViewUpdate: function (view, flag) {
|
|
33033
|
-
if (!view || !
|
|
34865
|
+
if (!view || !view[CELL_VIEW_MARKER]) return false;
|
|
33034
34866
|
const model = view.model;
|
|
33035
34867
|
if (model.isElement()) return false;
|
|
33036
34868
|
const dumpOptions = {
|
|
@@ -33145,6 +34977,12 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
33145
34977
|
const {
|
|
33146
34978
|
model
|
|
33147
34979
|
} = view;
|
|
34980
|
+
if (view[GRAPH_LAYER_VIEW_MARKER]) {
|
|
34981
|
+
if (flag & FLAG_REMOVE) {
|
|
34982
|
+
this.removeLayerView(view);
|
|
34983
|
+
return 0;
|
|
34984
|
+
}
|
|
34985
|
+
}
|
|
33148
34986
|
if (view[CELL_VIEW_MARKER]) {
|
|
33149
34987
|
if (flag & FLAG_REMOVE) {
|
|
33150
34988
|
this.removeView(model);
|
|
@@ -33744,7 +35582,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
33744
35582
|
}
|
|
33745
35583
|
this.options.frozen = updates.keyFrozen = false;
|
|
33746
35584
|
if (updates.sort) {
|
|
33747
|
-
this.
|
|
35585
|
+
this.sortLayerViews();
|
|
33748
35586
|
updates.sort = false;
|
|
33749
35587
|
}
|
|
33750
35588
|
},
|
|
@@ -33772,8 +35610,8 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
33772
35610
|
this.freeze();
|
|
33773
35611
|
this._updates.disabled = true;
|
|
33774
35612
|
//clean up all DOM elements/views to prevent memory leaks
|
|
33775
|
-
this.removeLayers();
|
|
33776
35613
|
this.removeViews();
|
|
35614
|
+
this._removeLayerViews();
|
|
33777
35615
|
},
|
|
33778
35616
|
getComputedSize: function () {
|
|
33779
35617
|
var options = this.options;
|
|
@@ -34011,7 +35849,17 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
34011
35849
|
if (opt && opt.useModelGeometry) {
|
|
34012
35850
|
return this.model.getBBox() || new Rect();
|
|
34013
35851
|
}
|
|
34014
|
-
|
|
35852
|
+
const graphLayerViews = this.getGraphLayerViews();
|
|
35853
|
+
// Return an empty rectangle if there are no layers
|
|
35854
|
+
// should not happen in practice
|
|
35855
|
+
if (graphLayerViews.length === 0) {
|
|
35856
|
+
return new Rect();
|
|
35857
|
+
}
|
|
35858
|
+
|
|
35859
|
+
// Combine content area rectangles from all layers,
|
|
35860
|
+
// considering only graph layer views to exclude non-cell elements (e.g., grid, tools)
|
|
35861
|
+
const bbox = Rect.fromRectUnion(...graphLayerViews.map(view => view.vel.getBBox()));
|
|
35862
|
+
return bbox;
|
|
34015
35863
|
},
|
|
34016
35864
|
// Return the dimensions of the content bbox in the paper units (as it appears on screen).
|
|
34017
35865
|
getContentBBox: function (opt) {
|
|
@@ -34087,7 +35935,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
34087
35935
|
cid,
|
|
34088
35936
|
model: cell,
|
|
34089
35937
|
interactive,
|
|
34090
|
-
labelsLayer: labelsLayer === true ?
|
|
35938
|
+
labelsLayer: labelsLayer === true ? paperLayers.LABELS : labelsLayer
|
|
34091
35939
|
});
|
|
34092
35940
|
},
|
|
34093
35941
|
_resolveCellViewClass: function (cell) {
|
|
@@ -34248,7 +36096,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
34248
36096
|
this.unfreeze({
|
|
34249
36097
|
key
|
|
34250
36098
|
});
|
|
34251
|
-
this.
|
|
36099
|
+
this.sortLayerViews();
|
|
34252
36100
|
},
|
|
34253
36101
|
removeViews: function () {
|
|
34254
36102
|
// Remove all views and their references from the paper.
|
|
@@ -34262,7 +36110,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
34262
36110
|
this._viewPlaceholders = {};
|
|
34263
36111
|
this._idToCid = {};
|
|
34264
36112
|
},
|
|
34265
|
-
|
|
36113
|
+
sortLayerViews: function () {
|
|
34266
36114
|
if (!this.isExactSorting()) {
|
|
34267
36115
|
// noop
|
|
34268
36116
|
return;
|
|
@@ -34272,38 +36120,16 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
34272
36120
|
this._updates.sort = true;
|
|
34273
36121
|
return;
|
|
34274
36122
|
}
|
|
34275
|
-
this.
|
|
36123
|
+
this.sortLayerViewsExact();
|
|
34276
36124
|
},
|
|
34277
|
-
|
|
34278
|
-
|
|
34279
|
-
// associated model `z` attribute.
|
|
34280
|
-
|
|
34281
|
-
var cellNodes = Array.from(this.cells.childNodes).filter(node => node.getAttribute('model-id'));
|
|
34282
|
-
var cells = this.model.get('cells');
|
|
34283
|
-
sortElements(cellNodes, function (a, b) {
|
|
34284
|
-
var cellA = cells.get(a.getAttribute('model-id'));
|
|
34285
|
-
var cellB = cells.get(b.getAttribute('model-id'));
|
|
34286
|
-
var zA = cellA.attributes.z || 0;
|
|
34287
|
-
var zB = cellB.attributes.z || 0;
|
|
34288
|
-
return zA === zB ? 0 : zA < zB ? -1 : 1;
|
|
34289
|
-
});
|
|
36125
|
+
sortLayerViewsExact: function () {
|
|
36126
|
+
this.getGraphLayerViews().forEach(view => view.sortExact());
|
|
34290
36127
|
},
|
|
34291
36128
|
insertView: function (view, isInitialInsert) {
|
|
34292
|
-
|
|
34293
|
-
|
|
34294
|
-
|
|
34295
|
-
|
|
34296
|
-
const layerName = model.get('layer') || this.DEFAULT_CELL_LAYER;
|
|
34297
|
-
const layerView = this.getLayerView(layerName);
|
|
34298
|
-
switch (this.options.sorting) {
|
|
34299
|
-
case sortingTypes.APPROX:
|
|
34300
|
-
layerView.insertSortedNode(el, model.get('z'));
|
|
34301
|
-
break;
|
|
34302
|
-
case sortingTypes.EXACT:
|
|
34303
|
-
default:
|
|
34304
|
-
layerView.insertNode(el);
|
|
34305
|
-
break;
|
|
34306
|
-
}
|
|
36129
|
+
// layer can be null if it is added to the graph with 'dry' option
|
|
36130
|
+
const layerId = this.model.getCellLayerId(view.model);
|
|
36131
|
+
const layerView = this.getLayerView(layerId);
|
|
36132
|
+
layerView.insertCellView(view);
|
|
34307
36133
|
view.onMount(isInitialInsert);
|
|
34308
36134
|
},
|
|
34309
36135
|
_hideView: function (viewLike) {
|
|
@@ -34358,7 +36184,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
34358
36184
|
// Find the first view climbing up the DOM tree starting at element `el`. Note that `el` can also
|
|
34359
36185
|
// be a selector or a jQuery object.
|
|
34360
36186
|
findView: function ($el) {
|
|
34361
|
-
var el = isString($el) ? this.
|
|
36187
|
+
var el = isString($el) ? this.layers.querySelector($el) : $el instanceof $ ? $el[0] : $el;
|
|
34362
36188
|
var id = this.findAttribute('model-id', el);
|
|
34363
36189
|
if (id) return this._views[id];
|
|
34364
36190
|
return undefined;
|
|
@@ -34396,7 +36222,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
34396
36222
|
var views = this.model.getElements().map(this.findViewByModel, this);
|
|
34397
36223
|
return views.filter(function (view) {
|
|
34398
36224
|
return view && view.vel.getBBox({
|
|
34399
|
-
target: this.
|
|
36225
|
+
target: this.layers
|
|
34400
36226
|
}).containsPoint(p);
|
|
34401
36227
|
}, this);
|
|
34402
36228
|
},
|
|
@@ -34410,7 +36236,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
34410
36236
|
var method = opt.strict ? 'containsRect' : 'intersect';
|
|
34411
36237
|
return views.filter(function (view) {
|
|
34412
36238
|
return view && rect[method](view.vel.getBBox({
|
|
34413
|
-
target: this.
|
|
36239
|
+
target: this.layers
|
|
34414
36240
|
}));
|
|
34415
36241
|
}, this);
|
|
34416
36242
|
},
|
|
@@ -35194,7 +37020,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
35194
37020
|
if (this.GUARDED_TAG_NAMES.includes(target.tagName)) {
|
|
35195
37021
|
return true;
|
|
35196
37022
|
}
|
|
35197
|
-
if (view && view.model && view.model
|
|
37023
|
+
if (view && view.model && view.model[CELL_MARKER]) {
|
|
35198
37024
|
return false;
|
|
35199
37025
|
}
|
|
35200
37026
|
if (this.el === target || this.svg.contains(target)) {
|
|
@@ -35209,12 +37035,12 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
35209
37035
|
options.gridSize = gridSize;
|
|
35210
37036
|
if (options.drawGrid && !options.drawGridSize) {
|
|
35211
37037
|
// Do not redraw the grid if the `drawGridSize` is set.
|
|
35212
|
-
this.getLayerView(
|
|
37038
|
+
this.getLayerView(paperLayers.GRID).renderGrid();
|
|
35213
37039
|
}
|
|
35214
37040
|
return this;
|
|
35215
37041
|
},
|
|
35216
37042
|
setGrid: function (drawGrid) {
|
|
35217
|
-
this.getLayerView(
|
|
37043
|
+
this.getLayerView(paperLayers.GRID).setGrid(drawGrid);
|
|
35218
37044
|
return this;
|
|
35219
37045
|
},
|
|
35220
37046
|
updateBackgroundImage: function (opt) {
|
|
@@ -35539,194 +37365,9 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
35539
37365
|
}
|
|
35540
37366
|
}, {
|
|
35541
37367
|
sorting: sortingTypes,
|
|
35542
|
-
Layers:
|
|
35543
|
-
backgroundPatterns
|
|
35544
|
-
|
|
35545
|
-
// d b
|
|
35546
|
-
// q p
|
|
35547
|
-
|
|
35548
|
-
var canvas = document.createElement('canvas');
|
|
35549
|
-
var imgWidth = img.width;
|
|
35550
|
-
var imgHeight = img.height;
|
|
35551
|
-
canvas.width = 2 * imgWidth;
|
|
35552
|
-
canvas.height = 2 * imgHeight;
|
|
35553
|
-
var ctx = canvas.getContext('2d');
|
|
35554
|
-
// top-left image
|
|
35555
|
-
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
35556
|
-
// xy-flipped bottom-right image
|
|
35557
|
-
ctx.setTransform(-1, 0, 0, -1, canvas.width, canvas.height);
|
|
35558
|
-
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
35559
|
-
// x-flipped top-right image
|
|
35560
|
-
ctx.setTransform(-1, 0, 0, 1, canvas.width, 0);
|
|
35561
|
-
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
35562
|
-
// y-flipped bottom-left image
|
|
35563
|
-
ctx.setTransform(1, 0, 0, -1, 0, canvas.height);
|
|
35564
|
-
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
35565
|
-
return canvas;
|
|
35566
|
-
},
|
|
35567
|
-
flipX: function (img) {
|
|
35568
|
-
// d b
|
|
35569
|
-
// d b
|
|
35570
|
-
|
|
35571
|
-
var canvas = document.createElement('canvas');
|
|
35572
|
-
var imgWidth = img.width;
|
|
35573
|
-
var imgHeight = img.height;
|
|
35574
|
-
canvas.width = imgWidth * 2;
|
|
35575
|
-
canvas.height = imgHeight;
|
|
35576
|
-
var ctx = canvas.getContext('2d');
|
|
35577
|
-
// left image
|
|
35578
|
-
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
35579
|
-
// flipped right image
|
|
35580
|
-
ctx.translate(2 * imgWidth, 0);
|
|
35581
|
-
ctx.scale(-1, 1);
|
|
35582
|
-
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
35583
|
-
return canvas;
|
|
35584
|
-
},
|
|
35585
|
-
flipY: function (img) {
|
|
35586
|
-
// d d
|
|
35587
|
-
// q q
|
|
35588
|
-
|
|
35589
|
-
var canvas = document.createElement('canvas');
|
|
35590
|
-
var imgWidth = img.width;
|
|
35591
|
-
var imgHeight = img.height;
|
|
35592
|
-
canvas.width = imgWidth;
|
|
35593
|
-
canvas.height = imgHeight * 2;
|
|
35594
|
-
var ctx = canvas.getContext('2d');
|
|
35595
|
-
// top image
|
|
35596
|
-
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
35597
|
-
// flipped bottom image
|
|
35598
|
-
ctx.translate(0, 2 * imgHeight);
|
|
35599
|
-
ctx.scale(1, -1);
|
|
35600
|
-
ctx.drawImage(img, 0, 0, imgWidth, imgHeight);
|
|
35601
|
-
return canvas;
|
|
35602
|
-
},
|
|
35603
|
-
watermark: function (img, opt) {
|
|
35604
|
-
// d
|
|
35605
|
-
// d
|
|
35606
|
-
|
|
35607
|
-
opt = opt || {};
|
|
35608
|
-
var imgWidth = img.width;
|
|
35609
|
-
var imgHeight = img.height;
|
|
35610
|
-
var canvas = document.createElement('canvas');
|
|
35611
|
-
canvas.width = imgWidth * 3;
|
|
35612
|
-
canvas.height = imgHeight * 3;
|
|
35613
|
-
var ctx = canvas.getContext('2d');
|
|
35614
|
-
var angle = isNumber(opt.watermarkAngle) ? -opt.watermarkAngle : -20;
|
|
35615
|
-
var radians = toRad(angle);
|
|
35616
|
-
var stepX = canvas.width / 4;
|
|
35617
|
-
var stepY = canvas.height / 4;
|
|
35618
|
-
for (var i = 0; i < 4; i++) {
|
|
35619
|
-
for (var j = 0; j < 4; j++) {
|
|
35620
|
-
if ((i + j) % 2 > 0) {
|
|
35621
|
-
// reset the current transformations
|
|
35622
|
-
ctx.setTransform(1, 0, 0, 1, (2 * i - 1) * stepX, (2 * j - 1) * stepY);
|
|
35623
|
-
ctx.rotate(radians);
|
|
35624
|
-
ctx.drawImage(img, -imgWidth / 2, -imgHeight / 2, imgWidth, imgHeight);
|
|
35625
|
-
}
|
|
35626
|
-
}
|
|
35627
|
-
}
|
|
35628
|
-
return canvas;
|
|
35629
|
-
}
|
|
35630
|
-
},
|
|
35631
|
-
gridPatterns: {
|
|
35632
|
-
dot: [{
|
|
35633
|
-
color: '#AAAAAA',
|
|
35634
|
-
thickness: 1,
|
|
35635
|
-
markup: 'rect',
|
|
35636
|
-
render: function (el, opt) {
|
|
35637
|
-
V(el).attr({
|
|
35638
|
-
width: opt.thickness,
|
|
35639
|
-
height: opt.thickness,
|
|
35640
|
-
fill: opt.color
|
|
35641
|
-
});
|
|
35642
|
-
}
|
|
35643
|
-
}],
|
|
35644
|
-
fixedDot: [{
|
|
35645
|
-
color: '#AAAAAA',
|
|
35646
|
-
thickness: 1,
|
|
35647
|
-
markup: 'rect',
|
|
35648
|
-
render: function (el, opt) {
|
|
35649
|
-
V(el).attr({
|
|
35650
|
-
fill: opt.color
|
|
35651
|
-
});
|
|
35652
|
-
},
|
|
35653
|
-
update: function (el, opt, paper) {
|
|
35654
|
-
const {
|
|
35655
|
-
sx,
|
|
35656
|
-
sy
|
|
35657
|
-
} = paper.scale();
|
|
35658
|
-
const width = sx <= 1 ? opt.thickness : opt.thickness / sx;
|
|
35659
|
-
const height = sy <= 1 ? opt.thickness : opt.thickness / sy;
|
|
35660
|
-
V(el).attr({
|
|
35661
|
-
width,
|
|
35662
|
-
height
|
|
35663
|
-
});
|
|
35664
|
-
}
|
|
35665
|
-
}],
|
|
35666
|
-
mesh: [{
|
|
35667
|
-
color: '#AAAAAA',
|
|
35668
|
-
thickness: 1,
|
|
35669
|
-
markup: 'path',
|
|
35670
|
-
render: function (el, opt) {
|
|
35671
|
-
var d;
|
|
35672
|
-
var width = opt.width;
|
|
35673
|
-
var height = opt.height;
|
|
35674
|
-
var thickness = opt.thickness;
|
|
35675
|
-
if (width - thickness >= 0 && height - thickness >= 0) {
|
|
35676
|
-
d = ['M', width, 0, 'H0 M0 0 V0', height].join(' ');
|
|
35677
|
-
} else {
|
|
35678
|
-
d = 'M 0 0 0 0';
|
|
35679
|
-
}
|
|
35680
|
-
V(el).attr({
|
|
35681
|
-
'd': d,
|
|
35682
|
-
stroke: opt.color,
|
|
35683
|
-
'stroke-width': opt.thickness
|
|
35684
|
-
});
|
|
35685
|
-
}
|
|
35686
|
-
}],
|
|
35687
|
-
doubleMesh: [{
|
|
35688
|
-
color: '#AAAAAA',
|
|
35689
|
-
thickness: 1,
|
|
35690
|
-
markup: 'path',
|
|
35691
|
-
render: function (el, opt) {
|
|
35692
|
-
var d;
|
|
35693
|
-
var width = opt.width;
|
|
35694
|
-
var height = opt.height;
|
|
35695
|
-
var thickness = opt.thickness;
|
|
35696
|
-
if (width - thickness >= 0 && height - thickness >= 0) {
|
|
35697
|
-
d = ['M', width, 0, 'H0 M0 0 V0', height].join(' ');
|
|
35698
|
-
} else {
|
|
35699
|
-
d = 'M 0 0 0 0';
|
|
35700
|
-
}
|
|
35701
|
-
V(el).attr({
|
|
35702
|
-
'd': d,
|
|
35703
|
-
stroke: opt.color,
|
|
35704
|
-
'stroke-width': opt.thickness
|
|
35705
|
-
});
|
|
35706
|
-
}
|
|
35707
|
-
}, {
|
|
35708
|
-
color: '#000000',
|
|
35709
|
-
thickness: 3,
|
|
35710
|
-
scaleFactor: 4,
|
|
35711
|
-
markup: 'path',
|
|
35712
|
-
render: function (el, opt) {
|
|
35713
|
-
var d;
|
|
35714
|
-
var width = opt.width;
|
|
35715
|
-
var height = opt.height;
|
|
35716
|
-
var thickness = opt.thickness;
|
|
35717
|
-
if (width - thickness >= 0 && height - thickness >= 0) {
|
|
35718
|
-
d = ['M', width, 0, 'H0 M0 0 V0', height].join(' ');
|
|
35719
|
-
} else {
|
|
35720
|
-
d = 'M 0 0 0 0';
|
|
35721
|
-
}
|
|
35722
|
-
V(el).attr({
|
|
35723
|
-
'd': d,
|
|
35724
|
-
stroke: opt.color,
|
|
35725
|
-
'stroke-width': opt.thickness
|
|
35726
|
-
});
|
|
35727
|
-
}
|
|
35728
|
-
}]
|
|
35729
|
-
}
|
|
37368
|
+
Layers: paperLayers,
|
|
37369
|
+
backgroundPatterns,
|
|
37370
|
+
gridPatterns
|
|
35730
37371
|
});
|
|
35731
37372
|
|
|
35732
37373
|
const ToolView = View.extend({
|
|
@@ -35825,7 +37466,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
35825
37466
|
tools: null,
|
|
35826
37467
|
relatedView: null,
|
|
35827
37468
|
name: null
|
|
35828
|
-
// layer?:
|
|
37469
|
+
// layer?: Paper.Layers.TOOLS
|
|
35829
37470
|
// z?: number
|
|
35830
37471
|
},
|
|
35831
37472
|
configure: function (options) {
|
|
@@ -35939,7 +37580,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
35939
37580
|
},
|
|
35940
37581
|
getLayer() {
|
|
35941
37582
|
const {
|
|
35942
|
-
layer =
|
|
37583
|
+
layer = Paper.Layers.TOOLS
|
|
35943
37584
|
} = this.options;
|
|
35944
37585
|
return layer;
|
|
35945
37586
|
},
|
|
@@ -35968,21 +37609,26 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
35968
37609
|
|
|
35969
37610
|
var index$2 = {
|
|
35970
37611
|
__proto__: null,
|
|
35971
|
-
CELL_VIEW_MARKER: CELL_VIEW_MARKER,
|
|
35972
37612
|
Cell: Cell,
|
|
37613
|
+
CellCollection: CellCollection,
|
|
35973
37614
|
CellView: CellView,
|
|
37615
|
+
DEFAULT_GRAPH_LAYER_TYPE: DEFAULT_GRAPH_LAYER_TYPE,
|
|
35974
37616
|
Element: Element$1,
|
|
35975
37617
|
ElementView: ElementView,
|
|
35976
37618
|
Graph: Graph,
|
|
37619
|
+
GraphLayer: GraphLayer,
|
|
37620
|
+
GraphLayerCollection: GraphLayerCollection,
|
|
37621
|
+
GraphLayerView: GraphLayerView,
|
|
37622
|
+
GridLayerView: GridLayerView,
|
|
35977
37623
|
HighlighterView: HighlighterView,
|
|
35978
|
-
|
|
37624
|
+
LayerView: LayerView,
|
|
35979
37625
|
Link: Link$1,
|
|
35980
37626
|
LinkView: LinkView,
|
|
35981
37627
|
Paper: Paper,
|
|
35982
|
-
PaperLayer: PaperLayer,
|
|
35983
37628
|
ToolView: ToolView,
|
|
35984
37629
|
ToolsView: ToolsView,
|
|
35985
|
-
attributes: attributes
|
|
37630
|
+
attributes: attributes,
|
|
37631
|
+
sortingTypes: sortingTypes
|
|
35986
37632
|
};
|
|
35987
37633
|
|
|
35988
37634
|
// Vertex Handles
|
|
@@ -37989,7 +39635,7 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
37989
39635
|
Remove: Remove
|
|
37990
39636
|
};
|
|
37991
39637
|
|
|
37992
|
-
var version = "4.2.0-
|
|
39638
|
+
var version = "4.2.0-beta.2";
|
|
37993
39639
|
|
|
37994
39640
|
const Vectorizer = V;
|
|
37995
39641
|
const layout$1 = {
|