@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/src/dia/ToolView.mjs
CHANGED
|
@@ -69,6 +69,10 @@ export const ToolView = mvc.View.extend({
|
|
|
69
69
|
return !!this._visible;
|
|
70
70
|
},
|
|
71
71
|
|
|
72
|
+
isOverlay: function() {
|
|
73
|
+
return !!this.parentView && this.parentView.hasLayer();
|
|
74
|
+
},
|
|
75
|
+
|
|
72
76
|
focus: function() {
|
|
73
77
|
var opacity = this.options.focusOpacity;
|
|
74
78
|
if (isFinite(opacity)) this.el.style.opacity = opacity;
|
package/src/dia/ToolsView.mjs
CHANGED
|
@@ -138,12 +138,21 @@ export const ToolsView = mvc.View.extend({
|
|
|
138
138
|
this.tools = null;
|
|
139
139
|
},
|
|
140
140
|
|
|
141
|
+
getLayer() {
|
|
142
|
+
const { layer = LayersNames.TOOLS } = this.options;
|
|
143
|
+
return layer;
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
hasLayer() {
|
|
147
|
+
return !!this.getLayer();
|
|
148
|
+
},
|
|
149
|
+
|
|
141
150
|
mount: function() {
|
|
142
151
|
const { options, el } = this;
|
|
143
|
-
const { relatedView,
|
|
152
|
+
const { relatedView, z } = options;
|
|
144
153
|
if (relatedView) {
|
|
145
|
-
if (
|
|
146
|
-
relatedView.paper.getLayerView(
|
|
154
|
+
if (this.hasLayer()) {
|
|
155
|
+
relatedView.paper.getLayerView(this.getLayer()).insertSortedNode(el, z);
|
|
147
156
|
} else {
|
|
148
157
|
relatedView.el.appendChild(el);
|
|
149
158
|
}
|
|
@@ -54,9 +54,10 @@ const textAttributesNS = {
|
|
|
54
54
|
const eol = attrs.eol;
|
|
55
55
|
const x = attrs.x;
|
|
56
56
|
let textPath = attrs['text-path'];
|
|
57
|
+
const useNoBreakSpace = attrs['use-no-break-space'] === true;
|
|
57
58
|
// Update the text only if there was a change in the string
|
|
58
59
|
// or any of its attributes.
|
|
59
|
-
const textHash = JSON.stringify([text, lineHeight, annotations, textVerticalAnchor, eol, displayEmpty, textPath, x, fontSize]);
|
|
60
|
+
const textHash = JSON.stringify([text, lineHeight, annotations, textVerticalAnchor, eol, displayEmpty, textPath, x, fontSize, useNoBreakSpace]);
|
|
60
61
|
if (cache === undefined || cache !== textHash) {
|
|
61
62
|
// Chrome bug:
|
|
62
63
|
// <tspan> positions defined as `em` are not updated
|
|
@@ -79,7 +80,8 @@ const textAttributesNS = {
|
|
|
79
80
|
x,
|
|
80
81
|
textVerticalAnchor,
|
|
81
82
|
eol,
|
|
82
|
-
displayEmpty
|
|
83
|
+
displayEmpty,
|
|
84
|
+
useNoBreakSpace
|
|
83
85
|
});
|
|
84
86
|
$.data.set(node, cacheName, textHash);
|
|
85
87
|
}
|
package/src/dia/ports.mjs
CHANGED
|
@@ -4,14 +4,20 @@ import { Rect, Point } from '../g/index.mjs';
|
|
|
4
4
|
import * as Port from '../layout/ports/port.mjs';
|
|
5
5
|
import * as PortLabel from '../layout/ports/portLabel.mjs';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
const DEFAULT_PORT_POSITION_NAME = 'left';
|
|
8
|
+
const DEFAULT_ABSOLUTE_PORT_POSITION_NAME = 'absolute';
|
|
9
|
+
const DEFAULT_PORT_LABEL_POSITION_NAME = 'left';
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
const PortData = function(model) {
|
|
12
|
+
|
|
13
|
+
const { portLayoutNamespace = Port, portLabelLayoutNamespace = PortLabel } = model;
|
|
14
|
+
|
|
15
|
+
const clonedData = util.cloneDeep(model.get('ports')) || {};
|
|
10
16
|
this.ports = [];
|
|
11
17
|
this.portsMap = {};
|
|
12
18
|
this.groups = {};
|
|
13
|
-
this.portLayoutNamespace =
|
|
14
|
-
this.portLabelLayoutNamespace =
|
|
19
|
+
this.portLayoutNamespace = portLayoutNamespace;
|
|
20
|
+
this.portLabelLayoutNamespace = portLabelLayoutNamespace;
|
|
15
21
|
this.metrics = {};
|
|
16
22
|
this.metricsKey = null;
|
|
17
23
|
|
|
@@ -45,7 +51,10 @@ PortData.prototype = {
|
|
|
45
51
|
});
|
|
46
52
|
},
|
|
47
53
|
|
|
54
|
+
// Calculate SVG transformations based on evaluated group + port data
|
|
55
|
+
// NOTE: This function is also called for ports without a group (groupName = undefined)
|
|
48
56
|
getGroupPortsMetrics: function(groupName, rect) {
|
|
57
|
+
|
|
49
58
|
const { x = 0, y = 0, width = 0, height = 0 } = rect;
|
|
50
59
|
const metricsKey = `${x}:${y}:${width}:${height}`;
|
|
51
60
|
if (this.metricsKey !== metricsKey) {
|
|
@@ -53,11 +62,13 @@ PortData.prototype = {
|
|
|
53
62
|
this.metrics = {};
|
|
54
63
|
this.metricsKey = metricsKey;
|
|
55
64
|
}
|
|
65
|
+
|
|
56
66
|
let groupPortsMetrics = this.metrics[groupName];
|
|
57
67
|
if (groupPortsMetrics) {
|
|
58
68
|
// Return cached metrics
|
|
59
69
|
return groupPortsMetrics;
|
|
60
70
|
}
|
|
71
|
+
|
|
61
72
|
// Calculate the metrics
|
|
62
73
|
groupPortsMetrics = this.resolveGroupPortsMetrics(groupName, new Rect(x, y, width, height));
|
|
63
74
|
this.metrics[groupName] = groupPortsMetrics;
|
|
@@ -66,27 +77,33 @@ PortData.prototype = {
|
|
|
66
77
|
|
|
67
78
|
resolveGroupPortsMetrics: function(groupName, elBBox) {
|
|
68
79
|
|
|
69
|
-
|
|
70
|
-
|
|
80
|
+
// `groupName` of `undefined` (= not a string) means "the group of ports which do not have the `group` property".
|
|
81
|
+
const isNoGroup = (groupName === undefined);
|
|
71
82
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
var namespace = this.portLayoutNamespace;
|
|
75
|
-
if (!namespace[groupPositionName]) {
|
|
76
|
-
groupPositionName = 'left';
|
|
77
|
-
}
|
|
83
|
+
const group = this.getGroup(groupName);
|
|
84
|
+
const ports = this.getPortsByGroup(groupName);
|
|
78
85
|
|
|
79
|
-
|
|
80
|
-
var portsArgs = ports.map(function(port) {
|
|
86
|
+
const portsArgs = ports.map(function(port) {
|
|
81
87
|
return port && port.position && port.position.args;
|
|
82
88
|
});
|
|
83
|
-
var groupPortTransformations = namespace[groupPositionName](portsArgs, elBBox, groupArgs);
|
|
84
89
|
|
|
85
|
-
|
|
90
|
+
// Get an array of transformations of individual ports according to the group's port layout function:
|
|
91
|
+
let groupPortTransformations;
|
|
92
|
+
if (isNoGroup) {
|
|
93
|
+
// Apply default port layout function to the set of ports without `group` property.
|
|
94
|
+
const noGroup = this._evaluateGroup({});
|
|
95
|
+
groupPortTransformations = this._getGroupPortTransformations(noGroup, portsArgs, elBBox);
|
|
96
|
+
|
|
97
|
+
} else {
|
|
98
|
+
groupPortTransformations = this._getGroupPortTransformations(group, portsArgs, elBBox);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
let accumulator = {
|
|
86
102
|
ports: ports,
|
|
87
103
|
result: {}
|
|
88
104
|
};
|
|
89
105
|
|
|
106
|
+
// For each individual port transformation, find the information necessary to calculate SVG transformations:
|
|
90
107
|
util.toArray(groupPortTransformations).reduce((res, portTransformation, index) => {
|
|
91
108
|
const port = res.ports[index];
|
|
92
109
|
const portId = port.id;
|
|
@@ -94,7 +111,7 @@ PortData.prototype = {
|
|
|
94
111
|
index,
|
|
95
112
|
portId,
|
|
96
113
|
portTransformation: portTransformation,
|
|
97
|
-
labelTransformation: this.
|
|
114
|
+
labelTransformation: this._getPortLabelTransformation(port, Point(portTransformation), elBBox),
|
|
98
115
|
portAttrs: port.attrs,
|
|
99
116
|
portSize: port.size,
|
|
100
117
|
labelSize: port.label.size
|
|
@@ -105,13 +122,21 @@ PortData.prototype = {
|
|
|
105
122
|
return accumulator.result;
|
|
106
123
|
},
|
|
107
124
|
|
|
108
|
-
|
|
125
|
+
_getGroupPortTransformations: function(group, portsArgs, elBBox) {
|
|
109
126
|
|
|
110
|
-
|
|
111
|
-
|
|
127
|
+
const groupPosition = group.position || {};
|
|
128
|
+
const groupPositionArgs = groupPosition.args || {};
|
|
129
|
+
const groupPositionLayoutCallback = groupPosition.layoutCallback;
|
|
130
|
+
return groupPositionLayoutCallback(portsArgs, elBBox, groupPositionArgs);
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
_getPortLabelTransformation: function(port, portPosition, elBBox) {
|
|
112
134
|
|
|
113
|
-
|
|
114
|
-
|
|
135
|
+
const portLabelPosition = port.label.position || {};
|
|
136
|
+
const portLabelPositionArgs = portLabelPosition.args || {};
|
|
137
|
+
const portLabelPositionLayoutCallback = portLabelPosition.layoutCallback;
|
|
138
|
+
if (portLabelPositionLayoutCallback) {
|
|
139
|
+
return portLabelPositionLayoutCallback(portPosition, elBBox, portLabelPositionArgs);
|
|
115
140
|
}
|
|
116
141
|
|
|
117
142
|
return null;
|
|
@@ -119,7 +144,8 @@ PortData.prototype = {
|
|
|
119
144
|
|
|
120
145
|
_init: function(data) {
|
|
121
146
|
|
|
122
|
-
//
|
|
147
|
+
// Prepare groups:
|
|
148
|
+
// NOTE: This overwrites passed group properties with evaluated group properties.
|
|
123
149
|
if (util.isObject(data.groups)) {
|
|
124
150
|
var groups = Object.keys(data.groups);
|
|
125
151
|
for (var i = 0, n = groups.length; i < n; i++) {
|
|
@@ -128,7 +154,8 @@ PortData.prototype = {
|
|
|
128
154
|
}
|
|
129
155
|
}
|
|
130
156
|
|
|
131
|
-
//
|
|
157
|
+
// Prepare ports:
|
|
158
|
+
// NOTE: This overwrites passed port properties with evaluated port properties, plus mixed-in evaluated group properties (see above).
|
|
132
159
|
var ports = util.toArray(data.items);
|
|
133
160
|
for (var j = 0, m = ports.length; j < m; j++) {
|
|
134
161
|
const resolvedPort = this._evaluatePort(ports[j]);
|
|
@@ -139,92 +166,185 @@ PortData.prototype = {
|
|
|
139
166
|
|
|
140
167
|
_evaluateGroup: function(group) {
|
|
141
168
|
|
|
142
|
-
return util.merge(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
169
|
+
return util.merge(
|
|
170
|
+
{},
|
|
171
|
+
group,
|
|
172
|
+
{
|
|
173
|
+
position: this._evaluateGroupPositionProperty(group),
|
|
174
|
+
label: this._evaluateGroupLabelProperty(group)
|
|
175
|
+
}
|
|
176
|
+
);
|
|
146
177
|
},
|
|
147
178
|
|
|
148
|
-
|
|
179
|
+
_evaluateGroupPositionProperty: function(group) {
|
|
149
180
|
|
|
150
|
-
|
|
181
|
+
const namespace = this.portLayoutNamespace;
|
|
182
|
+
const groupPosition = group.position;
|
|
183
|
+
if (groupPosition === undefined) {
|
|
184
|
+
const layoutCallback = this._resolveLayoutCallbackOrThrow(namespace, DEFAULT_PORT_POSITION_NAME, 'Default port group');
|
|
185
|
+
return { layoutCallback };
|
|
151
186
|
|
|
152
|
-
|
|
187
|
+
} else if (util.isFunction(groupPosition)) {
|
|
188
|
+
return { layoutCallback: groupPosition };
|
|
153
189
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
190
|
+
} else if (util.isObject(groupPosition)) {
|
|
191
|
+
if (groupPosition.name) {
|
|
192
|
+
const layoutCallback = this._resolveLayoutCallbackOrThrow(namespace, groupPosition.name, 'Provided port group');
|
|
193
|
+
return { layoutCallback, args: groupPosition.args };
|
|
194
|
+
} else {
|
|
195
|
+
const layoutCallback = this._resolveLayoutCallbackOrThrow(namespace, DEFAULT_PORT_POSITION_NAME, 'Default port group');
|
|
196
|
+
return { layoutCallback, args: groupPosition.args };
|
|
197
|
+
}
|
|
160
198
|
|
|
161
|
-
|
|
162
|
-
|
|
199
|
+
} else if (util.isString(groupPosition)) {
|
|
200
|
+
// TODO: Remove legacy signature (see `this._evaluateGroupLabelPositionProperty()`).
|
|
201
|
+
const layoutCallback = this._resolveLayoutCallbackOrThrow(namespace, groupPosition, 'Provided port group');
|
|
202
|
+
return { layoutCallback };
|
|
163
203
|
|
|
164
|
-
|
|
204
|
+
} else if (Array.isArray(groupPosition)) {
|
|
205
|
+
// TODO: Remove legacy signature (see `this._evaluateGroupLabelPositionProperty()`).
|
|
206
|
+
const layoutCallback = this._resolveLayoutCallbackOrThrow(namespace, DEFAULT_ABSOLUTE_PORT_POSITION_NAME, 'Default absolute port group');
|
|
207
|
+
return { layoutCallback, args: { x: groupPosition[0], y: groupPosition[1] }};
|
|
165
208
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
169
|
-
if (util.isNumber(group.z) || group.z === 'auto') {
|
|
170
|
-
return group.z;
|
|
209
|
+
} else {
|
|
210
|
+
throw new Error('dia.Element: Provided port group position value has an invalid type.');
|
|
171
211
|
}
|
|
172
|
-
return 'auto';
|
|
173
212
|
},
|
|
174
213
|
|
|
175
|
-
|
|
214
|
+
_evaluateGroupLabelProperty: function(group) {
|
|
215
|
+
|
|
216
|
+
const groupLabel = group.label;
|
|
217
|
+
if (!groupLabel) {
|
|
218
|
+
return {
|
|
219
|
+
position: this._evaluateGroupLabelPositionProperty({})
|
|
220
|
+
};
|
|
221
|
+
}
|
|
176
222
|
|
|
177
223
|
return util.merge(
|
|
224
|
+
{},
|
|
225
|
+
groupLabel,
|
|
178
226
|
{
|
|
179
|
-
|
|
180
|
-
args: {}
|
|
181
|
-
},
|
|
182
|
-
group.position,
|
|
183
|
-
{
|
|
184
|
-
// TODO: remove `port.args` backwards compatibility
|
|
185
|
-
// NOTE: `x != null` is equivalent to `x !== null && x !== undefined`
|
|
186
|
-
args: (((port.position != null) && (port.position.args != null)) ? port.position.args : port.args)
|
|
227
|
+
position: this._evaluateGroupLabelPositionProperty(groupLabel)
|
|
187
228
|
}
|
|
188
229
|
);
|
|
189
230
|
},
|
|
190
231
|
|
|
191
|
-
|
|
232
|
+
_evaluateGroupLabelPositionProperty: function(groupLabel) {
|
|
233
|
+
|
|
234
|
+
const namespace = this.portLabelLayoutNamespace;
|
|
235
|
+
const groupLabelPosition = groupLabel.position;
|
|
236
|
+
if (groupLabelPosition === undefined) {
|
|
237
|
+
const layoutCallback = this._resolveLayoutCallbackOrThrow(namespace, DEFAULT_PORT_LABEL_POSITION_NAME, 'Default port group label');
|
|
238
|
+
return { layoutCallback };
|
|
192
239
|
|
|
193
|
-
|
|
194
|
-
|
|
240
|
+
} else if (util.isFunction(groupLabelPosition)) {
|
|
241
|
+
return { layoutCallback: groupLabelPosition };
|
|
195
242
|
|
|
196
|
-
if (util.
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
} else if (util.isObject(position)) {
|
|
208
|
-
positionName = position.name;
|
|
209
|
-
util.assign(args, position.args);
|
|
243
|
+
} else if (util.isObject(groupLabelPosition)) {
|
|
244
|
+
if (groupLabelPosition.name) {
|
|
245
|
+
const layoutCallback = this._resolveLayoutCallbackOrThrow(namespace, groupLabelPosition.name, 'Provided port group label');
|
|
246
|
+
return { layoutCallback, args: groupLabelPosition.args };
|
|
247
|
+
} else {
|
|
248
|
+
const layoutCallback = this._resolveLayoutCallbackOrThrow(namespace, DEFAULT_PORT_LABEL_POSITION_NAME, 'Default port group label');
|
|
249
|
+
return { layoutCallback, args: groupLabelPosition.args };
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
} else {
|
|
253
|
+
throw new Error('dia.Element: Provided port group label position value has an invalid type.');
|
|
210
254
|
}
|
|
255
|
+
},
|
|
256
|
+
|
|
257
|
+
_evaluatePort: function(port) {
|
|
211
258
|
|
|
212
|
-
|
|
259
|
+
const group = this.getGroup(port.group);
|
|
213
260
|
|
|
214
|
-
|
|
215
|
-
|
|
261
|
+
const evaluated = util.assign({}, port);
|
|
262
|
+
evaluated.markup = evaluated.markup || group.markup;
|
|
263
|
+
evaluated.attrs = util.merge({}, group.attrs, evaluated.attrs);
|
|
264
|
+
evaluated.position = this._evaluatePortPositionProperty(group, evaluated);
|
|
265
|
+
evaluated.label = this._evaluatePortLabelProperty(group, evaluated);
|
|
266
|
+
evaluated.z = this._evaluatePortZProperty(group, evaluated);
|
|
267
|
+
evaluated.size = util.assign({}, group.size, evaluated.size);
|
|
268
|
+
return evaluated;
|
|
269
|
+
},
|
|
270
|
+
|
|
271
|
+
_evaluatePortPositionProperty: function(group, port) {
|
|
272
|
+
|
|
273
|
+
return {
|
|
274
|
+
args: util.merge(
|
|
275
|
+
{},
|
|
276
|
+
// NOTE: `x != null` is equivalent to `x !== null && x !== undefined`.
|
|
277
|
+
(group.position != null) ? group.position.args : {},
|
|
278
|
+
// Port can overwrite `group.position.args` via `port.position.args` or `port.args`.
|
|
279
|
+
// TODO: Remove `port.args` backwards compatibility.
|
|
280
|
+
(((port.position != null) && (port.position.args != null)) ? port.position.args : port.args))
|
|
281
|
+
};
|
|
282
|
+
},
|
|
283
|
+
|
|
284
|
+
_evaluatePortLabelProperty: function(group, port) {
|
|
285
|
+
|
|
286
|
+
const groupLabel = group.label;
|
|
287
|
+
const portLabel = port.label;
|
|
288
|
+
if (!portLabel) {
|
|
289
|
+
return util.assign(
|
|
290
|
+
{},
|
|
291
|
+
groupLabel
|
|
292
|
+
);
|
|
216
293
|
}
|
|
217
|
-
|
|
294
|
+
|
|
295
|
+
return util.merge(
|
|
296
|
+
{},
|
|
297
|
+
groupLabel,
|
|
298
|
+
util.merge(
|
|
299
|
+
{},
|
|
300
|
+
portLabel,
|
|
301
|
+
{
|
|
302
|
+
position: this._evaluatePortLabelPositionProperty(portLabel)
|
|
303
|
+
}
|
|
304
|
+
)
|
|
305
|
+
);
|
|
218
306
|
},
|
|
219
307
|
|
|
220
|
-
|
|
308
|
+
_evaluatePortLabelPositionProperty: function(portLabel) {
|
|
309
|
+
|
|
310
|
+
const namespace = this.portLabelLayoutNamespace;
|
|
311
|
+
const portLabelPosition = portLabel.position;
|
|
312
|
+
if (portLabelPosition === undefined) {
|
|
313
|
+
return {};
|
|
314
|
+
|
|
315
|
+
} else if (util.isFunction(portLabelPosition)) {
|
|
316
|
+
return { layoutCallback: portLabelPosition };
|
|
317
|
+
|
|
318
|
+
} else if (util.isObject(portLabelPosition)) {
|
|
319
|
+
if (portLabelPosition.name) {
|
|
320
|
+
const layoutCallback = this._resolveLayoutCallbackOrThrow(namespace, portLabelPosition.name, 'Provided port label');
|
|
321
|
+
return { layoutCallback, args: portLabelPosition.args };
|
|
322
|
+
} else {
|
|
323
|
+
return { args: portLabelPosition.args };
|
|
324
|
+
}
|
|
221
325
|
|
|
222
|
-
|
|
326
|
+
} else {
|
|
327
|
+
throw new Error('dia.Element: Provided port label position value has an invalid type.');
|
|
328
|
+
}
|
|
329
|
+
},
|
|
223
330
|
|
|
224
|
-
|
|
225
|
-
ret.position = this._getPosition(label.position, setDefaults);
|
|
331
|
+
_evaluatePortZProperty: function(group, port) {
|
|
226
332
|
|
|
227
|
-
|
|
333
|
+
if (util.isNumber(port.z)) {
|
|
334
|
+
return port.z;
|
|
335
|
+
}
|
|
336
|
+
if (util.isNumber(group.z) || group.z === 'auto') {
|
|
337
|
+
return group.z;
|
|
338
|
+
}
|
|
339
|
+
return 'auto';
|
|
340
|
+
},
|
|
341
|
+
|
|
342
|
+
_resolveLayoutCallbackOrThrow: function(namespace, name, errorSubstring) {
|
|
343
|
+
const layoutCallback = namespace[name];
|
|
344
|
+
if (!layoutCallback) {
|
|
345
|
+
throw new Error(`dia.Element: ${errorSubstring} layout name is not recognized.`);
|
|
346
|
+
}
|
|
347
|
+
return layoutCallback;
|
|
228
348
|
}
|
|
229
349
|
};
|
|
230
350
|
|
|
@@ -613,7 +733,7 @@ export const elementPortPrototype = {
|
|
|
613
733
|
prevPortData = this._portSettingsData.getPorts();
|
|
614
734
|
}
|
|
615
735
|
|
|
616
|
-
this._portSettingsData = new PortData(this
|
|
736
|
+
this._portSettingsData = new PortData(this);
|
|
617
737
|
|
|
618
738
|
var curPortData = this._portSettingsData.getPorts();
|
|
619
739
|
|
|
@@ -2,30 +2,36 @@ import { HoverConnect as LinkHoverConnect } from '../cellTools/HoverConnect.mjs'
|
|
|
2
2
|
import V from '../V/index.mjs';
|
|
3
3
|
import * as g from '../g/index.mjs';
|
|
4
4
|
import { isCalcExpression, evalCalcExpression } from '../util/calc.mjs';
|
|
5
|
-
import { getViewBBox } from '../cellTools/helpers.mjs';
|
|
5
|
+
import { getToolOptions, getViewBBox } from '../cellTools/helpers.mjs';
|
|
6
6
|
|
|
7
7
|
export const HoverConnect = LinkHoverConnect.extend({
|
|
8
8
|
|
|
9
9
|
getTrackPath() {
|
|
10
|
-
const { relatedView: view
|
|
10
|
+
const { relatedView: view } = this;
|
|
11
11
|
let {
|
|
12
12
|
useModelGeometry,
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
relative,
|
|
14
|
+
trackPath = 'M 0 0 H calc(w) V calc(h) H 0 Z'
|
|
15
|
+
} = getToolOptions(this);
|
|
15
16
|
if (typeof trackPath === 'function') {
|
|
16
17
|
trackPath = trackPath.call(this, view);
|
|
17
18
|
}
|
|
18
19
|
if (isCalcExpression(trackPath)) {
|
|
19
|
-
const bbox = getViewBBox(view, useModelGeometry);
|
|
20
|
+
const bbox = getViewBBox(view, { useModelGeometry, relative });
|
|
20
21
|
trackPath = evalCalcExpression(trackPath, bbox);
|
|
21
22
|
}
|
|
22
23
|
return new g.Path(V.normalizePathData(trackPath));
|
|
23
24
|
},
|
|
24
25
|
|
|
25
26
|
getTrackMatrix() {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
if (this.isOverlay()) return this.getTrackMatrixAbsolute();
|
|
28
|
+
return V.createSVGMatrix();
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
getTrackMatrixAbsolute() {
|
|
32
|
+
const { relatedView: view } = this;
|
|
33
|
+
let { useModelGeometry, rotate } = getToolOptions(this);
|
|
34
|
+
let bbox = getViewBBox(view, { useModelGeometry });
|
|
29
35
|
const angle = view.model.angle();
|
|
30
36
|
if (!rotate) bbox = bbox.bbox(angle);
|
|
31
37
|
let matrix = V.createSVGMatrix().translate(bbox.x + bbox.width / 2, bbox.y + bbox.height / 2);
|
package/src/env/index.mjs
CHANGED
|
@@ -9,9 +9,12 @@ export const env = {
|
|
|
9
9
|
/SVGForeignObject/.test(({}).toString.call(document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject')));
|
|
10
10
|
},
|
|
11
11
|
|
|
12
|
-
// works for iOS
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
// works for: (1) macOS Safari, (2) any WKWebView, (3) any iOS browser (including Safari, CriOS, EdgiOS, OPR, FxiOS)
|
|
13
|
+
isAppleWebKit: function() {
|
|
14
|
+
const userAgent = navigator.userAgent;
|
|
15
|
+
const isAppleWebKit = /applewebkit/i.test(userAgent);
|
|
16
|
+
const isChromium = /chrome/i.test(userAgent); // e.g. Chrome, Edge, Opera, SamsungBrowser
|
|
17
|
+
return isAppleWebKit && !isChromium;
|
|
15
18
|
}
|
|
16
19
|
},
|
|
17
20
|
|
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
import * as g from '../../g/index.mjs';
|
|
2
2
|
import * as util from '../../util/index.mjs';
|
|
3
3
|
|
|
4
|
+
function parseCoordinate(coordinate, dimension, bbox, value) {
|
|
5
|
+
|
|
6
|
+
if (util.isPercentage(value)) {
|
|
7
|
+
return parseFloat(value) / 100 * bbox[dimension];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (util.isCalcExpression(value)) {
|
|
11
|
+
return Number(util.evalCalcExpression(value, bbox));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (typeof value === 'string') {
|
|
15
|
+
const num = Number(value);
|
|
16
|
+
if (isNaN(num)) {
|
|
17
|
+
throw new TypeError(
|
|
18
|
+
`Cannot convert port coordinate ${coordinate}: "${value}" to a number`
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
return num;
|
|
22
|
+
}
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
|
|
4
26
|
function portTransformAttrs(point, angle, opt) {
|
|
5
27
|
|
|
6
28
|
var trans = point.toJSON();
|
|
@@ -52,20 +74,14 @@ function ellipseLayout(ports, elBBox, startAngle, stepFn) {
|
|
|
52
74
|
});
|
|
53
75
|
}
|
|
54
76
|
|
|
55
|
-
|
|
56
77
|
function argTransform(bbox, args) {
|
|
57
78
|
let { x, y, angle } = args;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
y = parseFloat(y) / 100 * bbox.height;
|
|
65
|
-
} else if (util.isCalcExpression(y)) {
|
|
66
|
-
y = Number(util.evalCalcExpression(y, bbox));
|
|
67
|
-
}
|
|
68
|
-
return { x, y, angle };
|
|
79
|
+
|
|
80
|
+
return {
|
|
81
|
+
x: parseCoordinate('x', 'width', bbox, x),
|
|
82
|
+
y: parseCoordinate('y', 'height', bbox, y),
|
|
83
|
+
angle
|
|
84
|
+
};
|
|
69
85
|
}
|
|
70
86
|
|
|
71
87
|
// Creates a point stored in arguments
|
|
@@ -74,14 +90,13 @@ function argPoint(bbox, args) {
|
|
|
74
90
|
return new g.Point(x || 0, y || 0);
|
|
75
91
|
}
|
|
76
92
|
|
|
77
|
-
|
|
78
93
|
/**
|
|
79
94
|
* @param {Array<Object>} ports
|
|
80
95
|
* @param {g.Rect} elBBox
|
|
81
96
|
* @param {Object=} opt opt Group options
|
|
82
97
|
* @returns {Array<g.Point>}
|
|
83
98
|
*/
|
|
84
|
-
export const absolute = function(ports, elBBox) {
|
|
99
|
+
export const absolute = function(ports, elBBox, opt) {
|
|
85
100
|
return ports.map(port => {
|
|
86
101
|
const transformation = argPoint(elBBox, port).round().toJSON();
|
|
87
102
|
transformation.angle = port.angle || 0;
|
|
@@ -90,6 +105,7 @@ export const absolute = function(ports, elBBox) {
|
|
|
90
105
|
};
|
|
91
106
|
|
|
92
107
|
/**
|
|
108
|
+
* @deprecated
|
|
93
109
|
* @param {Array<Object>} ports
|
|
94
110
|
* @param {g.Rect} elBBox
|
|
95
111
|
* @param {Object=} opt opt Group options
|
|
@@ -184,4 +200,3 @@ export const ellipse = function(ports, elBBox, opt) {
|
|
|
184
200
|
return (index + 0.5 - count / 2) * stepAngle;
|
|
185
201
|
});
|
|
186
202
|
};
|
|
187
|
-
|
package/src/mvc/View.mjs
CHANGED
|
@@ -18,8 +18,12 @@ export const View = ViewBase.extend({
|
|
|
18
18
|
|
|
19
19
|
DETACHABLE: true,
|
|
20
20
|
UPDATE_PRIORITY: 2,
|
|
21
|
+
|
|
22
|
+
/** @deprecated is no longer used (moved to Paper) */
|
|
21
23
|
FLAG_INSERT: 1<<30,
|
|
24
|
+
/** @deprecated is no longer used */
|
|
22
25
|
FLAG_REMOVE: 1<<29,
|
|
26
|
+
/** @deprecated is no longer used */
|
|
23
27
|
FLAG_INIT: 1<<28,
|
|
24
28
|
|
|
25
29
|
constructor: function(options) {
|
package/src/mvc/ViewBase.mjs
CHANGED
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
// Creating a ViewBase creates its initial element outside of the DOM,
|
|
25
25
|
// if an existing element is not provided...
|
|
26
26
|
export var ViewBase = function(options) {
|
|
27
|
-
this.cid = uniqueId('view');
|
|
27
|
+
this.cid = (options && options.cid) || uniqueId('view');
|
|
28
28
|
this.preinitialize.apply(this, arguments);
|
|
29
29
|
assign(this, pick(options, viewOptions));
|
|
30
30
|
this._ensureElement();
|