@joint/core 4.2.0-alpha.0 → 4.2.0-alpha.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 -2
- package/dist/joint.d.ts +280 -149
- package/dist/joint.js +1427 -475
- package/dist/joint.min.js +4 -3
- package/dist/joint.nowrap.js +1427 -475
- package/dist/joint.nowrap.min.js +4 -3
- package/dist/vectorizer.js +21 -8
- package/dist/vectorizer.min.js +4 -3
- package/dist/version.mjs +1 -1
- package/package.json +7 -7
- 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 +8 -0
- package/src/dia/Cell.mjs +26 -10
- package/src/dia/CellView.mjs +7 -0
- package/src/dia/Element.mjs +4 -2
- package/src/dia/ElementView.mjs +2 -1
- package/src/dia/HighlighterView.mjs +22 -0
- package/src/dia/LinkView.mjs +118 -98
- package/src/dia/Paper.mjs +697 -209
- package/src/dia/ToolView.mjs +4 -0
- package/src/dia/ToolsView.mjs +12 -3
- package/src/dia/attributes/text.mjs +4 -2
- package/src/dia/ports.mjs +202 -82
- 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/View.mjs +4 -0
- package/src/mvc/ViewBase.mjs +1 -1
- package/types/geometry.d.ts +64 -60
- package/types/joint.d.ts +205 -88
- package/types/vectorizer.d.ts +11 -1
package/dist/joint.nowrap.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
/*! JointJS v4.2.0-alpha.
|
|
2
|
-
|
|
1
|
+
/*! JointJS v4.2.0-alpha.1 (2025-09-25) - JavaScript diagramming library
|
|
3
2
|
|
|
4
3
|
This Source Code Form is subject to the terms of the Mozilla Public
|
|
5
4
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
6
5
|
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
7
6
|
*/
|
|
7
|
+
|
|
8
8
|
var joint = (function (exports) {
|
|
9
9
|
'use strict';
|
|
10
10
|
|
|
@@ -9859,8 +9859,11 @@ var joint = (function (exports) {
|
|
|
9859
9859
|
});
|
|
9860
9860
|
|
|
9861
9861
|
/**
|
|
9862
|
-
*
|
|
9863
|
-
* @
|
|
9862
|
+
* Calculates the transformation matrix from this element to the target element.
|
|
9863
|
+
* @param {SVGElement|V} target - The target element.
|
|
9864
|
+
* @param {Object} [opt] - Options object for transformation calculation.
|
|
9865
|
+
* @param {boolean} [opt.safe] - Use a safe traversal method to compute the matrix.
|
|
9866
|
+
* @returns {DOMMatrix} The transformation matrix from this element to the target element.
|
|
9864
9867
|
*/
|
|
9865
9868
|
VPrototype.getTransformToElement = function (target, opt) {
|
|
9866
9869
|
const node = this.node;
|
|
@@ -10193,11 +10196,18 @@ var joint = (function (exports) {
|
|
|
10193
10196
|
}
|
|
10194
10197
|
VPrototype.text = function (content, opt) {
|
|
10195
10198
|
if (content && typeof content !== 'string') throw new Error('Vectorizer: text() expects the first argument to be a string.');
|
|
10196
|
-
|
|
10197
|
-
// Replace all spaces with the Unicode No-break space (http://www.fileformat.info/info/unicode/char/a0/index.htm).
|
|
10198
|
-
// IE would otherwise collapse all spaces into one.
|
|
10199
|
-
content = V.sanitizeText(content);
|
|
10200
10199
|
opt || (opt = {});
|
|
10200
|
+
|
|
10201
|
+
// Backwards-compatibility: if no content was provided, treat it as an
|
|
10202
|
+
// empty string so that subsequent string operations (e.g. split) do
|
|
10203
|
+
// not throw and behaviour matches the previous implementation that
|
|
10204
|
+
// always sanitised the input.
|
|
10205
|
+
if (content == null) content = '';
|
|
10206
|
+
if (opt.useNoBreakSpace) {
|
|
10207
|
+
// Replace all spaces with the Unicode No-break space (http://www.fileformat.info/info/unicode/char/a0/index.htm).
|
|
10208
|
+
// IE would otherwise collapse all spaces into one.
|
|
10209
|
+
content = V.sanitizeText(content);
|
|
10210
|
+
}
|
|
10201
10211
|
// Should we allow the text to be selected?
|
|
10202
10212
|
var displayEmpty = opt.displayEmpty;
|
|
10203
10213
|
// End of Line character
|
|
@@ -10940,6 +10950,9 @@ var joint = (function (exports) {
|
|
|
10940
10950
|
// also exposed so that the programmer can use it in case he needs to. This is useful e.g. in tests
|
|
10941
10951
|
// when you want to compare the actual DOM text content without having to add the unicode character in
|
|
10942
10952
|
// the place of all spaces.
|
|
10953
|
+
/**
|
|
10954
|
+
* @deprecated Use regular spaces and rely on xml:space="preserve" instead.
|
|
10955
|
+
*/
|
|
10943
10956
|
V.sanitizeText = function (text) {
|
|
10944
10957
|
return (text || '').replace(/ /g, '\u00A0');
|
|
10945
10958
|
};
|
|
@@ -12487,6 +12500,14 @@ var joint = (function (exports) {
|
|
|
12487
12500
|
});
|
|
12488
12501
|
|
|
12489
12502
|
const config$3 = {
|
|
12503
|
+
// How the cell attributes are merged when `cell.prop()` is called.
|
|
12504
|
+
// DEFAULT: the arrays are merged into the source array.
|
|
12505
|
+
cellMergeStrategy: null,
|
|
12506
|
+
// How the cell default attributes are merged with the attributes provided
|
|
12507
|
+
// in the cell constructor.
|
|
12508
|
+
// DEFAULT: the arrays are merged by replacing the source array
|
|
12509
|
+
// with the destination array.
|
|
12510
|
+
cellDefaultsMergeStrategy: null,
|
|
12490
12511
|
// When set to `true` the cell selectors could be defined as CSS selectors.
|
|
12491
12512
|
// If not, only JSON Markup selectors are taken into account.
|
|
12492
12513
|
useCSSSelectors: false,
|
|
@@ -15031,9 +15052,10 @@ var joint = (function (exports) {
|
|
|
15031
15052
|
const eol = attrs.eol;
|
|
15032
15053
|
const x = attrs.x;
|
|
15033
15054
|
let textPath = attrs['text-path'];
|
|
15055
|
+
const useNoBreakSpace = attrs['use-no-break-space'] === true;
|
|
15034
15056
|
// Update the text only if there was a change in the string
|
|
15035
15057
|
// or any of its attributes.
|
|
15036
|
-
const textHash = JSON.stringify([text, lineHeight, annotations, textVerticalAnchor, eol, displayEmpty, textPath, x, fontSize]);
|
|
15058
|
+
const textHash = JSON.stringify([text, lineHeight, annotations, textVerticalAnchor, eol, displayEmpty, textPath, x, fontSize, useNoBreakSpace]);
|
|
15037
15059
|
if (cache === undefined || cache !== textHash) {
|
|
15038
15060
|
// Chrome bug:
|
|
15039
15061
|
// <tspan> positions defined as `em` are not updated
|
|
@@ -15058,7 +15080,8 @@ var joint = (function (exports) {
|
|
|
15058
15080
|
x,
|
|
15059
15081
|
textVerticalAnchor,
|
|
15060
15082
|
eol,
|
|
15061
|
-
displayEmpty
|
|
15083
|
+
displayEmpty,
|
|
15084
|
+
useNoBreakSpace
|
|
15062
15085
|
});
|
|
15063
15086
|
$.data.set(node, cacheName, textHash);
|
|
15064
15087
|
}
|
|
@@ -15574,12 +15597,18 @@ var joint = (function (exports) {
|
|
|
15574
15597
|
if (defaults = result(this, 'defaults')) {
|
|
15575
15598
|
//<custom code>
|
|
15576
15599
|
// Replaced the call to _.defaults with util.merge.
|
|
15577
|
-
const customizer = options && options.mergeArrays === true ? false : attributesMerger;
|
|
15600
|
+
const customizer = options && options.mergeArrays === true ? false : config$3.cellDefaultsMergeStrategy || attributesMerger;
|
|
15578
15601
|
attrs = merge({}, defaults, attrs, customizer);
|
|
15579
15602
|
//</custom code>
|
|
15580
15603
|
}
|
|
15581
15604
|
this.set(attrs, options);
|
|
15582
15605
|
this.changed = {};
|
|
15606
|
+
if (options && options.portLayoutNamespace) {
|
|
15607
|
+
this.portLayoutNamespace = options.portLayoutNamespace;
|
|
15608
|
+
}
|
|
15609
|
+
if (options && options.portLabelLayoutNamespace) {
|
|
15610
|
+
this.portLabelLayoutNamespace = options.portLabelLayoutNamespace;
|
|
15611
|
+
}
|
|
15583
15612
|
this.initialize.apply(this, arguments);
|
|
15584
15613
|
},
|
|
15585
15614
|
translate: function (dx, dy, opt) {
|
|
@@ -15973,7 +16002,11 @@ var joint = (function (exports) {
|
|
|
15973
16002
|
if (!opt.deep) {
|
|
15974
16003
|
// Shallow cloning.
|
|
15975
16004
|
|
|
15976
|
-
|
|
16005
|
+
// Preserve the original's `portLayoutNamespace` and `portLabelLayoutNamespace`.
|
|
16006
|
+
const clone = new this.constructor(this.attributes, {
|
|
16007
|
+
portLayoutNamespace: this.portLayoutNamespace,
|
|
16008
|
+
portLabelLayoutNamespace: this.portLabelLayoutNamespace
|
|
16009
|
+
});
|
|
15977
16010
|
// We don't want the clone to have the same ID as the original.
|
|
15978
16011
|
clone.set(this.getIdAttribute(), this.generateId());
|
|
15979
16012
|
// A shallow cloned element does not carry over the original embeds.
|
|
@@ -15985,7 +16018,7 @@ var joint = (function (exports) {
|
|
|
15985
16018
|
} else {
|
|
15986
16019
|
// Deep cloning.
|
|
15987
16020
|
|
|
15988
|
-
// For a deep clone, simply call `
|
|
16021
|
+
// For a deep clone, simply call `util.cloneCells()` with the cell and all its embedded cells.
|
|
15989
16022
|
return toArray$1(cloneCells([this].concat(this.getEmbeddedCells({
|
|
15990
16023
|
deep: true
|
|
15991
16024
|
}))));
|
|
@@ -16050,7 +16083,7 @@ var joint = (function (exports) {
|
|
|
16050
16083
|
options.rewrite && unsetByPath(baseAttributes, path, '/');
|
|
16051
16084
|
|
|
16052
16085
|
// Merge update with the model attributes.
|
|
16053
|
-
var attributes = merge(baseAttributes, update);
|
|
16086
|
+
var attributes = merge(baseAttributes, update, config$3.cellMergeStrategy);
|
|
16054
16087
|
// Finally, set the property to the updated attributes.
|
|
16055
16088
|
return this.set(property, attributes[property], options);
|
|
16056
16089
|
} else {
|
|
@@ -16072,11 +16105,11 @@ var joint = (function (exports) {
|
|
|
16072
16105
|
// Merging the values of changed attributes with the current ones.
|
|
16073
16106
|
const {
|
|
16074
16107
|
changedValue
|
|
16075
|
-
} = merge({}, {
|
|
16108
|
+
} = merge(merge({}, {
|
|
16076
16109
|
changedValue: this.attributes[key]
|
|
16077
|
-
}, {
|
|
16110
|
+
}), {
|
|
16078
16111
|
changedValue: props[key]
|
|
16079
|
-
});
|
|
16112
|
+
}, config$3.cellMergeStrategy);
|
|
16080
16113
|
changedAttributes[key] = changedValue;
|
|
16081
16114
|
}
|
|
16082
16115
|
return this.set(changedAttributes, options);
|
|
@@ -16310,9 +16343,10 @@ var joint = (function (exports) {
|
|
|
16310
16343
|
}
|
|
16311
16344
|
}, {
|
|
16312
16345
|
getAttributeDefinition: function (attrName) {
|
|
16313
|
-
|
|
16314
|
-
|
|
16315
|
-
|
|
16346
|
+
const defNS = this.attributes;
|
|
16347
|
+
const globalDefNS = attributes;
|
|
16348
|
+
const definition = defNS && defNS[attrName] || globalDefNS[attrName];
|
|
16349
|
+
return definition !== undefined ? definition : null;
|
|
16316
16350
|
},
|
|
16317
16351
|
define: function (type, defaults, protoProps, staticProps) {
|
|
16318
16352
|
protoProps = assign({
|
|
@@ -16618,6 +16652,22 @@ var joint = (function (exports) {
|
|
|
16618
16652
|
wrappers: wrappers
|
|
16619
16653
|
};
|
|
16620
16654
|
|
|
16655
|
+
function parseCoordinate(coordinate, dimension, bbox, value) {
|
|
16656
|
+
if (isPercentage(value)) {
|
|
16657
|
+
return parseFloat(value) / 100 * bbox[dimension];
|
|
16658
|
+
}
|
|
16659
|
+
if (isCalcExpression(value)) {
|
|
16660
|
+
return Number(evalCalcExpression(value, bbox));
|
|
16661
|
+
}
|
|
16662
|
+
if (typeof value === 'string') {
|
|
16663
|
+
const num = Number(value);
|
|
16664
|
+
if (isNaN(num)) {
|
|
16665
|
+
throw new TypeError(`Cannot convert port coordinate ${coordinate}: "${value}" to a number`);
|
|
16666
|
+
}
|
|
16667
|
+
return num;
|
|
16668
|
+
}
|
|
16669
|
+
return value;
|
|
16670
|
+
}
|
|
16621
16671
|
function portTransformAttrs(point, angle, opt) {
|
|
16622
16672
|
var trans = point.toJSON();
|
|
16623
16673
|
trans.angle = angle || 0;
|
|
@@ -16661,19 +16711,9 @@ var joint = (function (exports) {
|
|
|
16661
16711
|
y,
|
|
16662
16712
|
angle
|
|
16663
16713
|
} = args;
|
|
16664
|
-
if (isPercentage(x)) {
|
|
16665
|
-
x = parseFloat(x) / 100 * bbox.width;
|
|
16666
|
-
} else if (isCalcExpression(x)) {
|
|
16667
|
-
x = Number(evalCalcExpression(x, bbox));
|
|
16668
|
-
}
|
|
16669
|
-
if (isPercentage(y)) {
|
|
16670
|
-
y = parseFloat(y) / 100 * bbox.height;
|
|
16671
|
-
} else if (isCalcExpression(y)) {
|
|
16672
|
-
y = Number(evalCalcExpression(y, bbox));
|
|
16673
|
-
}
|
|
16674
16714
|
return {
|
|
16675
|
-
x,
|
|
16676
|
-
y,
|
|
16715
|
+
x: parseCoordinate('x', 'width', bbox, x),
|
|
16716
|
+
y: parseCoordinate('y', 'height', bbox, y),
|
|
16677
16717
|
angle
|
|
16678
16718
|
};
|
|
16679
16719
|
}
|
|
@@ -16693,7 +16733,7 @@ var joint = (function (exports) {
|
|
|
16693
16733
|
* @param {Object=} opt opt Group options
|
|
16694
16734
|
* @returns {Array<g.Point>}
|
|
16695
16735
|
*/
|
|
16696
|
-
const absolute = function (ports, elBBox) {
|
|
16736
|
+
const absolute = function (ports, elBBox, opt) {
|
|
16697
16737
|
return ports.map(port => {
|
|
16698
16738
|
const transformation = argPoint(elBBox, port).round().toJSON();
|
|
16699
16739
|
transformation.angle = port.angle || 0;
|
|
@@ -16702,6 +16742,7 @@ var joint = (function (exports) {
|
|
|
16702
16742
|
};
|
|
16703
16743
|
|
|
16704
16744
|
/**
|
|
16745
|
+
* @deprecated
|
|
16705
16746
|
* @param {Array<Object>} ports
|
|
16706
16747
|
* @param {g.Rect} elBBox
|
|
16707
16748
|
* @param {Object=} opt opt Group options
|
|
@@ -16966,7 +17007,7 @@ var joint = (function (exports) {
|
|
|
16966
17007
|
}
|
|
16967
17008
|
});
|
|
16968
17009
|
}
|
|
16969
|
-
const manual = function (
|
|
17010
|
+
const manual = function (portPosition, elBBox, opt) {
|
|
16970
17011
|
return labelAttributes(opt);
|
|
16971
17012
|
};
|
|
16972
17013
|
const left$1 = function (portPosition, elBBox, opt) {
|
|
@@ -17047,13 +17088,20 @@ var joint = (function (exports) {
|
|
|
17047
17088
|
top: top$1
|
|
17048
17089
|
};
|
|
17049
17090
|
|
|
17050
|
-
|
|
17051
|
-
|
|
17091
|
+
const DEFAULT_PORT_POSITION_NAME = 'left';
|
|
17092
|
+
const DEFAULT_ABSOLUTE_PORT_POSITION_NAME = 'absolute';
|
|
17093
|
+
const DEFAULT_PORT_LABEL_POSITION_NAME = 'left';
|
|
17094
|
+
const PortData = function (model) {
|
|
17095
|
+
const {
|
|
17096
|
+
portLayoutNamespace = Port,
|
|
17097
|
+
portLabelLayoutNamespace = PortLabel
|
|
17098
|
+
} = model;
|
|
17099
|
+
const clonedData = cloneDeep(model.get('ports')) || {};
|
|
17052
17100
|
this.ports = [];
|
|
17053
17101
|
this.portsMap = {};
|
|
17054
17102
|
this.groups = {};
|
|
17055
|
-
this.portLayoutNamespace =
|
|
17056
|
-
this.portLabelLayoutNamespace =
|
|
17103
|
+
this.portLayoutNamespace = portLayoutNamespace;
|
|
17104
|
+
this.portLabelLayoutNamespace = portLabelLayoutNamespace;
|
|
17057
17105
|
this.metrics = {};
|
|
17058
17106
|
this.metricsKey = null;
|
|
17059
17107
|
this._init(clonedData);
|
|
@@ -17078,6 +17126,8 @@ var joint = (function (exports) {
|
|
|
17078
17126
|
return port.group === groupName;
|
|
17079
17127
|
});
|
|
17080
17128
|
},
|
|
17129
|
+
// Calculate SVG transformations based on evaluated group + port data
|
|
17130
|
+
// NOTE: This function is also called for ports without a group (groupName = undefined)
|
|
17081
17131
|
getGroupPortsMetrics: function (groupName, rect) {
|
|
17082
17132
|
const {
|
|
17083
17133
|
x = 0,
|
|
@@ -17096,29 +17146,36 @@ var joint = (function (exports) {
|
|
|
17096
17146
|
// Return cached metrics
|
|
17097
17147
|
return groupPortsMetrics;
|
|
17098
17148
|
}
|
|
17149
|
+
|
|
17099
17150
|
// Calculate the metrics
|
|
17100
17151
|
groupPortsMetrics = this.resolveGroupPortsMetrics(groupName, new Rect(x, y, width, height));
|
|
17101
17152
|
this.metrics[groupName] = groupPortsMetrics;
|
|
17102
17153
|
return groupPortsMetrics;
|
|
17103
17154
|
},
|
|
17104
17155
|
resolveGroupPortsMetrics: function (groupName, elBBox) {
|
|
17105
|
-
|
|
17106
|
-
|
|
17107
|
-
|
|
17108
|
-
|
|
17109
|
-
|
|
17110
|
-
if (!namespace[groupPositionName]) {
|
|
17111
|
-
groupPositionName = 'left';
|
|
17112
|
-
}
|
|
17113
|
-
var groupArgs = groupPosition.args || {};
|
|
17114
|
-
var portsArgs = ports.map(function (port) {
|
|
17156
|
+
// `groupName` of `undefined` (= not a string) means "the group of ports which do not have the `group` property".
|
|
17157
|
+
const isNoGroup = groupName === undefined;
|
|
17158
|
+
const group = this.getGroup(groupName);
|
|
17159
|
+
const ports = this.getPortsByGroup(groupName);
|
|
17160
|
+
const portsArgs = ports.map(function (port) {
|
|
17115
17161
|
return port && port.position && port.position.args;
|
|
17116
17162
|
});
|
|
17117
|
-
|
|
17118
|
-
|
|
17163
|
+
|
|
17164
|
+
// Get an array of transformations of individual ports according to the group's port layout function:
|
|
17165
|
+
let groupPortTransformations;
|
|
17166
|
+
if (isNoGroup) {
|
|
17167
|
+
// Apply default port layout function to the set of ports without `group` property.
|
|
17168
|
+
const noGroup = this._evaluateGroup({});
|
|
17169
|
+
groupPortTransformations = this._getGroupPortTransformations(noGroup, portsArgs, elBBox);
|
|
17170
|
+
} else {
|
|
17171
|
+
groupPortTransformations = this._getGroupPortTransformations(group, portsArgs, elBBox);
|
|
17172
|
+
}
|
|
17173
|
+
let accumulator = {
|
|
17119
17174
|
ports: ports,
|
|
17120
17175
|
result: {}
|
|
17121
17176
|
};
|
|
17177
|
+
|
|
17178
|
+
// For each individual port transformation, find the information necessary to calculate SVG transformations:
|
|
17122
17179
|
toArray$1(groupPortTransformations).reduce((res, portTransformation, index) => {
|
|
17123
17180
|
const port = res.ports[index];
|
|
17124
17181
|
const portId = port.id;
|
|
@@ -17126,7 +17183,7 @@ var joint = (function (exports) {
|
|
|
17126
17183
|
index,
|
|
17127
17184
|
portId,
|
|
17128
17185
|
portTransformation: portTransformation,
|
|
17129
|
-
labelTransformation: this.
|
|
17186
|
+
labelTransformation: this._getPortLabelTransformation(port, Point(portTransformation), elBBox),
|
|
17130
17187
|
portAttrs: port.attrs,
|
|
17131
17188
|
portSize: port.size,
|
|
17132
17189
|
labelSize: port.label.size
|
|
@@ -17135,16 +17192,24 @@ var joint = (function (exports) {
|
|
|
17135
17192
|
}, accumulator);
|
|
17136
17193
|
return accumulator.result;
|
|
17137
17194
|
},
|
|
17138
|
-
|
|
17139
|
-
|
|
17140
|
-
|
|
17141
|
-
|
|
17142
|
-
|
|
17195
|
+
_getGroupPortTransformations: function (group, portsArgs, elBBox) {
|
|
17196
|
+
const groupPosition = group.position || {};
|
|
17197
|
+
const groupPositionArgs = groupPosition.args || {};
|
|
17198
|
+
const groupPositionLayoutCallback = groupPosition.layoutCallback;
|
|
17199
|
+
return groupPositionLayoutCallback(portsArgs, elBBox, groupPositionArgs);
|
|
17200
|
+
},
|
|
17201
|
+
_getPortLabelTransformation: function (port, portPosition, elBBox) {
|
|
17202
|
+
const portLabelPosition = port.label.position || {};
|
|
17203
|
+
const portLabelPositionArgs = portLabelPosition.args || {};
|
|
17204
|
+
const portLabelPositionLayoutCallback = portLabelPosition.layoutCallback;
|
|
17205
|
+
if (portLabelPositionLayoutCallback) {
|
|
17206
|
+
return portLabelPositionLayoutCallback(portPosition, elBBox, portLabelPositionArgs);
|
|
17143
17207
|
}
|
|
17144
17208
|
return null;
|
|
17145
17209
|
},
|
|
17146
17210
|
_init: function (data) {
|
|
17147
|
-
//
|
|
17211
|
+
// Prepare groups:
|
|
17212
|
+
// NOTE: This overwrites passed group properties with evaluated group properties.
|
|
17148
17213
|
if (isObject(data.groups)) {
|
|
17149
17214
|
var groups = Object.keys(data.groups);
|
|
17150
17215
|
for (var i = 0, n = groups.length; i < n; i++) {
|
|
@@ -17153,7 +17218,8 @@ var joint = (function (exports) {
|
|
|
17153
17218
|
}
|
|
17154
17219
|
}
|
|
17155
17220
|
|
|
17156
|
-
//
|
|
17221
|
+
// Prepare ports:
|
|
17222
|
+
// NOTE: This overwrites passed port properties with evaluated port properties, plus mixed-in evaluated group properties (see above).
|
|
17157
17223
|
var ports = toArray$1(data.items);
|
|
17158
17224
|
for (var j = 0, m = ports.length; j < m; j++) {
|
|
17159
17225
|
const resolvedPort = this._evaluatePort(ports[j]);
|
|
@@ -17162,23 +17228,155 @@ var joint = (function (exports) {
|
|
|
17162
17228
|
}
|
|
17163
17229
|
},
|
|
17164
17230
|
_evaluateGroup: function (group) {
|
|
17165
|
-
return merge(group, {
|
|
17166
|
-
position: this.
|
|
17167
|
-
label: this.
|
|
17231
|
+
return merge({}, group, {
|
|
17232
|
+
position: this._evaluateGroupPositionProperty(group),
|
|
17233
|
+
label: this._evaluateGroupLabelProperty(group)
|
|
17234
|
+
});
|
|
17235
|
+
},
|
|
17236
|
+
_evaluateGroupPositionProperty: function (group) {
|
|
17237
|
+
const namespace = this.portLayoutNamespace;
|
|
17238
|
+
const groupPosition = group.position;
|
|
17239
|
+
if (groupPosition === undefined) {
|
|
17240
|
+
const layoutCallback = this._resolveLayoutCallbackOrThrow(namespace, DEFAULT_PORT_POSITION_NAME, 'Default port group');
|
|
17241
|
+
return {
|
|
17242
|
+
layoutCallback
|
|
17243
|
+
};
|
|
17244
|
+
} else if (isFunction(groupPosition)) {
|
|
17245
|
+
return {
|
|
17246
|
+
layoutCallback: groupPosition
|
|
17247
|
+
};
|
|
17248
|
+
} else if (isObject(groupPosition)) {
|
|
17249
|
+
if (groupPosition.name) {
|
|
17250
|
+
const layoutCallback = this._resolveLayoutCallbackOrThrow(namespace, groupPosition.name, 'Provided port group');
|
|
17251
|
+
return {
|
|
17252
|
+
layoutCallback,
|
|
17253
|
+
args: groupPosition.args
|
|
17254
|
+
};
|
|
17255
|
+
} else {
|
|
17256
|
+
const layoutCallback = this._resolveLayoutCallbackOrThrow(namespace, DEFAULT_PORT_POSITION_NAME, 'Default port group');
|
|
17257
|
+
return {
|
|
17258
|
+
layoutCallback,
|
|
17259
|
+
args: groupPosition.args
|
|
17260
|
+
};
|
|
17261
|
+
}
|
|
17262
|
+
} else if (isString(groupPosition)) {
|
|
17263
|
+
// TODO: Remove legacy signature (see `this._evaluateGroupLabelPositionProperty()`).
|
|
17264
|
+
const layoutCallback = this._resolveLayoutCallbackOrThrow(namespace, groupPosition, 'Provided port group');
|
|
17265
|
+
return {
|
|
17266
|
+
layoutCallback
|
|
17267
|
+
};
|
|
17268
|
+
} else if (Array.isArray(groupPosition)) {
|
|
17269
|
+
// TODO: Remove legacy signature (see `this._evaluateGroupLabelPositionProperty()`).
|
|
17270
|
+
const layoutCallback = this._resolveLayoutCallbackOrThrow(namespace, DEFAULT_ABSOLUTE_PORT_POSITION_NAME, 'Default absolute port group');
|
|
17271
|
+
return {
|
|
17272
|
+
layoutCallback,
|
|
17273
|
+
args: {
|
|
17274
|
+
x: groupPosition[0],
|
|
17275
|
+
y: groupPosition[1]
|
|
17276
|
+
}
|
|
17277
|
+
};
|
|
17278
|
+
} else {
|
|
17279
|
+
throw new Error('dia.Element: Provided port group position value has an invalid type.');
|
|
17280
|
+
}
|
|
17281
|
+
},
|
|
17282
|
+
_evaluateGroupLabelProperty: function (group) {
|
|
17283
|
+
const groupLabel = group.label;
|
|
17284
|
+
if (!groupLabel) {
|
|
17285
|
+
return {
|
|
17286
|
+
position: this._evaluateGroupLabelPositionProperty({})
|
|
17287
|
+
};
|
|
17288
|
+
}
|
|
17289
|
+
return merge({}, groupLabel, {
|
|
17290
|
+
position: this._evaluateGroupLabelPositionProperty(groupLabel)
|
|
17168
17291
|
});
|
|
17169
17292
|
},
|
|
17293
|
+
_evaluateGroupLabelPositionProperty: function (groupLabel) {
|
|
17294
|
+
const namespace = this.portLabelLayoutNamespace;
|
|
17295
|
+
const groupLabelPosition = groupLabel.position;
|
|
17296
|
+
if (groupLabelPosition === undefined) {
|
|
17297
|
+
const layoutCallback = this._resolveLayoutCallbackOrThrow(namespace, DEFAULT_PORT_LABEL_POSITION_NAME, 'Default port group label');
|
|
17298
|
+
return {
|
|
17299
|
+
layoutCallback
|
|
17300
|
+
};
|
|
17301
|
+
} else if (isFunction(groupLabelPosition)) {
|
|
17302
|
+
return {
|
|
17303
|
+
layoutCallback: groupLabelPosition
|
|
17304
|
+
};
|
|
17305
|
+
} else if (isObject(groupLabelPosition)) {
|
|
17306
|
+
if (groupLabelPosition.name) {
|
|
17307
|
+
const layoutCallback = this._resolveLayoutCallbackOrThrow(namespace, groupLabelPosition.name, 'Provided port group label');
|
|
17308
|
+
return {
|
|
17309
|
+
layoutCallback,
|
|
17310
|
+
args: groupLabelPosition.args
|
|
17311
|
+
};
|
|
17312
|
+
} else {
|
|
17313
|
+
const layoutCallback = this._resolveLayoutCallbackOrThrow(namespace, DEFAULT_PORT_LABEL_POSITION_NAME, 'Default port group label');
|
|
17314
|
+
return {
|
|
17315
|
+
layoutCallback,
|
|
17316
|
+
args: groupLabelPosition.args
|
|
17317
|
+
};
|
|
17318
|
+
}
|
|
17319
|
+
} else {
|
|
17320
|
+
throw new Error('dia.Element: Provided port group label position value has an invalid type.');
|
|
17321
|
+
}
|
|
17322
|
+
},
|
|
17170
17323
|
_evaluatePort: function (port) {
|
|
17171
|
-
|
|
17172
|
-
|
|
17324
|
+
const group = this.getGroup(port.group);
|
|
17325
|
+
const evaluated = assign({}, port);
|
|
17173
17326
|
evaluated.markup = evaluated.markup || group.markup;
|
|
17174
17327
|
evaluated.attrs = merge({}, group.attrs, evaluated.attrs);
|
|
17175
|
-
evaluated.position = this.
|
|
17176
|
-
evaluated.label =
|
|
17177
|
-
evaluated.z = this.
|
|
17328
|
+
evaluated.position = this._evaluatePortPositionProperty(group, evaluated);
|
|
17329
|
+
evaluated.label = this._evaluatePortLabelProperty(group, evaluated);
|
|
17330
|
+
evaluated.z = this._evaluatePortZProperty(group, evaluated);
|
|
17178
17331
|
evaluated.size = assign({}, group.size, evaluated.size);
|
|
17179
17332
|
return evaluated;
|
|
17180
17333
|
},
|
|
17181
|
-
|
|
17334
|
+
_evaluatePortPositionProperty: function (group, port) {
|
|
17335
|
+
return {
|
|
17336
|
+
args: merge({},
|
|
17337
|
+
// NOTE: `x != null` is equivalent to `x !== null && x !== undefined`.
|
|
17338
|
+
group.position != null ? group.position.args : {},
|
|
17339
|
+
// Port can overwrite `group.position.args` via `port.position.args` or `port.args`.
|
|
17340
|
+
// TODO: Remove `port.args` backwards compatibility.
|
|
17341
|
+
port.position != null && port.position.args != null ? port.position.args : port.args)
|
|
17342
|
+
};
|
|
17343
|
+
},
|
|
17344
|
+
_evaluatePortLabelProperty: function (group, port) {
|
|
17345
|
+
const groupLabel = group.label;
|
|
17346
|
+
const portLabel = port.label;
|
|
17347
|
+
if (!portLabel) {
|
|
17348
|
+
return assign({}, groupLabel);
|
|
17349
|
+
}
|
|
17350
|
+
return merge({}, groupLabel, merge({}, portLabel, {
|
|
17351
|
+
position: this._evaluatePortLabelPositionProperty(portLabel)
|
|
17352
|
+
}));
|
|
17353
|
+
},
|
|
17354
|
+
_evaluatePortLabelPositionProperty: function (portLabel) {
|
|
17355
|
+
const namespace = this.portLabelLayoutNamespace;
|
|
17356
|
+
const portLabelPosition = portLabel.position;
|
|
17357
|
+
if (portLabelPosition === undefined) {
|
|
17358
|
+
return {};
|
|
17359
|
+
} else if (isFunction(portLabelPosition)) {
|
|
17360
|
+
return {
|
|
17361
|
+
layoutCallback: portLabelPosition
|
|
17362
|
+
};
|
|
17363
|
+
} else if (isObject(portLabelPosition)) {
|
|
17364
|
+
if (portLabelPosition.name) {
|
|
17365
|
+
const layoutCallback = this._resolveLayoutCallbackOrThrow(namespace, portLabelPosition.name, 'Provided port label');
|
|
17366
|
+
return {
|
|
17367
|
+
layoutCallback,
|
|
17368
|
+
args: portLabelPosition.args
|
|
17369
|
+
};
|
|
17370
|
+
} else {
|
|
17371
|
+
return {
|
|
17372
|
+
args: portLabelPosition.args
|
|
17373
|
+
};
|
|
17374
|
+
}
|
|
17375
|
+
} else {
|
|
17376
|
+
throw new Error('dia.Element: Provided port label position value has an invalid type.');
|
|
17377
|
+
}
|
|
17378
|
+
},
|
|
17379
|
+
_evaluatePortZProperty: function (group, port) {
|
|
17182
17380
|
if (isNumber(port.z)) {
|
|
17183
17381
|
return port.z;
|
|
17184
17382
|
}
|
|
@@ -17187,47 +17385,12 @@ var joint = (function (exports) {
|
|
|
17187
17385
|
}
|
|
17188
17386
|
return 'auto';
|
|
17189
17387
|
},
|
|
17190
|
-
|
|
17191
|
-
|
|
17192
|
-
|
|
17193
|
-
|
|
17194
|
-
}, group.position, {
|
|
17195
|
-
// TODO: remove `port.args` backwards compatibility
|
|
17196
|
-
// NOTE: `x != null` is equivalent to `x !== null && x !== undefined`
|
|
17197
|
-
args: port.position != null && port.position.args != null ? port.position.args : port.args
|
|
17198
|
-
});
|
|
17199
|
-
},
|
|
17200
|
-
_getPosition: function (position, setDefault) {
|
|
17201
|
-
var args = {};
|
|
17202
|
-
var positionName;
|
|
17203
|
-
if (isFunction(position)) {
|
|
17204
|
-
positionName = 'fn';
|
|
17205
|
-
args.fn = position;
|
|
17206
|
-
} else if (isString(position)) {
|
|
17207
|
-
positionName = position;
|
|
17208
|
-
} else if (position === undefined) {
|
|
17209
|
-
positionName = setDefault ? 'left' : null;
|
|
17210
|
-
} else if (Array.isArray(position)) {
|
|
17211
|
-
positionName = 'absolute';
|
|
17212
|
-
args.x = position[0];
|
|
17213
|
-
args.y = position[1];
|
|
17214
|
-
} else if (isObject(position)) {
|
|
17215
|
-
positionName = position.name;
|
|
17216
|
-
assign(args, position.args);
|
|
17217
|
-
}
|
|
17218
|
-
var result = {
|
|
17219
|
-
args: args
|
|
17220
|
-
};
|
|
17221
|
-
if (positionName) {
|
|
17222
|
-
result.name = positionName;
|
|
17388
|
+
_resolveLayoutCallbackOrThrow: function (namespace, name, errorSubstring) {
|
|
17389
|
+
const layoutCallback = namespace[name];
|
|
17390
|
+
if (!layoutCallback) {
|
|
17391
|
+
throw new Error(`dia.Element: ${errorSubstring} layout name is not recognized.`);
|
|
17223
17392
|
}
|
|
17224
|
-
return
|
|
17225
|
-
},
|
|
17226
|
-
_getLabel: function (item, setDefaults) {
|
|
17227
|
-
var label = item.label || {};
|
|
17228
|
-
var ret = label;
|
|
17229
|
-
ret.position = this._getPosition(label.position, setDefaults);
|
|
17230
|
-
return ret;
|
|
17393
|
+
return layoutCallback;
|
|
17231
17394
|
}
|
|
17232
17395
|
};
|
|
17233
17396
|
const elementPortPrototype = {
|
|
@@ -17567,7 +17730,7 @@ var joint = (function (exports) {
|
|
|
17567
17730
|
if (this._portSettingsData) {
|
|
17568
17731
|
prevPortData = this._portSettingsData.getPorts();
|
|
17569
17732
|
}
|
|
17570
|
-
this._portSettingsData = new PortData(this
|
|
17733
|
+
this._portSettingsData = new PortData(this);
|
|
17571
17734
|
var curPortData = this._portSettingsData.getPorts();
|
|
17572
17735
|
if (prevPortData) {
|
|
17573
17736
|
var added = curPortData.filter(function (item) {
|
|
@@ -18275,8 +18438,10 @@ var joint = (function (exports) {
|
|
|
18275
18438
|
_fitToElements: function (opt = {}) {
|
|
18276
18439
|
let minBBox = null;
|
|
18277
18440
|
if (opt.minRect) {
|
|
18278
|
-
// Coerce `opt.minRect` to g.Rect
|
|
18279
|
-
|
|
18441
|
+
// Coerce `opt.minRect` to g.Rect
|
|
18442
|
+
// (missing properties are taken from this element's current bbox).
|
|
18443
|
+
const minRect = assign(this.getBBox(), opt.minRect);
|
|
18444
|
+
minBBox = new Rect(minRect);
|
|
18280
18445
|
}
|
|
18281
18446
|
const elementsBBox = this.graph.getCellsBBox(opt.elements);
|
|
18282
18447
|
// If no `opt.elements` were provided, do nothing (but if `opt.minRect` was provided, set that as this element's bbox instead).
|
|
@@ -18946,9 +19111,12 @@ var joint = (function (exports) {
|
|
|
18946
19111
|
svgforeignobject: function () {
|
|
18947
19112
|
return !!document.createElementNS && /SVGForeignObject/.test({}.toString.call(document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject')));
|
|
18948
19113
|
},
|
|
18949
|
-
// works for iOS
|
|
18950
|
-
|
|
18951
|
-
|
|
19114
|
+
// works for: (1) macOS Safari, (2) any WKWebView, (3) any iOS browser (including Safari, CriOS, EdgiOS, OPR, FxiOS)
|
|
19115
|
+
isAppleWebKit: function () {
|
|
19116
|
+
const userAgent = navigator.userAgent;
|
|
19117
|
+
const isAppleWebKit = /applewebkit/i.test(userAgent);
|
|
19118
|
+
const isChromium = /chrome/i.test(userAgent); // e.g. Chrome, Edge, Opera, SamsungBrowser
|
|
19119
|
+
return isAppleWebKit && !isChromium;
|
|
18952
19120
|
}
|
|
18953
19121
|
},
|
|
18954
19122
|
addTest: function (name, fn) {
|
|
@@ -20822,7 +20990,7 @@ var joint = (function (exports) {
|
|
|
20822
20990
|
// Creating a ViewBase creates its initial element outside of the DOM,
|
|
20823
20991
|
// if an existing element is not provided...
|
|
20824
20992
|
var ViewBase = function (options) {
|
|
20825
|
-
this.cid = uniqueId('view');
|
|
20993
|
+
this.cid = options && options.cid || uniqueId('view');
|
|
20826
20994
|
this.preinitialize.apply(this, arguments);
|
|
20827
20995
|
assign(this, pick(options, viewOptions));
|
|
20828
20996
|
this._ensureElement();
|
|
@@ -20978,8 +21146,11 @@ var joint = (function (exports) {
|
|
|
20978
21146
|
childNodes: null,
|
|
20979
21147
|
DETACHABLE: true,
|
|
20980
21148
|
UPDATE_PRIORITY: 2,
|
|
21149
|
+
/** @deprecated is no longer used (moved to Paper) */
|
|
20981
21150
|
FLAG_INSERT: 1 << 30,
|
|
21151
|
+
/** @deprecated is no longer used */
|
|
20982
21152
|
FLAG_REMOVE: 1 << 29,
|
|
21153
|
+
/** @deprecated is no longer used */
|
|
20983
21154
|
FLAG_INIT: 1 << 28,
|
|
20984
21155
|
constructor: function (options) {
|
|
20985
21156
|
this.requireSetThemeOverride = options && !!options.theme;
|
|
@@ -22091,6 +22262,31 @@ var joint = (function (exports) {
|
|
|
22091
22262
|
return null;
|
|
22092
22263
|
}
|
|
22093
22264
|
},
|
|
22265
|
+
// Check if the cellView has a highlighter with the given `id`.
|
|
22266
|
+
// If no `id` is provided, it checks if the cellView has any highlighter.
|
|
22267
|
+
has(cellView, id = null) {
|
|
22268
|
+
const {
|
|
22269
|
+
cid
|
|
22270
|
+
} = cellView;
|
|
22271
|
+
const {
|
|
22272
|
+
_views
|
|
22273
|
+
} = this;
|
|
22274
|
+
const refs = _views[cid];
|
|
22275
|
+
if (!refs) return false;
|
|
22276
|
+
if (id === null) {
|
|
22277
|
+
// any highlighter
|
|
22278
|
+
for (let hid in refs) {
|
|
22279
|
+
if (refs[hid] instanceof this) return true;
|
|
22280
|
+
}
|
|
22281
|
+
return false;
|
|
22282
|
+
} else {
|
|
22283
|
+
// single highlighter
|
|
22284
|
+
if (id in refs) {
|
|
22285
|
+
if (refs[id] instanceof this) return true;
|
|
22286
|
+
}
|
|
22287
|
+
return false;
|
|
22288
|
+
}
|
|
22289
|
+
},
|
|
22094
22290
|
add(cellView, nodeSelector, id, opt = {}) {
|
|
22095
22291
|
if (!id) throw new Error('dia.HighlighterView: An ID required.');
|
|
22096
22292
|
// Search the existing view amongst all the highlighters
|
|
@@ -28834,6 +29030,14 @@ var joint = (function (exports) {
|
|
|
28834
29030
|
}
|
|
28835
29031
|
});
|
|
28836
29032
|
|
|
29033
|
+
// Internal tag to identify this object as a cell view instance.
|
|
29034
|
+
// Used instead of `instanceof` for performance and cross-frame safety.
|
|
29035
|
+
|
|
29036
|
+
const CELL_VIEW_MARKER = Symbol('joint.cellViewMarker');
|
|
29037
|
+
Object.defineProperty(CellView.prototype, CELL_VIEW_MARKER, {
|
|
29038
|
+
value: true
|
|
29039
|
+
});
|
|
29040
|
+
|
|
28837
29041
|
const Flags$1 = {
|
|
28838
29042
|
TOOLS: CellView.Flags.TOOLS,
|
|
28839
29043
|
UPDATE: 'UPDATE',
|
|
@@ -29187,7 +29391,8 @@ var joint = (function (exports) {
|
|
|
29187
29391
|
});
|
|
29188
29392
|
data.initialParentId = parentId;
|
|
29189
29393
|
} else {
|
|
29190
|
-
data.initialParentId
|
|
29394
|
+
// `data.initialParentId` can be explicitly set to a dummy value to enable validation of unembedding.
|
|
29395
|
+
data.initialParentId = data.initialParentId || null;
|
|
29191
29396
|
}
|
|
29192
29397
|
},
|
|
29193
29398
|
processEmbedding: function (data = {}, evt, x, y) {
|
|
@@ -29666,6 +29871,8 @@ var joint = (function (exports) {
|
|
|
29666
29871
|
_labelCache: null,
|
|
29667
29872
|
_labelSelectors: null,
|
|
29668
29873
|
_V: null,
|
|
29874
|
+
_sourceMagnet: null,
|
|
29875
|
+
_targetMagnet: null,
|
|
29669
29876
|
_dragData: null,
|
|
29670
29877
|
// deprecated
|
|
29671
29878
|
|
|
@@ -29702,23 +29909,34 @@ var joint = (function (exports) {
|
|
|
29702
29909
|
initFlag: [Flags.RENDER, Flags.SOURCE, Flags.TARGET, Flags.TOOLS],
|
|
29703
29910
|
UPDATE_PRIORITY: 1,
|
|
29704
29911
|
EPSILON: 1e-6,
|
|
29705
|
-
confirmUpdate: function (flags, opt) {
|
|
29706
|
-
|
|
29912
|
+
confirmUpdate: function (flags, opt = {}) {
|
|
29913
|
+
const {
|
|
29914
|
+
paper,
|
|
29915
|
+
model
|
|
29916
|
+
} = this;
|
|
29917
|
+
const {
|
|
29918
|
+
attributes
|
|
29919
|
+
} = model;
|
|
29920
|
+
const {
|
|
29921
|
+
source: {
|
|
29922
|
+
id: sourceId
|
|
29923
|
+
},
|
|
29924
|
+
target: {
|
|
29925
|
+
id: targetId
|
|
29926
|
+
}
|
|
29927
|
+
} = attributes;
|
|
29707
29928
|
if (this.hasFlag(flags, Flags.SOURCE)) {
|
|
29708
|
-
|
|
29929
|
+
this._sourceMagnet = null; // reset cached source magnet
|
|
29930
|
+
this.checkEndModel('source', sourceId);
|
|
29709
29931
|
flags = this.removeFlag(flags, Flags.SOURCE);
|
|
29710
29932
|
}
|
|
29711
29933
|
if (this.hasFlag(flags, Flags.TARGET)) {
|
|
29712
|
-
|
|
29934
|
+
this._targetMagnet = null; // reset cached target magnet
|
|
29935
|
+
this.checkEndModel('target', targetId);
|
|
29713
29936
|
flags = this.removeFlag(flags, Flags.TARGET);
|
|
29714
29937
|
}
|
|
29715
|
-
|
|
29716
|
-
|
|
29717
|
-
sourceView,
|
|
29718
|
-
targetView
|
|
29719
|
-
} = this;
|
|
29720
|
-
if (paper && (sourceView && !paper.isViewMounted(sourceView) || targetView && !paper.isViewMounted(targetView))) {
|
|
29721
|
-
// Wait for the sourceView and targetView to be rendered
|
|
29938
|
+
if (paper && (sourceId && !paper.isCellVisible(sourceId) || targetId && !paper.isCellVisible(targetId))) {
|
|
29939
|
+
// Wait for the source and target views to be rendered
|
|
29722
29940
|
return flags;
|
|
29723
29941
|
}
|
|
29724
29942
|
if (this.hasFlag(flags, Flags.RENDER)) {
|
|
@@ -29726,18 +29944,12 @@ var joint = (function (exports) {
|
|
|
29726
29944
|
this.updateHighlighters(true);
|
|
29727
29945
|
this.updateTools(opt);
|
|
29728
29946
|
flags = this.removeFlag(flags, [Flags.RENDER, Flags.UPDATE, Flags.LABELS, Flags.TOOLS, Flags.CONNECTOR]);
|
|
29729
|
-
if (env.test('
|
|
29730
|
-
this.
|
|
29947
|
+
if (env.test('isAppleWebKit')) {
|
|
29948
|
+
this.__fixWebKitBug268376();
|
|
29731
29949
|
}
|
|
29732
29950
|
return flags;
|
|
29733
29951
|
}
|
|
29734
29952
|
let updateHighlighters = false;
|
|
29735
|
-
const {
|
|
29736
|
-
model
|
|
29737
|
-
} = this;
|
|
29738
|
-
const {
|
|
29739
|
-
attributes
|
|
29740
|
-
} = model;
|
|
29741
29953
|
let updateLabels = this.hasFlag(flags, Flags.LABELS);
|
|
29742
29954
|
if (updateLabels) {
|
|
29743
29955
|
this.onLabelsChange(model, attributes.labels, opt);
|
|
@@ -29776,8 +29988,8 @@ var joint = (function (exports) {
|
|
|
29776
29988
|
}
|
|
29777
29989
|
return flags;
|
|
29778
29990
|
},
|
|
29779
|
-
|
|
29780
|
-
//
|
|
29991
|
+
__fixWebKitBug268376: function () {
|
|
29992
|
+
// WebKit has a bug where any change after the first render is not reflected in the DOM.
|
|
29781
29993
|
// https://bugs.webkit.org/show_bug.cgi?id=268376
|
|
29782
29994
|
const {
|
|
29783
29995
|
el
|
|
@@ -30446,40 +30658,11 @@ var joint = (function (exports) {
|
|
|
30446
30658
|
if (id && id in metrics) delete metrics[id].magnetMatrix;
|
|
30447
30659
|
}
|
|
30448
30660
|
},
|
|
30449
|
-
|
|
30450
|
-
|
|
30451
|
-
|
|
30452
|
-
|
|
30453
|
-
|
|
30454
|
-
const endViewProperty = `${endType}View`;
|
|
30455
|
-
const endDef = model.get(endType);
|
|
30456
|
-
const endId = endDef && endDef.id;
|
|
30457
|
-
if (!endId) {
|
|
30458
|
-
// the link end is a point ~ rect 0x0
|
|
30459
|
-
this[endViewProperty] = null;
|
|
30460
|
-
this.updateEndMagnet(endType);
|
|
30461
|
-
return true;
|
|
30462
|
-
}
|
|
30463
|
-
const endModel = paper.getModelById(endId);
|
|
30464
|
-
if (!endModel) throw new Error('LinkView: invalid ' + endType + ' cell.');
|
|
30465
|
-
const endView = endModel.findView(paper);
|
|
30466
|
-
if (!endView) {
|
|
30467
|
-
// A view for a model should always exist
|
|
30468
|
-
return false;
|
|
30469
|
-
}
|
|
30470
|
-
this[endViewProperty] = endView;
|
|
30471
|
-
this.updateEndMagnet(endType);
|
|
30472
|
-
return true;
|
|
30473
|
-
},
|
|
30474
|
-
updateEndMagnet: function (endType) {
|
|
30475
|
-
const endMagnetProperty = `${endType}Magnet`;
|
|
30476
|
-
const endView = this.getEndView(endType);
|
|
30477
|
-
if (endView) {
|
|
30478
|
-
let connectedMagnet = endView.getMagnetFromLinkEnd(this.model.get(endType));
|
|
30479
|
-
if (connectedMagnet === endView.el) connectedMagnet = null;
|
|
30480
|
-
this[endMagnetProperty] = connectedMagnet;
|
|
30481
|
-
} else {
|
|
30482
|
-
this[endMagnetProperty] = null;
|
|
30661
|
+
checkEndModel: function (endType, endId) {
|
|
30662
|
+
if (!endId) return;
|
|
30663
|
+
const endModel = this.paper.getModelById(endId);
|
|
30664
|
+
if (!endModel) {
|
|
30665
|
+
throw new Error(`LinkView: invalid ${endType} cell.`);
|
|
30483
30666
|
}
|
|
30484
30667
|
},
|
|
30485
30668
|
_getLabelPositionProperty: function (idx) {
|
|
@@ -31244,52 +31427,30 @@ var joint = (function (exports) {
|
|
|
31244
31427
|
let isSnapped = false;
|
|
31245
31428
|
// checking view in close area of the pointer
|
|
31246
31429
|
|
|
31247
|
-
|
|
31248
|
-
|
|
31249
|
-
|
|
31250
|
-
|
|
31251
|
-
|
|
31252
|
-
height: 2 * r
|
|
31253
|
-
}, snapLinks.findInAreaOptions);
|
|
31254
|
-
var prevClosestView = data.closestView || null;
|
|
31255
|
-
var prevClosestMagnet = data.closestMagnet || null;
|
|
31256
|
-
var prevMagnetProxy = data.magnetProxy || null;
|
|
31430
|
+
const radius = snapLinks.radius || 50;
|
|
31431
|
+
const findInAreaOptions = snapLinks.findInAreaOptions;
|
|
31432
|
+
const prevClosestView = data.closestView || null;
|
|
31433
|
+
const prevClosestMagnet = data.closestMagnet || null;
|
|
31434
|
+
const prevMagnetProxy = data.magnetProxy || null;
|
|
31257
31435
|
data.closestView = data.closestMagnet = data.magnetProxy = null;
|
|
31258
|
-
|
|
31259
|
-
|
|
31260
|
-
|
|
31261
|
-
|
|
31262
|
-
// skip connecting to the element in case '.': { magnet: false } attribute present
|
|
31263
|
-
if (view.el.getAttribute('magnet') !== 'false') {
|
|
31264
|
-
candidates.push({
|
|
31265
|
-
bbox: view.model.getBBox(),
|
|
31266
|
-
magnet: view.el
|
|
31267
|
-
});
|
|
31436
|
+
const isValidCandidate = (view, magnet) => {
|
|
31437
|
+
// Do not snap to the current view
|
|
31438
|
+
if (view === this) {
|
|
31439
|
+
return false;
|
|
31268
31440
|
}
|
|
31269
|
-
|
|
31270
|
-
|
|
31271
|
-
|
|
31272
|
-
|
|
31273
|
-
|
|
31274
|
-
|
|
31275
|
-
|
|
31276
|
-
|
|
31277
|
-
|
|
31278
|
-
|
|
31279
|
-
|
|
31280
|
-
|
|
31281
|
-
|
|
31282
|
-
// the connection is looked up in a circle area by `distance < r`
|
|
31283
|
-
if (distance < minDistance) {
|
|
31284
|
-
const isAlreadyValidated = prevClosestMagnet === magnet;
|
|
31285
|
-
if (isAlreadyValidated || paper.options.validateConnection.apply(paper, data.validateConnectionArgs(view, view.el === magnet ? null : magnet))) {
|
|
31286
|
-
minDistance = distance;
|
|
31287
|
-
data.closestView = view;
|
|
31288
|
-
data.closestMagnet = magnet;
|
|
31289
|
-
}
|
|
31290
|
-
}
|
|
31291
|
-
});
|
|
31292
|
-
}, this);
|
|
31441
|
+
const isAlreadyValidated = prevClosestMagnet === magnet;
|
|
31442
|
+
return isAlreadyValidated || paper.options.validateConnection.apply(paper, data.validateConnectionArgs(view, view.el === magnet ? null : magnet));
|
|
31443
|
+
};
|
|
31444
|
+
const closest = paper.findClosestMagnetToPoint({
|
|
31445
|
+
x,
|
|
31446
|
+
y
|
|
31447
|
+
}, {
|
|
31448
|
+
radius,
|
|
31449
|
+
findInAreaOptions,
|
|
31450
|
+
filter: isValidCandidate
|
|
31451
|
+
});
|
|
31452
|
+
data.closestView = closest ? closest.view : null;
|
|
31453
|
+
data.closestMagnet = closest ? closest.magnet : null;
|
|
31293
31454
|
var end;
|
|
31294
31455
|
var magnetProxy = null;
|
|
31295
31456
|
var closestView = data.closestView;
|
|
@@ -31583,6 +31744,72 @@ var joint = (function (exports) {
|
|
|
31583
31744
|
}, {
|
|
31584
31745
|
Flags: Flags
|
|
31585
31746
|
});
|
|
31747
|
+
Object.defineProperty(LinkView.prototype, 'sourceView', {
|
|
31748
|
+
enumerable: true,
|
|
31749
|
+
get: function () {
|
|
31750
|
+
const source = this.model.attributes.source;
|
|
31751
|
+
if (source.id && this.paper) {
|
|
31752
|
+
return this.paper.findViewByModel(source.id);
|
|
31753
|
+
}
|
|
31754
|
+
return null;
|
|
31755
|
+
}
|
|
31756
|
+
});
|
|
31757
|
+
Object.defineProperty(LinkView.prototype, 'targetView', {
|
|
31758
|
+
enumerable: true,
|
|
31759
|
+
get: function () {
|
|
31760
|
+
const target = this.model.attributes.target;
|
|
31761
|
+
if (target.id && this.paper) {
|
|
31762
|
+
return this.paper.findViewByModel(target.id);
|
|
31763
|
+
}
|
|
31764
|
+
return null;
|
|
31765
|
+
}
|
|
31766
|
+
});
|
|
31767
|
+
Object.defineProperty(LinkView.prototype, 'sourceMagnet', {
|
|
31768
|
+
enumerable: true,
|
|
31769
|
+
get: function () {
|
|
31770
|
+
const sourceView = this.sourceView;
|
|
31771
|
+
if (!sourceView) return null;
|
|
31772
|
+
let sourceMagnet = null;
|
|
31773
|
+
// Check if the magnet is already found and cached.
|
|
31774
|
+
// We need to check if the cached magnet is still part of the source view.
|
|
31775
|
+
// The source view might have been disposed and recreated, or the magnet might have been changed.
|
|
31776
|
+
const cachedSourceMagnet = this._sourceMagnet;
|
|
31777
|
+
if (cachedSourceMagnet && sourceView.el.contains(cachedSourceMagnet)) {
|
|
31778
|
+
sourceMagnet = cachedSourceMagnet;
|
|
31779
|
+
} else {
|
|
31780
|
+
// If the cached magnet is not valid, we need to find the magnet.
|
|
31781
|
+
sourceMagnet = sourceView.getMagnetFromLinkEnd(this.model.attributes.source);
|
|
31782
|
+
}
|
|
31783
|
+
this._sourceMagnet = sourceMagnet;
|
|
31784
|
+
if (sourceMagnet === sourceView.el) {
|
|
31785
|
+
// If the source magnet is the element itself, we treat it as no magnet.
|
|
31786
|
+
return null;
|
|
31787
|
+
}
|
|
31788
|
+
return sourceMagnet;
|
|
31789
|
+
}
|
|
31790
|
+
});
|
|
31791
|
+
Object.defineProperty(LinkView.prototype, 'targetMagnet', {
|
|
31792
|
+
enumerable: true,
|
|
31793
|
+
get: function () {
|
|
31794
|
+
const targetView = this.targetView;
|
|
31795
|
+
if (!targetView) return null;
|
|
31796
|
+
let targetMagnet = null;
|
|
31797
|
+
// Check if the magnet is already found and cached (See `sourceMagnet` for explanation).
|
|
31798
|
+
const cachedTargetMagnet = this._targetMagnet;
|
|
31799
|
+
if (cachedTargetMagnet && targetView.el.contains(cachedTargetMagnet)) {
|
|
31800
|
+
targetMagnet = cachedTargetMagnet;
|
|
31801
|
+
} else {
|
|
31802
|
+
// If the cached magnet is not valid, we need to find the magnet.
|
|
31803
|
+
targetMagnet = targetView.getMagnetFromLinkEnd(this.model.attributes.target);
|
|
31804
|
+
}
|
|
31805
|
+
this._targetMagnet = targetMagnet;
|
|
31806
|
+
if (targetMagnet === targetView.el) {
|
|
31807
|
+
// If the target magnet is the element itself, we treat it as no magnet.
|
|
31808
|
+
return null;
|
|
31809
|
+
}
|
|
31810
|
+
return targetMagnet;
|
|
31811
|
+
}
|
|
31812
|
+
});
|
|
31586
31813
|
Object.defineProperty(LinkView.prototype, 'sourceBBox', {
|
|
31587
31814
|
enumerable: true,
|
|
31588
31815
|
get: function () {
|
|
@@ -31614,6 +31841,128 @@ var joint = (function (exports) {
|
|
|
31614
31841
|
}
|
|
31615
31842
|
});
|
|
31616
31843
|
|
|
31844
|
+
/**
|
|
31845
|
+
* Deque implementation for managing a double-ended queue.
|
|
31846
|
+
* This implementation uses a doubly linked list for efficient operations.
|
|
31847
|
+
* It supports operations like push, pop, move to head, and delete.
|
|
31848
|
+
* The deque maintains a map for O(1) access to nodes by key.
|
|
31849
|
+
*/
|
|
31850
|
+
class Deque {
|
|
31851
|
+
constructor() {
|
|
31852
|
+
this.head = null;
|
|
31853
|
+
this.tail = null;
|
|
31854
|
+
this.map = new Map(); // key -> node
|
|
31855
|
+
}
|
|
31856
|
+
|
|
31857
|
+
// Return an array of keys in the deque
|
|
31858
|
+
keys() {
|
|
31859
|
+
let current = this.head;
|
|
31860
|
+
const keys = [];
|
|
31861
|
+
while (current) {
|
|
31862
|
+
keys.push(current.key);
|
|
31863
|
+
current = current.next;
|
|
31864
|
+
}
|
|
31865
|
+
return keys;
|
|
31866
|
+
}
|
|
31867
|
+
|
|
31868
|
+
// Return the first node and remove it from the deque
|
|
31869
|
+
popHead() {
|
|
31870
|
+
if (!this.head) return null;
|
|
31871
|
+
const node = this.head;
|
|
31872
|
+
this.map.delete(node.key);
|
|
31873
|
+
this.head = node.next;
|
|
31874
|
+
if (this.head) {
|
|
31875
|
+
this.head.prev = null;
|
|
31876
|
+
} else {
|
|
31877
|
+
this.tail = null;
|
|
31878
|
+
}
|
|
31879
|
+
return node;
|
|
31880
|
+
}
|
|
31881
|
+
|
|
31882
|
+
// Add a new node to the back of the deque
|
|
31883
|
+
pushTail(key, value) {
|
|
31884
|
+
if (this.map.has(key)) {
|
|
31885
|
+
throw new Error(`Key "${key}" already exists in the deque.`);
|
|
31886
|
+
}
|
|
31887
|
+
const node = {
|
|
31888
|
+
key,
|
|
31889
|
+
value,
|
|
31890
|
+
prev: null,
|
|
31891
|
+
next: null
|
|
31892
|
+
};
|
|
31893
|
+
this.map.set(key, node);
|
|
31894
|
+
if (!this.tail) {
|
|
31895
|
+
this.head = this.tail = node;
|
|
31896
|
+
} else {
|
|
31897
|
+
this.tail.next = node;
|
|
31898
|
+
node.prev = this.tail;
|
|
31899
|
+
this.tail = node;
|
|
31900
|
+
}
|
|
31901
|
+
}
|
|
31902
|
+
|
|
31903
|
+
// Move a node from the deque to the head
|
|
31904
|
+
moveToHead(key) {
|
|
31905
|
+
const node = this.map.get(key);
|
|
31906
|
+
if (!node) return;
|
|
31907
|
+
if (node === this.head) return; // already at head
|
|
31908
|
+
// Remove node from its current position
|
|
31909
|
+
if (node.prev) node.prev.next = node.next;
|
|
31910
|
+
if (node.next) node.next.prev = node.prev;
|
|
31911
|
+
if (node === this.tail) this.tail = node.prev; // if it's the tail
|
|
31912
|
+
if (node === this.head) this.head = node.next; // if it's the head
|
|
31913
|
+
// Move node to head
|
|
31914
|
+
node.prev = null;
|
|
31915
|
+
node.next = this.head;
|
|
31916
|
+
if (this.head) {
|
|
31917
|
+
this.head.prev = node; // link old head back to new head
|
|
31918
|
+
}
|
|
31919
|
+
this.head = node; // update head to be the moved node
|
|
31920
|
+
if (!this.tail) {
|
|
31921
|
+
this.tail = node; // if it was the only node, set tail as well
|
|
31922
|
+
}
|
|
31923
|
+
}
|
|
31924
|
+
|
|
31925
|
+
// Return the first node without removing it
|
|
31926
|
+
peekHead() {
|
|
31927
|
+
return this.head || null;
|
|
31928
|
+
}
|
|
31929
|
+
|
|
31930
|
+
// Move the head node to the back of the deque
|
|
31931
|
+
rotate() {
|
|
31932
|
+
if (!this.head || !this.head.next) return;
|
|
31933
|
+
this.tail.next = this.head; // link tail to head
|
|
31934
|
+
this.head.prev = this.tail; // link head back to tail
|
|
31935
|
+
this.tail = this.head; // update tail to be the old head
|
|
31936
|
+
this.head = this.head.next; // move head to the next node
|
|
31937
|
+
this.tail.next = null; // set new tail's next to null
|
|
31938
|
+
this.head.prev = null; // set new head's prev to null
|
|
31939
|
+
}
|
|
31940
|
+
|
|
31941
|
+
// Remove a node from the deque
|
|
31942
|
+
delete(key) {
|
|
31943
|
+
const node = this.map.get(key);
|
|
31944
|
+
if (!node) return;
|
|
31945
|
+
if (node.prev) node.prev.next = node.next;else this.head = node.next;
|
|
31946
|
+
if (node.next) node.next.prev = node.prev;else this.tail = node.prev;
|
|
31947
|
+
this.map.delete(key);
|
|
31948
|
+
}
|
|
31949
|
+
|
|
31950
|
+
// Does the deque contain a node with the given key?
|
|
31951
|
+
has(key) {
|
|
31952
|
+
return this.map.has(key);
|
|
31953
|
+
}
|
|
31954
|
+
|
|
31955
|
+
// Get the node with the given key
|
|
31956
|
+
get(key) {
|
|
31957
|
+
return this.map.get(key) || null;
|
|
31958
|
+
}
|
|
31959
|
+
|
|
31960
|
+
// Number of nodes in the deque
|
|
31961
|
+
get length() {
|
|
31962
|
+
return this.map.size;
|
|
31963
|
+
}
|
|
31964
|
+
}
|
|
31965
|
+
|
|
31617
31966
|
const GridLayer = PaperLayer.extend({
|
|
31618
31967
|
style: {
|
|
31619
31968
|
'pointer-events': 'none'
|
|
@@ -31855,6 +32204,7 @@ var joint = (function (exports) {
|
|
|
31855
32204
|
}, {
|
|
31856
32205
|
name: LayersNames.TOOLS
|
|
31857
32206
|
}];
|
|
32207
|
+
const CELL_VIEW_PLACEHOLDER_MARKER = Symbol('joint.cellViewPlaceholderMarker');
|
|
31858
32208
|
const Paper = View.extend({
|
|
31859
32209
|
className: 'paper',
|
|
31860
32210
|
options: {
|
|
@@ -32005,6 +32355,7 @@ var joint = (function (exports) {
|
|
|
32005
32355
|
sorting: sortingTypes.APPROX,
|
|
32006
32356
|
frozen: false,
|
|
32007
32357
|
autoFreeze: false,
|
|
32358
|
+
viewManagement: false,
|
|
32008
32359
|
// no docs yet
|
|
32009
32360
|
onViewUpdate: function (view, flag, priority, opt, paper) {
|
|
32010
32361
|
// Do not update connected links when:
|
|
@@ -32012,7 +32363,7 @@ var joint = (function (exports) {
|
|
|
32012
32363
|
// 2. the view was just mounted (added back to the paper by viewport function)
|
|
32013
32364
|
// 3. the change was marked as `isolate`.
|
|
32014
32365
|
// 4. the view model was just removed from the graph
|
|
32015
|
-
if (flag & (
|
|
32366
|
+
if (flag & (paper.FLAG_INSERT | paper.FLAG_REMOVE) || opt.mounting || opt.isolate) return;
|
|
32016
32367
|
paper.requestConnectedLinksUpdate(view, priority, opt);
|
|
32017
32368
|
},
|
|
32018
32369
|
// no docs yet
|
|
@@ -32111,6 +32462,10 @@ var joint = (function (exports) {
|
|
|
32111
32462
|
DEFAULT_FIND_BUFFER: 200,
|
|
32112
32463
|
// Default layer to insert the cell views into.
|
|
32113
32464
|
DEFAULT_CELL_LAYER: LayersNames.CELLS,
|
|
32465
|
+
// Update flags
|
|
32466
|
+
FLAG_INSERT: 1 << 30,
|
|
32467
|
+
FLAG_REMOVE: 1 << 29,
|
|
32468
|
+
FLAG_INIT: 1 << 28,
|
|
32114
32469
|
init: function () {
|
|
32115
32470
|
const {
|
|
32116
32471
|
options
|
|
@@ -32122,6 +32477,10 @@ var joint = (function (exports) {
|
|
|
32122
32477
|
}
|
|
32123
32478
|
const model = this.model = options.model || new Graph();
|
|
32124
32479
|
|
|
32480
|
+
// This property tells us if we need to keep the compatibility
|
|
32481
|
+
// with the v4 API and behavior.
|
|
32482
|
+
this.legacyMode = !options.viewManagement;
|
|
32483
|
+
|
|
32125
32484
|
// Layers (SVGGroups)
|
|
32126
32485
|
this._layers = {
|
|
32127
32486
|
viewsMap: {},
|
|
@@ -32135,6 +32494,8 @@ var joint = (function (exports) {
|
|
|
32135
32494
|
|
|
32136
32495
|
// Hash of all cell views.
|
|
32137
32496
|
this._views = {};
|
|
32497
|
+
this._viewPlaceholders = {};
|
|
32498
|
+
this._idToCid = {};
|
|
32138
32499
|
|
|
32139
32500
|
// Mouse wheel events buffer
|
|
32140
32501
|
this._mw_evt_buffer = {
|
|
@@ -32144,24 +32505,21 @@ var joint = (function (exports) {
|
|
|
32144
32505
|
|
|
32145
32506
|
// Render existing cells in the graph
|
|
32146
32507
|
this.resetViews(model.attributes.cells.models);
|
|
32147
|
-
// Start the Rendering Loop
|
|
32148
|
-
if (!this.isFrozen() && this.isAsync()) this.updateViewsAsync();
|
|
32149
32508
|
},
|
|
32150
32509
|
_resetUpdates: function () {
|
|
32151
32510
|
if (this._updates && this._updates.id) cancelFrame(this._updates.id);
|
|
32152
32511
|
return this._updates = {
|
|
32153
32512
|
id: null,
|
|
32154
32513
|
priorities: [{}, {}, {}],
|
|
32155
|
-
|
|
32156
|
-
|
|
32157
|
-
unmounted: {},
|
|
32158
|
-
mounted: {},
|
|
32514
|
+
unmountedList: new Deque(),
|
|
32515
|
+
mountedList: new Deque(),
|
|
32159
32516
|
count: 0,
|
|
32160
32517
|
keyFrozen: false,
|
|
32161
32518
|
freezeKey: null,
|
|
32162
32519
|
sort: false,
|
|
32163
32520
|
disabled: false,
|
|
32164
|
-
idle: false
|
|
32521
|
+
idle: false,
|
|
32522
|
+
freshAfterReset: true
|
|
32165
32523
|
};
|
|
32166
32524
|
},
|
|
32167
32525
|
startListening: function () {
|
|
@@ -32184,14 +32542,21 @@ var joint = (function (exports) {
|
|
|
32184
32542
|
}
|
|
32185
32543
|
},
|
|
32186
32544
|
onCellRemoved: function (cell, _, opt) {
|
|
32187
|
-
const
|
|
32188
|
-
if (
|
|
32545
|
+
const viewLike = this._getCellViewLike(cell);
|
|
32546
|
+
if (!viewLike) return;
|
|
32547
|
+
if (viewLike[CELL_VIEW_PLACEHOLDER_MARKER]) {
|
|
32548
|
+
this._unregisterCellViewPlaceholder(viewLike);
|
|
32549
|
+
} else {
|
|
32550
|
+
this.requestViewUpdate(viewLike, this.FLAG_REMOVE, viewLike.UPDATE_PRIORITY, opt);
|
|
32551
|
+
}
|
|
32189
32552
|
},
|
|
32190
32553
|
onCellChange: function (cell, opt) {
|
|
32191
32554
|
if (cell === this.model.attributes.cells) return;
|
|
32192
32555
|
if (cell.hasChanged('layer') || cell.hasChanged('z') && this.options.sorting === sortingTypes.APPROX) {
|
|
32193
|
-
const
|
|
32194
|
-
if (
|
|
32556
|
+
const viewLike = this._getCellViewLike(cell);
|
|
32557
|
+
if (viewLike) {
|
|
32558
|
+
this.requestViewUpdate(viewLike, this.FLAG_INSERT, viewLike.UPDATE_PRIORITY, opt);
|
|
32559
|
+
}
|
|
32195
32560
|
}
|
|
32196
32561
|
},
|
|
32197
32562
|
onGraphReset: function (collection, opt) {
|
|
@@ -32203,7 +32568,7 @@ var joint = (function (exports) {
|
|
|
32203
32568
|
this.sortViews();
|
|
32204
32569
|
},
|
|
32205
32570
|
onGraphBatchStop: function (data) {
|
|
32206
|
-
if (this.isFrozen()) return;
|
|
32571
|
+
if (this.isFrozen() || this.isIdle()) return;
|
|
32207
32572
|
var name = data && data.batchName;
|
|
32208
32573
|
var graph = this.model;
|
|
32209
32574
|
if (!this.isAsync()) {
|
|
@@ -32263,6 +32628,16 @@ var joint = (function (exports) {
|
|
|
32263
32628
|
// Return the default highlighting options into the user specified options.
|
|
32264
32629
|
options.highlighting = defaultsDeep({}, highlighting, defaultHighlighting);
|
|
32265
32630
|
}
|
|
32631
|
+
// Copy and set defaults for the view management options.
|
|
32632
|
+
options.viewManagement = defaults({}, options.viewManagement, {
|
|
32633
|
+
// Whether to lazy initialize the cell views.
|
|
32634
|
+
lazyInitialize: !!options.viewManagement,
|
|
32635
|
+
// default `true` if options.viewManagement provided
|
|
32636
|
+
// Whether to add initialized cell views into the unmounted queue.
|
|
32637
|
+
initializeUnmounted: false,
|
|
32638
|
+
// Whether to dispose the cell views that are not visible.
|
|
32639
|
+
disposeHidden: false
|
|
32640
|
+
});
|
|
32266
32641
|
},
|
|
32267
32642
|
children: function () {
|
|
32268
32643
|
var ns = V.namespace;
|
|
@@ -32641,47 +33016,46 @@ var joint = (function (exports) {
|
|
|
32641
33016
|
var links = this.model.getConnectedLinks(model);
|
|
32642
33017
|
for (var j = 0, n = links.length; j < n; j++) {
|
|
32643
33018
|
var link = links[j];
|
|
32644
|
-
var linkView = this.
|
|
33019
|
+
var linkView = this._getCellViewLike(link);
|
|
32645
33020
|
if (!linkView) continue;
|
|
32646
|
-
|
|
32647
|
-
|
|
32648
|
-
if (
|
|
33021
|
+
// We do not have to update placeholder views.
|
|
33022
|
+
// They will be updated on initial render.
|
|
33023
|
+
if (linkView[CELL_VIEW_PLACEHOLDER_MARKER]) continue;
|
|
32649
33024
|
var nextPriority = Math.max(priority + 1, linkView.UPDATE_PRIORITY);
|
|
32650
|
-
this.scheduleViewUpdate(linkView, linkView.getFlag(
|
|
33025
|
+
this.scheduleViewUpdate(linkView, linkView.getFlag(LinkView.Flags.UPDATE), nextPriority, opt);
|
|
32651
33026
|
}
|
|
32652
33027
|
}
|
|
32653
33028
|
},
|
|
32654
33029
|
forcePostponedViewUpdate: function (view, flag) {
|
|
32655
33030
|
if (!view || !(view instanceof CellView)) return false;
|
|
32656
|
-
|
|
33031
|
+
const model = view.model;
|
|
32657
33032
|
if (model.isElement()) return false;
|
|
32658
|
-
|
|
32659
|
-
|
|
32660
|
-
|
|
32661
|
-
|
|
32662
|
-
|
|
32663
|
-
|
|
32664
|
-
|
|
32665
|
-
|
|
32666
|
-
|
|
32667
|
-
|
|
32668
|
-
|
|
32669
|
-
|
|
32670
|
-
|
|
32671
|
-
|
|
32672
|
-
|
|
32673
|
-
|
|
32674
|
-
|
|
32675
|
-
|
|
32676
|
-
|
|
32677
|
-
|
|
32678
|
-
return !this.dumpView(view, dumpOptions);
|
|
32679
|
-
}
|
|
33033
|
+
const dumpOptions = {
|
|
33034
|
+
silent: true
|
|
33035
|
+
};
|
|
33036
|
+
// LinkView is waiting for the target or the source cellView to be rendered
|
|
33037
|
+
// This can happen when the cells are not in the viewport.
|
|
33038
|
+
let sourceFlag = 0;
|
|
33039
|
+
const sourceCell = model.getSourceCell();
|
|
33040
|
+
if (sourceCell && !this.isCellVisible(sourceCell)) {
|
|
33041
|
+
const sourceView = this.findViewByModel(sourceCell);
|
|
33042
|
+
sourceFlag = this.dumpView(sourceView, dumpOptions);
|
|
33043
|
+
}
|
|
33044
|
+
let targetFlag = 0;
|
|
33045
|
+
const targetCell = model.getTargetCell();
|
|
33046
|
+
if (targetCell && !this.isCellVisible(targetCell)) {
|
|
33047
|
+
const targetView = this.findViewByModel(targetCell);
|
|
33048
|
+
targetFlag = this.dumpView(targetView, dumpOptions);
|
|
33049
|
+
}
|
|
33050
|
+
if (sourceFlag === 0 && targetFlag === 0) {
|
|
33051
|
+
// If leftover flag is 0, all view updates were done.
|
|
33052
|
+
return !this.dumpView(view, dumpOptions);
|
|
32680
33053
|
}
|
|
32681
33054
|
return false;
|
|
32682
33055
|
},
|
|
32683
33056
|
requestViewUpdate: function (view, flag, priority, opt) {
|
|
32684
33057
|
opt || (opt = {});
|
|
33058
|
+
// Note: `scheduleViewUpdate` wakes up the paper if it is idle.
|
|
32685
33059
|
this.scheduleViewUpdate(view, flag, priority, opt);
|
|
32686
33060
|
var isAsync = this.isAsync();
|
|
32687
33061
|
if (this.isFrozen() || isAsync && opt.async !== false) return;
|
|
@@ -32694,15 +33068,15 @@ var joint = (function (exports) {
|
|
|
32694
33068
|
_updates: updates,
|
|
32695
33069
|
options
|
|
32696
33070
|
} = this;
|
|
32697
|
-
if (updates.idle) {
|
|
32698
|
-
|
|
32699
|
-
|
|
32700
|
-
this.unfreeze();
|
|
32701
|
-
}
|
|
33071
|
+
if (updates.idle && options.autoFreeze) {
|
|
33072
|
+
this.legacyMode ? this.unfreeze() // Restart rendering loop without original options
|
|
33073
|
+
: this.wakeUp();
|
|
32702
33074
|
}
|
|
32703
33075
|
const {
|
|
32704
33076
|
FLAG_REMOVE,
|
|
32705
|
-
FLAG_INSERT
|
|
33077
|
+
FLAG_INSERT
|
|
33078
|
+
} = this;
|
|
33079
|
+
const {
|
|
32706
33080
|
UPDATE_PRIORITY,
|
|
32707
33081
|
cid
|
|
32708
33082
|
} = view;
|
|
@@ -32749,16 +33123,13 @@ var joint = (function (exports) {
|
|
|
32749
33123
|
dumpView: function (view, opt = {}) {
|
|
32750
33124
|
const flag = this.dumpViewUpdate(view);
|
|
32751
33125
|
if (!flag) return 0;
|
|
32752
|
-
|
|
32753
|
-
if (shouldNotify) this.notifyBeforeRender(opt);
|
|
33126
|
+
this.notifyBeforeRender(opt);
|
|
32754
33127
|
const leftover = this.updateView(view, flag, opt);
|
|
32755
|
-
|
|
32756
|
-
|
|
32757
|
-
|
|
32758
|
-
|
|
32759
|
-
|
|
32760
|
-
this.notifyAfterRender(stats, opt);
|
|
32761
|
-
}
|
|
33128
|
+
const stats = {
|
|
33129
|
+
updated: 1,
|
|
33130
|
+
priority: view.UPDATE_PRIORITY
|
|
33131
|
+
};
|
|
33132
|
+
this.notifyAfterRender(stats, opt);
|
|
32762
33133
|
return leftover;
|
|
32763
33134
|
},
|
|
32764
33135
|
updateView: function (view, flag, opt) {
|
|
@@ -32766,10 +33137,12 @@ var joint = (function (exports) {
|
|
|
32766
33137
|
const {
|
|
32767
33138
|
FLAG_REMOVE,
|
|
32768
33139
|
FLAG_INSERT,
|
|
32769
|
-
FLAG_INIT
|
|
33140
|
+
FLAG_INIT
|
|
33141
|
+
} = this;
|
|
33142
|
+
const {
|
|
32770
33143
|
model
|
|
32771
33144
|
} = view;
|
|
32772
|
-
if (view
|
|
33145
|
+
if (view[CELL_VIEW_MARKER]) {
|
|
32773
33146
|
if (flag & FLAG_REMOVE) {
|
|
32774
33147
|
this.removeView(model);
|
|
32775
33148
|
return 0;
|
|
@@ -32795,58 +33168,70 @@ var joint = (function (exports) {
|
|
|
32795
33168
|
registerUnmountedView: function (view) {
|
|
32796
33169
|
var cid = view.cid;
|
|
32797
33170
|
var updates = this._updates;
|
|
32798
|
-
if (
|
|
32799
|
-
|
|
32800
|
-
updates.
|
|
32801
|
-
|
|
33171
|
+
if (updates.unmountedList.has(cid)) return 0;
|
|
33172
|
+
const flag = this.FLAG_INSERT;
|
|
33173
|
+
updates.unmountedList.pushTail(cid, flag);
|
|
33174
|
+
updates.mountedList.delete(cid);
|
|
32802
33175
|
return flag;
|
|
32803
33176
|
},
|
|
32804
33177
|
registerMountedView: function (view) {
|
|
32805
33178
|
var cid = view.cid;
|
|
32806
33179
|
var updates = this._updates;
|
|
32807
|
-
if (
|
|
32808
|
-
updates.
|
|
32809
|
-
|
|
32810
|
-
|
|
32811
|
-
|
|
33180
|
+
if (updates.mountedList.has(cid)) return 0;
|
|
33181
|
+
const unmountedItem = updates.unmountedList.get(cid);
|
|
33182
|
+
const flag = unmountedItem ? unmountedItem.value : 0;
|
|
33183
|
+
updates.unmountedList.delete(cid);
|
|
33184
|
+
updates.mountedList.pushTail(cid);
|
|
32812
33185
|
return flag;
|
|
32813
33186
|
},
|
|
32814
|
-
|
|
32815
|
-
|
|
32816
|
-
|
|
32817
|
-
|
|
32818
|
-
|
|
33187
|
+
isCellVisible: function (cellOrId) {
|
|
33188
|
+
const cid = cellOrId && this._idToCid[cellOrId.id || cellOrId];
|
|
33189
|
+
if (!cid) return false; // The view is not registered.
|
|
33190
|
+
return this.isViewMounted(cid);
|
|
33191
|
+
},
|
|
33192
|
+
isViewMounted: function (viewOrCid) {
|
|
33193
|
+
if (!viewOrCid) return false;
|
|
33194
|
+
let cid;
|
|
33195
|
+
if (viewOrCid[CELL_VIEW_MARKER] || viewOrCid[CELL_VIEW_PLACEHOLDER_MARKER]) {
|
|
33196
|
+
cid = viewOrCid.cid;
|
|
33197
|
+
} else {
|
|
33198
|
+
cid = viewOrCid;
|
|
33199
|
+
}
|
|
33200
|
+
return this._updates.mountedList.has(cid);
|
|
32819
33201
|
},
|
|
33202
|
+
/**
|
|
33203
|
+
* @deprecated use `updateCellsVisibility` instead.
|
|
33204
|
+
* `paper.updateCellsVisibility({ cellVisibility: () => true });`
|
|
33205
|
+
*/
|
|
32820
33206
|
dumpViews: function (opt) {
|
|
32821
|
-
|
|
33207
|
+
// Update cell visibility without `cellVisibility` callback i.e. make the cells visible
|
|
33208
|
+
const passingOpt = defaults({}, opt, {
|
|
33209
|
+
cellVisibility: null,
|
|
32822
33210
|
viewport: null
|
|
32823
33211
|
});
|
|
32824
|
-
this.
|
|
32825
|
-
this.updateViews(passingOpt);
|
|
33212
|
+
this.updateCellsVisibility(passingOpt);
|
|
32826
33213
|
},
|
|
32827
|
-
|
|
32828
|
-
|
|
33214
|
+
/**
|
|
33215
|
+
* Process all scheduled updates synchronously.
|
|
33216
|
+
*/
|
|
33217
|
+
updateViews: function (opt = {}) {
|
|
32829
33218
|
this.notifyBeforeRender(opt);
|
|
32830
|
-
|
|
32831
|
-
|
|
32832
|
-
|
|
32833
|
-
|
|
32834
|
-
do {
|
|
32835
|
-
batchCount++;
|
|
32836
|
-
batchStats = this.updateViewsBatch(opt);
|
|
32837
|
-
updateCount += batchStats.updated;
|
|
32838
|
-
priority = Math.min(batchStats.priority, priority);
|
|
32839
|
-
} while (!batchStats.empty);
|
|
33219
|
+
const batchStats = this.updateViewsBatch({
|
|
33220
|
+
...opt,
|
|
33221
|
+
batchSize: Infinity
|
|
33222
|
+
});
|
|
32840
33223
|
const stats = {
|
|
32841
|
-
updated:
|
|
32842
|
-
|
|
32843
|
-
|
|
33224
|
+
updated: batchStats.updated,
|
|
33225
|
+
priority: batchStats.priority,
|
|
33226
|
+
// For backward compatibility. Will be removed in the future.
|
|
33227
|
+
batches: Number.isFinite(opt.batchSize) ? Math.ceil(batchStats.updated / opt.batchSize) : 1
|
|
32844
33228
|
};
|
|
32845
33229
|
this.notifyAfterRender(stats, opt);
|
|
32846
33230
|
return stats;
|
|
32847
33231
|
},
|
|
32848
33232
|
hasScheduledUpdates: function () {
|
|
32849
|
-
const
|
|
33233
|
+
const updates = this._updates;
|
|
33234
|
+
const priorities = updates.priorities;
|
|
32850
33235
|
const priorityIndexes = Object.keys(priorities); // convert priorities to a dense array
|
|
32851
33236
|
let i = priorityIndexes.length;
|
|
32852
33237
|
while (i > 0 && i--) {
|
|
@@ -32859,15 +33244,43 @@ var joint = (function (exports) {
|
|
|
32859
33244
|
opt || (opt = {});
|
|
32860
33245
|
data || (data = {
|
|
32861
33246
|
processed: 0,
|
|
32862
|
-
priority: MIN_PRIORITY
|
|
33247
|
+
priority: MIN_PRIORITY,
|
|
33248
|
+
checkedUnmounted: 0,
|
|
33249
|
+
checkedMounted: 0
|
|
32863
33250
|
});
|
|
32864
33251
|
const {
|
|
32865
33252
|
_updates: updates,
|
|
32866
33253
|
options
|
|
32867
33254
|
} = this;
|
|
32868
|
-
const
|
|
32869
|
-
|
|
33255
|
+
const {
|
|
33256
|
+
id,
|
|
33257
|
+
mountedList,
|
|
33258
|
+
unmountedList,
|
|
33259
|
+
freshAfterReset
|
|
33260
|
+
} = updates;
|
|
33261
|
+
|
|
33262
|
+
// Should we run the next batch update this frame?
|
|
33263
|
+
let runBatchUpdate = true;
|
|
33264
|
+
if (!id) {
|
|
33265
|
+
// If there's no scheduled frame, no batch update is needed.
|
|
33266
|
+
runBatchUpdate = false;
|
|
33267
|
+
} else {
|
|
33268
|
+
// Cancel any scheduled frame.
|
|
32870
33269
|
cancelFrame(id);
|
|
33270
|
+
if (freshAfterReset) {
|
|
33271
|
+
// First update after a reset.
|
|
33272
|
+
updates.freshAfterReset = false;
|
|
33273
|
+
// When `initializeUnmounted` is enabled, there are no scheduled updates.
|
|
33274
|
+
// We check whether the `mountedList` and `unmountedList` are empty.
|
|
33275
|
+
if (!this.legacyMode && mountedList.length === 0 && unmountedList.length === 0) {
|
|
33276
|
+
// No updates to process; We trigger before/after render events via `updateViews`.
|
|
33277
|
+
// Note: If `autoFreeze` is enabled, 'idle' event triggers next frame.
|
|
33278
|
+
this.updateViews();
|
|
33279
|
+
runBatchUpdate = false;
|
|
33280
|
+
}
|
|
33281
|
+
}
|
|
33282
|
+
}
|
|
33283
|
+
if (runBatchUpdate) {
|
|
32871
33284
|
if (data.processed === 0 && this.hasScheduledUpdates()) {
|
|
32872
33285
|
this.notifyBeforeRender(opt);
|
|
32873
33286
|
}
|
|
@@ -32876,7 +33289,7 @@ var joint = (function (exports) {
|
|
|
32876
33289
|
mountBatchSize: MOUNT_BATCH_SIZE - stats.mounted,
|
|
32877
33290
|
unmountBatchSize: MOUNT_BATCH_SIZE - stats.unmounted
|
|
32878
33291
|
});
|
|
32879
|
-
const checkStats = this.
|
|
33292
|
+
const checkStats = this.scheduleCellsVisibilityUpdate(passingOpt);
|
|
32880
33293
|
const unmountCount = checkStats.unmounted;
|
|
32881
33294
|
const mountCount = checkStats.mounted;
|
|
32882
33295
|
let processed = data.processed;
|
|
@@ -32897,11 +33310,21 @@ var joint = (function (exports) {
|
|
|
32897
33310
|
} else {
|
|
32898
33311
|
data.processed = processed;
|
|
32899
33312
|
}
|
|
33313
|
+
data.checkedUnmounted = 0;
|
|
33314
|
+
data.checkedMounted = 0;
|
|
32900
33315
|
} else {
|
|
32901
|
-
|
|
32902
|
-
|
|
33316
|
+
data.checkedUnmounted += Math.max(passingOpt.mountBatchSize, 0);
|
|
33317
|
+
data.checkedMounted += Math.max(passingOpt.unmountBatchSize, 0);
|
|
33318
|
+
// The `scheduleCellsVisibilityUpdate` could have scheduled some insertions
|
|
33319
|
+
// (note that removals are currently done synchronously).
|
|
33320
|
+
if (options.autoFreeze && !this.hasScheduledUpdates()) {
|
|
33321
|
+
// If there are no updates scheduled and we checked all unmounted views,
|
|
33322
|
+
if (data.checkedUnmounted >= unmountedList.length && data.checkedMounted >= mountedList.length) {
|
|
33323
|
+
// We freeze the paper and notify the idle state.
|
|
32903
33324
|
this.freeze();
|
|
32904
|
-
updates.idle =
|
|
33325
|
+
updates.idle = {
|
|
33326
|
+
wakeUpOptions: opt
|
|
33327
|
+
};
|
|
32905
33328
|
this.trigger('render:idle', opt);
|
|
32906
33329
|
}
|
|
32907
33330
|
}
|
|
@@ -32920,6 +33343,7 @@ var joint = (function (exports) {
|
|
|
32920
33343
|
updates.id = nextFrame(this.updateViewsAsync, this, opt, data);
|
|
32921
33344
|
},
|
|
32922
33345
|
notifyBeforeRender: function (opt = {}) {
|
|
33346
|
+
if (opt.silent) return;
|
|
32923
33347
|
let beforeFn = opt.beforeRender;
|
|
32924
33348
|
if (typeof beforeFn !== 'function') {
|
|
32925
33349
|
beforeFn = this.options.beforeRender;
|
|
@@ -32928,6 +33352,7 @@ var joint = (function (exports) {
|
|
|
32928
33352
|
beforeFn.call(this, opt, this);
|
|
32929
33353
|
},
|
|
32930
33354
|
notifyAfterRender: function (stats, opt = {}) {
|
|
33355
|
+
if (opt.silent) return;
|
|
32931
33356
|
let afterFn = opt.afterRender;
|
|
32932
33357
|
if (typeof afterFn !== 'function') {
|
|
32933
33358
|
afterFn = this.options.afterRender;
|
|
@@ -32937,6 +33362,58 @@ var joint = (function (exports) {
|
|
|
32937
33362
|
}
|
|
32938
33363
|
this.trigger('render:done', stats, opt);
|
|
32939
33364
|
},
|
|
33365
|
+
prioritizeCellViewMount: function (cellOrId) {
|
|
33366
|
+
if (!cellOrId) return false;
|
|
33367
|
+
const cid = this._idToCid[cellOrId.id || cellOrId];
|
|
33368
|
+
if (!cid) return false;
|
|
33369
|
+
const {
|
|
33370
|
+
unmountedList
|
|
33371
|
+
} = this._updates;
|
|
33372
|
+
if (!unmountedList.has(cid)) return false;
|
|
33373
|
+
// Move the view to the head of the mounted list
|
|
33374
|
+
unmountedList.moveToHead(cid);
|
|
33375
|
+
return true;
|
|
33376
|
+
},
|
|
33377
|
+
prioritizeCellViewUnmount: function (cellOrId) {
|
|
33378
|
+
if (!cellOrId) return false;
|
|
33379
|
+
const cid = this._idToCid[cellOrId.id || cellOrId];
|
|
33380
|
+
if (!cid) return false;
|
|
33381
|
+
const {
|
|
33382
|
+
mountedList
|
|
33383
|
+
} = this._updates;
|
|
33384
|
+
if (!mountedList.has(cid)) return false;
|
|
33385
|
+
// Move the view to the head of the unmounted list
|
|
33386
|
+
mountedList.moveToHead(cid);
|
|
33387
|
+
return true;
|
|
33388
|
+
},
|
|
33389
|
+
_evalCellVisibility: function (viewLike, isMounted, visibilityCallback) {
|
|
33390
|
+
if (!visibilityCallback || !viewLike.DETACHABLE) return true;
|
|
33391
|
+
if (this.legacyMode) {
|
|
33392
|
+
return visibilityCallback.call(this, viewLike, isMounted, this);
|
|
33393
|
+
}
|
|
33394
|
+
// The visibility check runs for CellView only.
|
|
33395
|
+
if (!viewLike[CELL_VIEW_MARKER] && !viewLike[CELL_VIEW_PLACEHOLDER_MARKER]) return true;
|
|
33396
|
+
// The cellView model must be a member of this graph.
|
|
33397
|
+
if (viewLike.model.graph !== this.model) {
|
|
33398
|
+
// It could have been removed from the graph.
|
|
33399
|
+
// If the view was mounted, we keep it mounted.
|
|
33400
|
+
return isMounted;
|
|
33401
|
+
}
|
|
33402
|
+
return visibilityCallback.call(this, viewLike.model, isMounted, this);
|
|
33403
|
+
},
|
|
33404
|
+
_getCellVisibilityCallback: function (opt) {
|
|
33405
|
+
const {
|
|
33406
|
+
options
|
|
33407
|
+
} = this;
|
|
33408
|
+
if (this.legacyMode) {
|
|
33409
|
+
const viewportFn = 'viewport' in opt ? opt.viewport : options.viewport;
|
|
33410
|
+
if (typeof viewportFn === 'function') return viewportFn;
|
|
33411
|
+
} else {
|
|
33412
|
+
const isVisibleFn = 'cellVisibility' in opt ? opt.cellVisibility : options.cellVisibility;
|
|
33413
|
+
if (typeof isVisibleFn === 'function') return isVisibleFn;
|
|
33414
|
+
}
|
|
33415
|
+
return null;
|
|
33416
|
+
},
|
|
32940
33417
|
updateViewsBatch: function (opt) {
|
|
32941
33418
|
opt || (opt = {});
|
|
32942
33419
|
var batchSize = opt.batchSize || UPDATE_BATCH_SIZE;
|
|
@@ -32949,8 +33426,7 @@ var joint = (function (exports) {
|
|
|
32949
33426
|
var empty = true;
|
|
32950
33427
|
var options = this.options;
|
|
32951
33428
|
var priorities = updates.priorities;
|
|
32952
|
-
|
|
32953
|
-
if (typeof viewportFn !== 'function') viewportFn = null;
|
|
33429
|
+
const visibilityCb = this._getCellVisibilityCallback(opt);
|
|
32954
33430
|
var postponeViewFn = options.onViewPostponed;
|
|
32955
33431
|
if (typeof postponeViewFn !== 'function') postponeViewFn = null;
|
|
32956
33432
|
var priorityIndexes = Object.keys(priorities); // convert priorities to a dense array
|
|
@@ -32964,31 +33440,53 @@ var joint = (function (exports) {
|
|
|
32964
33440
|
}
|
|
32965
33441
|
var view = views[cid];
|
|
32966
33442
|
if (!view) {
|
|
32967
|
-
|
|
32968
|
-
|
|
32969
|
-
|
|
33443
|
+
view = this._viewPlaceholders[cid];
|
|
33444
|
+
if (!view) {
|
|
33445
|
+
/**
|
|
33446
|
+
* This can occur when:
|
|
33447
|
+
* - the model is removed and a new model with the same id is added
|
|
33448
|
+
* - the view `initialize` method was overridden and the view was not registered
|
|
33449
|
+
* - an mvc.View scheduled an update, was removed and paper was not notified
|
|
33450
|
+
*/
|
|
33451
|
+
delete priorityUpdates[cid];
|
|
33452
|
+
continue;
|
|
33453
|
+
}
|
|
32970
33454
|
}
|
|
32971
33455
|
var currentFlag = priorityUpdates[cid];
|
|
32972
|
-
if ((currentFlag &
|
|
33456
|
+
if ((currentFlag & this.FLAG_REMOVE) === 0) {
|
|
32973
33457
|
// We should never check a view for viewport if we are about to remove the view
|
|
32974
|
-
|
|
32975
|
-
if (
|
|
33458
|
+
const isMounted = !updates.unmountedList.has(cid);
|
|
33459
|
+
if (!this._evalCellVisibility(view, isMounted, visibilityCb)) {
|
|
32976
33460
|
// Unmount View
|
|
32977
|
-
if (
|
|
33461
|
+
if (isMounted) {
|
|
33462
|
+
// The view is currently mounted. Hide the view (detach or remove it).
|
|
32978
33463
|
this.registerUnmountedView(view);
|
|
32979
|
-
this.
|
|
33464
|
+
this._hideView(view);
|
|
33465
|
+
} else {
|
|
33466
|
+
// The view is not mounted. We can just update the unmounted list.
|
|
33467
|
+
// We ADD the current flag to the flag that was already scheduled.
|
|
33468
|
+
this._mergeUnmountedViewScheduledUpdates(cid, currentFlag);
|
|
32980
33469
|
}
|
|
32981
|
-
|
|
33470
|
+
// Delete the current update as it has been processed.
|
|
32982
33471
|
delete priorityUpdates[cid];
|
|
32983
33472
|
unmountCount++;
|
|
32984
33473
|
continue;
|
|
32985
33474
|
}
|
|
32986
33475
|
// Mount View
|
|
32987
|
-
if (
|
|
32988
|
-
|
|
33476
|
+
if (view[CELL_VIEW_PLACEHOLDER_MARKER]) {
|
|
33477
|
+
view = this._resolveCellViewPlaceholder(view);
|
|
33478
|
+
// Newly initialized view needs to be initialized
|
|
33479
|
+
currentFlag |= this.getCellViewInitFlag(view);
|
|
33480
|
+
}
|
|
33481
|
+
if (!isMounted) {
|
|
33482
|
+
currentFlag |= this.FLAG_INSERT;
|
|
32989
33483
|
mountCount++;
|
|
32990
33484
|
}
|
|
32991
33485
|
currentFlag |= this.registerMountedView(view);
|
|
33486
|
+
} else if (view[CELL_VIEW_PLACEHOLDER_MARKER]) {
|
|
33487
|
+
// We are trying to remove a placeholder view.
|
|
33488
|
+
// This should not occur as the placeholder should have been unregistered
|
|
33489
|
+
continue;
|
|
32992
33490
|
}
|
|
32993
33491
|
var leftoverFlag = this.updateView(view, currentFlag, opt);
|
|
32994
33492
|
if (leftoverFlag > 0) {
|
|
@@ -33014,102 +33512,127 @@ var joint = (function (exports) {
|
|
|
33014
33512
|
empty: empty
|
|
33015
33513
|
};
|
|
33016
33514
|
},
|
|
33515
|
+
getCellViewInitFlag: function (cellView) {
|
|
33516
|
+
return this.FLAG_INIT | cellView.getFlag(result(cellView, 'initFlag'));
|
|
33517
|
+
},
|
|
33518
|
+
/**
|
|
33519
|
+
* @ignore This method returns an array of cellViewLike objects and therefore
|
|
33520
|
+
* is meant for internal/test use only.
|
|
33521
|
+
* The view placeholders are not exposed via public API.
|
|
33522
|
+
*/
|
|
33017
33523
|
getUnmountedViews: function () {
|
|
33018
33524
|
const updates = this._updates;
|
|
33019
|
-
const
|
|
33020
|
-
const
|
|
33021
|
-
|
|
33022
|
-
for (
|
|
33023
|
-
|
|
33525
|
+
const unmountedViews = new Array(updates.unmountedList.length);
|
|
33526
|
+
const unmountedCids = updates.unmountedList.keys();
|
|
33527
|
+
let i = 0;
|
|
33528
|
+
for (const cid of unmountedCids) {
|
|
33529
|
+
// If the view is a placeholder, it won't be in the global views map
|
|
33530
|
+
// If the view is not a cell view, it won't be in the viewPlaceholders map
|
|
33531
|
+
unmountedViews[i++] = views[cid] || this._viewPlaceholders[cid];
|
|
33024
33532
|
}
|
|
33025
33533
|
return unmountedViews;
|
|
33026
33534
|
},
|
|
33535
|
+
/**
|
|
33536
|
+
* @ignore This method returns an array of cellViewLike objects and therefore
|
|
33537
|
+
* is meant for internal/test use only.
|
|
33538
|
+
* The view placeholders are not exposed via public API.
|
|
33539
|
+
*/
|
|
33027
33540
|
getMountedViews: function () {
|
|
33028
33541
|
const updates = this._updates;
|
|
33029
|
-
const
|
|
33030
|
-
const
|
|
33031
|
-
|
|
33032
|
-
for (
|
|
33033
|
-
mountedViews[i] = views[
|
|
33542
|
+
const mountedViews = new Array(updates.mountedList.length);
|
|
33543
|
+
const mountedCids = updates.mountedList.keys();
|
|
33544
|
+
let i = 0;
|
|
33545
|
+
for (const cid of mountedCids) {
|
|
33546
|
+
mountedViews[i++] = views[cid] || this._viewPlaceholders[cid];
|
|
33034
33547
|
}
|
|
33035
33548
|
return mountedViews;
|
|
33036
33549
|
},
|
|
33037
|
-
checkUnmountedViews: function (
|
|
33550
|
+
checkUnmountedViews: function (visibilityCb, opt) {
|
|
33038
33551
|
opt || (opt = {});
|
|
33039
33552
|
var mountCount = 0;
|
|
33040
|
-
if (typeof
|
|
33553
|
+
if (typeof visibilityCb !== 'function') visibilityCb = null;
|
|
33041
33554
|
var batchSize = 'mountBatchSize' in opt ? opt.mountBatchSize : Infinity;
|
|
33042
33555
|
var updates = this._updates;
|
|
33043
|
-
var
|
|
33044
|
-
var
|
|
33045
|
-
|
|
33046
|
-
|
|
33047
|
-
|
|
33048
|
-
|
|
33049
|
-
if (!view)
|
|
33050
|
-
|
|
33556
|
+
var unmountedList = updates.unmountedList;
|
|
33557
|
+
for (var i = 0, n = Math.min(unmountedList.length, batchSize); i < n; i++) {
|
|
33558
|
+
const {
|
|
33559
|
+
key: cid
|
|
33560
|
+
} = unmountedList.peekHead();
|
|
33561
|
+
let view = views[cid] || this._viewPlaceholders[cid];
|
|
33562
|
+
if (!view) {
|
|
33563
|
+
// This should not occur
|
|
33564
|
+
continue;
|
|
33565
|
+
}
|
|
33566
|
+
if (!this._evalCellVisibility(view, false, visibilityCb)) {
|
|
33051
33567
|
// Push at the end of all unmounted ids, so this can be check later again
|
|
33052
|
-
|
|
33568
|
+
unmountedList.rotate();
|
|
33053
33569
|
continue;
|
|
33054
33570
|
}
|
|
33571
|
+
// Remove the view from the unmounted list
|
|
33572
|
+
const {
|
|
33573
|
+
value: prevFlag
|
|
33574
|
+
} = unmountedList.popHead();
|
|
33055
33575
|
mountCount++;
|
|
33056
|
-
|
|
33576
|
+
const flag = this.registerMountedView(view) | prevFlag;
|
|
33057
33577
|
if (flag) this.scheduleViewUpdate(view, flag, view.UPDATE_PRIORITY, {
|
|
33058
33578
|
mounting: true
|
|
33059
33579
|
});
|
|
33060
33580
|
}
|
|
33061
|
-
// Get rid of views, that have been mounted
|
|
33062
|
-
unmountedCids.splice(0, i);
|
|
33063
33581
|
return mountCount;
|
|
33064
33582
|
},
|
|
33065
|
-
checkMountedViews: function (
|
|
33583
|
+
checkMountedViews: function (visibilityCb, opt) {
|
|
33066
33584
|
opt || (opt = {});
|
|
33067
33585
|
var unmountCount = 0;
|
|
33068
|
-
if (typeof
|
|
33586
|
+
if (typeof visibilityCb !== 'function') return unmountCount;
|
|
33069
33587
|
var batchSize = 'unmountBatchSize' in opt ? opt.unmountBatchSize : Infinity;
|
|
33070
33588
|
var updates = this._updates;
|
|
33071
|
-
|
|
33072
|
-
var
|
|
33073
|
-
|
|
33074
|
-
|
|
33075
|
-
|
|
33076
|
-
|
|
33077
|
-
if (!view)
|
|
33078
|
-
|
|
33589
|
+
const mountedList = updates.mountedList;
|
|
33590
|
+
for (var i = 0, n = Math.min(mountedList.length, batchSize); i < n; i++) {
|
|
33591
|
+
const {
|
|
33592
|
+
key: cid
|
|
33593
|
+
} = mountedList.peekHead();
|
|
33594
|
+
const view = views[cid];
|
|
33595
|
+
if (!view) {
|
|
33596
|
+
// A view (not a cell view) has been removed from the paper.
|
|
33597
|
+
// Remove it from the mounted list and continue.
|
|
33598
|
+
mountedList.popHead();
|
|
33599
|
+
continue;
|
|
33600
|
+
}
|
|
33601
|
+
if (this._evalCellVisibility(view, true, visibilityCb)) {
|
|
33079
33602
|
// Push at the end of all mounted ids, so this can be check later again
|
|
33080
|
-
|
|
33603
|
+
mountedList.rotate();
|
|
33081
33604
|
continue;
|
|
33082
33605
|
}
|
|
33606
|
+
// Remove the view from the mounted list
|
|
33607
|
+
mountedList.popHead();
|
|
33083
33608
|
unmountCount++;
|
|
33084
33609
|
var flag = this.registerUnmountedView(view);
|
|
33085
|
-
if (flag)
|
|
33610
|
+
if (flag) {
|
|
33611
|
+
this._hideView(view);
|
|
33612
|
+
}
|
|
33086
33613
|
}
|
|
33087
|
-
// Get rid of views, that have been unmounted
|
|
33088
|
-
mountedCids.splice(0, i);
|
|
33089
33614
|
return unmountCount;
|
|
33090
33615
|
},
|
|
33091
33616
|
checkViewVisibility: function (cellView, opt = {}) {
|
|
33092
|
-
|
|
33093
|
-
if (typeof viewportFn !== 'function') viewportFn = null;
|
|
33617
|
+
const visibilityCb = this._getCellVisibilityCallback(opt);
|
|
33094
33618
|
const updates = this._updates;
|
|
33095
33619
|
const {
|
|
33096
|
-
|
|
33097
|
-
|
|
33620
|
+
mountedList,
|
|
33621
|
+
unmountedList
|
|
33098
33622
|
} = updates;
|
|
33099
|
-
const visible =
|
|
33623
|
+
const visible = this._evalCellVisibility(cellView, false, visibilityCb);
|
|
33100
33624
|
let isUnmounted = false;
|
|
33101
33625
|
let isMounted = false;
|
|
33102
|
-
if (cellView.cid
|
|
33626
|
+
if (mountedList.has(cellView.cid) && !visible) {
|
|
33103
33627
|
const flag = this.registerUnmountedView(cellView);
|
|
33104
|
-
if (flag) this.
|
|
33105
|
-
|
|
33106
|
-
updates.mountedCids.splice(i, 1);
|
|
33628
|
+
if (flag) this._hideView(cellView);
|
|
33629
|
+
mountedList.delete(cellView.cid);
|
|
33107
33630
|
isUnmounted = true;
|
|
33108
33631
|
}
|
|
33109
|
-
if (!isUnmounted && cellView.cid
|
|
33110
|
-
const
|
|
33111
|
-
|
|
33112
|
-
|
|
33632
|
+
if (!isUnmounted && unmountedList.has(cellView.cid) && visible) {
|
|
33633
|
+
const unmountedItem = unmountedList.get(cellView.cid);
|
|
33634
|
+
unmountedList.delete(cellView.cid);
|
|
33635
|
+
const flag = unmountedItem.value | this.registerMountedView(cellView);
|
|
33113
33636
|
if (flag) this.scheduleViewUpdate(cellView, flag, cellView.UPDATE_PRIORITY, {
|
|
33114
33637
|
mounting: true
|
|
33115
33638
|
});
|
|
@@ -33120,24 +33643,64 @@ var joint = (function (exports) {
|
|
|
33120
33643
|
unmounted: isUnmounted ? 1 : 0
|
|
33121
33644
|
};
|
|
33122
33645
|
},
|
|
33123
|
-
|
|
33124
|
-
|
|
33646
|
+
/**
|
|
33647
|
+
* @public
|
|
33648
|
+
* Update the visibility of a single cell.
|
|
33649
|
+
*/
|
|
33650
|
+
updateCellVisibility: function (cell, opt = {}) {
|
|
33651
|
+
const cellViewLike = this._getCellViewLike(cell);
|
|
33652
|
+
if (!cellViewLike) return;
|
|
33653
|
+
const stats = this.checkViewVisibility(cellViewLike, opt);
|
|
33654
|
+
// Note: `unmounted` views are removed immediately
|
|
33655
|
+
if (stats.mounted > 0) {
|
|
33656
|
+
// Mounting is scheduled. Run the update.
|
|
33657
|
+
// Note: the view might be a placeholder.
|
|
33658
|
+
this.requireView(cell, opt);
|
|
33659
|
+
}
|
|
33660
|
+
},
|
|
33661
|
+
/**
|
|
33662
|
+
* @public
|
|
33663
|
+
* Update the visibility of all cells.
|
|
33664
|
+
*/
|
|
33665
|
+
updateCellsVisibility: function (opt = {}) {
|
|
33666
|
+
// Check the visibility of all cells and schedule their updates.
|
|
33667
|
+
this.scheduleCellsVisibilityUpdate(opt);
|
|
33668
|
+
// Perform the scheduled updates while avoiding re-evaluating the visibility.
|
|
33669
|
+
const keepCurrentVisibility = (_, isVisible) => isVisible;
|
|
33670
|
+
this.updateViews({
|
|
33671
|
+
...opt,
|
|
33672
|
+
cellVisibility: keepCurrentVisibility
|
|
33673
|
+
});
|
|
33674
|
+
},
|
|
33675
|
+
/**
|
|
33676
|
+
* @protected
|
|
33677
|
+
* Run visibility checks for all cells and schedule their updates.
|
|
33678
|
+
*/
|
|
33679
|
+
scheduleCellsVisibilityUpdate(opt) {
|
|
33680
|
+
const passingOpt = defaults({}, opt, {
|
|
33125
33681
|
mountBatchSize: Infinity,
|
|
33126
33682
|
unmountBatchSize: Infinity
|
|
33127
33683
|
});
|
|
33128
|
-
|
|
33129
|
-
|
|
33684
|
+
const visibilityCb = this._getCellVisibilityCallback(passingOpt);
|
|
33685
|
+
const unmountedCount = this.checkMountedViews(visibilityCb, passingOpt);
|
|
33130
33686
|
if (unmountedCount > 0) {
|
|
33131
33687
|
// Do not check views, that have been just unmounted and pushed at the end of the cids array
|
|
33132
|
-
var
|
|
33133
|
-
passingOpt.mountBatchSize = Math.min(
|
|
33688
|
+
var unmountedList = this._updates.unmountedList;
|
|
33689
|
+
passingOpt.mountBatchSize = Math.min(unmountedList.length - unmountedCount, passingOpt.mountBatchSize);
|
|
33134
33690
|
}
|
|
33135
|
-
|
|
33691
|
+
const mountedCount = this.checkUnmountedViews(visibilityCb, passingOpt);
|
|
33136
33692
|
return {
|
|
33137
33693
|
mounted: mountedCount,
|
|
33138
33694
|
unmounted: unmountedCount
|
|
33139
33695
|
};
|
|
33140
33696
|
},
|
|
33697
|
+
/**
|
|
33698
|
+
* @deprecated use `updateCellsVisibility` instead
|
|
33699
|
+
* This method will be renamed and made private in the future.
|
|
33700
|
+
*/
|
|
33701
|
+
checkViewport: function (opt) {
|
|
33702
|
+
return this.scheduleCellsVisibilityUpdate(opt);
|
|
33703
|
+
},
|
|
33141
33704
|
freeze: function (opt) {
|
|
33142
33705
|
opt || (opt = {});
|
|
33143
33706
|
var updates = this._updates;
|
|
@@ -33153,6 +33716,10 @@ var joint = (function (exports) {
|
|
|
33153
33716
|
this.options.frozen = true;
|
|
33154
33717
|
var id = updates.id;
|
|
33155
33718
|
updates.id = null;
|
|
33719
|
+
if (!this.legacyMode) {
|
|
33720
|
+
// Make sure the `freeze()` method ends the idle state.
|
|
33721
|
+
updates.idle = false;
|
|
33722
|
+
}
|
|
33156
33723
|
if (this.isAsync() && id) cancelFrame(id);
|
|
33157
33724
|
},
|
|
33158
33725
|
unfreeze: function (opt) {
|
|
@@ -33165,6 +33732,7 @@ var joint = (function (exports) {
|
|
|
33165
33732
|
updates.freezeKey = null;
|
|
33166
33733
|
// key passed, but the paper is already freezed
|
|
33167
33734
|
if (key && key === freezeKey && updates.keyFrozen) return;
|
|
33735
|
+
updates.idle = false;
|
|
33168
33736
|
if (this.isAsync()) {
|
|
33169
33737
|
this.freeze();
|
|
33170
33738
|
this.updateViewsAsync(opt);
|
|
@@ -33177,11 +33745,22 @@ var joint = (function (exports) {
|
|
|
33177
33745
|
updates.sort = false;
|
|
33178
33746
|
}
|
|
33179
33747
|
},
|
|
33748
|
+
wakeUp: function () {
|
|
33749
|
+
if (!this.isIdle()) return;
|
|
33750
|
+
this.unfreeze(this._updates.idle.wakeUpOptions);
|
|
33751
|
+
},
|
|
33180
33752
|
isAsync: function () {
|
|
33181
33753
|
return !!this.options.async;
|
|
33182
33754
|
},
|
|
33183
33755
|
isFrozen: function () {
|
|
33184
|
-
return !!this.options.frozen;
|
|
33756
|
+
return !!this.options.frozen && !this.isIdle();
|
|
33757
|
+
},
|
|
33758
|
+
isIdle: function () {
|
|
33759
|
+
if (this.legacyMode) {
|
|
33760
|
+
// Not implemented in the legacy mode.
|
|
33761
|
+
return false;
|
|
33762
|
+
}
|
|
33763
|
+
return !!(this._updates && this._updates.idle);
|
|
33185
33764
|
},
|
|
33186
33765
|
isExactSorting: function () {
|
|
33187
33766
|
return this.options.sorting === sortingTypes.EXACT;
|
|
@@ -33461,21 +34040,65 @@ var joint = (function (exports) {
|
|
|
33461
34040
|
}
|
|
33462
34041
|
return restrictedArea;
|
|
33463
34042
|
},
|
|
33464
|
-
|
|
34043
|
+
_resolveCellViewPlaceholder: function (placeholder) {
|
|
34044
|
+
const {
|
|
34045
|
+
model,
|
|
34046
|
+
viewClass,
|
|
34047
|
+
cid
|
|
34048
|
+
} = placeholder;
|
|
34049
|
+
const view = this._initializeCellView(viewClass, model, cid);
|
|
34050
|
+
this._registerCellView(view);
|
|
34051
|
+
this._unregisterCellViewPlaceholder(placeholder);
|
|
34052
|
+
return view;
|
|
34053
|
+
},
|
|
34054
|
+
_registerCellViewPlaceholder: function (cell, cid = uniqueId('view')) {
|
|
34055
|
+
const ViewClass = this._resolveCellViewClass(cell);
|
|
34056
|
+
const placeholder = {
|
|
34057
|
+
// A tag to identify the placeholder from a CellView.
|
|
34058
|
+
[CELL_VIEW_PLACEHOLDER_MARKER]: true,
|
|
34059
|
+
cid,
|
|
34060
|
+
model: cell,
|
|
34061
|
+
DETACHABLE: true,
|
|
34062
|
+
viewClass: ViewClass,
|
|
34063
|
+
UPDATE_PRIORITY: ViewClass.prototype.UPDATE_PRIORITY
|
|
34064
|
+
};
|
|
34065
|
+
this._viewPlaceholders[cid] = placeholder;
|
|
34066
|
+
return placeholder;
|
|
34067
|
+
},
|
|
34068
|
+
_registerCellView: function (cellView) {
|
|
34069
|
+
cellView.paper = this;
|
|
34070
|
+
this._views[cellView.model.id] = cellView;
|
|
34071
|
+
},
|
|
34072
|
+
_unregisterCellViewPlaceholder: function (placeholder) {
|
|
34073
|
+
delete this._viewPlaceholders[placeholder.cid];
|
|
34074
|
+
},
|
|
34075
|
+
_initializeCellView: function (ViewClass, cell, cid) {
|
|
34076
|
+
const {
|
|
34077
|
+
options
|
|
34078
|
+
} = this;
|
|
34079
|
+
const {
|
|
34080
|
+
interactive,
|
|
34081
|
+
labelsLayer
|
|
34082
|
+
} = options;
|
|
34083
|
+
return new ViewClass({
|
|
34084
|
+
cid,
|
|
34085
|
+
model: cell,
|
|
34086
|
+
interactive,
|
|
34087
|
+
labelsLayer: labelsLayer === true ? LayersNames.LABELS : labelsLayer
|
|
34088
|
+
});
|
|
34089
|
+
},
|
|
34090
|
+
_resolveCellViewClass: function (cell) {
|
|
33465
34091
|
const {
|
|
33466
34092
|
options
|
|
33467
34093
|
} = this;
|
|
34094
|
+
const {
|
|
34095
|
+
cellViewNamespace
|
|
34096
|
+
} = options;
|
|
34097
|
+
const type = cell.get('type') + 'View';
|
|
34098
|
+
const namespaceViewClass = getByPath(cellViewNamespace, type, '.');
|
|
33468
34099
|
// A class taken from the paper options.
|
|
33469
|
-
|
|
33470
|
-
|
|
33471
|
-
// A default basic class (either dia.ElementView or dia.LinkView)
|
|
33472
|
-
var defaultViewClass;
|
|
33473
|
-
|
|
33474
|
-
// A special class defined for this model in the corresponding namespace.
|
|
33475
|
-
// e.g. joint.shapes.standard.Rectangle searches for joint.shapes.standard.RectangleView
|
|
33476
|
-
var namespace = options.cellViewNamespace;
|
|
33477
|
-
var type = cell.get('type') + 'View';
|
|
33478
|
-
var namespaceViewClass = getByPath(namespace, type, '.');
|
|
34100
|
+
let optionalViewClass;
|
|
34101
|
+
let defaultViewClass;
|
|
33479
34102
|
if (cell.isLink()) {
|
|
33480
34103
|
optionalViewClass = options.linkView;
|
|
33481
34104
|
defaultViewClass = LinkView;
|
|
@@ -33483,7 +34106,6 @@ var joint = (function (exports) {
|
|
|
33483
34106
|
optionalViewClass = options.elementView;
|
|
33484
34107
|
defaultViewClass = ElementView;
|
|
33485
34108
|
}
|
|
33486
|
-
|
|
33487
34109
|
// a) the paper options view is a class (deprecated)
|
|
33488
34110
|
// 1. search the namespace for a view
|
|
33489
34111
|
// 2. if no view was found, use view from the paper options
|
|
@@ -33491,12 +34113,33 @@ var joint = (function (exports) {
|
|
|
33491
34113
|
// 1. call the function from the paper options
|
|
33492
34114
|
// 2. if no view was return, search the namespace for a view
|
|
33493
34115
|
// 3. if no view was found, use the default
|
|
33494
|
-
|
|
33495
|
-
|
|
33496
|
-
|
|
33497
|
-
|
|
33498
|
-
|
|
33499
|
-
|
|
34116
|
+
return optionalViewClass.prototype instanceof ViewBase ? namespaceViewClass || optionalViewClass : optionalViewClass.call(this, cell) || namespaceViewClass || defaultViewClass;
|
|
34117
|
+
},
|
|
34118
|
+
// Returns a CellView instance or its placeholder for the given cell.
|
|
34119
|
+
_getCellViewLike: function (cell) {
|
|
34120
|
+
let id;
|
|
34121
|
+
if (isString(cell) || isNumber(cell)) {
|
|
34122
|
+
// If the cell is a string or number, it is an id of the view.
|
|
34123
|
+
id = cell;
|
|
34124
|
+
} else if (cell) {
|
|
34125
|
+
// If the cell is an object, it should have an id property.
|
|
34126
|
+
id = cell.id;
|
|
34127
|
+
} else {
|
|
34128
|
+
// If the cell is falsy, return null.
|
|
34129
|
+
return null;
|
|
34130
|
+
}
|
|
34131
|
+
const view = this._views[id];
|
|
34132
|
+
if (view) return view;
|
|
34133
|
+
|
|
34134
|
+
// If the view is not found, it may be a placeholder
|
|
34135
|
+
const cid = this._idToCid[id];
|
|
34136
|
+
if (cid) {
|
|
34137
|
+
return this._viewPlaceholders[cid];
|
|
34138
|
+
}
|
|
34139
|
+
return null;
|
|
34140
|
+
},
|
|
34141
|
+
createViewForModel: function (cell, cid) {
|
|
34142
|
+
return this._initializeCellView(this._resolveCellViewClass(cell), cell, cid);
|
|
33500
34143
|
},
|
|
33501
34144
|
removeView: function (cell) {
|
|
33502
34145
|
const {
|
|
@@ -33512,13 +34155,14 @@ var joint = (function (exports) {
|
|
|
33512
34155
|
cid
|
|
33513
34156
|
} = view;
|
|
33514
34157
|
const {
|
|
33515
|
-
|
|
33516
|
-
|
|
34158
|
+
mountedList,
|
|
34159
|
+
unmountedList
|
|
33517
34160
|
} = _updates;
|
|
33518
34161
|
view.remove();
|
|
33519
34162
|
delete _views[id];
|
|
33520
|
-
delete
|
|
33521
|
-
delete
|
|
34163
|
+
delete this._idToCid[id];
|
|
34164
|
+
mountedList.delete(cid);
|
|
34165
|
+
unmountedList.delete(cid);
|
|
33522
34166
|
}
|
|
33523
34167
|
return view;
|
|
33524
34168
|
},
|
|
@@ -33532,7 +34176,7 @@ var joint = (function (exports) {
|
|
|
33532
34176
|
if (id in views) {
|
|
33533
34177
|
view = views[id];
|
|
33534
34178
|
if (view.model === cell) {
|
|
33535
|
-
flag =
|
|
34179
|
+
flag = this.FLAG_INSERT;
|
|
33536
34180
|
create = false;
|
|
33537
34181
|
} else {
|
|
33538
34182
|
// The view for this `id` already exist.
|
|
@@ -33542,13 +34186,42 @@ var joint = (function (exports) {
|
|
|
33542
34186
|
}
|
|
33543
34187
|
}
|
|
33544
34188
|
if (create) {
|
|
33545
|
-
|
|
33546
|
-
|
|
33547
|
-
|
|
34189
|
+
const {
|
|
34190
|
+
viewManagement
|
|
34191
|
+
} = this.options;
|
|
34192
|
+
const cid = uniqueId('view');
|
|
34193
|
+
this._idToCid[cell.id] = cid;
|
|
34194
|
+
if (viewManagement.lazyInitialize) {
|
|
34195
|
+
// Register only a placeholder for the view
|
|
34196
|
+
view = this._registerCellViewPlaceholder(cell, cid);
|
|
34197
|
+
flag = this.registerUnmountedView(view);
|
|
34198
|
+
} else {
|
|
34199
|
+
// Create a new view instance
|
|
34200
|
+
view = this.createViewForModel(cell, cid);
|
|
34201
|
+
this._registerCellView(view);
|
|
34202
|
+
flag = this.registerUnmountedView(view);
|
|
34203
|
+
// The newly created view needs to be initialized
|
|
34204
|
+
flag |= this.getCellViewInitFlag(view);
|
|
34205
|
+
}
|
|
34206
|
+
if (viewManagement.initializeUnmounted) {
|
|
34207
|
+
// Save the initialization flags for later and exit early
|
|
34208
|
+
this._mergeUnmountedViewScheduledUpdates(cid, flag);
|
|
34209
|
+
return view;
|
|
34210
|
+
}
|
|
33548
34211
|
}
|
|
33549
34212
|
this.requestViewUpdate(view, flag, view.UPDATE_PRIORITY, opt);
|
|
33550
34213
|
return view;
|
|
33551
34214
|
},
|
|
34215
|
+
// Update the view flags in the `unmountedList` using the bitwise OR operation
|
|
34216
|
+
_mergeUnmountedViewScheduledUpdates: function (cid, flag) {
|
|
34217
|
+
const {
|
|
34218
|
+
unmountedList
|
|
34219
|
+
} = this._updates;
|
|
34220
|
+
const unmountedItem = unmountedList.get(cid);
|
|
34221
|
+
if (unmountedItem) {
|
|
34222
|
+
unmountedItem.value |= flag;
|
|
34223
|
+
}
|
|
34224
|
+
},
|
|
33552
34225
|
onImageDragStart: function () {
|
|
33553
34226
|
// This is the only way to prevent image dragging in Firefox that works.
|
|
33554
34227
|
// Setting -moz-user-select: none, draggable="false" attribute or user-drag: none didn't help.
|
|
@@ -33558,11 +34231,11 @@ var joint = (function (exports) {
|
|
|
33558
34231
|
resetViews: function (cells, opt) {
|
|
33559
34232
|
opt || (opt = {});
|
|
33560
34233
|
cells || (cells = []);
|
|
34234
|
+
// Allows to unfreeze normally while in the idle state using autoFreeze option
|
|
34235
|
+
const key = (this.legacyMode ? this.options.autoFreeze : this.isIdle()) ? null : 'reset';
|
|
33561
34236
|
this._resetUpdates();
|
|
33562
34237
|
// clearing views removes any event listeners
|
|
33563
34238
|
this.removeViews();
|
|
33564
|
-
// Allows to unfreeze normally while in the idle state using autoFreeze option
|
|
33565
|
-
const key = this.options.autoFreeze ? null : 'reset';
|
|
33566
34239
|
this.freeze({
|
|
33567
34240
|
key
|
|
33568
34241
|
});
|
|
@@ -33575,15 +34248,23 @@ var joint = (function (exports) {
|
|
|
33575
34248
|
this.sortViews();
|
|
33576
34249
|
},
|
|
33577
34250
|
removeViews: function () {
|
|
33578
|
-
|
|
34251
|
+
// Remove all views and their references from the paper.
|
|
34252
|
+
for (const id in this._views) {
|
|
34253
|
+
const view = this._views[id];
|
|
34254
|
+
if (view) {
|
|
34255
|
+
view.remove();
|
|
34256
|
+
}
|
|
34257
|
+
}
|
|
33579
34258
|
this._views = {};
|
|
34259
|
+
this._viewPlaceholders = {};
|
|
34260
|
+
this._idToCid = {};
|
|
33580
34261
|
},
|
|
33581
34262
|
sortViews: function () {
|
|
33582
34263
|
if (!this.isExactSorting()) {
|
|
33583
34264
|
// noop
|
|
33584
34265
|
return;
|
|
33585
34266
|
}
|
|
33586
|
-
if (this.isFrozen()) {
|
|
34267
|
+
if (this.isFrozen() || this.isIdle()) {
|
|
33587
34268
|
// sort views once unfrozen
|
|
33588
34269
|
this._updates.sort = true;
|
|
33589
34270
|
return;
|
|
@@ -33622,9 +34303,54 @@ var joint = (function (exports) {
|
|
|
33622
34303
|
}
|
|
33623
34304
|
view.onMount(isInitialInsert);
|
|
33624
34305
|
},
|
|
33625
|
-
|
|
33626
|
-
|
|
33627
|
-
|
|
34306
|
+
_hideView: function (viewLike) {
|
|
34307
|
+
if (!viewLike || viewLike[CELL_VIEW_PLACEHOLDER_MARKER]) {
|
|
34308
|
+
// A placeholder view was never mounted
|
|
34309
|
+
return;
|
|
34310
|
+
}
|
|
34311
|
+
if (viewLike[CELL_VIEW_MARKER]) {
|
|
34312
|
+
this._hideCellView(viewLike);
|
|
34313
|
+
} else {
|
|
34314
|
+
// A generic view that is not a cell view.
|
|
34315
|
+
viewLike.unmount();
|
|
34316
|
+
}
|
|
34317
|
+
},
|
|
34318
|
+
// If `cellVisibility` returns `false`, the view will be hidden using this method.
|
|
34319
|
+
_hideCellView: function (cellView) {
|
|
34320
|
+
if (this.options.viewManagement.disposeHidden) {
|
|
34321
|
+
if (this._disposeCellView(cellView)) return;
|
|
34322
|
+
}
|
|
34323
|
+
// Detach the view from the paper, but keep it in memory
|
|
34324
|
+
this._detachCellView(cellView);
|
|
34325
|
+
},
|
|
34326
|
+
_disposeCellView: function (cellView) {
|
|
34327
|
+
if (HighlighterView.has(cellView) || cellView.hasTools()) {
|
|
34328
|
+
// We currently do not dispose views which has a highlighter or tools attached
|
|
34329
|
+
// Note: Possible improvement would be to serialize highlighters/tools and
|
|
34330
|
+
// restore them on view re-mount.
|
|
34331
|
+
return false;
|
|
34332
|
+
}
|
|
34333
|
+
const cell = cellView.model;
|
|
34334
|
+
// Remove the view from the paper and dispose it
|
|
34335
|
+
cellView.remove();
|
|
34336
|
+
delete this._views[cell.id];
|
|
34337
|
+
this._registerCellViewPlaceholder(cell, cellView.cid);
|
|
34338
|
+
return true;
|
|
34339
|
+
},
|
|
34340
|
+
// Dispose (release resources) all hidden views.
|
|
34341
|
+
disposeHiddenCellViews: function () {
|
|
34342
|
+
// Only cell views can be in the unmounted list (not in the legacy mode).
|
|
34343
|
+
if (this.legacyMode) return;
|
|
34344
|
+
const unmountedCids = this._updates.unmountedList.keys();
|
|
34345
|
+
for (const cid of unmountedCids) {
|
|
34346
|
+
const cellView = views[cid];
|
|
34347
|
+
cellView && this._disposeCellView(cellView);
|
|
34348
|
+
}
|
|
34349
|
+
},
|
|
34350
|
+
// Detach a view from the paper, but keep it in memory.
|
|
34351
|
+
_detachCellView(cellView) {
|
|
34352
|
+
cellView.unmount();
|
|
34353
|
+
cellView.onDetach();
|
|
33628
34354
|
},
|
|
33629
34355
|
// Find the first view climbing up the DOM tree starting at element `el`. Note that `el` can also
|
|
33630
34356
|
// be a selector or a jQuery object.
|
|
@@ -33635,9 +34361,31 @@ var joint = (function (exports) {
|
|
|
33635
34361
|
return undefined;
|
|
33636
34362
|
},
|
|
33637
34363
|
// Find a view for a model `cell`. `cell` can also be a string or number representing a model `id`.
|
|
33638
|
-
findViewByModel: function (
|
|
33639
|
-
|
|
33640
|
-
return
|
|
34364
|
+
findViewByModel: function (cellOrId) {
|
|
34365
|
+
const cellViewLike = this._getCellViewLike(cellOrId);
|
|
34366
|
+
if (!cellViewLike) return undefined;
|
|
34367
|
+
if (cellViewLike[CELL_VIEW_MARKER]) {
|
|
34368
|
+
// If the view is not a placeholder, return it directly
|
|
34369
|
+
return cellViewLike;
|
|
34370
|
+
}
|
|
34371
|
+
// We do not expose placeholder views directly. We resolve them before returning.
|
|
34372
|
+
const cellView = this._resolveCellViewPlaceholder(cellViewLike);
|
|
34373
|
+
const flag = this.getCellViewInitFlag(cellView);
|
|
34374
|
+
if (this.isViewMounted(cellView)) {
|
|
34375
|
+
// The view was acting as a placeholder and is already present in the `mounted` list,
|
|
34376
|
+
// indicating that its visibility has been checked, but the update hasn't occurred yet.
|
|
34377
|
+
// Placeholders are resolved during the update routine. Since we're handling it
|
|
34378
|
+
// manually here, we must ensure the view is properly initialized on the next update.
|
|
34379
|
+
this.scheduleViewUpdate(cellView, flag, cellView.UPDATE_PRIORITY, {
|
|
34380
|
+
// It's important to run in isolation to avoid triggering the update of
|
|
34381
|
+
// connected links
|
|
34382
|
+
isolate: true
|
|
34383
|
+
});
|
|
34384
|
+
} else {
|
|
34385
|
+
// Update the flags in the `unmounted` list
|
|
34386
|
+
this._mergeUnmountedViewScheduledUpdates(cellView.cid, flag);
|
|
34387
|
+
}
|
|
34388
|
+
return cellView;
|
|
33641
34389
|
},
|
|
33642
34390
|
// Find all views at given point
|
|
33643
34391
|
findViewsFromPoint: function (p) {
|
|
@@ -33684,6 +34432,93 @@ var joint = (function (exports) {
|
|
|
33684
34432
|
// because the `strict` option works differently for querying at a point
|
|
33685
34433
|
extArea => this.model.findCellsInArea(extArea), opt);
|
|
33686
34434
|
},
|
|
34435
|
+
findClosestMagnetToPoint: function (point, options = {}) {
|
|
34436
|
+
let minDistance = Number.MAX_SAFE_INTEGER;
|
|
34437
|
+
let bestPriority = -Infinity;
|
|
34438
|
+
const pointer = new Point(point);
|
|
34439
|
+
const radius = options.radius || Number.MAX_SAFE_INTEGER;
|
|
34440
|
+
const viewsInArea = this.findCellViewsInArea({
|
|
34441
|
+
x: pointer.x - radius,
|
|
34442
|
+
y: pointer.y - radius,
|
|
34443
|
+
width: 2 * radius,
|
|
34444
|
+
height: 2 * radius
|
|
34445
|
+
}, options.findInAreaOptions);
|
|
34446
|
+
// Enable all connections by default
|
|
34447
|
+
const filterFn = typeof options.filter === 'function' ? options.filter : null;
|
|
34448
|
+
let closestView = null;
|
|
34449
|
+
let closestMagnet = null;
|
|
34450
|
+
|
|
34451
|
+
// Note: If snapRadius is smaller than magnet size, views will not be found.
|
|
34452
|
+
viewsInArea.forEach(view => {
|
|
34453
|
+
const candidates = [];
|
|
34454
|
+
const {
|
|
34455
|
+
model
|
|
34456
|
+
} = view;
|
|
34457
|
+
// skip connecting to the element in case '.': { magnet: false } attribute present
|
|
34458
|
+
if (view.el.getAttribute('magnet') !== 'false') {
|
|
34459
|
+
if (model.isLink()) {
|
|
34460
|
+
const connection = view.getConnection();
|
|
34461
|
+
candidates.push({
|
|
34462
|
+
// find distance from the closest point of a link to pointer coordinates
|
|
34463
|
+
priority: 0,
|
|
34464
|
+
distance: connection.closestPoint(pointer).squaredDistance(pointer),
|
|
34465
|
+
magnet: view.el
|
|
34466
|
+
});
|
|
34467
|
+
} else {
|
|
34468
|
+
candidates.push({
|
|
34469
|
+
// Set the priority to the level of nested elements of the model
|
|
34470
|
+
// To ensure that the embedded cells get priority over the parent cells
|
|
34471
|
+
priority: model.getAncestors().length,
|
|
34472
|
+
// find distance from the center of the model to pointer coordinates
|
|
34473
|
+
distance: model.getBBox().center().squaredDistance(pointer),
|
|
34474
|
+
magnet: view.el
|
|
34475
|
+
});
|
|
34476
|
+
}
|
|
34477
|
+
}
|
|
34478
|
+
view.$('[magnet]').toArray().forEach(magnet => {
|
|
34479
|
+
const magnetBBox = view.getNodeBBox(magnet);
|
|
34480
|
+
let magnetDistance = magnetBBox.pointNearestToPoint(pointer).squaredDistance(pointer);
|
|
34481
|
+
if (magnetBBox.containsPoint(pointer)) {
|
|
34482
|
+
// Pointer sits inside this magnet.
|
|
34483
|
+
// Push its distance far into the negative range so any
|
|
34484
|
+
// "under-pointer" magnet outranks magnets that are only nearby
|
|
34485
|
+
// (positive distance) and every non-magnet candidate.
|
|
34486
|
+
// We add the original distance back to keep ordering among
|
|
34487
|
+
// overlapping magnets: the one whose border is closest to the
|
|
34488
|
+
// pointer (smaller original distance) still wins.
|
|
34489
|
+
magnetDistance = -Number.MAX_SAFE_INTEGER + magnetDistance;
|
|
34490
|
+
}
|
|
34491
|
+
|
|
34492
|
+
// Check if magnet is inside the snap radius.
|
|
34493
|
+
if (magnetDistance <= radius * radius) {
|
|
34494
|
+
candidates.push({
|
|
34495
|
+
// Give magnets priority over other candidates.
|
|
34496
|
+
priority: Number.MAX_SAFE_INTEGER,
|
|
34497
|
+
distance: magnetDistance,
|
|
34498
|
+
magnet
|
|
34499
|
+
});
|
|
34500
|
+
}
|
|
34501
|
+
});
|
|
34502
|
+
candidates.forEach(candidate => {
|
|
34503
|
+
const {
|
|
34504
|
+
magnet,
|
|
34505
|
+
distance,
|
|
34506
|
+
priority
|
|
34507
|
+
} = candidate;
|
|
34508
|
+
const isBetterCandidate = priority > bestPriority || priority === bestPriority && distance < minDistance;
|
|
34509
|
+
if (isBetterCandidate && (!filterFn || filterFn(view, magnet))) {
|
|
34510
|
+
bestPriority = priority;
|
|
34511
|
+
minDistance = distance;
|
|
34512
|
+
closestView = view;
|
|
34513
|
+
closestMagnet = magnet;
|
|
34514
|
+
}
|
|
34515
|
+
});
|
|
34516
|
+
});
|
|
34517
|
+
return closestView ? {
|
|
34518
|
+
view: closestView,
|
|
34519
|
+
magnet: closestMagnet
|
|
34520
|
+
} : null;
|
|
34521
|
+
},
|
|
33687
34522
|
_findInExtendedArea: function (area, findCellsFn, opt = {}) {
|
|
33688
34523
|
const {
|
|
33689
34524
|
buffer = this.DEFAULT_FIND_BUFFER
|
|
@@ -34066,8 +34901,11 @@ var joint = (function (exports) {
|
|
|
34066
34901
|
if (mousemoved <= this.options.moveThreshold) return;
|
|
34067
34902
|
evt = normalizeEvent(evt);
|
|
34068
34903
|
var localPoint = this.snapToGrid(evt.clientX, evt.clientY);
|
|
34069
|
-
|
|
34904
|
+
let view = data.sourceView;
|
|
34070
34905
|
if (view) {
|
|
34906
|
+
// The view could have been disposed during dragging
|
|
34907
|
+
// e.g. dragged outside of the viewport and hidden
|
|
34908
|
+
view = this.findViewByModel(view.model);
|
|
34071
34909
|
view.pointermove(evt, localPoint.x, localPoint.y);
|
|
34072
34910
|
} else {
|
|
34073
34911
|
this.trigger('blank:pointermove', evt, localPoint.x, localPoint.y);
|
|
@@ -34078,8 +34916,11 @@ var joint = (function (exports) {
|
|
|
34078
34916
|
this.undelegateDocumentEvents();
|
|
34079
34917
|
var normalizedEvt = normalizeEvent(evt);
|
|
34080
34918
|
var localPoint = this.snapToGrid(normalizedEvt.clientX, normalizedEvt.clientY);
|
|
34081
|
-
|
|
34919
|
+
let view = this.eventData(evt).sourceView;
|
|
34082
34920
|
if (view) {
|
|
34921
|
+
// The view could have been disposed during dragging
|
|
34922
|
+
// e.g. dragged outside of the viewport and hidden
|
|
34923
|
+
view = this.findViewByModel(view.model);
|
|
34083
34924
|
view.pointerup(normalizedEvt, localPoint.x, localPoint.y);
|
|
34084
34925
|
} else {
|
|
34085
34926
|
this.trigger('blank:pointerup', normalizedEvt, localPoint.x, localPoint.y);
|
|
@@ -34945,6 +35786,9 @@ var joint = (function (exports) {
|
|
|
34945
35786
|
isVisible: function () {
|
|
34946
35787
|
return !!this._visible;
|
|
34947
35788
|
},
|
|
35789
|
+
isOverlay: function () {
|
|
35790
|
+
return !!this.parentView && this.parentView.hasLayer();
|
|
35791
|
+
},
|
|
34948
35792
|
focus: function () {
|
|
34949
35793
|
var opacity = this.options.focusOpacity;
|
|
34950
35794
|
if (isFinite(opacity)) this.el.style.opacity = opacity;
|
|
@@ -35090,6 +35934,15 @@ var joint = (function (exports) {
|
|
|
35090
35934
|
}
|
|
35091
35935
|
this.tools = null;
|
|
35092
35936
|
},
|
|
35937
|
+
getLayer() {
|
|
35938
|
+
const {
|
|
35939
|
+
layer = LayersNames.TOOLS
|
|
35940
|
+
} = this.options;
|
|
35941
|
+
return layer;
|
|
35942
|
+
},
|
|
35943
|
+
hasLayer() {
|
|
35944
|
+
return !!this.getLayer();
|
|
35945
|
+
},
|
|
35093
35946
|
mount: function () {
|
|
35094
35947
|
const {
|
|
35095
35948
|
options,
|
|
@@ -35097,12 +35950,11 @@ var joint = (function (exports) {
|
|
|
35097
35950
|
} = this;
|
|
35098
35951
|
const {
|
|
35099
35952
|
relatedView,
|
|
35100
|
-
layer = LayersNames.TOOLS,
|
|
35101
35953
|
z
|
|
35102
35954
|
} = options;
|
|
35103
35955
|
if (relatedView) {
|
|
35104
|
-
if (
|
|
35105
|
-
relatedView.paper.getLayerView(
|
|
35956
|
+
if (this.hasLayer()) {
|
|
35957
|
+
relatedView.paper.getLayerView(this.getLayer()).insertSortedNode(el, z);
|
|
35106
35958
|
} else {
|
|
35107
35959
|
relatedView.el.appendChild(el);
|
|
35108
35960
|
}
|
|
@@ -35113,6 +35965,7 @@ var joint = (function (exports) {
|
|
|
35113
35965
|
|
|
35114
35966
|
var index$2 = {
|
|
35115
35967
|
__proto__: null,
|
|
35968
|
+
CELL_VIEW_MARKER: CELL_VIEW_MARKER,
|
|
35116
35969
|
Cell: Cell,
|
|
35117
35970
|
CellView: CellView,
|
|
35118
35971
|
Element: Element$1,
|
|
@@ -35461,12 +36314,57 @@ var joint = (function (exports) {
|
|
|
35461
36314
|
VertexHandle: VertexHandle // keep as class property
|
|
35462
36315
|
});
|
|
35463
36316
|
|
|
35464
|
-
|
|
36317
|
+
/**
|
|
36318
|
+
* Common helper for getting a cell view’s bounding box,
|
|
36319
|
+
* configurable with `useModelGeometry`, `relative`, and `el`.
|
|
36320
|
+
*/
|
|
36321
|
+
function getViewBBox(view, {
|
|
36322
|
+
useModelGeometry = false,
|
|
36323
|
+
relative = false,
|
|
36324
|
+
el = view.el
|
|
36325
|
+
} = {}) {
|
|
35465
36326
|
const {
|
|
35466
36327
|
model
|
|
35467
36328
|
} = view;
|
|
35468
|
-
|
|
35469
|
-
|
|
36329
|
+
let bbox;
|
|
36330
|
+
if (useModelGeometry) {
|
|
36331
|
+
// cell model bbox
|
|
36332
|
+
bbox = model.getBBox();
|
|
36333
|
+
} else if (model.isLink()) {
|
|
36334
|
+
// link view bbox
|
|
36335
|
+
bbox = view.getConnection().bbox();
|
|
36336
|
+
} else {
|
|
36337
|
+
// element view bbox
|
|
36338
|
+
bbox = view.getNodeUnrotatedBBox(el);
|
|
36339
|
+
}
|
|
36340
|
+
if (relative) {
|
|
36341
|
+
// Relative to the element position.
|
|
36342
|
+
const position = model.position();
|
|
36343
|
+
bbox.x -= position.x;
|
|
36344
|
+
bbox.y -= position.y;
|
|
36345
|
+
}
|
|
36346
|
+
return bbox;
|
|
36347
|
+
}
|
|
36348
|
+
|
|
36349
|
+
/**
|
|
36350
|
+
* Retrieves the tool options.
|
|
36351
|
+
* Automatically overrides `useModelGeometry` and `rotate`
|
|
36352
|
+
* if the tool is positioned relative to the element.
|
|
36353
|
+
*/
|
|
36354
|
+
function getToolOptions(toolView) {
|
|
36355
|
+
// Positioning is relative if the tool is drawn within the element view.
|
|
36356
|
+
const relative = !toolView.isOverlay();
|
|
36357
|
+
const {
|
|
36358
|
+
useModelGeometry,
|
|
36359
|
+
rotate,
|
|
36360
|
+
...otherOptions
|
|
36361
|
+
} = toolView.options;
|
|
36362
|
+
return {
|
|
36363
|
+
...otherOptions,
|
|
36364
|
+
useModelGeometry: useModelGeometry || relative,
|
|
36365
|
+
rotate: rotate || relative,
|
|
36366
|
+
relative
|
|
36367
|
+
};
|
|
35470
36368
|
}
|
|
35471
36369
|
function getAnchor(coords, view, magnet) {
|
|
35472
36370
|
// take advantage of an existing logic inside of the
|
|
@@ -36304,29 +37202,40 @@ var joint = (function (exports) {
|
|
|
36304
37202
|
return this;
|
|
36305
37203
|
},
|
|
36306
37204
|
updateHandle: function (handleNode) {
|
|
37205
|
+
const {
|
|
37206
|
+
options: {
|
|
37207
|
+
handleAttributes
|
|
37208
|
+
}
|
|
37209
|
+
} = this;
|
|
37210
|
+
handleNode.setAttribute('transform', this.getHandleTransformString());
|
|
37211
|
+
if (handleAttributes) {
|
|
37212
|
+
for (let attrName in handleAttributes) {
|
|
37213
|
+
handleNode.setAttribute(attrName, handleAttributes[attrName]);
|
|
37214
|
+
}
|
|
37215
|
+
}
|
|
37216
|
+
},
|
|
37217
|
+
getHandleTransformString() {
|
|
36307
37218
|
const {
|
|
36308
37219
|
relatedView,
|
|
36309
37220
|
options
|
|
36310
37221
|
} = this;
|
|
37222
|
+
const {
|
|
37223
|
+
scale
|
|
37224
|
+
} = options;
|
|
36311
37225
|
const {
|
|
36312
37226
|
model
|
|
36313
37227
|
} = relatedView;
|
|
36314
37228
|
const relativePos = this.getPosition(relatedView, this);
|
|
36315
|
-
const
|
|
36316
|
-
|
|
36317
|
-
|
|
36318
|
-
|
|
36319
|
-
|
|
36320
|
-
let transformString = `translate(${
|
|
37229
|
+
const translate = this.isOverlay()
|
|
37230
|
+
// The tool is rendered in the coordinate system of the paper
|
|
37231
|
+
? model.getAbsolutePointFromRelative(relativePos)
|
|
37232
|
+
// The tool is rendered in the coordinate system of the relatedView
|
|
37233
|
+
: relativePos;
|
|
37234
|
+
let transformString = `translate(${translate.x},${translate.y})`;
|
|
36321
37235
|
if (scale) {
|
|
36322
37236
|
transformString += ` scale(${scale})`;
|
|
36323
37237
|
}
|
|
36324
|
-
|
|
36325
|
-
if (handleAttributes) {
|
|
36326
|
-
for (let attrName in handleAttributes) {
|
|
36327
|
-
handleNode.setAttribute(attrName, handleAttributes[attrName]);
|
|
36328
|
-
}
|
|
36329
|
-
}
|
|
37238
|
+
return transformString;
|
|
36330
37239
|
},
|
|
36331
37240
|
updateExtras: function (extrasNode) {
|
|
36332
37241
|
const {
|
|
@@ -36334,19 +37243,40 @@ var joint = (function (exports) {
|
|
|
36334
37243
|
options
|
|
36335
37244
|
} = this;
|
|
36336
37245
|
const {
|
|
36337
|
-
selector
|
|
36338
|
-
|
|
37246
|
+
selector,
|
|
37247
|
+
relative,
|
|
37248
|
+
useModelGeometry
|
|
37249
|
+
} = getToolOptions(this);
|
|
36339
37250
|
if (!selector) {
|
|
37251
|
+
// Hide the extras if no selector is given.
|
|
36340
37252
|
this.toggleExtras(false);
|
|
36341
37253
|
return;
|
|
36342
37254
|
}
|
|
36343
|
-
|
|
36344
|
-
|
|
37255
|
+
// Get the size for the extras rectangle and update it.
|
|
37256
|
+
let bbox;
|
|
37257
|
+
if (useModelGeometry) {
|
|
37258
|
+
if (selector !== 'root') {
|
|
37259
|
+
// A selector other than null or `root` was provided.
|
|
37260
|
+
console.warn('Control: selector will be ignored when `useModelGeometry` is used.');
|
|
37261
|
+
}
|
|
37262
|
+
bbox = getViewBBox(relatedView, {
|
|
37263
|
+
useModelGeometry,
|
|
37264
|
+
relative
|
|
37265
|
+
});
|
|
37266
|
+
} else {
|
|
37267
|
+
// The reference node for calculating the bounding box of the extras.
|
|
37268
|
+
const el = relatedView.findNode(selector);
|
|
37269
|
+
if (!el) throw new Error('Control: invalid selector.');
|
|
37270
|
+
bbox = getViewBBox(relatedView, {
|
|
37271
|
+
el
|
|
37272
|
+
});
|
|
37273
|
+
}
|
|
36345
37274
|
let padding = options.padding;
|
|
36346
37275
|
if (!isFinite(padding)) padding = 0;
|
|
36347
|
-
const bbox = relatedView.getNodeUnrotatedBBox(magnet);
|
|
36348
37276
|
const model = relatedView.model;
|
|
36349
|
-
|
|
37277
|
+
// With relative positioning, rotation is implicit
|
|
37278
|
+
// (the tool rotates along with the element).
|
|
37279
|
+
const angle = relative ? 0 : model.angle();
|
|
36350
37280
|
const center = bbox.center();
|
|
36351
37281
|
if (angle) center.rotate(model.getCenter(), -angle);
|
|
36352
37282
|
bbox.inflate(padding);
|
|
@@ -36557,8 +37487,7 @@ var joint = (function (exports) {
|
|
|
36557
37487
|
},
|
|
36558
37488
|
getElementMatrix() {
|
|
36559
37489
|
const {
|
|
36560
|
-
relatedView: view
|
|
36561
|
-
options
|
|
37490
|
+
relatedView: view
|
|
36562
37491
|
} = this;
|
|
36563
37492
|
let {
|
|
36564
37493
|
x = 0,
|
|
@@ -36566,9 +37495,13 @@ var joint = (function (exports) {
|
|
|
36566
37495
|
offset = {},
|
|
36567
37496
|
useModelGeometry,
|
|
36568
37497
|
rotate,
|
|
36569
|
-
scale
|
|
36570
|
-
|
|
36571
|
-
|
|
37498
|
+
scale,
|
|
37499
|
+
relative
|
|
37500
|
+
} = getToolOptions(this);
|
|
37501
|
+
let bbox = getViewBBox(view, {
|
|
37502
|
+
useModelGeometry,
|
|
37503
|
+
relative
|
|
37504
|
+
});
|
|
36572
37505
|
const angle = view.model.angle();
|
|
36573
37506
|
if (!rotate) bbox = bbox.bbox(angle);
|
|
36574
37507
|
const {
|
|
@@ -36586,7 +37519,9 @@ var joint = (function (exports) {
|
|
|
36586
37519
|
y = Number(evalCalcExpression(y, bbox));
|
|
36587
37520
|
}
|
|
36588
37521
|
let matrix = V.createSVGMatrix().translate(bbox.x + bbox.width / 2, bbox.y + bbox.height / 2);
|
|
36589
|
-
|
|
37522
|
+
// With relative positioning, rotation is implicit
|
|
37523
|
+
// (the tool rotates along with the element).
|
|
37524
|
+
if (rotate && !relative) matrix = matrix.rotate(angle);
|
|
36590
37525
|
matrix = matrix.translate(x + offsetX - bbox.width / 2, y + offsetY - bbox.height / 2);
|
|
36591
37526
|
if (scale) matrix = matrix.scale(scale);
|
|
36592
37527
|
return matrix;
|
|
@@ -36684,26 +37619,32 @@ var joint = (function (exports) {
|
|
|
36684
37619
|
update: function () {
|
|
36685
37620
|
const {
|
|
36686
37621
|
relatedView: view,
|
|
36687
|
-
options,
|
|
36688
37622
|
vel
|
|
36689
37623
|
} = this;
|
|
36690
37624
|
const {
|
|
36691
37625
|
useModelGeometry,
|
|
36692
|
-
rotate
|
|
36693
|
-
|
|
36694
|
-
|
|
36695
|
-
|
|
36696
|
-
|
|
36697
|
-
|
|
36698
|
-
|
|
36699
|
-
|
|
37626
|
+
rotate,
|
|
37627
|
+
relative,
|
|
37628
|
+
padding
|
|
37629
|
+
} = getToolOptions(this);
|
|
37630
|
+
const normalizedPadding = normalizeSides(padding);
|
|
37631
|
+
let bbox = getViewBBox(view, {
|
|
37632
|
+
useModelGeometry,
|
|
37633
|
+
relative
|
|
37634
|
+
}).moveAndExpand({
|
|
37635
|
+
x: -normalizedPadding.left,
|
|
37636
|
+
y: -normalizedPadding.top,
|
|
37637
|
+
width: normalizedPadding.left + normalizedPadding.right,
|
|
37638
|
+
height: normalizedPadding.top + normalizedPadding.bottom
|
|
36700
37639
|
});
|
|
36701
|
-
|
|
36702
|
-
|
|
36703
|
-
|
|
37640
|
+
const model = view.model;
|
|
37641
|
+
// With relative positioning, rotation is implicit
|
|
37642
|
+
// (the tool rotates along with the element).
|
|
37643
|
+
if (model.isElement() && !relative) {
|
|
37644
|
+
const angle = model.angle();
|
|
36704
37645
|
if (angle) {
|
|
36705
37646
|
if (rotate) {
|
|
36706
|
-
|
|
37647
|
+
const origin = model.getCenter();
|
|
36707
37648
|
vel.rotate(angle, origin.x, origin.y, {
|
|
36708
37649
|
absolute: true
|
|
36709
37650
|
});
|
|
@@ -36929,13 +37870,16 @@ var joint = (function (exports) {
|
|
|
36929
37870
|
getTrackMatrix() {
|
|
36930
37871
|
return V.createSVGMatrix();
|
|
36931
37872
|
},
|
|
37873
|
+
getTrackMatrixAbsolute() {
|
|
37874
|
+
return this.getTrackMatrix();
|
|
37875
|
+
},
|
|
36932
37876
|
getTrackRatioFromEvent(evt) {
|
|
36933
37877
|
const {
|
|
36934
37878
|
relatedView,
|
|
36935
37879
|
trackPath
|
|
36936
37880
|
} = this;
|
|
36937
37881
|
const localPoint = relatedView.paper.clientToLocalPoint(evt.clientX, evt.clientY);
|
|
36938
|
-
const trackPoint = V.transformPoint(localPoint, this.
|
|
37882
|
+
const trackPoint = V.transformPoint(localPoint, this.getTrackMatrixAbsolute().inverse());
|
|
36939
37883
|
return trackPath.closestPointLength(trackPoint);
|
|
36940
37884
|
},
|
|
36941
37885
|
canShowButton() {
|
|
@@ -36989,32 +37933,40 @@ var joint = (function (exports) {
|
|
|
36989
37933
|
const HoverConnect = HoverConnect$1.extend({
|
|
36990
37934
|
getTrackPath() {
|
|
36991
37935
|
const {
|
|
36992
|
-
relatedView: view
|
|
36993
|
-
options
|
|
37936
|
+
relatedView: view
|
|
36994
37937
|
} = this;
|
|
36995
37938
|
let {
|
|
36996
37939
|
useModelGeometry,
|
|
37940
|
+
relative,
|
|
36997
37941
|
trackPath = 'M 0 0 H calc(w) V calc(h) H 0 Z'
|
|
36998
|
-
} =
|
|
37942
|
+
} = getToolOptions(this);
|
|
36999
37943
|
if (typeof trackPath === 'function') {
|
|
37000
37944
|
trackPath = trackPath.call(this, view);
|
|
37001
37945
|
}
|
|
37002
37946
|
if (isCalcExpression(trackPath)) {
|
|
37003
|
-
const bbox = getViewBBox(view,
|
|
37947
|
+
const bbox = getViewBBox(view, {
|
|
37948
|
+
useModelGeometry,
|
|
37949
|
+
relative
|
|
37950
|
+
});
|
|
37004
37951
|
trackPath = evalCalcExpression(trackPath, bbox);
|
|
37005
37952
|
}
|
|
37006
37953
|
return new Path$1(V.normalizePathData(trackPath));
|
|
37007
37954
|
},
|
|
37008
37955
|
getTrackMatrix() {
|
|
37956
|
+
if (this.isOverlay()) return this.getTrackMatrixAbsolute();
|
|
37957
|
+
return V.createSVGMatrix();
|
|
37958
|
+
},
|
|
37959
|
+
getTrackMatrixAbsolute() {
|
|
37009
37960
|
const {
|
|
37010
|
-
relatedView: view
|
|
37011
|
-
options
|
|
37961
|
+
relatedView: view
|
|
37012
37962
|
} = this;
|
|
37013
37963
|
let {
|
|
37014
37964
|
useModelGeometry,
|
|
37015
37965
|
rotate
|
|
37016
|
-
} =
|
|
37017
|
-
let bbox = getViewBBox(view,
|
|
37966
|
+
} = getToolOptions(this);
|
|
37967
|
+
let bbox = getViewBBox(view, {
|
|
37968
|
+
useModelGeometry
|
|
37969
|
+
});
|
|
37018
37970
|
const angle = view.model.angle();
|
|
37019
37971
|
if (!rotate) bbox = bbox.bbox(angle);
|
|
37020
37972
|
let matrix = V.createSVGMatrix().translate(bbox.x + bbox.width / 2, bbox.y + bbox.height / 2);
|
|
@@ -37034,7 +37986,7 @@ var joint = (function (exports) {
|
|
|
37034
37986
|
Remove: Remove
|
|
37035
37987
|
};
|
|
37036
37988
|
|
|
37037
|
-
var version = "4.2.0-alpha.
|
|
37989
|
+
var version = "4.2.0-alpha.1";
|
|
37038
37990
|
|
|
37039
37991
|
const Vectorizer = V;
|
|
37040
37992
|
const layout$1 = {
|