@joint/core 4.0.0

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.
Files changed (139) hide show
  1. package/LICENSE +376 -0
  2. package/README.md +49 -0
  3. package/dist/geometry.js +6486 -0
  4. package/dist/geometry.min.js +8 -0
  5. package/dist/joint.d.ts +5536 -0
  6. package/dist/joint.js +39629 -0
  7. package/dist/joint.min.js +8 -0
  8. package/dist/joint.nowrap.js +39626 -0
  9. package/dist/joint.nowrap.min.js +8 -0
  10. package/dist/vectorizer.js +9135 -0
  11. package/dist/vectorizer.min.js +8 -0
  12. package/dist/version.mjs +3 -0
  13. package/index.js +3 -0
  14. package/joint.mjs +27 -0
  15. package/package.json +192 -0
  16. package/src/V/annotation.mjs +0 -0
  17. package/src/V/index.mjs +2642 -0
  18. package/src/anchors/index.mjs +123 -0
  19. package/src/config/index.mjs +12 -0
  20. package/src/connectionPoints/index.mjs +202 -0
  21. package/src/connectionStrategies/index.mjs +73 -0
  22. package/src/connectors/curve.mjs +553 -0
  23. package/src/connectors/index.mjs +6 -0
  24. package/src/connectors/jumpover.mjs +452 -0
  25. package/src/connectors/normal.mjs +12 -0
  26. package/src/connectors/rounded.mjs +17 -0
  27. package/src/connectors/smooth.mjs +44 -0
  28. package/src/connectors/straight.mjs +110 -0
  29. package/src/dia/Cell.mjs +945 -0
  30. package/src/dia/CellView.mjs +1316 -0
  31. package/src/dia/Element.mjs +519 -0
  32. package/src/dia/ElementView.mjs +859 -0
  33. package/src/dia/Graph.mjs +1112 -0
  34. package/src/dia/HighlighterView.mjs +319 -0
  35. package/src/dia/Link.mjs +565 -0
  36. package/src/dia/LinkView.mjs +2207 -0
  37. package/src/dia/Paper.mjs +3171 -0
  38. package/src/dia/PaperLayer.mjs +75 -0
  39. package/src/dia/ToolView.mjs +69 -0
  40. package/src/dia/ToolsView.mjs +128 -0
  41. package/src/dia/attributes/calc.mjs +128 -0
  42. package/src/dia/attributes/connection.mjs +75 -0
  43. package/src/dia/attributes/defs.mjs +76 -0
  44. package/src/dia/attributes/eval.mjs +64 -0
  45. package/src/dia/attributes/index.mjs +69 -0
  46. package/src/dia/attributes/legacy.mjs +148 -0
  47. package/src/dia/attributes/offset.mjs +53 -0
  48. package/src/dia/attributes/props.mjs +30 -0
  49. package/src/dia/attributes/shape.mjs +92 -0
  50. package/src/dia/attributes/text.mjs +180 -0
  51. package/src/dia/index.mjs +13 -0
  52. package/src/dia/layers/GridLayer.mjs +176 -0
  53. package/src/dia/ports.mjs +874 -0
  54. package/src/elementTools/Control.mjs +153 -0
  55. package/src/elementTools/HoverConnect.mjs +37 -0
  56. package/src/elementTools/index.mjs +5 -0
  57. package/src/env/index.mjs +43 -0
  58. package/src/g/bezier.mjs +175 -0
  59. package/src/g/curve.mjs +956 -0
  60. package/src/g/ellipse.mjs +245 -0
  61. package/src/g/extend.mjs +64 -0
  62. package/src/g/geometry.helpers.mjs +58 -0
  63. package/src/g/index.mjs +17 -0
  64. package/src/g/intersection.mjs +511 -0
  65. package/src/g/line.bearing.mjs +30 -0
  66. package/src/g/line.length.mjs +5 -0
  67. package/src/g/line.mjs +356 -0
  68. package/src/g/line.squaredLength.mjs +10 -0
  69. package/src/g/path.mjs +2260 -0
  70. package/src/g/point.mjs +375 -0
  71. package/src/g/points.mjs +247 -0
  72. package/src/g/polygon.mjs +51 -0
  73. package/src/g/polyline.mjs +523 -0
  74. package/src/g/rect.mjs +556 -0
  75. package/src/g/types.mjs +10 -0
  76. package/src/highlighters/addClass.mjs +27 -0
  77. package/src/highlighters/index.mjs +5 -0
  78. package/src/highlighters/list.mjs +111 -0
  79. package/src/highlighters/mask.mjs +220 -0
  80. package/src/highlighters/opacity.mjs +17 -0
  81. package/src/highlighters/stroke.mjs +100 -0
  82. package/src/layout/index.mjs +4 -0
  83. package/src/layout/ports/port.mjs +188 -0
  84. package/src/layout/ports/portLabel.mjs +224 -0
  85. package/src/linkAnchors/index.mjs +76 -0
  86. package/src/linkTools/Anchor.mjs +235 -0
  87. package/src/linkTools/Arrowhead.mjs +103 -0
  88. package/src/linkTools/Boundary.mjs +48 -0
  89. package/src/linkTools/Button.mjs +121 -0
  90. package/src/linkTools/Connect.mjs +85 -0
  91. package/src/linkTools/HoverConnect.mjs +161 -0
  92. package/src/linkTools/Segments.mjs +393 -0
  93. package/src/linkTools/Vertices.mjs +253 -0
  94. package/src/linkTools/helpers.mjs +33 -0
  95. package/src/linkTools/index.mjs +8 -0
  96. package/src/mvc/Collection.mjs +560 -0
  97. package/src/mvc/Data.mjs +46 -0
  98. package/src/mvc/Dom/Dom.mjs +587 -0
  99. package/src/mvc/Dom/Event.mjs +130 -0
  100. package/src/mvc/Dom/animations.mjs +122 -0
  101. package/src/mvc/Dom/events.mjs +69 -0
  102. package/src/mvc/Dom/index.mjs +13 -0
  103. package/src/mvc/Dom/methods.mjs +392 -0
  104. package/src/mvc/Dom/props.mjs +77 -0
  105. package/src/mvc/Dom/vars.mjs +5 -0
  106. package/src/mvc/Events.mjs +337 -0
  107. package/src/mvc/Listener.mjs +33 -0
  108. package/src/mvc/Model.mjs +239 -0
  109. package/src/mvc/View.mjs +323 -0
  110. package/src/mvc/ViewBase.mjs +182 -0
  111. package/src/mvc/index.mjs +9 -0
  112. package/src/mvc/mvcUtils.mjs +90 -0
  113. package/src/polyfills/array.js +4 -0
  114. package/src/polyfills/base64.js +68 -0
  115. package/src/polyfills/index.mjs +5 -0
  116. package/src/polyfills/number.js +3 -0
  117. package/src/polyfills/string.js +3 -0
  118. package/src/polyfills/typedArray.js +47 -0
  119. package/src/routers/index.mjs +6 -0
  120. package/src/routers/manhattan.mjs +856 -0
  121. package/src/routers/metro.mjs +91 -0
  122. package/src/routers/normal.mjs +6 -0
  123. package/src/routers/oneSide.mjs +60 -0
  124. package/src/routers/orthogonal.mjs +323 -0
  125. package/src/routers/rightAngle.mjs +1056 -0
  126. package/src/shapes/index.mjs +3 -0
  127. package/src/shapes/standard.mjs +755 -0
  128. package/src/util/cloneCells.mjs +67 -0
  129. package/src/util/getRectPoint.mjs +65 -0
  130. package/src/util/index.mjs +5 -0
  131. package/src/util/svgTagTemplate.mjs +110 -0
  132. package/src/util/util.mjs +1754 -0
  133. package/src/util/utilHelpers.mjs +2402 -0
  134. package/src/util/wrappers.mjs +56 -0
  135. package/types/geometry.d.ts +815 -0
  136. package/types/index.d.ts +53 -0
  137. package/types/joint.d.ts +4391 -0
  138. package/types/joint.head.d.ts +12 -0
  139. package/types/vectorizer.d.ts +327 -0
@@ -0,0 +1,393 @@
1
+ import * as g from '../g/index.mjs';
2
+ import V from '../V/index.mjs';
3
+ import * as util from '../util/index.mjs';
4
+ import * as mvc from '../mvc/index.mjs';
5
+ import { ToolView } from '../dia/ToolView.mjs';
6
+ import { getAnchor } from './helpers.mjs';
7
+
8
+ var SegmentHandle = mvc.View.extend({
9
+ tagName: 'g',
10
+ svgElement: true,
11
+ className: 'marker-segment',
12
+ events: {
13
+ mousedown: 'onPointerDown',
14
+ touchstart: 'onPointerDown'
15
+ },
16
+ documentEvents: {
17
+ mousemove: 'onPointerMove',
18
+ touchmove: 'onPointerMove',
19
+ mouseup: 'onPointerUp',
20
+ touchend: 'onPointerUp',
21
+ touchcancel: 'onPointerUp'
22
+ },
23
+ children: [{
24
+ tagName: 'line',
25
+ selector: 'line',
26
+ attributes: {
27
+ 'stroke': '#33334F',
28
+ 'stroke-width': 2,
29
+ 'fill': 'none',
30
+ 'pointer-events': 'none'
31
+ }
32
+ }, {
33
+ tagName: 'rect',
34
+ selector: 'handle',
35
+ attributes: {
36
+ 'width': 20,
37
+ 'height': 8,
38
+ 'x': -10,
39
+ 'y': -4,
40
+ 'rx': 4,
41
+ 'ry': 4,
42
+ 'fill': '#33334F',
43
+ 'stroke': '#FFFFFF',
44
+ 'stroke-width': 2
45
+ }
46
+ }],
47
+ onRender: function() {
48
+ this.renderChildren();
49
+ },
50
+ position: function(x, y, angle, view) {
51
+ const { scale } = this.options;
52
+ let matrix = V.createSVGMatrix().translate(x, y).rotate(angle);
53
+ if (scale) matrix = matrix.scale(scale);
54
+
55
+ var handle = this.childNodes.handle;
56
+ handle.setAttribute('transform', V.matrixToTransformString(matrix));
57
+ handle.setAttribute('cursor', (angle % 180 === 0) ? 'row-resize' : 'col-resize');
58
+
59
+ var viewPoint = view.getClosestPoint(new g.Point(x, y));
60
+ var line = this.childNodes.line;
61
+ line.setAttribute('x1', x);
62
+ line.setAttribute('y1', y);
63
+ line.setAttribute('x2', viewPoint.x);
64
+ line.setAttribute('y2', viewPoint.y);
65
+ },
66
+ onPointerDown: function(evt) {
67
+ if (this.options.guard(evt)) return;
68
+ this.trigger('change:start', this, evt);
69
+ evt.stopPropagation();
70
+ evt.preventDefault();
71
+ this.options.paper.undelegateEvents();
72
+ this.delegateDocumentEvents(null, evt.data);
73
+ },
74
+ onPointerMove: function(evt) {
75
+ this.trigger('changing', this, evt);
76
+ },
77
+ onPointerUp: function(evt) {
78
+ this.undelegateDocumentEvents();
79
+ this.options.paper.delegateEvents();
80
+ this.trigger('change:end', this, evt);
81
+ },
82
+ show: function() {
83
+ this.el.style.display = '';
84
+ },
85
+ hide: function() {
86
+ this.el.style.display = 'none';
87
+ }
88
+ });
89
+
90
+ export const Segments = ToolView.extend({
91
+ name: 'segments',
92
+ precision: .5,
93
+ options: {
94
+ handleClass: SegmentHandle,
95
+ segmentLengthThreshold: 40,
96
+ redundancyRemoval: true,
97
+ anchor: getAnchor,
98
+ snapRadius: 10,
99
+ snapHandle: true,
100
+ stopPropagation: true
101
+ },
102
+ handles: null,
103
+ onRender: function() {
104
+ this.resetHandles();
105
+ var relatedView = this.relatedView;
106
+ var vertices = relatedView.model.vertices();
107
+ vertices.unshift(relatedView.sourcePoint);
108
+ vertices.push(relatedView.targetPoint);
109
+ for (var i = 0, n = vertices.length; i < n - 1; i++) {
110
+ var vertex = vertices[i];
111
+ var nextVertex = vertices[i + 1];
112
+ var handle = this.renderHandle(vertex, nextVertex);
113
+ this.simulateRelatedView(handle.el);
114
+ this.handles.push(handle);
115
+ handle.options.index = i;
116
+ }
117
+ return this;
118
+ },
119
+ renderHandle: function(vertex, nextVertex) {
120
+ var handle = new (this.options.handleClass)({
121
+ paper: this.paper,
122
+ scale: this.options.scale,
123
+ guard: evt => this.guard(evt)
124
+ });
125
+ handle.render();
126
+ this.updateHandle(handle, vertex, nextVertex);
127
+ handle.vel.appendTo(this.el);
128
+ this.startHandleListening(handle);
129
+ return handle;
130
+ },
131
+ update: function() {
132
+ this.render();
133
+ return this;
134
+ },
135
+ startHandleListening: function(handle) {
136
+ this.listenTo(handle, 'change:start', this.onHandleChangeStart);
137
+ this.listenTo(handle, 'changing', this.onHandleChanging);
138
+ this.listenTo(handle, 'change:end', this.onHandleChangeEnd);
139
+ },
140
+ resetHandles: function() {
141
+ var handles = this.handles;
142
+ this.handles = [];
143
+ this.stopListening();
144
+ if (!Array.isArray(handles)) return;
145
+ for (var i = 0, n = handles.length; i < n; i++) {
146
+ handles[i].remove();
147
+ }
148
+ },
149
+ shiftHandleIndexes: function(value) {
150
+ var handles = this.handles;
151
+ for (var i = 0, n = handles.length; i < n; i++) handles[i].options.index += value;
152
+ },
153
+ resetAnchor: function(type, anchor) {
154
+ var relatedModel = this.relatedView.model;
155
+ if (anchor) {
156
+ relatedModel.prop([type, 'anchor'], anchor, {
157
+ rewrite: true,
158
+ ui: true,
159
+ tool: this.cid
160
+ });
161
+ } else {
162
+ relatedModel.removeProp([type, 'anchor'], {
163
+ ui: true,
164
+ tool: this.cid
165
+ });
166
+ }
167
+ },
168
+ snapHandle: function(handle, position, data) {
169
+
170
+ var index = handle.options.index;
171
+ var linkView = this.relatedView;
172
+ var link = linkView.model;
173
+ var vertices = link.vertices();
174
+ var axis = handle.options.axis;
175
+ var prev = vertices[index - 2] || data.sourceAnchor;
176
+ var next = vertices[index + 1] || data.targetAnchor;
177
+ var snapRadius = this.options.snapRadius;
178
+ if (Math.abs(position[axis] - prev[axis]) < snapRadius) {
179
+ position[axis] = prev[axis];
180
+ } else if (Math.abs(position[axis] - next[axis]) < snapRadius) {
181
+ position[axis] = next[axis];
182
+ }
183
+ return position;
184
+ },
185
+
186
+ onHandleChanging: function(handle, evt) {
187
+
188
+ const { options } = this;
189
+ var data = this.eventData(evt);
190
+ var relatedView = this.relatedView;
191
+ var paper = relatedView.paper;
192
+ var index = handle.options.index - 1;
193
+ var normalizedEvent = util.normalizeEvent(evt);
194
+ var coords = paper.snapToGrid(normalizedEvent.clientX, normalizedEvent.clientY);
195
+ var position = this.snapHandle(handle, coords.clone(), data);
196
+ var axis = handle.options.axis;
197
+ var offset = (this.options.snapHandle) ? 0 : (coords[axis] - position[axis]);
198
+ var link = relatedView.model;
199
+ var vertices = util.cloneDeep(link.vertices());
200
+ var anchorFn = this.options.anchor;
201
+ if (typeof anchorFn !== 'function') anchorFn = null;
202
+
203
+ const handleIndex = handle.options.index;
204
+
205
+ const vertexPoints = [relatedView.sourcePoint.clone(), ...vertices, relatedView.targetPoint.clone()];
206
+ let indexOffset = 0;
207
+
208
+ // check if vertex before handle vertex exists
209
+ if (handleIndex - 1 >= 0) {
210
+ const v1 = vertexPoints[handleIndex - 1];
211
+ const v2 = vertexPoints[handleIndex];
212
+
213
+ const theta = new g.Line(v1, v2).vector().theta();
214
+
215
+ // check only non-orthogonal segments
216
+ if (theta % 90 !== 0) {
217
+ vertices.splice(handleIndex - 1, 0, data.originalVertices[handleIndex - 1]);
218
+ indexOffset++;
219
+ this.shiftHandleIndexes(1);
220
+ }
221
+ }
222
+
223
+ var vertex = vertices[index + indexOffset];
224
+ var nextVertex = vertices[index + 1 + indexOffset];
225
+
226
+ // check if vertex after handle vertex exists
227
+ if (handleIndex + 2 < vertexPoints.length) {
228
+ const v1 = vertexPoints[handleIndex + 1];
229
+ const v2 = vertexPoints[handleIndex + 2];
230
+
231
+ const theta = new g.Line(v1, v2).vector().theta();
232
+
233
+ // check only non-orthogonal segments
234
+ if (theta % 90 !== 0) {
235
+ const isSingleVertex = data.originalVertices.length === 1;
236
+ const origVIndex = isSingleVertex ? 0 : handleIndex;
237
+ const additionalOffset = data.firstHandleShifted && !isSingleVertex ? 1 : 0;
238
+ let nextVIndex = 1 + indexOffset;
239
+ vertices.splice(handleIndex + nextVIndex, 0, data.originalVertices[origVIndex - additionalOffset]);
240
+ }
241
+ }
242
+
243
+ // First Segment
244
+ var sourceView = relatedView.sourceView;
245
+ var sourceBBox = relatedView.sourceBBox;
246
+ var changeSourceAnchor = false;
247
+ var deleteSourceAnchor = false;
248
+ if (!vertex) {
249
+ vertex = relatedView.sourceAnchor.toJSON();
250
+ vertex[axis] = position[axis];
251
+ if (sourceBBox.containsPoint(vertex)) {
252
+ vertex[axis] = position[axis];
253
+ changeSourceAnchor = true;
254
+ } else {
255
+ // we left the area of the source magnet for the first time
256
+ vertices.unshift(vertex);
257
+ this.shiftHandleIndexes(1);
258
+ data.firstHandleShifted = true;
259
+ deleteSourceAnchor = true;
260
+ }
261
+ } else if (index === 0) {
262
+ if (sourceBBox.containsPoint(vertex)) {
263
+ vertices.shift();
264
+ this.shiftHandleIndexes(-1);
265
+ changeSourceAnchor = true;
266
+ } else {
267
+ vertex[axis] = position[axis];
268
+ deleteSourceAnchor = true;
269
+ }
270
+ } else {
271
+ vertex[axis] = position[axis];
272
+ }
273
+
274
+ if (anchorFn && sourceView) {
275
+ if (changeSourceAnchor) {
276
+ var sourceAnchorPosition = data.sourceAnchor.clone();
277
+ sourceAnchorPosition[axis] = position[axis];
278
+ var sourceAnchor = anchorFn.call(relatedView, sourceAnchorPosition, sourceView, relatedView.sourceMagnet || sourceView.el, 'source', relatedView);
279
+ this.resetAnchor('source', sourceAnchor);
280
+ }
281
+ if (deleteSourceAnchor) {
282
+ this.resetAnchor('source', data.sourceAnchorDef);
283
+ }
284
+ }
285
+
286
+ // Last segment
287
+ var targetView = relatedView.targetView;
288
+ var targetBBox = relatedView.targetBBox;
289
+ var changeTargetAnchor = false;
290
+ var deleteTargetAnchor = false;
291
+ if (!nextVertex) {
292
+ nextVertex = relatedView.targetAnchor.toJSON();
293
+ nextVertex[axis] = position[axis];
294
+ if (targetBBox.containsPoint(nextVertex)) {
295
+ changeTargetAnchor = true;
296
+ } else {
297
+ // we left the area of the target magnet for the first time
298
+ vertices.push(nextVertex);
299
+ deleteTargetAnchor = true;
300
+ }
301
+ } else if (index === vertices.length - 2) {
302
+ if (targetBBox.containsPoint(nextVertex)) {
303
+ vertices.pop();
304
+ changeTargetAnchor = true;
305
+ } else {
306
+ nextVertex[axis] = position[axis];
307
+ deleteTargetAnchor = true;
308
+ }
309
+ } else {
310
+ nextVertex[axis] = position[axis];
311
+ }
312
+
313
+ if (anchorFn && targetView) {
314
+ if (changeTargetAnchor) {
315
+ var targetAnchorPosition = data.targetAnchor.clone();
316
+ targetAnchorPosition[axis] = position[axis];
317
+ var targetAnchor = anchorFn.call(relatedView, targetAnchorPosition, targetView, relatedView.targetMagnet || targetView.el, 'target', relatedView);
318
+ this.resetAnchor('target', targetAnchor);
319
+ }
320
+ if (deleteTargetAnchor) {
321
+ this.resetAnchor('target', data.targetAnchorDef);
322
+ }
323
+ }
324
+ if (vertices.some(v => !v)) {
325
+ // This can happen when the link is using a smart routing and the number of
326
+ // vertices is not the same as the number of route points.
327
+ throw new Error('Segments: incompatible router in use');
328
+ }
329
+ link.vertices(vertices, { ui: true, tool: this.cid });
330
+ this.updateHandle(handle, vertex, nextVertex, offset);
331
+ if (!options.stopPropagation) relatedView.notifyPointermove(normalizedEvent, coords.x, coords.y);
332
+ },
333
+ onHandleChangeStart: function(handle, evt) {
334
+ const { options, handles, relatedView: linkView } = this;
335
+ const { model, paper } = linkView;
336
+ var index = handle.options.index;
337
+ if (!Array.isArray(handles)) return;
338
+ for (var i = 0, n = handles.length; i < n; i++) {
339
+ if (i !== index) handles[i].hide();
340
+ }
341
+ this.focus();
342
+ this.eventData(evt, {
343
+ sourceAnchor: linkView.sourceAnchor.clone(),
344
+ targetAnchor: linkView.targetAnchor.clone(),
345
+ sourceAnchorDef: util.clone(model.prop(['source', 'anchor'])),
346
+ targetAnchorDef: util.clone(model.prop(['target', 'anchor'])),
347
+ originalVertices: util.cloneDeep(model.vertices()),
348
+ firstHandleShifted: false
349
+ });
350
+ model.startBatch('segment-move', { ui: true, tool: this.cid });
351
+ if (!options.stopPropagation) linkView.notifyPointerdown(...paper.getPointerArgs(evt));
352
+ },
353
+ onHandleChangeEnd: function(_handle, evt) {
354
+ const { options, relatedView: linkView }= this;
355
+ const { paper, model } = linkView;
356
+ if (options.redundancyRemoval) {
357
+ linkView.removeRedundantLinearVertices({ ui: true, tool: this.cid });
358
+ }
359
+ const normalizedEvent = util.normalizeEvent(evt);
360
+ const coords = paper.snapToGrid(normalizedEvent.clientX, normalizedEvent.clientY);
361
+ this.render();
362
+ this.blur();
363
+ model.stopBatch('segment-move', { ui: true, tool: this.cid });
364
+ if (!options.stopPropagation) linkView.notifyPointerup(normalizedEvent, coords.x, coords.y);
365
+ linkView.checkMouseleave(normalizedEvent);
366
+ },
367
+ updateHandle: function(handle, vertex, nextVertex, offset) {
368
+ var vertical = Math.abs(vertex.x - nextVertex.x) < this.precision;
369
+ var horizontal = Math.abs(vertex.y - nextVertex.y) < this.precision;
370
+ if (vertical || horizontal) {
371
+ var segmentLine = new g.Line(vertex, nextVertex);
372
+ var length = segmentLine.length();
373
+ if (length < this.options.segmentLengthThreshold) {
374
+ handle.hide();
375
+ } else {
376
+ var position = segmentLine.midpoint();
377
+ var axis = (vertical) ? 'x' : 'y';
378
+ position[axis] += offset || 0;
379
+ var angle = segmentLine.vector().vectorAngle(new g.Point(1, 0));
380
+ handle.position(position.x, position.y, angle, this.relatedView);
381
+ handle.show();
382
+ handle.options.axis = axis;
383
+ }
384
+ } else {
385
+ handle.hide();
386
+ }
387
+ },
388
+ onRemove: function() {
389
+ this.resetHandles();
390
+ }
391
+ }, {
392
+ SegmentHandle: SegmentHandle // keep as class property
393
+ });
@@ -0,0 +1,253 @@
1
+ import * as g from '../g/index.mjs';
2
+ import * as util from '../util/index.mjs';
3
+ import * as mvc from '../mvc/index.mjs';
4
+ import { ToolView } from '../dia/ToolView.mjs';
5
+ import V from '../V/index.mjs';
6
+
7
+
8
+ // Vertex Handles
9
+ var VertexHandle = mvc.View.extend({
10
+ tagName: 'circle',
11
+ svgElement: true,
12
+ className: 'marker-vertex',
13
+ events: {
14
+ mousedown: 'onPointerDown',
15
+ touchstart: 'onPointerDown',
16
+ dblclick: 'onDoubleClick',
17
+ dbltap: 'onDoubleClick'
18
+ },
19
+ documentEvents: {
20
+ mousemove: 'onPointerMove',
21
+ touchmove: 'onPointerMove',
22
+ mouseup: 'onPointerUp',
23
+ touchend: 'onPointerUp',
24
+ touchcancel: 'onPointerUp'
25
+ },
26
+ attributes: {
27
+ 'r': 6,
28
+ 'fill': '#33334F',
29
+ 'stroke': '#FFFFFF',
30
+ 'stroke-width': 2,
31
+ 'cursor': 'move'
32
+ },
33
+ position: function(x, y) {
34
+ const { vel, options } = this;
35
+ const { scale } = options;
36
+ let matrix = V.createSVGMatrix().translate(x, y);
37
+ if (scale) matrix = matrix.scale(scale);
38
+ vel.transform(matrix, { absolute: true });
39
+ },
40
+ onPointerDown: function(evt) {
41
+ if (this.options.guard(evt)) return;
42
+ evt.stopPropagation();
43
+ evt.preventDefault();
44
+ this.options.paper.undelegateEvents();
45
+ this.delegateDocumentEvents(null, evt.data);
46
+ this.trigger('will-change', this, evt);
47
+ },
48
+ onPointerMove: function(evt) {
49
+ this.trigger('changing', this, evt);
50
+ },
51
+ onDoubleClick: function(evt) {
52
+ this.trigger('remove', this, evt);
53
+ },
54
+ onPointerUp: function(evt) {
55
+ this.trigger('changed', this, evt);
56
+ this.undelegateDocumentEvents();
57
+ this.options.paper.delegateEvents();
58
+ }
59
+ });
60
+
61
+ export const Vertices = ToolView.extend({
62
+ name: 'vertices',
63
+ options: {
64
+ handleClass: VertexHandle,
65
+ snapRadius: 20,
66
+ redundancyRemoval: true,
67
+ vertexAdding: true,
68
+ stopPropagation: true,
69
+ scale: null
70
+ },
71
+ children: [{
72
+ tagName: 'path',
73
+ selector: 'connection',
74
+ className: 'joint-vertices-path',
75
+ attributes: {
76
+ 'fill': 'none',
77
+ 'stroke': 'transparent',
78
+ 'stroke-width': 10,
79
+ 'cursor': 'cell'
80
+ }
81
+ }],
82
+ handles: null,
83
+ events: {
84
+ 'mousedown .joint-vertices-path': 'onPathPointerDown',
85
+ 'touchstart .joint-vertices-path': 'onPathPointerDown'
86
+ },
87
+ onRender: function() {
88
+ if (this.options.vertexAdding) {
89
+ this.renderChildren();
90
+ this.updatePath();
91
+ }
92
+ this.resetHandles();
93
+ this.renderHandles();
94
+ return this;
95
+ },
96
+ update: function() {
97
+ var relatedView = this.relatedView;
98
+ var vertices = relatedView.model.vertices();
99
+ if (vertices.length === this.handles.length) {
100
+ this.updateHandles();
101
+ } else {
102
+ this.resetHandles();
103
+ this.renderHandles();
104
+ }
105
+ if (this.options.vertexAdding) {
106
+ this.updatePath();
107
+ }
108
+ return this;
109
+ },
110
+ resetHandles: function() {
111
+ var handles = this.handles;
112
+ this.handles = [];
113
+ this.stopListening();
114
+ if (!Array.isArray(handles)) return;
115
+ for (var i = 0, n = handles.length; i < n; i++) {
116
+ handles[i].remove();
117
+ }
118
+ },
119
+ renderHandles: function() {
120
+ var relatedView = this.relatedView;
121
+ var vertices = relatedView.model.vertices();
122
+ for (var i = 0, n = vertices.length; i < n; i++) {
123
+ var vertex = vertices[i];
124
+ var handle = new (this.options.handleClass)({
125
+ index: i,
126
+ paper: this.paper,
127
+ scale: this.options.scale,
128
+ guard: evt => this.guard(evt)
129
+ });
130
+ handle.render();
131
+ handle.position(vertex.x, vertex.y);
132
+ this.simulateRelatedView(handle.el);
133
+ handle.vel.appendTo(this.el);
134
+ this.handles.push(handle);
135
+ this.startHandleListening(handle);
136
+ }
137
+ },
138
+ updateHandles: function() {
139
+ var relatedView = this.relatedView;
140
+ var vertices = relatedView.model.vertices();
141
+ for (var i = 0, n = vertices.length; i < n; i++) {
142
+ var vertex = vertices[i];
143
+ var handle = this.handles[i];
144
+ if (!handle) return;
145
+ handle.position(vertex.x, vertex.y);
146
+ }
147
+ },
148
+ updatePath: function() {
149
+ var connection = this.childNodes.connection;
150
+ if (connection) connection.setAttribute('d', this.relatedView.getSerializedConnection());
151
+ },
152
+ startHandleListening: function(handle) {
153
+ const { vertexRemoving = true, vertexMoving = true } = this.options;
154
+ if (vertexMoving) {
155
+ this.listenTo(handle, 'will-change', this.onHandleWillChange);
156
+ this.listenTo(handle, 'changing', this.onHandleChanging);
157
+ this.listenTo(handle, 'changed', this.onHandleChanged);
158
+ }
159
+ if (vertexRemoving) {
160
+ this.listenTo(handle, 'remove', this.onHandleRemove);
161
+ }
162
+ },
163
+ getNeighborPoints: function(index) {
164
+ var linkView = this.relatedView;
165
+ var vertices = linkView.model.vertices();
166
+ var prev = (index > 0) ? vertices[index - 1] : linkView.sourceAnchor;
167
+ var next = (index < vertices.length - 1) ? vertices[index + 1] : linkView.targetAnchor;
168
+ return {
169
+ prev: new g.Point(prev),
170
+ next: new g.Point(next)
171
+ };
172
+ },
173
+ onHandleWillChange: function(_handle, evt) {
174
+ this.focus();
175
+ const { relatedView, options } = this;
176
+ relatedView.model.startBatch('vertex-move', { ui: true, tool: this.cid });
177
+ if (!options.stopPropagation) relatedView.notifyPointerdown(...relatedView.paper.getPointerArgs(evt));
178
+ },
179
+ onHandleChanging: function(handle, evt) {
180
+ const { options, relatedView: linkView } = this;
181
+ var index = handle.options.index;
182
+ var [normalizedEvent, x, y] = linkView.paper.getPointerArgs(evt);
183
+ var vertex = { x, y };
184
+ this.snapVertex(vertex, index);
185
+ linkView.model.vertex(index, vertex, { ui: true, tool: this.cid });
186
+ handle.position(vertex.x, vertex.y);
187
+ if (!options.stopPropagation) linkView.notifyPointermove(normalizedEvent, x, y);
188
+ },
189
+ onHandleChanged: function(_handle, evt) {
190
+ const { options, relatedView: linkView } = this;
191
+ if (options.vertexAdding) this.updatePath();
192
+ if (!options.redundancyRemoval) {
193
+ linkView.checkMouseleave(util.normalizeEvent(evt));
194
+ return;
195
+ }
196
+ var verticesRemoved = linkView.removeRedundantLinearVertices({ ui: true, tool: this.cid });
197
+ if (verticesRemoved) this.render();
198
+ this.blur();
199
+ linkView.model.stopBatch('vertex-move', { ui: true, tool: this.cid });
200
+ if (this.eventData(evt).vertexAdded) {
201
+ linkView.model.stopBatch('vertex-add', { ui: true, tool: this.cid });
202
+ }
203
+ var [normalizedEvt, x, y] = linkView.paper.getPointerArgs(evt);
204
+ if (!options.stopPropagation) linkView.notifyPointerup(normalizedEvt, x, y);
205
+ linkView.checkMouseleave(normalizedEvt);
206
+ },
207
+ snapVertex: function(vertex, index) {
208
+ var snapRadius = this.options.snapRadius;
209
+ if (snapRadius > 0) {
210
+ var neighbors = this.getNeighborPoints(index);
211
+ var prev = neighbors.prev;
212
+ var next = neighbors.next;
213
+ if (Math.abs(vertex.x - prev.x) < snapRadius) {
214
+ vertex.x = prev.x;
215
+ } else if (Math.abs(vertex.x - next.x) < snapRadius) {
216
+ vertex.x = next.x;
217
+ }
218
+ if (Math.abs(vertex.y - prev.y) < snapRadius) {
219
+ vertex.y = neighbors.prev.y;
220
+ } else if (Math.abs(vertex.y - next.y) < snapRadius) {
221
+ vertex.y = next.y;
222
+ }
223
+ }
224
+ },
225
+ onHandleRemove: function(handle, evt) {
226
+ var index = handle.options.index;
227
+ var linkView = this.relatedView;
228
+ linkView.model.removeVertex(index, { ui: true });
229
+ if (this.options.vertexAdding) this.updatePath();
230
+ linkView.checkMouseleave(util.normalizeEvent(evt));
231
+ },
232
+ onPathPointerDown: function(evt) {
233
+ if (this.guard(evt)) return;
234
+ evt.stopPropagation();
235
+ evt.preventDefault();
236
+ var normalizedEvent = util.normalizeEvent(evt);
237
+ var vertex = this.paper.snapToGrid(normalizedEvent.clientX, normalizedEvent.clientY).toJSON();
238
+ var relatedView = this.relatedView;
239
+ relatedView.model.startBatch('vertex-add', { ui: true, tool: this.cid });
240
+ var index = relatedView.getVertexIndex(vertex.x, vertex.y);
241
+ this.snapVertex(vertex, index);
242
+ relatedView.model.insertVertex(index, vertex, { ui: true, tool: this.cid });
243
+ this.update();
244
+ var handle = this.handles[index];
245
+ this.eventData(normalizedEvent, { vertexAdded: true });
246
+ handle.onPointerDown(normalizedEvent);
247
+ },
248
+ onRemove: function() {
249
+ this.resetHandles();
250
+ }
251
+ }, {
252
+ VertexHandle: VertexHandle // keep as class property
253
+ });
@@ -0,0 +1,33 @@
1
+ import * as connectionStrategies from '../connectionStrategies/index.mjs';
2
+
3
+ export function getViewBBox(view, useModelGeometry) {
4
+ const { model } = view;
5
+ if (useModelGeometry) return model.getBBox();
6
+ return (model.isLink()) ? view.getConnection().bbox() : view.getNodeUnrotatedBBox(view.el);
7
+ }
8
+
9
+ export function getAnchor(coords, view, magnet) {
10
+ // take advantage of an existing logic inside of the
11
+ // pin relative connection strategy
12
+ var end = connectionStrategies.pinRelative.call(
13
+ this.paper,
14
+ {},
15
+ view,
16
+ magnet,
17
+ coords,
18
+ this.model
19
+ );
20
+ return end.anchor;
21
+ }
22
+
23
+ export function snapAnchor(coords, view, magnet, type, relatedView, toolView) {
24
+ var snapRadius = toolView.options.snapRadius;
25
+ var isSource = (type === 'source');
26
+ var refIndex = (isSource ? 0 : -1);
27
+ var ref = this.model.vertex(refIndex) || this.getEndAnchor(isSource ? 'target' : 'source');
28
+ if (ref) {
29
+ if (Math.abs(ref.x - coords.x) < snapRadius) coords.x = ref.x;
30
+ if (Math.abs(ref.y - coords.y) < snapRadius) coords.y = ref.y;
31
+ }
32
+ return coords;
33
+ }
@@ -0,0 +1,8 @@
1
+ export * from './Vertices.mjs';
2
+ export * from './Segments.mjs';
3
+ export * from './Arrowhead.mjs';
4
+ export * from './Boundary.mjs';
5
+ export * from './Anchor.mjs';
6
+ export * from './Button.mjs';
7
+ export * from './Connect.mjs';
8
+ export * from './HoverConnect.mjs';