@elyra/canvas 12.36.0 → 12.37.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.
- package/dist/canvas-constants-766c12a9.js +2 -0
- package/dist/{canvas-constants-85883d4c.js.map → canvas-constants-766c12a9.js.map} +1 -1
- package/dist/canvas-constants-f4219d26.js +2 -0
- package/dist/{canvas-constants-d8652829.js.map → canvas-constants-f4219d26.js.map} +1 -1
- package/dist/canvas-controller-62b66fc8.js +2 -0
- package/dist/canvas-controller-62b66fc8.js.map +1 -0
- package/dist/canvas-controller-76f68572.js +2 -0
- package/dist/canvas-controller-76f68572.js.map +1 -0
- package/dist/common-canvas-339584b8.js +2 -0
- package/dist/common-canvas-339584b8.js.map +1 -0
- package/dist/common-canvas-c728f092.js +2 -0
- package/dist/common-canvas-c728f092.js.map +1 -0
- package/dist/common-canvas.es.js +1 -1
- package/dist/common-canvas.es.js.map +1 -1
- package/dist/common-canvas.js +1 -1
- package/dist/common-canvas.js.map +1 -1
- package/dist/common-properties-009d29d6.js +2 -0
- package/dist/{common-properties-a34905c3.js.map → common-properties-009d29d6.js.map} +1 -1
- package/dist/common-properties-99d34523.js +2 -0
- package/dist/{common-properties-d5775a12.js.map → common-properties-99d34523.js.map} +1 -1
- package/dist/context-menu-wrapper-624a1e7c.js +2 -0
- package/dist/context-menu-wrapper-624a1e7c.js.map +1 -0
- package/dist/context-menu-wrapper-ab018d6e.js +2 -0
- package/dist/context-menu-wrapper-ab018d6e.js.map +1 -0
- package/dist/{datarecord-metadata-v3-schema-531c7b07.js → datarecord-metadata-v3-schema-1f21696a.js} +2 -2
- package/dist/{datarecord-metadata-v3-schema-531c7b07.js.map → datarecord-metadata-v3-schema-1f21696a.js.map} +1 -1
- package/dist/{datarecord-metadata-v3-schema-28d4d7bb.js → datarecord-metadata-v3-schema-c2ad8862.js} +2 -2
- package/dist/{datarecord-metadata-v3-schema-28d4d7bb.js.map → datarecord-metadata-v3-schema-c2ad8862.js.map} +1 -1
- package/dist/flexible-table-4cf19e2e.js +2 -0
- package/dist/flexible-table-4cf19e2e.js.map +1 -0
- package/dist/flexible-table-8d10f5c9.js +2 -0
- package/dist/flexible-table-8d10f5c9.js.map +1 -0
- package/dist/{icon-909437d7.js → icon-5e06bfe1.js} +2 -2
- package/dist/{icon-909437d7.js.map → icon-5e06bfe1.js.map} +1 -1
- package/dist/{icon-de9c6b33.js → icon-8433d369.js} +2 -2
- package/dist/{icon-de9c6b33.js.map → icon-8433d369.js.map} +1 -1
- package/dist/{index-9960d3bf.js → index-2a61be58.js} +2 -2
- package/dist/{index-9960d3bf.js.map → index-2a61be58.js.map} +1 -1
- package/dist/{index-61e4a113.js → index-9a355ed6.js} +2 -2
- package/dist/{index-61e4a113.js.map → index-9a355ed6.js.map} +1 -1
- package/dist/lib/canvas-controller.es.js +1 -1
- package/dist/lib/canvas-controller.js +1 -1
- package/dist/lib/canvas.es.js +1 -1
- package/dist/lib/canvas.js +1 -1
- package/dist/lib/context-menu.es.js +1 -1
- package/dist/lib/context-menu.js +1 -1
- package/dist/lib/properties/field-picker.es.js +1 -1
- package/dist/lib/properties/field-picker.js +1 -1
- package/dist/lib/properties/flexible-table.es.js +1 -1
- package/dist/lib/properties/flexible-table.js +1 -1
- package/dist/lib/properties.es.js +1 -1
- package/dist/lib/properties.js +1 -1
- package/dist/styles/common-canvas.min.css +1 -1
- package/dist/styles/common-canvas.min.css.map +1 -1
- package/dist/{toolbar-cdb38f4a.js → toolbar-76733735.js} +2 -2
- package/dist/{toolbar-cdb38f4a.js.map → toolbar-76733735.js.map} +1 -1
- package/dist/{toolbar-3b5a592c.js → toolbar-85e1e463.js} +2 -2
- package/dist/{toolbar-3b5a592c.js.map → toolbar-85e1e463.js.map} +1 -1
- package/locales/common-canvas/locales/en.json +1 -1
- package/locales/common-canvas/locales/eo.json +1 -1
- package/package.json +2 -3
- package/src/common-canvas/canvas-controller.js +7 -0
- package/src/common-canvas/cc-contents.jsx +42 -4
- package/src/common-canvas/common-canvas-utils.js +9 -2
- package/src/common-canvas/common-canvas.scss +30 -3
- package/src/common-canvas/constants/canvas-constants.js +0 -6
- package/src/common-canvas/svg-canvas-d3.js +1 -3
- package/src/common-canvas/svg-canvas-d3.scss +0 -26
- package/src/common-canvas/svg-canvas-pipeline.js +6 -0
- package/src/common-canvas/svg-canvas-renderer.js +488 -2815
- package/src/common-canvas/svg-canvas-utils-drag-det-link.js +491 -0
- package/src/common-canvas/svg-canvas-utils-drag-new-link.js +595 -0
- package/src/common-canvas/svg-canvas-utils-drag-objects.js +832 -0
- package/src/common-canvas/svg-canvas-utils-external.js +82 -16
- package/src/common-canvas/svg-canvas-utils-zoom.js +780 -0
- package/src/context-menu/common-context-menu.jsx +57 -26
- package/src/context-menu/context-menu.scss +33 -53
- package/src/notification-panel/notification-panel.jsx +6 -1
- package/src/notification-panel/notification-panel.scss +4 -2
- package/src/palette/palette-content-list-item.jsx +23 -7
- package/stats.html +1 -1
- package/dist/canvas-constants-85883d4c.js +0 -2
- package/dist/canvas-constants-d8652829.js +0 -2
- package/dist/canvas-controller-7beb80ec.js +0 -2
- package/dist/canvas-controller-7beb80ec.js.map +0 -1
- package/dist/canvas-controller-b70d0f98.js +0 -2
- package/dist/canvas-controller-b70d0f98.js.map +0 -1
- package/dist/common-canvas-86fb7d21.js +0 -2
- package/dist/common-canvas-86fb7d21.js.map +0 -1
- package/dist/common-canvas-a6bfce5e.js +0 -2
- package/dist/common-canvas-a6bfce5e.js.map +0 -1
- package/dist/common-properties-a34905c3.js +0 -2
- package/dist/common-properties-d5775a12.js +0 -2
- package/dist/context-menu-wrapper-19a1cf72.js +0 -2
- package/dist/context-menu-wrapper-19a1cf72.js.map +0 -1
- package/dist/context-menu-wrapper-c3a98c63.js +0 -2
- package/dist/context-menu-wrapper-c3a98c63.js.map +0 -1
- package/dist/extends-093996c9.js +0 -2
- package/dist/extends-093996c9.js.map +0 -1
- package/dist/extends-1b35a664.js +0 -2
- package/dist/extends-1b35a664.js.map +0 -1
- package/dist/flexible-table-b9c08069.js +0 -2
- package/dist/flexible-table-b9c08069.js.map +0 -1
- package/dist/flexible-table-ddd6132b.js +0 -2
- package/dist/flexible-table-ddd6132b.js.map +0 -1
|
@@ -0,0 +1,832 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2017-2023 Elyra Authors
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/* eslint no-lonely-if: "off" */
|
|
18
|
+
|
|
19
|
+
import * as d3Drag from "d3-drag";
|
|
20
|
+
import * as d3Selection from "d3-selection";
|
|
21
|
+
const d3 = Object.assign({}, d3Drag, d3Selection);
|
|
22
|
+
|
|
23
|
+
import Logger from "../logging/canvas-logger.js";
|
|
24
|
+
import CanvasUtils from "./common-canvas-utils.js";
|
|
25
|
+
import { SNAP_TO_GRID_AFTER, SNAP_TO_GRID_DURING, LINK_SELECTION_DETACHABLE }
|
|
26
|
+
from "./constants/canvas-constants.js";
|
|
27
|
+
|
|
28
|
+
// This utility files provides a drag handler which manages drag operations to move
|
|
29
|
+
// and resize nodes and comments.
|
|
30
|
+
|
|
31
|
+
export default class SVGCanvasUtilsDragObjects {
|
|
32
|
+
constructor(renderer) {
|
|
33
|
+
this.ren = renderer;
|
|
34
|
+
|
|
35
|
+
this.logger = new Logger("SVGCanvasUtilsDragObjects");
|
|
36
|
+
|
|
37
|
+
// Keeps track of the size and position, at the start of the sizing event,
|
|
38
|
+
// of the object (node or comment) being sized.
|
|
39
|
+
this.resizeObjInitialInfo = null;
|
|
40
|
+
|
|
41
|
+
// Allows us to track the sizing behavior of comments
|
|
42
|
+
this.commentSizing = false;
|
|
43
|
+
this.commentSizingDirection = null;
|
|
44
|
+
this.commentSizingCursor = "";
|
|
45
|
+
|
|
46
|
+
// Allows us to track the sizing behavior of nodes
|
|
47
|
+
this.nodeSizing = false;
|
|
48
|
+
this.nodeSizingDirection = null;
|
|
49
|
+
this.nodeSizingCursor = "";
|
|
50
|
+
this.nodeSizingObjectsInfo = {};
|
|
51
|
+
this.nodeSizingDetLinksInfo = {};
|
|
52
|
+
|
|
53
|
+
// Keeps track of the size and position, during a sizing event, of the
|
|
54
|
+
// object (node or comment) being sized, before it is snapped to grid.
|
|
55
|
+
this.notSnappedXPos = 0;
|
|
56
|
+
this.notSnappedYPos = 0;
|
|
57
|
+
this.notSnappedWidth = 0;
|
|
58
|
+
this.notSnappedHeight = 0;
|
|
59
|
+
|
|
60
|
+
// Object to store variables for drag behavior or nodes and comments.
|
|
61
|
+
this.draggingObjectData = null;
|
|
62
|
+
|
|
63
|
+
// Flag to indicate if the current drag operation is for a node that can
|
|
64
|
+
// be inserted into a link. Such a node would need input and output ports.
|
|
65
|
+
this.existingNodeInsertableIntoLink = false;
|
|
66
|
+
|
|
67
|
+
// Flag to indicate if the current drag operation is for a node that can
|
|
68
|
+
// be attached to a detached link.
|
|
69
|
+
this.existingNodeAttachableToDetachedLinks = false;
|
|
70
|
+
|
|
71
|
+
// Create a drag handler for resizing and moving nodes and comments.
|
|
72
|
+
this.dragObjectHandler = d3.drag()
|
|
73
|
+
.on("start", this.dragStartObject.bind(this))
|
|
74
|
+
.on("drag", this.dragObject.bind(this))
|
|
75
|
+
.on("end", this.dragEndObject.bind(this));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Returns the dragObjectsHandler
|
|
79
|
+
getDragObjectHandler() {
|
|
80
|
+
return this.dragObjectHandler;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Returns true if a sizing operation is currently underway.
|
|
84
|
+
isSizing() {
|
|
85
|
+
return this.nodeSizing || this.commentSizing;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Returns truthy if a moving operation is currently underway.
|
|
89
|
+
isMoving() {
|
|
90
|
+
return this.draggingObjectData;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
mouseEnterNodeSizingArea(d3Event, d) {
|
|
94
|
+
if (this.ren.config.enableEditingActions && // Only set cursor when we are able to resize nodes
|
|
95
|
+
this.isNodeResizable(d) &&
|
|
96
|
+
!this.ren.isRegionSelectOrSizingInProgress()) { // Don't switch sizing direction if we are already sizing
|
|
97
|
+
let cursorType = "default";
|
|
98
|
+
if (!this.isPointerCloseToBodyEdge(d3Event, d)) {
|
|
99
|
+
this.nodeSizingDirection = this.getSizingDirection(d3Event, d, d.layout.nodeCornerResizeArea);
|
|
100
|
+
this.nodeSizingCursor = this.getCursorBasedOnDirection(this.nodeSizingDirection);
|
|
101
|
+
cursorType = this.nodeSizingCursor;
|
|
102
|
+
}
|
|
103
|
+
d3.select(d3Event.currentTarget).style("cursor", cursorType);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
mouseDownNodeSizingArea(d) {
|
|
108
|
+
if (this.isNodeResizable(d)) {
|
|
109
|
+
this.nodeSizing = true;
|
|
110
|
+
// Note - node resizing and finalization of size is handled by drag functions.
|
|
111
|
+
this.ren.addTempCursorOverlay(this.nodeSizingCursor);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
mouseLeaveNodeSizingArea(d3Event) {
|
|
116
|
+
d3.select(d3Event.currentTarget).style("cursor", "default");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
mouseEnterCommentSizingArea(d3Event, d) {
|
|
120
|
+
if (this.ren.config.enableEditingActions && // Only set cursor when we are able to edit comments
|
|
121
|
+
!this.ren.isRegionSelectOrSizingInProgress()) { // Don't switch sizing direction if we are already sizing
|
|
122
|
+
let cursorType = "default";
|
|
123
|
+
if (!this.isPointerCloseToBodyEdge(d3Event, d)) {
|
|
124
|
+
this.commentSizingDirection = this.getSizingDirection(d3Event, d, this.ren.canvasLayout.commentCornerResizeArea);
|
|
125
|
+
this.commentSizingCursor = this.getCursorBasedOnDirection(this.commentSizingDirection);
|
|
126
|
+
cursorType = this.commentSizingCursor;
|
|
127
|
+
}
|
|
128
|
+
d3.select(d3Event.currentTarget).style("cursor", cursorType);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
mouseDownCommentSizingArea() {
|
|
133
|
+
// Note - comment resizing and finalization of size is handled by drag functions.
|
|
134
|
+
this.commentSizing = true;
|
|
135
|
+
this.ren.addTempCursorOverlay(this.commentSizingCursor);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
mouseLeaveCommentSizingArea(d3Event) {
|
|
139
|
+
d3.select(d3Event.currentTarget).style("cursor", "default");
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
dragStartObject(d3Event, d) {
|
|
143
|
+
this.logger.logStartTimer("dragStartObject");
|
|
144
|
+
|
|
145
|
+
this.ren.closeContextMenuIfOpen();
|
|
146
|
+
|
|
147
|
+
if (this.commentSizing) {
|
|
148
|
+
this.initializeResizeVariables(d);
|
|
149
|
+
|
|
150
|
+
} else if (this.nodeSizing) {
|
|
151
|
+
this.initializeResizeVariables(d);
|
|
152
|
+
|
|
153
|
+
} else {
|
|
154
|
+
this.dragObjectsStart(d3Event, d);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
this.logger.logEndTimer("dragStartObject", true);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
dragObject(d3Event, d) {
|
|
161
|
+
this.logger.logStartTimer("dragObject");
|
|
162
|
+
if (this.commentSizing) {
|
|
163
|
+
this.resizeComment(d3Event, d);
|
|
164
|
+
|
|
165
|
+
} else if (this.nodeSizing) {
|
|
166
|
+
this.resizeNode(d3Event, d);
|
|
167
|
+
|
|
168
|
+
} else {
|
|
169
|
+
this.dragObjectsAction(d3Event);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
this.logger.logEndTimer("dragObject", true);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
dragEndObject(d3Event, d) {
|
|
176
|
+
this.logger.logStartTimer("dragEndObject");
|
|
177
|
+
|
|
178
|
+
this.ren.removeTempCursorOverlay();
|
|
179
|
+
|
|
180
|
+
if (this.commentSizing) {
|
|
181
|
+
this.endCommentSizing(d);
|
|
182
|
+
this.commentSizing = false;
|
|
183
|
+
|
|
184
|
+
} else if (this.nodeSizing) {
|
|
185
|
+
this.endNodeSizing(d);
|
|
186
|
+
this.nodeSizing = false;
|
|
187
|
+
|
|
188
|
+
} else {
|
|
189
|
+
this.dragObjectsEnd(d3Event, d);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
this.logger.logEndTimer("dragEndObject", true);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Records the initial starting position of the object being sized so
|
|
196
|
+
// that drag increments can be added to the original starting
|
|
197
|
+
// position to aid calculating the snap-to-grid position.
|
|
198
|
+
initializeResizeVariables(resizeObj) {
|
|
199
|
+
this.resizeObjInitialInfo = {
|
|
200
|
+
x_pos: resizeObj.x_pos, y_pos: resizeObj.y_pos, width: resizeObj.width, height: resizeObj.height };
|
|
201
|
+
this.notSnappedXPos = resizeObj.x_pos;
|
|
202
|
+
this.notSnappedYPos = resizeObj.y_pos;
|
|
203
|
+
this.notSnappedWidth = resizeObj.width;
|
|
204
|
+
this.notSnappedHeight = resizeObj.height;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// This method allows us to avoid a strange behavior which only appears in the
|
|
208
|
+
// Chrome browser. That is, when the mouse pointer is inside the
|
|
209
|
+
// node/comment selection highlight area but is close to either the
|
|
210
|
+
// right or bottom side of the node/comment body, any mousedown events will go
|
|
211
|
+
// to the body instead of the highlight area. We use this method to detect
|
|
212
|
+
// this situation and use the result to decide whether to display the sizing
|
|
213
|
+
// cursor or not.
|
|
214
|
+
isPointerCloseToBodyEdge(d3Event, d) {
|
|
215
|
+
const pos = this.ren.getTransformedMousePos(d3Event);
|
|
216
|
+
const rightEdge = d.x_pos + d.width;
|
|
217
|
+
const bottomEdge = d.y_pos + d.height;
|
|
218
|
+
|
|
219
|
+
// Is the pointer within 1 pixel of the right edge of the node or comment
|
|
220
|
+
const rightEdgeState =
|
|
221
|
+
pos.x >= rightEdge && pos.x <= rightEdge + 1 &&
|
|
222
|
+
pos.y >= 0 && pos.y <= bottomEdge;
|
|
223
|
+
|
|
224
|
+
// Is the pointer within 1 pixel of the bottom edge of the node or comment
|
|
225
|
+
const bottomEdgeState =
|
|
226
|
+
pos.y >= bottomEdge && pos.y <= bottomEdge + 1 &&
|
|
227
|
+
pos.x >= 0 && pos.x <= rightEdge;
|
|
228
|
+
|
|
229
|
+
return rightEdgeState || bottomEdgeState;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Returns the comment or supernode sizing direction (i.e. one of n, s, e, w, nw, ne,
|
|
233
|
+
// sw or se) based on the current mouse position and the position and
|
|
234
|
+
// dimensions of the comment or node outline.
|
|
235
|
+
getSizingDirection(d3Event, d, cornerResizeArea) {
|
|
236
|
+
var xPart = "";
|
|
237
|
+
var yPart = "";
|
|
238
|
+
|
|
239
|
+
const transPos = this.ren.getTransformedMousePos(d3Event);
|
|
240
|
+
if (transPos.x < d.x_pos + cornerResizeArea) {
|
|
241
|
+
xPart = "w";
|
|
242
|
+
} else if (transPos.x > d.x_pos + d.width - cornerResizeArea) {
|
|
243
|
+
xPart = "e";
|
|
244
|
+
}
|
|
245
|
+
if (transPos.y < d.y_pos + cornerResizeArea) {
|
|
246
|
+
yPart = "n";
|
|
247
|
+
} else if (transPos.y > d.y_pos + d.height - cornerResizeArea) {
|
|
248
|
+
yPart = "s";
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return yPart + xPart;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Returns a cursor type based on the currect comment sizing direction.
|
|
255
|
+
// Possible values are: ns-resize, ew-resize, nwse-resize or nesw-resize.
|
|
256
|
+
getCursorBasedOnDirection(direction) {
|
|
257
|
+
var cursorType;
|
|
258
|
+
switch (direction) {
|
|
259
|
+
case "n":
|
|
260
|
+
case "s":
|
|
261
|
+
cursorType = "ns-resize";
|
|
262
|
+
break;
|
|
263
|
+
case "e":
|
|
264
|
+
case "w":
|
|
265
|
+
cursorType = "ew-resize";
|
|
266
|
+
break;
|
|
267
|
+
case "nw":
|
|
268
|
+
case "se":
|
|
269
|
+
cursorType = "nwse-resize";
|
|
270
|
+
break;
|
|
271
|
+
case "ne":
|
|
272
|
+
case "sw":
|
|
273
|
+
cursorType = "nesw-resize";
|
|
274
|
+
break;
|
|
275
|
+
default:
|
|
276
|
+
cursorType = "";
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
return cursorType;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Returns true if the node should be resizeable. Expanded supernodes are
|
|
283
|
+
// always resizabele and all other nodes, except collapsed supernodes, are
|
|
284
|
+
// resizeable when enableResizableNodes is switched on.
|
|
285
|
+
isNodeResizable(node) {
|
|
286
|
+
if (!this.ren.config.enableEditingActions ||
|
|
287
|
+
CanvasUtils.isSuperBindingNode(node) ||
|
|
288
|
+
CanvasUtils.isCollapsedSupernode(node) ||
|
|
289
|
+
(!this.ren.config.enableResizableNodes && !CanvasUtils.isExpandedSupernode(node))) {
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Sets the size and position of the node in the canvasInfo.nodes
|
|
296
|
+
// array based on the position of the pointer during the resize action
|
|
297
|
+
// then redraws the nodes and links (the link positions may move based
|
|
298
|
+
// on the node size change).
|
|
299
|
+
resizeNode(d3Event, resizeObj) {
|
|
300
|
+
const oldSupernode = Object.assign({}, resizeObj);
|
|
301
|
+
const minHeight = this.getMinHeight(resizeObj);
|
|
302
|
+
const minWidth = this.getMinWidth(resizeObj);
|
|
303
|
+
|
|
304
|
+
const delta = this.resizeObject(d3Event, resizeObj,
|
|
305
|
+
this.nodeSizingDirection, minWidth, minHeight);
|
|
306
|
+
|
|
307
|
+
if (delta && (delta.x_pos !== 0 || delta.y_pos !== 0 || delta.width !== 0 || delta.height !== 0)) {
|
|
308
|
+
if (CanvasUtils.isSupernode(resizeObj) &&
|
|
309
|
+
this.ren.config.enableMoveNodesOnSupernodeResize) {
|
|
310
|
+
const objectsInfo = CanvasUtils.moveSurroundingObjects(
|
|
311
|
+
oldSupernode,
|
|
312
|
+
this.ren.activePipeline.getNodesAndComments(),
|
|
313
|
+
this.nodeSizingDirection,
|
|
314
|
+
resizeObj.width,
|
|
315
|
+
resizeObj.height,
|
|
316
|
+
true // Pass true to indicate that object positions should be updated.
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
const linksInfo = CanvasUtils.moveSurroundingDetachedLinks(
|
|
320
|
+
oldSupernode,
|
|
321
|
+
this.ren.activePipeline.links,
|
|
322
|
+
this.nodeSizingDirection,
|
|
323
|
+
resizeObj.width,
|
|
324
|
+
resizeObj.height,
|
|
325
|
+
true // Pass true to indicate that link positions should be updated.
|
|
326
|
+
);
|
|
327
|
+
|
|
328
|
+
// Overwrite the object and link info with any new info.
|
|
329
|
+
this.nodeSizingObjectsInfo = Object.assign(this.nodeSizingObjectsInfo, objectsInfo);
|
|
330
|
+
this.nodeSizingDetLinksInfo = Object.assign(this.nodeSizingDetLinksInfo, linksInfo);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
this.logger.logStartTimer("displayObjects");
|
|
334
|
+
|
|
335
|
+
this.ren.displayMovedComments();
|
|
336
|
+
this.ren.displayMovedNodes();
|
|
337
|
+
this.ren.displaySingleNode(resizeObj);
|
|
338
|
+
this.ren.displayMovedLinks();
|
|
339
|
+
this.ren.displayCanvasAccoutrements();
|
|
340
|
+
|
|
341
|
+
if (CanvasUtils.isSupernode(resizeObj)) {
|
|
342
|
+
if (this.ren.dispUtils.isDisplayingSubFlow()) {
|
|
343
|
+
this.ren.displayBindingNodesToFitSVG();
|
|
344
|
+
}
|
|
345
|
+
this.ren.superRenderers.forEach((renderer) => renderer.displaySVGToFitSupernode());
|
|
346
|
+
}
|
|
347
|
+
this.logger.logEndTimer("displayObjects");
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Sets the size and position of the comment in the canvasInfo.comments
|
|
352
|
+
// array based on the position of the pointer during the resize action
|
|
353
|
+
// then redraws the comment and links (the link positions may move based
|
|
354
|
+
// on the comment size change).
|
|
355
|
+
resizeComment(d3Event, resizeObj) {
|
|
356
|
+
this.resizeObject(d3Event, resizeObj, this.commentSizingDirection, 20, 20);
|
|
357
|
+
this.ren.displaySingleComment(resizeObj);
|
|
358
|
+
this.ren.displayMovedLinks();
|
|
359
|
+
this.ren.displayCanvasAccoutrements();
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Sets the size and position of the object in the canvasInfo
|
|
363
|
+
// array based on the position of the pointer during the resize action.
|
|
364
|
+
resizeObject(d3Event, canvasObj, direction, minWidth, minHeight) {
|
|
365
|
+
let incrementX = 0;
|
|
366
|
+
let incrementY = 0;
|
|
367
|
+
let incrementWidth = 0;
|
|
368
|
+
let incrementHeight = 0;
|
|
369
|
+
|
|
370
|
+
if (direction.indexOf("e") > -1) {
|
|
371
|
+
incrementWidth += d3Event.dx;
|
|
372
|
+
}
|
|
373
|
+
if (direction.indexOf("s") > -1) {
|
|
374
|
+
incrementHeight += d3Event.dy;
|
|
375
|
+
}
|
|
376
|
+
if (direction.indexOf("n") > -1) {
|
|
377
|
+
incrementY += d3Event.dy;
|
|
378
|
+
incrementHeight -= d3Event.dy;
|
|
379
|
+
}
|
|
380
|
+
if (direction.indexOf("w") > -1) {
|
|
381
|
+
incrementX += d3Event.dx;
|
|
382
|
+
incrementWidth -= d3Event.dx;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
let xPos = 0;
|
|
386
|
+
let yPos = 0;
|
|
387
|
+
let width = 0;
|
|
388
|
+
let height = 0;
|
|
389
|
+
|
|
390
|
+
if (this.ren.config.enableSnapToGridType === SNAP_TO_GRID_DURING) {
|
|
391
|
+
// Calculate where the object being resized would be and its size given
|
|
392
|
+
// current increments.
|
|
393
|
+
this.notSnappedXPos += incrementX;
|
|
394
|
+
this.notSnappedYPos += incrementY;
|
|
395
|
+
this.notSnappedWidth += incrementWidth;
|
|
396
|
+
this.notSnappedHeight += incrementHeight;
|
|
397
|
+
|
|
398
|
+
xPos = CanvasUtils.snapToGrid(this.notSnappedXPos, this.ren.canvasLayout.snapToGridXPx);
|
|
399
|
+
yPos = CanvasUtils.snapToGrid(this.notSnappedYPos, this.ren.canvasLayout.snapToGridYPx);
|
|
400
|
+
width = CanvasUtils.snapToGrid(this.notSnappedWidth, this.ren.canvasLayout.snapToGridXPx);
|
|
401
|
+
height = CanvasUtils.snapToGrid(this.notSnappedHeight, this.ren.canvasLayout.snapToGridYPx);
|
|
402
|
+
|
|
403
|
+
width = Math.max(width, minWidth);
|
|
404
|
+
height = Math.max(height, minHeight);
|
|
405
|
+
|
|
406
|
+
} else {
|
|
407
|
+
xPos = canvasObj.x_pos + incrementX;
|
|
408
|
+
yPos = canvasObj.y_pos + incrementY;
|
|
409
|
+
width = canvasObj.width + incrementWidth;
|
|
410
|
+
height = canvasObj.height + incrementHeight;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
// Don't allow the object area to shrink below the min width and height.
|
|
414
|
+
// For comment sizing, errors may occur especially if the width becomes
|
|
415
|
+
// less that one character's width. For node sizing we want at least some
|
|
416
|
+
// area to display the sub-flow.
|
|
417
|
+
if (width < minWidth || height < minHeight) {
|
|
418
|
+
return null;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const delta = {
|
|
422
|
+
width: width - canvasObj.width,
|
|
423
|
+
height: height - canvasObj.height,
|
|
424
|
+
x_pos: xPos - canvasObj.x_pos,
|
|
425
|
+
y_pos: yPos - canvasObj.y_pos
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
canvasObj.x_pos = xPos;
|
|
429
|
+
canvasObj.y_pos = yPos;
|
|
430
|
+
canvasObj.width = width;
|
|
431
|
+
canvasObj.height = height;
|
|
432
|
+
|
|
433
|
+
return delta;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// Finalises the sizing of a node by calling editActionHandler
|
|
437
|
+
// with an editNode action.
|
|
438
|
+
endNodeSizing(node) {
|
|
439
|
+
let resizeObj = node;
|
|
440
|
+
if (this.ren.config.enableSnapToGridType === SNAP_TO_GRID_AFTER) {
|
|
441
|
+
resizeObj = this.snapToGridObject(resizeObj);
|
|
442
|
+
resizeObj = this.restrictNodeSizingToMinimums(resizeObj);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// If the dimensions or position has changed, issue the "resizeObjects" command.
|
|
446
|
+
// Note: x_pos or y_pos might change on resize if the node is sized
|
|
447
|
+
// upwards or to the left.
|
|
448
|
+
if (this.resizeObjInitialInfo.x_pos !== resizeObj.x_pos ||
|
|
449
|
+
this.resizeObjInitialInfo.y_pos !== resizeObj.y_pos ||
|
|
450
|
+
this.resizeObjInitialInfo.width !== resizeObj.width ||
|
|
451
|
+
this.resizeObjInitialInfo.height !== resizeObj.height) {
|
|
452
|
+
// Add the dimensions of the object being resized to the array of object infos.
|
|
453
|
+
this.nodeSizingObjectsInfo[resizeObj.id] = {
|
|
454
|
+
width: resizeObj.width,
|
|
455
|
+
height: resizeObj.height,
|
|
456
|
+
x_pos: resizeObj.x_pos,
|
|
457
|
+
y_pos: resizeObj.y_pos
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
// If the node has been resized set the resize properties appropriately.
|
|
461
|
+
// We use some padding because sometimes, when a node is sized back to its
|
|
462
|
+
// original dimensions, it isn't retunred to EXACTLY its default width/height.
|
|
463
|
+
if (resizeObj.height > resizeObj.layout.defaultNodeHeight + 2 ||
|
|
464
|
+
resizeObj.width > resizeObj.layout.defaultNodeWidth + 2) {
|
|
465
|
+
this.nodeSizingObjectsInfo[resizeObj.id].isResized = true;
|
|
466
|
+
this.nodeSizingObjectsInfo[resizeObj.id].resizeWidth = resizeObj.width;
|
|
467
|
+
this.nodeSizingObjectsInfo[resizeObj.id].resizeHeight = resizeObj.height;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
this.ren.canvasController.editActionHandler({
|
|
471
|
+
editType: "resizeObjects",
|
|
472
|
+
editSource: "canvas",
|
|
473
|
+
objectsInfo: this.nodeSizingObjectsInfo,
|
|
474
|
+
detachedLinksInfo: this.nodeSizingDetLinksInfo,
|
|
475
|
+
pipelineId: this.ren.activePipeline.id
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// Finalises the sizing of a comment by calling editActionHandler
|
|
481
|
+
// with an editComment action.
|
|
482
|
+
endCommentSizing(comment) {
|
|
483
|
+
let resizeObj = comment;
|
|
484
|
+
if (this.ren.config.enableSnapToGridType === SNAP_TO_GRID_AFTER) {
|
|
485
|
+
resizeObj = this.snapToGridObject(resizeObj);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// If the dimensions or position has changed, issue the command.
|
|
489
|
+
// Note: x_pos or y_pos might change on resize if the node is sized
|
|
490
|
+
// upwards or to the left.
|
|
491
|
+
if (this.resizeObjInitialInfo.x_pos !== resizeObj.x_pos ||
|
|
492
|
+
this.resizeObjInitialInfo.y_pos !== resizeObj.y_pos ||
|
|
493
|
+
this.resizeObjInitialInfo.width !== resizeObj.width ||
|
|
494
|
+
this.resizeObjInitialInfo.height !== resizeObj.height) {
|
|
495
|
+
const commentSizingObjectsInfo = [];
|
|
496
|
+
commentSizingObjectsInfo[resizeObj.id] = {
|
|
497
|
+
width: resizeObj.width,
|
|
498
|
+
height: resizeObj.height,
|
|
499
|
+
x_pos: resizeObj.x_pos,
|
|
500
|
+
y_pos: resizeObj.y_pos
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
const data = {
|
|
504
|
+
editType: "resizeObjects",
|
|
505
|
+
editSource: "canvas",
|
|
506
|
+
objectsInfo: commentSizingObjectsInfo,
|
|
507
|
+
detachedLinksInfo: {}, // Comments cannot have detached links
|
|
508
|
+
pipelineId: this.ren.activePipeline.id
|
|
509
|
+
};
|
|
510
|
+
this.ren.canvasController.editActionHandler(data);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// Ensure the snap-to-grid does not make the width or height smaller than
|
|
515
|
+
// the minimums allowed.
|
|
516
|
+
restrictNodeSizingToMinimums(resizeObj) {
|
|
517
|
+
const minHeight = this.getMinHeight(resizeObj);
|
|
518
|
+
const minWidth = this.getMinWidth(resizeObj);
|
|
519
|
+
resizeObj.width = Math.max(resizeObj.width, minWidth);
|
|
520
|
+
resizeObj.height = Math.max(resizeObj.height, minHeight);
|
|
521
|
+
return resizeObj;
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// Returns the minimum allowed height for the node passed in. For supernodes
|
|
525
|
+
// this means combining the bigger of the space for the inputs and output ports
|
|
526
|
+
// with some space for the top of the display frame and the padding at the
|
|
527
|
+
// bottom of the frame. Then the bigger of that height versus the default
|
|
528
|
+
// supernode minimum height is retunred.
|
|
529
|
+
getMinHeight(node) {
|
|
530
|
+
if (CanvasUtils.isSupernode(node)) {
|
|
531
|
+
const minHt = Math.max(node.inputPortsHeight, node.outputPortsHeight) +
|
|
532
|
+
this.ren.canvasLayout.supernodeTopAreaHeight + this.ren.canvasLayout.supernodeSVGAreaPadding;
|
|
533
|
+
return Math.max(this.ren.canvasLayout.supernodeMinHeight, minHt);
|
|
534
|
+
}
|
|
535
|
+
return node.layout.defaultNodeHeight;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
// Returns the minimum allowed width for the node passed in.
|
|
539
|
+
getMinWidth(node) {
|
|
540
|
+
if (CanvasUtils.isSupernode(node)) {
|
|
541
|
+
return this.ren.canvasLayout.supernodeMinWidth;
|
|
542
|
+
}
|
|
543
|
+
return node.layout.defaultNodeWidth;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// Starts the dragging action for canvas objects (nodes and comments).
|
|
547
|
+
dragObjectsStart(d3Event, d) {
|
|
548
|
+
// Ensure flags are false before staring a new drag.
|
|
549
|
+
this.existingNodeInsertableIntoLink = false;
|
|
550
|
+
this.existingNodeAttachableToDetachedLinks = false;
|
|
551
|
+
|
|
552
|
+
this.draggingObjectData = {
|
|
553
|
+
dragOffsetX: 0,
|
|
554
|
+
dragOffsetY: 0,
|
|
555
|
+
dragRunningX: 0,
|
|
556
|
+
dragRunningY: 0,
|
|
557
|
+
dragObjects: this.getDragObjects(d)
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
if (this.draggingObjectData.dragObjects?.length > 0) {
|
|
561
|
+
this.draggingObjectData.dragStartX = this.draggingObjectData.dragObjects[0].x_pos;
|
|
562
|
+
this.draggingObjectData.dragStartY = this.draggingObjectData.dragObjects[0].y_pos;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// If we are dragging an 'insertable' node, set it to be translucent so
|
|
566
|
+
// that, when it is dragged over a link line, the highlightd line can be seen OK.
|
|
567
|
+
if (this.isExistingNodeInsertableIntoLink()) {
|
|
568
|
+
// Only style the node to be translucent if this action isn't cancelled
|
|
569
|
+
// by the user releasing the mouse button within 200 ms of pressing it.
|
|
570
|
+
// This stops the node flashing when the user is only selecting it.
|
|
571
|
+
this.startNodeInsertingInLink = setTimeout(() => {
|
|
572
|
+
this.existingNodeInsertableIntoLink = true;
|
|
573
|
+
this.setNodeTranslucentState(this.draggingObjectData.dragObjects[0].id, true);
|
|
574
|
+
this.ren.setDataLinkSelectionAreaWider(true);
|
|
575
|
+
}, 200);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// If we are dragging an 'attachable' node, set it to be translucent so
|
|
579
|
+
// that, when it is dragged over link lines, the highlightd lines can be seen OK.
|
|
580
|
+
if (this.isExistingNodeAttachableToDetachedLinks()) {
|
|
581
|
+
// Only style the node to be translucent if this action isn't cancelled
|
|
582
|
+
// by the user releasing the mouse button within 200 ms of pressing it.
|
|
583
|
+
// This stops the node from being made translucent when the user is only selecting it.
|
|
584
|
+
this.startNodeAttachingToDetachedLinks = setTimeout(() => {
|
|
585
|
+
this.existingNodeAttachableToDetachedLinks = true;
|
|
586
|
+
this.setNodeTranslucentState(this.draggingObjectData.dragObjects[0].id, true);
|
|
587
|
+
}, 200);
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// Performs the dragging action for canvas objects (nodes and comments).
|
|
592
|
+
dragObjectsAction(d3Event) {
|
|
593
|
+
this.draggingObjectData.dragOffsetX += d3Event.dx;
|
|
594
|
+
this.draggingObjectData.dragOffsetY += d3Event.dy;
|
|
595
|
+
|
|
596
|
+
// Limit the size a drag can be so, when the user is dragging objects in
|
|
597
|
+
// an in-place subflow they do not drag them too far.
|
|
598
|
+
// this.logger.log("Drag offset X = " + this.dragOffsetX + " y = " + this.draggingObjectData.dragOffsetY);
|
|
599
|
+
if (this.ren.dispUtils.isDisplayingSubFlowInPlace() &&
|
|
600
|
+
(this.draggingObjectData.dragOffsetX > 1000 || this.draggingObjectData.dragOffsetX < -1000 ||
|
|
601
|
+
this.draggingObjectData.dragOffsetY > 1000 || this.draggingObjectData.dragOffsetY < -1000)) {
|
|
602
|
+
this.draggingObjectData.dragOffsetX -= d3Event.dx;
|
|
603
|
+
this.draggingObjectData.dragOffsetY -= d3Event.dy;
|
|
604
|
+
|
|
605
|
+
} else {
|
|
606
|
+
let increment = { x: 0, y: 0 };
|
|
607
|
+
|
|
608
|
+
if (this.ren.config.enableSnapToGridType === SNAP_TO_GRID_DURING) {
|
|
609
|
+
const stgPos = this.snapToGridDraggedNode(this.draggingObjectData);
|
|
610
|
+
|
|
611
|
+
increment = {
|
|
612
|
+
x: stgPos.x - this.draggingObjectData.dragObjects[0].x_pos,
|
|
613
|
+
y: stgPos.y - this.draggingObjectData.dragObjects[0].y_pos
|
|
614
|
+
};
|
|
615
|
+
|
|
616
|
+
} else {
|
|
617
|
+
increment = {
|
|
618
|
+
x: d3Event.dx,
|
|
619
|
+
y: d3Event.dy
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
this.draggingObjectData.dragRunningX += increment.x;
|
|
624
|
+
this.draggingObjectData.dragRunningY += increment.y;
|
|
625
|
+
|
|
626
|
+
this.draggingObjectData.dragObjects.forEach((d) => {
|
|
627
|
+
d.x_pos += increment.x;
|
|
628
|
+
d.y_pos += increment.y;
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
if (this.ren.config.enableLinkSelection === LINK_SELECTION_DETACHABLE) {
|
|
632
|
+
this.ren.activePipeline.getSelectedLinks().forEach((link) => {
|
|
633
|
+
if (link.srcPos) {
|
|
634
|
+
link.srcPos.x_pos += increment.x;
|
|
635
|
+
link.srcPos.y_pos += increment.y;
|
|
636
|
+
}
|
|
637
|
+
if (link.trgPos) {
|
|
638
|
+
link.trgPos.x_pos += increment.x;
|
|
639
|
+
link.trgPos.y_pos += increment.y;
|
|
640
|
+
}
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
this.ren.displayMovedComments();
|
|
646
|
+
this.ren.displayMovedNodes();
|
|
647
|
+
this.ren.displayMovedLinks();
|
|
648
|
+
this.ren.displayCanvasAccoutrements();
|
|
649
|
+
|
|
650
|
+
if (this.ren.dispUtils.isDisplayingSubFlowInPlace()) {
|
|
651
|
+
this.ren.displaySVGToFitSupernode();
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
|
|
655
|
+
if (this.existingNodeInsertableIntoLink) {
|
|
656
|
+
const link = this.ren.getLinkAtMousePos(d3Event.sourceEvent.clientX, d3Event.sourceEvent.clientY);
|
|
657
|
+
// Set highlighting when there is no link because this will turn
|
|
658
|
+
// current highlighting off. And only switch on highlighting when we are
|
|
659
|
+
// over a fully attached link (not a detached link) and provided the
|
|
660
|
+
// link is not to/from the node being dragged (which is possible in
|
|
661
|
+
// some odd situations).
|
|
662
|
+
if (!link ||
|
|
663
|
+
(this.ren.isLinkFullyAttached(link) &&
|
|
664
|
+
this.draggingObjectData.dragObjects[0].id !== link.srcNodeId &&
|
|
665
|
+
this.draggingObjectData.dragObjects[0].id !== link.trgNodeId)) {
|
|
666
|
+
this.ren.setInsertNodeIntoLinkHighlighting(link);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
if (this.existingNodeAttachableToDetachedLinks) {
|
|
671
|
+
// const mousePos = this.ren.getTransformedMousePos(d3Event);
|
|
672
|
+
const node = this.draggingObjectData.dragObjects[0];
|
|
673
|
+
const ghostArea = {
|
|
674
|
+
x1: node.x_pos,
|
|
675
|
+
y1: node.y_pos,
|
|
676
|
+
x2: node.x_pos + node.width,
|
|
677
|
+
y2: node.y_pos + node.height
|
|
678
|
+
};
|
|
679
|
+
const links = this.ren.getAttachableLinksForNodeAtPos(node, ghostArea);
|
|
680
|
+
this.ren.setDetachedLinkHighlighting(links);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// Ends the dragging action for canvas objects (nodes and comments).
|
|
685
|
+
dragObjectsEnd(d3Event, d) {
|
|
686
|
+
// Save a local reference to this.draggingObjectData so we can set it to null before
|
|
687
|
+
// calling the canvas-controller. This means the this.draggingObjectData object will
|
|
688
|
+
// be null when the canvas is refreshed.
|
|
689
|
+
const draggingObjectData = this.draggingObjectData;
|
|
690
|
+
this.draggingObjectData = null;
|
|
691
|
+
|
|
692
|
+
// Cancels the styling of insertable/attachable nodes if the user releases
|
|
693
|
+
// the mouse button with 200 milliseconds of pressing it on the node. This
|
|
694
|
+
// stops the node flashing when the user just selects the node.
|
|
695
|
+
clearTimeout(this.startNodeInsertingInLink);
|
|
696
|
+
clearTimeout(this.startNodeAttachingToDetachedLinks);
|
|
697
|
+
|
|
698
|
+
// If the pointer hasn't moved and enableDragWithoutSelect is enabled we interpret
|
|
699
|
+
// that as a select on the object.
|
|
700
|
+
if (draggingObjectData.dragOffsetX === 0 &&
|
|
701
|
+
draggingObjectData.dragOffsetY === 0 &&
|
|
702
|
+
this.ren.config.enableDragWithoutSelect) {
|
|
703
|
+
this.ren.selectObjectSourceEvent(d3Event, d);
|
|
704
|
+
|
|
705
|
+
} else {
|
|
706
|
+
if (draggingObjectData.dragRunningX !== 0 ||
|
|
707
|
+
draggingObjectData.dragRunningY !== 0) {
|
|
708
|
+
let dragFinalOffset = null;
|
|
709
|
+
if (this.ren.config.enableSnapToGridType === SNAP_TO_GRID_AFTER) {
|
|
710
|
+
const stgPos = this.snapToGridDraggedNode(draggingObjectData);
|
|
711
|
+
dragFinalOffset = {
|
|
712
|
+
x: stgPos.x - draggingObjectData.dragStartX,
|
|
713
|
+
y: stgPos.y - draggingObjectData.dragStartY
|
|
714
|
+
};
|
|
715
|
+
} else {
|
|
716
|
+
dragFinalOffset = { x: draggingObjectData.dragRunningX, y: draggingObjectData.dragRunningY };
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
if (this.existingNodeInsertableIntoLink &&
|
|
720
|
+
this.ren.dragOverLink) {
|
|
721
|
+
this.ren.canvasController.editActionHandler({
|
|
722
|
+
editType: "insertNodeIntoLink",
|
|
723
|
+
editSource: "canvas",
|
|
724
|
+
node: draggingObjectData.dragObjects[0],
|
|
725
|
+
link: this.ren.dragOverLink,
|
|
726
|
+
offsetX: dragFinalOffset.x,
|
|
727
|
+
offsetY: dragFinalOffset.y,
|
|
728
|
+
pipelineId: this.ren.activePipeline.id });
|
|
729
|
+
|
|
730
|
+
} else if (this.existingNodeAttachableToDetachedLinks &&
|
|
731
|
+
this.ren.dragOverDetachedLinks.length > 0) {
|
|
732
|
+
this.ren.canvasController.editActionHandler({
|
|
733
|
+
editType: "attachNodeToLinks",
|
|
734
|
+
editSource: "canvas",
|
|
735
|
+
node: draggingObjectData.dragObjects[0],
|
|
736
|
+
detachedLinks: this.ren.dragOverDetachedLinks,
|
|
737
|
+
offsetX: dragFinalOffset.x,
|
|
738
|
+
offsetY: dragFinalOffset.y,
|
|
739
|
+
pipelineId: this.ren.activePipeline.id });
|
|
740
|
+
|
|
741
|
+
} else {
|
|
742
|
+
this.ren.canvasController.editActionHandler({
|
|
743
|
+
editType: "moveObjects",
|
|
744
|
+
editSource: "canvas",
|
|
745
|
+
nodes: draggingObjectData.dragObjects.map((o) => o.id),
|
|
746
|
+
links: this.ren.activePipeline.getSelectedDetachedLinks(),
|
|
747
|
+
offsetX: dragFinalOffset.x,
|
|
748
|
+
offsetY: dragFinalOffset.y,
|
|
749
|
+
pipelineId: this.ren.activePipeline.id });
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
// Switch off any drag highlighting
|
|
755
|
+
this.ren.setDataLinkSelectionAreaWider(false);
|
|
756
|
+
this.unsetNodeTranslucentState(draggingObjectData.dragObjects);
|
|
757
|
+
this.ren.unsetInsertNodeIntoLinkHighlighting();
|
|
758
|
+
this.ren.unsetDetachedLinkHighlighting();
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
// Returns an array of objects to drag. If enableDragWithoutSelect is true,
|
|
762
|
+
// and the object on which this drag start has initiated is not in the
|
|
763
|
+
// set of selected objects, then just that object is to be dragged. Otherwise,
|
|
764
|
+
// the selected objects are the objects to be dragged.
|
|
765
|
+
getDragObjects(d) {
|
|
766
|
+
const selectedObjects = this.ren.activePipeline.getSelectedNodesAndComments();
|
|
767
|
+
|
|
768
|
+
if (this.ren.config.enableDragWithoutSelect &&
|
|
769
|
+
selectedObjects.findIndex((o) => o.id === d.id) === -1) {
|
|
770
|
+
return [d];
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
return selectedObjects;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
// Returns true if the current drag objects array has a single node which
|
|
777
|
+
// is 'insertable' into a data link between nodes on the canvas. Returns
|
|
778
|
+
// false otherwise, including if a single comment is being dragged.
|
|
779
|
+
isExistingNodeInsertableIntoLink() {
|
|
780
|
+
return (this.ren.config.enableInsertNodeDroppedOnLink &&
|
|
781
|
+
this.draggingObjectData.dragObjects.length === 1 &&
|
|
782
|
+
CanvasUtils.isNode(this.draggingObjectData.dragObjects[0]) &&
|
|
783
|
+
CanvasUtils.hasInputAndOutputPorts(this.draggingObjectData.dragObjects[0]) &&
|
|
784
|
+
!CanvasUtils.isNodeDefaultPortsCardinalityAtMax(this.draggingObjectData.dragObjects[0], this.ren.activePipeline.links));
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
// Returns true if the current drag objects array has a single node which
|
|
788
|
+
// is 'attachable' to any detached link on the canvas. Returns false otherwise,
|
|
789
|
+
// including if a single comment is being dragged.
|
|
790
|
+
isExistingNodeAttachableToDetachedLinks() {
|
|
791
|
+
return (this.ren.config.enableLinkSelection === LINK_SELECTION_DETACHABLE &&
|
|
792
|
+
this.draggingObjectData.dragObjects.length === 1 &&
|
|
793
|
+
CanvasUtils.isNode(this.draggingObjectData.dragObjects[0]));
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
// Switches on or off the translucent state of the node identified by the
|
|
797
|
+
// node ID passed in. This is used when an 'insertable' node is dragged on
|
|
798
|
+
// the canvas. It makes is easier for the user to see the highlighted link
|
|
799
|
+
// when the node is dragged over it.
|
|
800
|
+
setNodeTranslucentState(nodeId, state) {
|
|
801
|
+
this.ren.getNodeGroupSelectionById(nodeId).classed("d3-node-group-translucent", state);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
// Switched off the translucent state of the objects being dragged (if
|
|
805
|
+
// there are any).
|
|
806
|
+
unsetNodeTranslucentState(dragObjects) {
|
|
807
|
+
if (dragObjects?.length > 0) {
|
|
808
|
+
this.setNodeTranslucentState(dragObjects[0].id, false);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
// Returns the snap-to-grid position of the object positioned at
|
|
813
|
+
// this.draggingObjectData.dragStartX and this.draggingObjectData.dragStartY after applying the current offset of
|
|
814
|
+
// this.draggingObjectData.dragOffsetX and this.draggingObjectData.dragOffsetY.
|
|
815
|
+
snapToGridDraggedNode(draggingObjectData) {
|
|
816
|
+
const objPosX = draggingObjectData.dragStartX + draggingObjectData.dragOffsetX;
|
|
817
|
+
const objPosY = draggingObjectData.dragStartY + draggingObjectData.dragOffsetY;
|
|
818
|
+
|
|
819
|
+
return this.ren.snapToGridPosition({ x: objPosX, y: objPosY });
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
// Returns the object passed in with its position and size snapped to
|
|
823
|
+
// the current grid dimensions. Used when the object is being resized.
|
|
824
|
+
snapToGridObject(inResizeObj) {
|
|
825
|
+
const resizeObj = inResizeObj;
|
|
826
|
+
resizeObj.x_pos = CanvasUtils.snapToGrid(resizeObj.x_pos, this.ren.canvasLayout.snapToGridXPx);
|
|
827
|
+
resizeObj.y_pos = CanvasUtils.snapToGrid(resizeObj.y_pos, this.ren.canvasLayout.snapToGridYPx);
|
|
828
|
+
resizeObj.width = CanvasUtils.snapToGrid(resizeObj.width, this.ren.canvasLayout.snapToGridXPx);
|
|
829
|
+
resizeObj.height = CanvasUtils.snapToGrid(resizeObj.height, this.ren.canvasLayout.snapToGridYPx);
|
|
830
|
+
return resizeObj;
|
|
831
|
+
}
|
|
832
|
+
}
|