@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.
@@ -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;
@@ -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, layer = LayersNames.TOOLS, z } = options;
152
+ const { relatedView, z } = options;
144
153
  if (relatedView) {
145
- if (layer) {
146
- relatedView.paper.getLayerView(layer).insertSortedNode(el, z);
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
- var PortData = function(data) {
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
- var clonedData = util.cloneDeep(data) || {};
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 = Port;
14
- this.portLabelLayoutNamespace = PortLabel;
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
- var group = this.getGroup(groupName);
70
- var ports = this.getPortsByGroup(groupName);
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
- var groupPosition = group.position || {};
73
- var groupPositionName = groupPosition.name;
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
- var groupArgs = groupPosition.args || {};
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
- var accumulator = {
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._getPortLabelLayout(port, Point(portTransformation), elBBox),
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
- _getPortLabelLayout: function(port, portPosition, elBBox) {
125
+ _getGroupPortTransformations: function(group, portsArgs, elBBox) {
109
126
 
110
- var namespace = this.portLabelLayoutNamespace;
111
- var labelPosition = port.label.position.name || 'left';
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
- if (namespace[labelPosition]) {
114
- return namespace[labelPosition](portPosition, elBBox, port.label.position.args);
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
- // prepare groups
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
- // prepare ports
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(group, {
143
- position: this._getPosition(group.position, true),
144
- label: this._getLabel(group, true)
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
- _evaluatePort: function(port) {
179
+ _evaluateGroupPositionProperty: function(group) {
149
180
 
150
- var evaluated = util.assign({}, port);
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
- var group = this.getGroup(port.group);
187
+ } else if (util.isFunction(groupPosition)) {
188
+ return { layoutCallback: groupPosition };
153
189
 
154
- evaluated.markup = evaluated.markup || group.markup;
155
- evaluated.attrs = util.merge({}, group.attrs, evaluated.attrs);
156
- evaluated.position = this._createPositionNode(group, evaluated);
157
- evaluated.label = util.merge({}, group.label, this._getLabel(evaluated));
158
- evaluated.z = this._getZIndex(group, evaluated);
159
- evaluated.size = util.assign({}, group.size, evaluated.size);
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
- return evaluated;
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
- _getZIndex: function(group, port) {
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
- if (util.isNumber(port.z)) {
167
- return port.z;
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
- _createPositionNode: function(group, port) {
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
- name: 'left',
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
- _getPosition: function(position, setDefault) {
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
- var args = {};
194
- var positionName;
240
+ } else if (util.isFunction(groupLabelPosition)) {
241
+ return { layoutCallback: groupLabelPosition };
195
242
 
196
- if (util.isFunction(position)) {
197
- positionName = 'fn';
198
- args.fn = position;
199
- } else if (util.isString(position)) {
200
- positionName = position;
201
- } else if (position === undefined) {
202
- positionName = setDefault ? 'left' : null;
203
- } else if (Array.isArray(position)) {
204
- positionName = 'absolute';
205
- args.x = position[0];
206
- args.y = position[1];
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
- var result = { args: args };
259
+ const group = this.getGroup(port.group);
213
260
 
214
- if (positionName) {
215
- result.name = positionName;
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
- return result;
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
- _getLabel: function(item, setDefaults) {
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
- var label = item.label || {};
326
+ } else {
327
+ throw new Error('dia.Element: Provided port label position value has an invalid type.');
328
+ }
329
+ },
223
330
 
224
- var ret = label;
225
- ret.position = this._getPosition(label.position, setDefaults);
331
+ _evaluatePortZProperty: function(group, port) {
226
332
 
227
- return ret;
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.get('ports'));
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, options } = this;
10
+ const { relatedView: view } = this;
11
11
  let {
12
12
  useModelGeometry,
13
- trackPath = 'M 0 0 H calc(w) V calc(h) H 0 Z'
14
- } = options;
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
- const { relatedView: view, options } = this;
27
- let { useModelGeometry, rotate } = options;
28
- let bbox = getViewBBox(view, useModelGeometry);
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 browsers too
13
- isSafari: function() {
14
- return /Safari/.test(navigator.userAgent) && /Apple Computer/.test(navigator.vendor);
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
- if (util.isPercentage(x)) {
59
- x = parseFloat(x) / 100 * bbox.width;
60
- } else if (util.isCalcExpression(x)) {
61
- x = Number(util.evalCalcExpression(x, bbox));
62
- }
63
- if (util.isPercentage(y)) {
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
-
@@ -167,7 +167,7 @@ function radialLayout(portCenterOffset, autoOrient, opt) {
167
167
  });
168
168
  }
169
169
 
170
- export const manual = function(_portPosition, _elBBox, opt) {
170
+ export const manual = function(portPosition, elBBox, opt) {
171
171
  return labelAttributes(opt);
172
172
  };
173
173
 
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) {
@@ -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();