@joint/core 4.2.0-alpha.0 → 4.2.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/geometry.js +2 -2
- package/dist/geometry.min.js +3 -3
- package/dist/joint.d.ts +595 -198
- package/dist/joint.js +3895 -1304
- package/dist/joint.min.js +3 -3
- package/dist/joint.nowrap.js +3895 -1304
- package/dist/joint.nowrap.min.js +3 -3
- package/dist/vectorizer.js +21 -8
- package/dist/vectorizer.min.js +3 -3
- package/dist/version.mjs +1 -1
- package/package.json +13 -13
- package/src/V/index.mjs +20 -5
- package/src/alg/Deque.mjs +126 -0
- package/src/cellTools/Boundary.mjs +15 -13
- package/src/cellTools/Button.mjs +7 -5
- package/src/cellTools/Control.mjs +37 -14
- package/src/cellTools/HoverConnect.mjs +5 -1
- package/src/cellTools/helpers.mjs +44 -3
- package/src/config/index.mjs +11 -1
- package/src/dia/Cell.mjs +96 -83
- package/src/dia/CellCollection.mjs +136 -0
- package/src/dia/CellView.mjs +6 -0
- package/src/dia/Element.mjs +6 -5
- package/src/dia/ElementView.mjs +2 -1
- 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/HighlighterView.mjs +22 -0
- package/src/dia/{PaperLayer.mjs → LayerView.mjs} +52 -17
- package/src/dia/LegacyGraphLayerView.mjs +14 -0
- package/src/dia/LinkView.mjs +118 -98
- package/src/dia/Paper.mjs +1441 -620
- package/src/dia/ToolView.mjs +4 -0
- package/src/dia/ToolsView.mjs +14 -5
- package/src/dia/attributes/text.mjs +4 -2
- package/src/dia/index.mjs +6 -1
- package/src/dia/ports.mjs +213 -84
- package/src/dia/symbols.mjs +24 -0
- package/src/elementTools/HoverConnect.mjs +14 -8
- package/src/env/index.mjs +6 -3
- package/src/layout/ports/port.mjs +30 -15
- package/src/layout/ports/portLabel.mjs +1 -1
- package/src/mvc/Collection.mjs +19 -19
- package/src/mvc/Model.mjs +13 -10
- package/src/mvc/View.mjs +4 -0
- package/src/mvc/ViewBase.mjs +1 -1
- package/types/geometry.d.ts +64 -60
- package/types/joint.d.ts +520 -137
- package/types/vectorizer.d.ts +11 -1
package/src/dia/Cell.mjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
uniqueId,
|
|
3
2
|
union,
|
|
4
3
|
result,
|
|
5
4
|
merge,
|
|
@@ -32,7 +31,8 @@ import { Model } from '../mvc/Model.mjs';
|
|
|
32
31
|
import { cloneCells } from '../util/cloneCells.mjs';
|
|
33
32
|
import { attributes } from './attributes/index.mjs';
|
|
34
33
|
import * as g from '../g/index.mjs';
|
|
35
|
-
|
|
34
|
+
import { config } from '../config/index.mjs';
|
|
35
|
+
import { CELL_MARKER } from './symbols.mjs';
|
|
36
36
|
|
|
37
37
|
// Cell base model.
|
|
38
38
|
// --------------------------
|
|
@@ -61,30 +61,21 @@ function removeEmptyAttributes(obj) {
|
|
|
61
61
|
|
|
62
62
|
export const Cell = Model.extend({
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (options && options.parse) attrs = this.parse(attrs, options) || {};
|
|
78
|
-
if ((defaults = result(this, 'defaults'))) {
|
|
79
|
-
//<custom code>
|
|
80
|
-
// Replaced the call to _.defaults with util.merge.
|
|
81
|
-
const customizer = (options && options.mergeArrays === true) ? false : attributesMerger;
|
|
82
|
-
attrs = merge({}, defaults, attrs, customizer);
|
|
83
|
-
//</custom code>
|
|
64
|
+
cidPrefix: 'c',
|
|
65
|
+
|
|
66
|
+
// Default attributes are merged deeply instead of shallowly.
|
|
67
|
+
_setDefaults: function(ctorAttributes, options) {
|
|
68
|
+
let attributes;
|
|
69
|
+
const attributeDefaults = result(this, 'defaults');
|
|
70
|
+
if (attributeDefaults) {
|
|
71
|
+
const customizer = (options && options.mergeArrays === true)
|
|
72
|
+
? false
|
|
73
|
+
: config.cellDefaultsMergeStrategy || attributesMerger;
|
|
74
|
+
attributes = merge({}, attributeDefaults, ctorAttributes, customizer);
|
|
75
|
+
} else {
|
|
76
|
+
attributes = ctorAttributes;
|
|
84
77
|
}
|
|
85
|
-
this.set(
|
|
86
|
-
this.changed = {};
|
|
87
|
-
this.initialize.apply(this, arguments);
|
|
78
|
+
this.set(attributes, options);
|
|
88
79
|
},
|
|
89
80
|
|
|
90
81
|
translate: function(dx, dy, opt) {
|
|
@@ -133,10 +124,10 @@ export const Cell = Model.extend({
|
|
|
133
124
|
return finalAttributes;
|
|
134
125
|
},
|
|
135
126
|
|
|
136
|
-
initialize: function(
|
|
127
|
+
initialize: function(attributes) {
|
|
137
128
|
|
|
138
129
|
const idAttribute = this.getIdAttribute();
|
|
139
|
-
if (!
|
|
130
|
+
if (!attributes || attributes[idAttribute] === undefined) {
|
|
140
131
|
this.set(idAttribute, this.generateId(), { silent: true });
|
|
141
132
|
}
|
|
142
133
|
|
|
@@ -212,42 +203,20 @@ export const Cell = Model.extend({
|
|
|
212
203
|
},
|
|
213
204
|
|
|
214
205
|
remove: function(opt = {}) {
|
|
215
|
-
|
|
216
|
-
// Store the graph in a variable because `this.graph` won't be accessible
|
|
217
|
-
// after `this.trigger('remove', ...)` down below.
|
|
218
206
|
const { graph, collection } = this;
|
|
219
|
-
|
|
207
|
+
// If the cell is part of a graph, remove it using the graph API.
|
|
208
|
+
// To make sure the cell is removed in a batch operation.
|
|
209
|
+
if (graph) {
|
|
210
|
+
graph.removeCell(this, opt);
|
|
211
|
+
} else {
|
|
220
212
|
// The collection is a common mvc collection (not the graph collection).
|
|
221
213
|
if (collection) collection.remove(this, opt);
|
|
222
|
-
return this;
|
|
223
214
|
}
|
|
224
|
-
|
|
225
|
-
graph.startBatch('remove');
|
|
226
|
-
|
|
227
|
-
// First, unembed this cell from its parent cell if there is one.
|
|
228
|
-
const parentCell = this.getParentCell();
|
|
229
|
-
if (parentCell) {
|
|
230
|
-
parentCell.unembed(this, opt);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// Remove also all the cells, which were embedded into this cell
|
|
234
|
-
const embeddedCells = this.getEmbeddedCells();
|
|
235
|
-
for (let i = 0, n = embeddedCells.length; i < n; i++) {
|
|
236
|
-
const embed = embeddedCells[i];
|
|
237
|
-
if (embed) {
|
|
238
|
-
embed.remove(opt);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
this.trigger('remove', this, graph.attributes.cells, opt);
|
|
243
|
-
|
|
244
|
-
graph.stopBatch('remove');
|
|
245
|
-
|
|
246
215
|
return this;
|
|
247
216
|
},
|
|
248
217
|
|
|
249
218
|
toFront: function(opt) {
|
|
250
|
-
|
|
219
|
+
const { graph } = this;
|
|
251
220
|
if (graph) {
|
|
252
221
|
opt = defaults(opt || {}, { foregroundEmbeds: true });
|
|
253
222
|
|
|
@@ -261,12 +230,14 @@ export const Cell = Model.extend({
|
|
|
261
230
|
|
|
262
231
|
const sortedCells = opt.foregroundEmbeds ? cells : sortBy(cells, cell => cell.z());
|
|
263
232
|
|
|
264
|
-
const
|
|
233
|
+
const layerId = graph.getCellLayerId(this);
|
|
234
|
+
|
|
235
|
+
const maxZ = graph.maxZIndex(layerId);
|
|
265
236
|
let z = maxZ - cells.length + 1;
|
|
266
237
|
|
|
267
|
-
const
|
|
238
|
+
const layerCells = graph.getLayer(layerId).cellCollection.toArray();
|
|
268
239
|
|
|
269
|
-
let shouldUpdate = (
|
|
240
|
+
let shouldUpdate = (layerCells.indexOf(sortedCells[0]) !== (layerCells.length - cells.length));
|
|
270
241
|
if (!shouldUpdate) {
|
|
271
242
|
shouldUpdate = sortedCells.some(function(cell, index) {
|
|
272
243
|
return cell.z() !== z + index;
|
|
@@ -290,7 +261,7 @@ export const Cell = Model.extend({
|
|
|
290
261
|
},
|
|
291
262
|
|
|
292
263
|
toBack: function(opt) {
|
|
293
|
-
|
|
264
|
+
const { graph } = this;
|
|
294
265
|
if (graph) {
|
|
295
266
|
opt = defaults(opt || {}, { foregroundEmbeds: true });
|
|
296
267
|
|
|
@@ -304,11 +275,13 @@ export const Cell = Model.extend({
|
|
|
304
275
|
|
|
305
276
|
const sortedCells = opt.foregroundEmbeds ? cells : sortBy(cells, cell => cell.z());
|
|
306
277
|
|
|
307
|
-
|
|
278
|
+
const layerId = graph.getCellLayerId(this);
|
|
308
279
|
|
|
309
|
-
|
|
280
|
+
let z = graph.minZIndex(layerId);
|
|
310
281
|
|
|
311
|
-
|
|
282
|
+
const layerCells = graph.getLayer(layerId).cellCollection.toArray();
|
|
283
|
+
|
|
284
|
+
let shouldUpdate = (layerCells.indexOf(sortedCells[0]) !== 0);
|
|
312
285
|
if (!shouldUpdate) {
|
|
313
286
|
shouldUpdate = sortedCells.some(function(cell, index) {
|
|
314
287
|
return cell.z() !== z + index;
|
|
@@ -543,7 +516,11 @@ export const Cell = Model.extend({
|
|
|
543
516
|
if (!opt.deep) {
|
|
544
517
|
// Shallow cloning.
|
|
545
518
|
|
|
546
|
-
|
|
519
|
+
// Preserve the original's `portLayoutNamespace` and `portLabelLayoutNamespace`.
|
|
520
|
+
const clone = new this.constructor(this.attributes, {
|
|
521
|
+
portLayoutNamespace: this.portLayoutNamespace,
|
|
522
|
+
portLabelLayoutNamespace: this.portLabelLayoutNamespace
|
|
523
|
+
});
|
|
547
524
|
// We don't want the clone to have the same ID as the original.
|
|
548
525
|
clone.set(this.getIdAttribute(), this.generateId());
|
|
549
526
|
// A shallow cloned element does not carry over the original embeds.
|
|
@@ -557,7 +534,7 @@ export const Cell = Model.extend({
|
|
|
557
534
|
} else {
|
|
558
535
|
// Deep cloning.
|
|
559
536
|
|
|
560
|
-
// For a deep clone, simply call `
|
|
537
|
+
// For a deep clone, simply call `util.cloneCells()` with the cell and all its embedded cells.
|
|
561
538
|
return toArray(cloneCells([this].concat(this.getEmbeddedCells({ deep: true }))));
|
|
562
539
|
}
|
|
563
540
|
},
|
|
@@ -630,7 +607,7 @@ export const Cell = Model.extend({
|
|
|
630
607
|
options.rewrite && unsetByPath(baseAttributes, path, '/');
|
|
631
608
|
|
|
632
609
|
// Merge update with the model attributes.
|
|
633
|
-
var attributes = merge(baseAttributes, update);
|
|
610
|
+
var attributes = merge(baseAttributes, update, config.cellMergeStrategy);
|
|
634
611
|
// Finally, set the property to the updated attributes.
|
|
635
612
|
return this.set(property, attributes[property], options);
|
|
636
613
|
|
|
@@ -653,7 +630,11 @@ export const Cell = Model.extend({
|
|
|
653
630
|
const changedAttributes = {};
|
|
654
631
|
for (const key in props) {
|
|
655
632
|
// Merging the values of changed attributes with the current ones.
|
|
656
|
-
const { changedValue } = merge(
|
|
633
|
+
const { changedValue } = merge(
|
|
634
|
+
merge({}, { changedValue: this.attributes[key] }),
|
|
635
|
+
{ changedValue: props[key] },
|
|
636
|
+
config.cellMergeStrategy
|
|
637
|
+
);
|
|
657
638
|
changedAttributes[key] = changedValue;
|
|
658
639
|
}
|
|
659
640
|
|
|
@@ -738,6 +719,7 @@ export const Cell = Model.extend({
|
|
|
738
719
|
|
|
739
720
|
var firstFrameTime = 0;
|
|
740
721
|
var interpolatingFunction;
|
|
722
|
+
const transitionKey = Array.isArray(path) ? path.join(delim) : path;
|
|
741
723
|
|
|
742
724
|
var setter = function(runtime) {
|
|
743
725
|
|
|
@@ -748,10 +730,10 @@ export const Cell = Model.extend({
|
|
|
748
730
|
progress = runtime / opt.duration;
|
|
749
731
|
|
|
750
732
|
if (progress < 1) {
|
|
751
|
-
this._transitionIds[
|
|
733
|
+
this._transitionIds[transitionKey] = id = nextFrame(setter);
|
|
752
734
|
} else {
|
|
753
735
|
progress = 1;
|
|
754
|
-
delete this._transitionIds[
|
|
736
|
+
delete this._transitionIds[transitionKey];
|
|
755
737
|
}
|
|
756
738
|
|
|
757
739
|
propertyValue = interpolatingFunction(opt.timingFunction(progress));
|
|
@@ -760,7 +742,7 @@ export const Cell = Model.extend({
|
|
|
760
742
|
|
|
761
743
|
this.prop(path, propertyValue, opt);
|
|
762
744
|
|
|
763
|
-
if (!id) this.trigger('transition:end', this,
|
|
745
|
+
if (!id) this.trigger('transition:end', this, transitionKey);
|
|
764
746
|
|
|
765
747
|
}.bind(this);
|
|
766
748
|
|
|
@@ -769,10 +751,10 @@ export const Cell = Model.extend({
|
|
|
769
751
|
|
|
770
752
|
var initiator = (callback) => {
|
|
771
753
|
|
|
772
|
-
if (_scheduledTransitionIds[
|
|
773
|
-
_scheduledTransitionIds[
|
|
774
|
-
if (_scheduledTransitionIds[
|
|
775
|
-
delete _scheduledTransitionIds[
|
|
754
|
+
if (_scheduledTransitionIds[transitionKey]) {
|
|
755
|
+
_scheduledTransitionIds[transitionKey] = without(_scheduledTransitionIds[transitionKey], initialId);
|
|
756
|
+
if (_scheduledTransitionIds[transitionKey].length === 0) {
|
|
757
|
+
delete _scheduledTransitionIds[transitionKey];
|
|
776
758
|
}
|
|
777
759
|
}
|
|
778
760
|
|
|
@@ -780,16 +762,16 @@ export const Cell = Model.extend({
|
|
|
780
762
|
|
|
781
763
|
interpolatingFunction = opt.valueFunction(getByPath(this.attributes, path, delim), value);
|
|
782
764
|
|
|
783
|
-
this._transitionIds[
|
|
765
|
+
this._transitionIds[transitionKey] = nextFrame(callback);
|
|
784
766
|
|
|
785
|
-
this.trigger('transition:start', this,
|
|
767
|
+
this.trigger('transition:start', this, transitionKey);
|
|
786
768
|
|
|
787
769
|
};
|
|
788
770
|
|
|
789
771
|
initialId = setTimeout(initiator, opt.delay, setter);
|
|
790
772
|
|
|
791
|
-
_scheduledTransitionIds[
|
|
792
|
-
_scheduledTransitionIds[
|
|
773
|
+
_scheduledTransitionIds[transitionKey] || (_scheduledTransitionIds[transitionKey] = []);
|
|
774
|
+
_scheduledTransitionIds[transitionKey].push(initialId);
|
|
793
775
|
|
|
794
776
|
return initialId;
|
|
795
777
|
},
|
|
@@ -805,7 +787,8 @@ export const Cell = Model.extend({
|
|
|
805
787
|
const { _scheduledTransitionIds = {}} = this;
|
|
806
788
|
let transitions = Object.keys(_scheduledTransitionIds);
|
|
807
789
|
if (path) {
|
|
808
|
-
|
|
790
|
+
// Ensure all path segments are strings for `isEqual` comparison, since it strictly compares values
|
|
791
|
+
const pathArray = Array.isArray(path) ? path.map(item => String(item)) : path.split(delim);
|
|
809
792
|
transitions = transitions.filter((key) => {
|
|
810
793
|
return isEqual(pathArray, key.split(delim).slice(0, pathArray.length));
|
|
811
794
|
});
|
|
@@ -824,7 +807,8 @@ export const Cell = Model.extend({
|
|
|
824
807
|
const { _transitionIds = {}} = this;
|
|
825
808
|
let transitions = Object.keys(_transitionIds);
|
|
826
809
|
if (path) {
|
|
827
|
-
|
|
810
|
+
// Ensure all path segments are strings for `isEqual` comparison, since it strictly compares values
|
|
811
|
+
const pathArray = Array.isArray(path) ? path.map(item => String(item)) : path.split(delim);
|
|
828
812
|
transitions = transitions.filter((key) => {
|
|
829
813
|
return isEqual(pathArray, key.split(delim).slice(0, pathArray.length));
|
|
830
814
|
});
|
|
@@ -844,7 +828,7 @@ export const Cell = Model.extend({
|
|
|
844
828
|
return this;
|
|
845
829
|
},
|
|
846
830
|
|
|
847
|
-
// A
|
|
831
|
+
// A shortcut making it easy to create constructs like the following:
|
|
848
832
|
// `var el = (new joint.shapes.standard.Rectangle()).addTo(graph)`.
|
|
849
833
|
addTo: function(graph, opt) {
|
|
850
834
|
|
|
@@ -946,15 +930,41 @@ export const Cell = Model.extend({
|
|
|
946
930
|
.getPointRotatedAroundCenter(this.angle(), x, y)
|
|
947
931
|
// Transform the absolute position into relative
|
|
948
932
|
.difference(this.position());
|
|
933
|
+
},
|
|
934
|
+
|
|
935
|
+
layer: function(layerId, opt) {
|
|
936
|
+
const layerAttribute = config.layerAttribute;
|
|
937
|
+
|
|
938
|
+
// Getter:
|
|
939
|
+
|
|
940
|
+
// If `undefined` return the current layer ID
|
|
941
|
+
if (layerId === undefined) {
|
|
942
|
+
return this.get(layerAttribute) || null;
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
// Setter:
|
|
946
|
+
|
|
947
|
+
// If strictly `null` unset the layer
|
|
948
|
+
if (layerId === null) {
|
|
949
|
+
return this.unset(layerAttribute, opt);
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
// Otherwise set the layer ID
|
|
953
|
+
if (!isString(layerId)) {
|
|
954
|
+
throw new Error('dia.Cell: Layer id must be a string.');
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
return this.set(layerAttribute, layerId, opt);
|
|
949
958
|
}
|
|
950
959
|
|
|
951
960
|
}, {
|
|
952
961
|
|
|
953
962
|
getAttributeDefinition: function(attrName) {
|
|
954
963
|
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
964
|
+
const defNS = this.attributes;
|
|
965
|
+
const globalDefNS = attributes;
|
|
966
|
+
const definition = (defNS && defNS[attrName]) || globalDefNS[attrName];
|
|
967
|
+
return definition !== undefined ? definition : null;
|
|
958
968
|
},
|
|
959
969
|
|
|
960
970
|
define: function(type, defaults, protoProps, staticProps) {
|
|
@@ -974,3 +984,6 @@ export const Cell = Model.extend({
|
|
|
974
984
|
}
|
|
975
985
|
});
|
|
976
986
|
|
|
987
|
+
Object.defineProperty(Cell.prototype, CELL_MARKER, {
|
|
988
|
+
value: true,
|
|
989
|
+
});
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import * as util from '../util/index.mjs';
|
|
2
|
+
import { Collection } from '../mvc/Collection.mjs';
|
|
3
|
+
import { CELL_MARKER, CELL_COLLECTION_MARKER } from './symbols.mjs';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @class CellCollection
|
|
7
|
+
* @description A CellCollection is a collection of cells which supports z-index management.
|
|
8
|
+
* Additionally, it facilitates creating cell models from JSON using cellNamespace
|
|
9
|
+
* and stores a reference to the graph when the cell model has been added.
|
|
10
|
+
*/
|
|
11
|
+
export class CellCollection extends Collection {
|
|
12
|
+
|
|
13
|
+
[CELL_COLLECTION_MARKER] = true;
|
|
14
|
+
|
|
15
|
+
initialize(_models, opt) {
|
|
16
|
+
this.layer = opt.layer;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Method for checking whether an object should be considered a model for
|
|
20
|
+
// the purposes of adding to the collection.
|
|
21
|
+
_isModel(model) {
|
|
22
|
+
return Boolean(model[CELL_MARKER]);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Overriding the default `model` method to create cell models
|
|
26
|
+
// based on their `type` attribute and the `cellNamespace` option.
|
|
27
|
+
model(attrs, opt) {
|
|
28
|
+
|
|
29
|
+
const namespace = this.cellNamespace;
|
|
30
|
+
|
|
31
|
+
if (!namespace) {
|
|
32
|
+
throw new Error('dia.CellCollection: cellNamespace is required to instantiate a Cell from JSON.');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const { type } = attrs;
|
|
36
|
+
|
|
37
|
+
// Find the model class based on the `type` attribute in the cell namespace
|
|
38
|
+
const ModelClass = util.getByPath(namespace, type, '.');
|
|
39
|
+
if (!ModelClass) {
|
|
40
|
+
throw new Error(`dia.Graph: Could not find cell constructor for type: '${type}'. Make sure to add the constructor to 'cellNamespace'.`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return new ModelClass(attrs, opt);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Override to set graph reference
|
|
47
|
+
_addReference(model, options) {
|
|
48
|
+
super._addReference(model, options);
|
|
49
|
+
|
|
50
|
+
// If not in `dry` mode and the model does not have a graph reference yet,
|
|
51
|
+
// set the reference.
|
|
52
|
+
if (!options.dry && !model.graph) {
|
|
53
|
+
model.graph = this.layer.graph;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Override to remove graph reference
|
|
58
|
+
_removeReference(model, options) {
|
|
59
|
+
super._removeReference(model, options);
|
|
60
|
+
|
|
61
|
+
// If not in `dry` mode and the model has a reference to this exact graph,
|
|
62
|
+
// remove the reference.
|
|
63
|
+
// Note: graph reference is removed from the layer after the `remove` event is fired.
|
|
64
|
+
// Due to this, event handlers can still access the graph during the `remove` event.
|
|
65
|
+
if (!options.dry && model.graph === this.layer.graph) {
|
|
66
|
+
model.graph = null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// remove graph reference additionally
|
|
71
|
+
_removeReferenceFast(model, options) {
|
|
72
|
+
model.off('all', this._onModelEvent, this);
|
|
73
|
+
|
|
74
|
+
if (!options.dry) {
|
|
75
|
+
// If not in `dry` mode and the model has a reference
|
|
76
|
+
// to this exact graph/collection, remove the reference.
|
|
77
|
+
if (this === model.collection) {
|
|
78
|
+
delete model.collection;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (model.graph === this.layer.graph) {
|
|
82
|
+
model.graph = null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// `comparator` makes it easy to sort cells based on their `z` index.
|
|
88
|
+
comparator(model) {
|
|
89
|
+
return model.get('z') || 0;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// This method overrides base mvc.Collection implementation
|
|
93
|
+
// in a way that improves performance of resetting large collections.
|
|
94
|
+
// For layers specifically, there is an option where we put references
|
|
95
|
+
// from the main collection in order to improve performance when
|
|
96
|
+
// there is only one layer
|
|
97
|
+
reset(models, options) {
|
|
98
|
+
options = util.assign({}, { add: true, remove: false, merge: false }, options);
|
|
99
|
+
|
|
100
|
+
for (let i = 0; i < this.models.length; i++) {
|
|
101
|
+
this._removeReferenceFast(this.models[i], options);
|
|
102
|
+
}
|
|
103
|
+
options.previousModels = this.models;
|
|
104
|
+
this._reset();
|
|
105
|
+
|
|
106
|
+
for (let i = 0; i < models.length; i++) {
|
|
107
|
+
const model = this._prepareModel(models[i], options);
|
|
108
|
+
if (model) {
|
|
109
|
+
this.models.push(model);
|
|
110
|
+
this._addReference(model, options);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
this.length = this.models.length;
|
|
115
|
+
|
|
116
|
+
const sort = this.comparator && options.sort !== false;
|
|
117
|
+
|
|
118
|
+
if (sort) {
|
|
119
|
+
this.sort({ silent: true });
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (!options.silent) {
|
|
123
|
+
this.trigger('reset', this, options);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return this.models;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
minZIndex() {
|
|
130
|
+
return (this.first()?.get('z') || 0);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
maxZIndex() {
|
|
134
|
+
return (this.last()?.get('z') || 0);
|
|
135
|
+
}
|
|
136
|
+
}
|
package/src/dia/CellView.mjs
CHANGED
|
@@ -21,6 +21,7 @@ import V from '../V/index.mjs';
|
|
|
21
21
|
import $ from '../mvc/Dom/index.mjs';
|
|
22
22
|
import { HighlighterView } from './HighlighterView.mjs';
|
|
23
23
|
import { evalAttributes, evalAttribute } from './attributes/eval.mjs';
|
|
24
|
+
import { CELL_VIEW_MARKER } from './symbols.mjs';
|
|
24
25
|
|
|
25
26
|
const HighlightingTypes = {
|
|
26
27
|
DEFAULT: 'default',
|
|
@@ -1393,4 +1394,9 @@ Object.defineProperty(CellView.prototype, 'useCSSSelectors', {
|
|
|
1393
1394
|
}
|
|
1394
1395
|
});
|
|
1395
1396
|
|
|
1397
|
+
// Internal tag to identify this object as a cell view instance.
|
|
1398
|
+
// Used instead of `instanceof` for performance and cross-frame safety.
|
|
1396
1399
|
|
|
1400
|
+
Object.defineProperty(CellView.prototype, CELL_VIEW_MARKER, {
|
|
1401
|
+
value: true,
|
|
1402
|
+
});
|
package/src/dia/Element.mjs
CHANGED
|
@@ -14,9 +14,8 @@ export const Element = Cell.extend({
|
|
|
14
14
|
angle: 0
|
|
15
15
|
},
|
|
16
16
|
|
|
17
|
-
initialize: function() {
|
|
18
|
-
|
|
19
|
-
this._initializePorts();
|
|
17
|
+
initialize: function(attributes, options) {
|
|
18
|
+
this._initializePorts(options);
|
|
20
19
|
Cell.prototype.initialize.apply(this, arguments);
|
|
21
20
|
},
|
|
22
21
|
|
|
@@ -421,8 +420,10 @@ export const Element = Cell.extend({
|
|
|
421
420
|
|
|
422
421
|
let minBBox = null;
|
|
423
422
|
if (opt.minRect) {
|
|
424
|
-
// Coerce `opt.minRect` to g.Rect
|
|
425
|
-
|
|
423
|
+
// Coerce `opt.minRect` to g.Rect
|
|
424
|
+
// (missing properties are taken from this element's current bbox).
|
|
425
|
+
const minRect = assign(this.getBBox(), opt.minRect);
|
|
426
|
+
minBBox = new Rect(minRect);
|
|
426
427
|
}
|
|
427
428
|
|
|
428
429
|
const elementsBBox = this.graph.getCellsBBox(opt.elements);
|
package/src/dia/ElementView.mjs
CHANGED
|
@@ -389,7 +389,8 @@ export const ElementView = CellView.extend({
|
|
|
389
389
|
parent.unembed(element, { ui: true });
|
|
390
390
|
data.initialParentId = parentId;
|
|
391
391
|
} else {
|
|
392
|
-
data.initialParentId
|
|
392
|
+
// `data.initialParentId` can be explicitly set to a dummy value to enable validation of unembedding.
|
|
393
|
+
data.initialParentId = data.initialParentId || null;
|
|
393
394
|
}
|
|
394
395
|
},
|
|
395
396
|
|