@elyra/canvas 12.35.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.
Files changed (111) hide show
  1. package/dist/canvas-constants-766c12a9.js +2 -0
  2. package/dist/{canvas-constants-85883d4c.js.map → canvas-constants-766c12a9.js.map} +1 -1
  3. package/dist/canvas-constants-f4219d26.js +2 -0
  4. package/dist/{canvas-constants-d8652829.js.map → canvas-constants-f4219d26.js.map} +1 -1
  5. package/dist/canvas-controller-62b66fc8.js +2 -0
  6. package/dist/canvas-controller-62b66fc8.js.map +1 -0
  7. package/dist/canvas-controller-76f68572.js +2 -0
  8. package/dist/canvas-controller-76f68572.js.map +1 -0
  9. package/dist/common-canvas-339584b8.js +2 -0
  10. package/dist/common-canvas-339584b8.js.map +1 -0
  11. package/dist/common-canvas-c728f092.js +2 -0
  12. package/dist/common-canvas-c728f092.js.map +1 -0
  13. package/dist/common-canvas.es.js +1 -1
  14. package/dist/common-canvas.es.js.map +1 -1
  15. package/dist/common-canvas.js +1 -1
  16. package/dist/common-canvas.js.map +1 -1
  17. package/dist/common-properties-009d29d6.js +2 -0
  18. package/dist/common-properties-009d29d6.js.map +1 -0
  19. package/dist/common-properties-99d34523.js +2 -0
  20. package/dist/common-properties-99d34523.js.map +1 -0
  21. package/dist/context-menu-wrapper-624a1e7c.js +2 -0
  22. package/dist/context-menu-wrapper-624a1e7c.js.map +1 -0
  23. package/dist/context-menu-wrapper-ab018d6e.js +2 -0
  24. package/dist/context-menu-wrapper-ab018d6e.js.map +1 -0
  25. package/dist/{datarecord-metadata-v3-schema-531c7b07.js → datarecord-metadata-v3-schema-1f21696a.js} +2 -2
  26. package/dist/{datarecord-metadata-v3-schema-531c7b07.js.map → datarecord-metadata-v3-schema-1f21696a.js.map} +1 -1
  27. package/dist/{datarecord-metadata-v3-schema-28d4d7bb.js → datarecord-metadata-v3-schema-c2ad8862.js} +2 -2
  28. package/dist/{datarecord-metadata-v3-schema-28d4d7bb.js.map → datarecord-metadata-v3-schema-c2ad8862.js.map} +1 -1
  29. package/dist/flexible-table-4cf19e2e.js +2 -0
  30. package/dist/flexible-table-4cf19e2e.js.map +1 -0
  31. package/dist/flexible-table-8d10f5c9.js +2 -0
  32. package/dist/flexible-table-8d10f5c9.js.map +1 -0
  33. package/dist/{icon-909437d7.js → icon-5e06bfe1.js} +2 -2
  34. package/dist/{icon-909437d7.js.map → icon-5e06bfe1.js.map} +1 -1
  35. package/dist/{icon-de9c6b33.js → icon-8433d369.js} +2 -2
  36. package/dist/{icon-de9c6b33.js.map → icon-8433d369.js.map} +1 -1
  37. package/dist/{index-9960d3bf.js → index-2a61be58.js} +2 -2
  38. package/dist/{index-9960d3bf.js.map → index-2a61be58.js.map} +1 -1
  39. package/dist/{index-61e4a113.js → index-9a355ed6.js} +2 -2
  40. package/dist/{index-61e4a113.js.map → index-9a355ed6.js.map} +1 -1
  41. package/dist/lib/canvas-controller.es.js +1 -1
  42. package/dist/lib/canvas-controller.js +1 -1
  43. package/dist/lib/canvas.es.js +1 -1
  44. package/dist/lib/canvas.js +1 -1
  45. package/dist/lib/context-menu.es.js +1 -1
  46. package/dist/lib/context-menu.js +1 -1
  47. package/dist/lib/properties/field-picker.es.js +1 -1
  48. package/dist/lib/properties/field-picker.js +1 -1
  49. package/dist/lib/properties/flexible-table.es.js +1 -1
  50. package/dist/lib/properties/flexible-table.js +1 -1
  51. package/dist/lib/properties.es.js +1 -1
  52. package/dist/lib/properties.js +1 -1
  53. package/dist/styles/common-canvas.min.css +1 -1
  54. package/dist/styles/common-canvas.min.css.map +1 -1
  55. package/dist/{toolbar-cdb38f4a.js → toolbar-76733735.js} +2 -2
  56. package/dist/{toolbar-cdb38f4a.js.map → toolbar-76733735.js.map} +1 -1
  57. package/dist/{toolbar-3b5a592c.js → toolbar-85e1e463.js} +2 -2
  58. package/dist/{toolbar-3b5a592c.js.map → toolbar-85e1e463.js.map} +1 -1
  59. package/locales/common-canvas/locales/en.json +1 -1
  60. package/locales/common-canvas/locales/eo.json +1 -1
  61. package/package.json +3 -4
  62. package/src/common-canvas/canvas-controller.js +15 -6
  63. package/src/common-canvas/cc-contents.jsx +44 -6
  64. package/src/common-canvas/common-canvas-utils.js +9 -2
  65. package/src/common-canvas/common-canvas.scss +30 -3
  66. package/src/common-canvas/constants/canvas-constants.js +0 -6
  67. package/src/common-canvas/svg-canvas-d3.js +1 -3
  68. package/src/common-canvas/svg-canvas-d3.scss +0 -26
  69. package/src/common-canvas/svg-canvas-pipeline.js +6 -0
  70. package/src/common-canvas/svg-canvas-renderer.js +490 -2804
  71. package/src/common-canvas/svg-canvas-utils-drag-det-link.js +491 -0
  72. package/src/common-canvas/svg-canvas-utils-drag-new-link.js +595 -0
  73. package/src/common-canvas/svg-canvas-utils-drag-objects.js +832 -0
  74. package/src/common-canvas/svg-canvas-utils-external.js +82 -16
  75. package/src/common-canvas/svg-canvas-utils-zoom.js +780 -0
  76. package/src/common-properties/common-properties.jsx +2 -0
  77. package/src/common-properties/components/editor-form/editor-form.jsx +5 -1
  78. package/src/common-properties/properties-main/properties-main.jsx +2 -0
  79. package/src/context-menu/common-context-menu.jsx +57 -26
  80. package/src/context-menu/context-menu.scss +33 -53
  81. package/src/notification-panel/notification-panel.jsx +6 -1
  82. package/src/notification-panel/notification-panel.scss +14 -8
  83. package/src/palette/palette-content-list-item.jsx +23 -7
  84. package/src/palette/palette.scss +4 -4
  85. package/stats.html +1 -1
  86. package/dist/canvas-constants-85883d4c.js +0 -2
  87. package/dist/canvas-constants-d8652829.js +0 -2
  88. package/dist/canvas-controller-c9f3bef9.js +0 -2
  89. package/dist/canvas-controller-c9f3bef9.js.map +0 -1
  90. package/dist/canvas-controller-f7820ab0.js +0 -2
  91. package/dist/canvas-controller-f7820ab0.js.map +0 -1
  92. package/dist/common-canvas-487520d3.js +0 -2
  93. package/dist/common-canvas-487520d3.js.map +0 -1
  94. package/dist/common-canvas-e1591f51.js +0 -2
  95. package/dist/common-canvas-e1591f51.js.map +0 -1
  96. package/dist/common-properties-580436d7.js +0 -2
  97. package/dist/common-properties-580436d7.js.map +0 -1
  98. package/dist/common-properties-98a9a99f.js +0 -2
  99. package/dist/common-properties-98a9a99f.js.map +0 -1
  100. package/dist/context-menu-wrapper-19a1cf72.js +0 -2
  101. package/dist/context-menu-wrapper-19a1cf72.js.map +0 -1
  102. package/dist/context-menu-wrapper-c3a98c63.js +0 -2
  103. package/dist/context-menu-wrapper-c3a98c63.js.map +0 -1
  104. package/dist/extends-093996c9.js +0 -2
  105. package/dist/extends-093996c9.js.map +0 -1
  106. package/dist/extends-1b35a664.js +0 -2
  107. package/dist/extends-1b35a664.js.map +0 -1
  108. package/dist/flexible-table-b9c08069.js +0 -2
  109. package/dist/flexible-table-b9c08069.js.map +0 -1
  110. package/dist/flexible-table-ddd6132b.js +0 -2
  111. package/dist/flexible-table-ddd6132b.js.map +0 -1
@@ -0,0 +1,595 @@
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 d3Ease from "d3-ease";
21
+ import * as d3Selection from "d3-selection";
22
+ const d3 = Object.assign({}, d3Drag, d3Ease, d3Selection);
23
+
24
+ import Logger from "../logging/canvas-logger.js";
25
+ import CanvasUtils from "./common-canvas-utils.js";
26
+ import { ASSOCIATION_LINK, COMMENT_LINK, NODE_LINK,
27
+ LINK_TYPE_CURVE, LINK_TYPE_STRAIGHT, LINK_SELECTION_DETACHABLE,
28
+ PORT_OBJECT_CIRCLE, PORT_OBJECT_IMAGE }
29
+ from "./constants/canvas-constants.js";
30
+
31
+ // This utility files provides a drag handler which manages drag operations to
32
+ // create new links either between nodes or from a comment to a node.
33
+
34
+ export default class SVGCanvasUtilsDragNewLink {
35
+ constructor(renderer) {
36
+ this.ren = renderer;
37
+
38
+ this.logger = new Logger("SVGCanvasUtilsDragNewLink");
39
+
40
+ // Object to store variables for dynamically drawing a new link line. The
41
+ // existence of this object means a new link is being drawn. A null means
42
+ // no link is currently being drawn.
43
+ this.drawingNewLinkData = null;
44
+
45
+ // Create a drag handler for resizing and moving nodes and comments.
46
+ this.dragNewLinkHandler = d3.drag()
47
+ .on("start", this.dragStartNewLink.bind(this))
48
+ .on("drag", this.dragMoveNewLink.bind(this))
49
+ .on("end", this.dragEndNewLink.bind(this));
50
+ }
51
+
52
+ // Returns the dragResizeObjectHandler
53
+ getDragNewLinkHandler() {
54
+ return this.dragNewLinkHandler;
55
+ }
56
+
57
+ // Returns true if a new link is currently being dragged.
58
+ isDragging() {
59
+ return this.drawingNewLinkData;
60
+ }
61
+
62
+ // Initialize new link creation info when a port node is dragged.
63
+ dragStartNewLink(d3Event, d) {
64
+ if (this.isEventForOutputPort(d3Event)) {
65
+ const node = this.getNodeForPort(d3Event);
66
+ this.startOutputPortNewLink(d, node);
67
+
68
+ } else if (this.isEventForInputPort(d3Event)) {
69
+ const node = this.getNodeForPort(d3Event);
70
+ this.startInputPortNewLink(d, node);
71
+
72
+ } else if (this.ren.activePipeline.getObjectTypeName(d) === "comment") {
73
+ this.startCommentNewLink(d);
74
+ }
75
+ }
76
+
77
+ // Draws an appropriate new link line when a port is being dragged.
78
+ dragMoveNewLink(d3Event) {
79
+ this.drawNewLink(d3Event);
80
+ }
81
+
82
+ // Completes the creation (or not) of a new link line when a port has
83
+ // finished being dragged.
84
+ dragEndNewLink(d3Event) {
85
+ this.completeNewLink(d3Event);
86
+ }
87
+
88
+ // Return true if the d3Event passed in is for an input port.
89
+ isEventForInputPort(d3Event) {
90
+ return this.targetContainsClass(d3Event, "d3-node-port-input") ||
91
+ this.targetContainsClass(d3Event, "d3-node-port-input-assoc");
92
+ }
93
+
94
+ // Return true if the d3Event passed in is for an output port.
95
+ isEventForOutputPort(d3Event) {
96
+ return this.targetContainsClass(d3Event, "d3-node-port-output") ||
97
+ this.targetContainsClass(d3Event, "d3-node-port-output-assoc");
98
+ }
99
+
100
+ // Returns true if the d3Event contains a current target with the spcified class name.
101
+ targetContainsClass(d3Event, className) {
102
+ return d3Event.sourceEvent?.currentTarget?.classList?.contains(className);
103
+ }
104
+
105
+ // Returns the node data for the target of the event passed in.
106
+ getNodeForPort(d3Event) {
107
+ return d3.select(d3Event.sourceEvent?.currentTarget?.parentNode).datum();
108
+ }
109
+
110
+ // Initialize this.drawingNewLinkData when dragging a comment port.
111
+ startCommentNewLink(comment) {
112
+ this.drawingNewLinkData = {
113
+ srcObjId: comment.id,
114
+ action: COMMENT_LINK,
115
+ startPos: {
116
+ x: comment.x_pos - this.ren.canvasLayout.commentHighlightGap,
117
+ y: comment.y_pos - this.ren.canvasLayout.commentHighlightGap
118
+ },
119
+ linkArray: []
120
+ };
121
+ }
122
+
123
+ // Initialize this.drawingNewLinkData when dragging an input port. This gesture
124
+ // is only supported for association link creation.
125
+ startInputPortNewLink(port, node) {
126
+ if (this.ren.config.enableAssocLinkCreation) {
127
+ const srcNode = this.ren.activePipeline.getNode(node.id);
128
+ this.drawingNewLinkData = {
129
+ srcObjId: node.id,
130
+ srcPortId: port.id,
131
+ action: this.ren.config.enableAssocLinkCreation ? ASSOCIATION_LINK : NODE_LINK,
132
+ srcNode: srcNode,
133
+ startPos: { x: srcNode.x_pos + port.cx, y: srcNode.y_pos + port.cy },
134
+ portType: "input",
135
+ portObject: node.layout.inputPortObject,
136
+ portImage: node.layout.inputPortImage,
137
+ portWidth: node.layout.inputPortWidth,
138
+ portHeight: node.layout.inputPortHeight,
139
+ portRadius: this.ren.getPortRadius(srcNode),
140
+ minInitialLine: srcNode.layout.minInitialLine,
141
+ guideObject: node.layout.inputPortGuideObject,
142
+ guideImage: node.layout.inputPortGuideImage,
143
+ linkArray: []
144
+ };
145
+ }
146
+ }
147
+
148
+ // Initialize this.drawingNewLinkData when dragging an output port.
149
+ startOutputPortNewLink(port, node) {
150
+ const srcNode = this.ren.activePipeline.getNode(node.id);
151
+ if (!CanvasUtils.isSrcCardinalityAtMax(port.id, srcNode, this.ren.activePipeline.links)) {
152
+ this.drawingNewLinkData = {
153
+ srcObjId: node.id,
154
+ srcPortId: port.id,
155
+ action: this.ren.config.enableAssocLinkCreation ? ASSOCIATION_LINK : NODE_LINK,
156
+ srcNode: srcNode,
157
+ startPos: { x: srcNode.x_pos + port.cx, y: srcNode.y_pos + port.cy },
158
+ portType: "output",
159
+ portObject: node.layout.outputPortObject,
160
+ portImage: node.layout.outputPortImage,
161
+ portWidth: node.layout.outputPortWidth,
162
+ portHeight: node.layout.outputPortHeight,
163
+ portRadius: this.ren.getPortRadius(srcNode),
164
+ minInitialLine: srcNode.layout.minInitialLine,
165
+ guideObject: node.layout.outputPortGuideObject,
166
+ guideImage: node.layout.outputPortGuideImage,
167
+ linkArray: []
168
+ };
169
+ if (this.ren.config.enableHighlightUnavailableNodes) {
170
+ this.ren.setUnavailableTargetNodesHighlighting(srcNode, port.id, this.ren.activePipeline.links);
171
+ }
172
+ }
173
+ }
174
+
175
+ drawNewLink(d3Event) {
176
+ if (this.ren.config.enableEditingActions === false || !this.drawingNewLinkData) {
177
+ return;
178
+ }
179
+
180
+ this.ren.closeContextMenuIfOpen();
181
+
182
+ const transPos = this.ren.getTransformedMousePos(d3Event);
183
+
184
+ if (this.drawingNewLinkData.action === COMMENT_LINK) {
185
+ this.drawNewCommentLinkForPorts(transPos);
186
+ } else {
187
+ this.drawNewNodeLinkForPorts(transPos);
188
+ }
189
+ // Switch on an attribute to indicate a new link is being dragged
190
+ // towards and over a target node.
191
+ if (this.ren.config.enableHighlightNodeOnNewLinkDrag) {
192
+ this.setNewLinkOverNode(d3Event);
193
+ }
194
+ }
195
+
196
+ drawNewCommentLinkForPorts(transPos) {
197
+ const srcComment = this.ren.activePipeline.getComment(this.drawingNewLinkData.srcObjId);
198
+ const startPos = this.ren.linkUtils.getNewStraightCommentLinkStartPos(srcComment, transPos);
199
+ const linkType = COMMENT_LINK;
200
+
201
+ this.drawingNewLinkData.linkArray = [{
202
+ "x1": startPos.x,
203
+ "y1": startPos.y,
204
+ "x2": transPos.x,
205
+ "y2": transPos.y,
206
+ "type": linkType }];
207
+
208
+ const connectionLineSel = this.ren.nodesLinksGrp.selectAll(".d3-new-connection-line");
209
+ const connectionGuideSel = this.ren.nodesLinksGrp.selectAll(".d3-new-connection-guide");
210
+
211
+ connectionLineSel
212
+ .data(this.drawingNewLinkData.linkArray)
213
+ .enter()
214
+ .append("path")
215
+ .attr("class", "d3-new-connection-line")
216
+ .attr("linkType", linkType)
217
+ .merge(connectionLineSel)
218
+ .attr("d", (d) => this.ren.linkUtils.getConnectorPathInfo(d).path);
219
+
220
+ connectionGuideSel
221
+ .data(this.drawingNewLinkData.linkArray)
222
+ .enter()
223
+ .append("circle")
224
+ .attr("class", "d3-new-connection-guide")
225
+ .attr("linkType", linkType)
226
+ .merge(connectionGuideSel)
227
+ .attr("cx", (d) => d.x2)
228
+ .attr("cy", (d) => d.y2)
229
+ .attr("r", this.ren.canvasLayout.commentPortRadius);
230
+
231
+ if (this.ren.canvasLayout.commentLinkArrowHead) {
232
+ const connectionArrowHeadSel = this.ren.nodesLinksGrp.selectAll(".d3-new-connection-arrow");
233
+
234
+ connectionArrowHeadSel
235
+ .data(this.drawingNewLinkData.linkArray)
236
+ .enter()
237
+ .append("path")
238
+ .attr("class", "d3-new-connection-arrow")
239
+ .attr("linkType", linkType)
240
+ .merge(connectionArrowHeadSel)
241
+ .attr("d", (d) => this.ren.getArrowHead(d))
242
+ .attr("transform", (d) => this.ren.getArrowHeadTransform(d));
243
+ }
244
+ }
245
+
246
+ drawNewNodeLinkForPorts(transPos) {
247
+ const linkType = this.ren.config.enableAssocLinkCreation ? ASSOCIATION_LINK : NODE_LINK;
248
+
249
+ let startPos;
250
+ if (this.ren.canvasLayout.linkType === LINK_TYPE_STRAIGHT) {
251
+ startPos = this.ren.linkUtils.getNewStraightNodeLinkStartPos(this.drawingNewLinkData.srcNode, transPos);
252
+ } else {
253
+ startPos = {
254
+ x: this.drawingNewLinkData.startPos.x,
255
+ y: this.drawingNewLinkData.startPos.y };
256
+ }
257
+
258
+ this.drawingNewLinkData.linkArray = [{
259
+ "x1": startPos.x,
260
+ "y1": startPos.y,
261
+ "x2": transPos.x,
262
+ "y2": transPos.y,
263
+ "originX": startPos.originX,
264
+ "originY": startPos.originY,
265
+ "type": linkType }];
266
+
267
+ if (this.ren.config.enableAssocLinkCreation) {
268
+ this.drawingNewLinkData.linkArray[0].assocLinkVariation =
269
+ this.ren.getNewLinkAssocVariation(
270
+ this.drawingNewLinkData.linkArray[0].x1,
271
+ this.drawingNewLinkData.linkArray[0].x2,
272
+ this.drawingNewLinkData.portType);
273
+ }
274
+
275
+ const pathInfo = this.ren.linkUtils.getConnectorPathInfo(
276
+ this.drawingNewLinkData.linkArray[0], this.drawingNewLinkData.minInitialLine);
277
+
278
+ const connectionLineSel = this.ren.nodesLinksGrp.selectAll(".d3-new-connection-line");
279
+ const connectionStartSel = this.ren.nodesLinksGrp.selectAll(".d3-new-connection-start");
280
+ const connectionGuideSel = this.ren.nodesLinksGrp.selectAll(".d3-new-connection-guide");
281
+
282
+ // For a straight node line, don't draw the new link line when the guide
283
+ // icon or object is inside the node boundary.
284
+ if (linkType === NODE_LINK &&
285
+ this.ren.canvasLayout.linkType === LINK_TYPE_STRAIGHT &&
286
+ this.ren.nodeUtils.isPointInNodeBoundary(transPos, this.drawingNewLinkData.srcNode)) {
287
+ this.removeNewLinkLine();
288
+
289
+ } else {
290
+ connectionLineSel
291
+ .data(this.drawingNewLinkData.linkArray)
292
+ .enter()
293
+ .append("path")
294
+ .attr("class", "d3-new-connection-line")
295
+ .attr("linkType", linkType)
296
+ .merge(connectionLineSel)
297
+ .attr("d", pathInfo.path)
298
+ .attr("transform", pathInfo.transform);
299
+ }
300
+
301
+ if (this.ren.canvasLayout.linkType !== LINK_TYPE_STRAIGHT) {
302
+ connectionStartSel
303
+ .data(this.drawingNewLinkData.linkArray)
304
+ .enter()
305
+ .append(this.drawingNewLinkData.portObject)
306
+ .attr("class", "d3-new-connection-start")
307
+ .attr("linkType", linkType)
308
+ .merge(connectionStartSel)
309
+ .each((d, i, startSel) => {
310
+ // No need to draw the starting object of the new line if it is an image.
311
+ if (this.drawingNewLinkData.portObject === PORT_OBJECT_CIRCLE) {
312
+ d3.select(startSel[i])
313
+ .attr("cx", d.x1)
314
+ .attr("cy", d.y1)
315
+ .attr("r", this.drawingNewLinkData.portRadius);
316
+ }
317
+ });
318
+ }
319
+
320
+ connectionGuideSel
321
+ .data(this.drawingNewLinkData.linkArray)
322
+ .enter()
323
+ .append(this.drawingNewLinkData.guideObject)
324
+ .attr("class", "d3-new-connection-guide")
325
+ .attr("linkType", linkType)
326
+ .merge(connectionGuideSel)
327
+ .each((d, i, guideSel) => {
328
+ if (this.drawingNewLinkData.guideObject === PORT_OBJECT_IMAGE) {
329
+ d3.select(guideSel[i])
330
+ .attr("xlink:href", this.drawingNewLinkData.guideImage)
331
+ .attr("x", d.x2 - (this.drawingNewLinkData.portWidth / 2))
332
+ .attr("y", d.y2 - (this.drawingNewLinkData.portHeight / 2))
333
+ .attr("width", this.drawingNewLinkData.portWidth)
334
+ .attr("height", this.drawingNewLinkData.portHeight)
335
+ .attr("transform", this.ren.getLinkImageTransform(d));
336
+ } else {
337
+ d3.select(guideSel[i])
338
+ .attr("cx", d.x2)
339
+ .attr("cy", d.y2)
340
+ .attr("r", this.drawingNewLinkData.portRadius);
341
+ }
342
+ });
343
+ }
344
+
345
+ removeNewLinkLine() {
346
+ this.ren.nodesLinksGrp.selectAll(".d3-new-connection-line").remove();
347
+ }
348
+
349
+ // Handles the completion of a new link being drawn from a source node.
350
+ completeNewLink(d3Event) {
351
+ if (this.ren.config.enableEditingActions === false || !this.drawingNewLinkData) {
352
+ return;
353
+ }
354
+
355
+ // Save a local reference to this.drawingNewLinkData so we can set it to null before
356
+ // calling the canvas-controller. This means the this.drawingNewLinkData object will
357
+ // be null when the canvas is refreshed.
358
+ const drawingNewLinkData = this.drawingNewLinkData;
359
+ this.drawingNewLinkData = null;
360
+
361
+ if (this.ren.config.enableHighlightUnavailableNodes) {
362
+ this.ren.unsetUnavailableNodesHighlighting();
363
+ }
364
+ var trgNode = this.ren.getNodeAtMousePos(d3Event);
365
+ if (trgNode !== null) {
366
+ this.completeNewLinkOnNode(d3Event, trgNode, drawingNewLinkData);
367
+ } else {
368
+ if (this.ren.config.enableLinkSelection === LINK_SELECTION_DETACHABLE &&
369
+ drawingNewLinkData.action === NODE_LINK &&
370
+ !this.ren.config.enableAssocLinkCreation) {
371
+ this.completeNewDetachedLink(d3Event, drawingNewLinkData);
372
+ } else {
373
+ this.stopDrawingNewLink(drawingNewLinkData);
374
+ }
375
+ }
376
+ }
377
+
378
+ // Handles the completion of a new link when the end is dropped on a node.
379
+ completeNewLinkOnNode(d3Event, trgNode, drawingNewLinkData) {
380
+ // If we completed a connection remove the new line objects.
381
+ this.removeNewLink();
382
+
383
+ // Switch 'new link over node' highlighting off
384
+ if (this.ren.config.enableHighlightNodeOnNewLinkDrag) {
385
+ this.ren.setLinkOverNodeCancel();
386
+ }
387
+
388
+ if (trgNode !== null) {
389
+ const type = drawingNewLinkData.action;
390
+ if (type === NODE_LINK) {
391
+ const srcNode = this.ren.activePipeline.getNode(drawingNewLinkData.srcObjId);
392
+ const srcPortId = drawingNewLinkData.srcPortId;
393
+ const trgPortId = this.ren.getInputNodePortId(d3Event, trgNode);
394
+
395
+ if (CanvasUtils.isDataConnectionAllowed(srcPortId, trgPortId, srcNode, trgNode, this.ren.activePipeline.links)) {
396
+ this.ren.canvasController.editActionHandler({
397
+ editType: "linkNodes",
398
+ editSource: "canvas",
399
+ nodes: [{ "id": drawingNewLinkData.srcObjId, "portId": drawingNewLinkData.srcPortId }],
400
+ targetNodes: [{ "id": trgNode.id, "portId": trgPortId }],
401
+ type: type,
402
+ linkType: "data", // Added for historical purposes - for WML Canvas support
403
+ pipelineId: this.ren.activePipeline.id });
404
+
405
+ } else if (this.ren.config.enableLinkReplaceOnNewConnection &&
406
+ CanvasUtils.isDataLinkReplacementAllowed(srcPortId, trgPortId, srcNode, trgNode, this.ren.activePipeline.links)) {
407
+ const linksToTrgPort = CanvasUtils.getDataLinksConnectedTo(trgPortId, trgNode, this.ren.activePipeline.links);
408
+ // We only replace a link to a maxed out cardinality port if there
409
+ // is only one link. i.e. the input port cardinality is 0:1
410
+ if (linksToTrgPort.length === 1) {
411
+ this.ren.canvasController.editActionHandler({
412
+ editType: "linkNodesAndReplace",
413
+ editSource: "canvas",
414
+ nodes: [{ "id": drawingNewLinkData.srcObjId, "portId": drawingNewLinkData.srcPortId }],
415
+ targetNodes: [{ "id": trgNode.id, "portId": trgPortId }],
416
+ type: type,
417
+ pipelineId: this.pipelineId,
418
+ replaceLink: linksToTrgPort[0]
419
+ });
420
+ }
421
+ }
422
+
423
+ } else if (type === ASSOCIATION_LINK) {
424
+ const srcNode = this.ren.activePipeline.getNode(drawingNewLinkData.srcObjId);
425
+
426
+ if (CanvasUtils.isAssocConnectionAllowed(srcNode, trgNode, this.ren.activePipeline.links)) {
427
+ this.ren.canvasController.editActionHandler({
428
+ editType: "linkNodes",
429
+ editSource: "canvas",
430
+ nodes: [{ "id": drawingNewLinkData.srcObjId }],
431
+ targetNodes: [{ "id": trgNode.id }],
432
+ type: type,
433
+ pipelineId: this.ren.activePipeline.id });
434
+ }
435
+
436
+ } else {
437
+ if (CanvasUtils.isCommentLinkConnectionAllowed(drawingNewLinkData.srcObjId, trgNode.id, this.ren.activePipeline.links)) {
438
+ this.ren.canvasController.editActionHandler({
439
+ editType: "linkComment",
440
+ editSource: "canvas",
441
+ nodes: [drawingNewLinkData.srcObjId],
442
+ targetNodes: [trgNode.id],
443
+ type: COMMENT_LINK,
444
+ linkType: "comment", // Added for historical purposes - for WML Canvas support
445
+ pipelineId: this.ren.activePipeline.id });
446
+ }
447
+ }
448
+ }
449
+ }
450
+
451
+ // Handles the completion of a new link when the end is dropped away from
452
+ // a node (when enableLinkSelection is set to LINK_SELECTION_DETACHABLE)
453
+ // which creates a new detached link.
454
+ completeNewDetachedLink(d3Event, drawingNewLinkData) {
455
+ // If we completed a connection remove the new line objects.
456
+ this.removeNewLink();
457
+
458
+ // Switch 'new link over node' highlighting off
459
+ if (this.ren.config.enableHighlightNodeOnNewLinkDrag) {
460
+ this.ren.setLinkOverNodeß();
461
+ }
462
+
463
+ const endPoint = this.ren.getTransformedMousePos(d3Event);
464
+ this.ren.canvasController.editActionHandler({
465
+ editType: "createDetachedLink",
466
+ editSource: "canvas",
467
+ srcNodeId: drawingNewLinkData.srcObjId,
468
+ srcNodePortId: drawingNewLinkData.srcPortId,
469
+ trgPos: endPoint,
470
+ type: NODE_LINK,
471
+ pipelineId: this.ren.activePipeline.id });
472
+ }
473
+
474
+ stopDrawingNewLink(drawingNewLinkData) {
475
+ // Switch 'new link over node' highlighting off
476
+ if (this.ren.config.enableHighlightNodeOnNewLinkDrag) {
477
+ this.ren.setLinkOverNodeCancel();
478
+ }
479
+
480
+ this.stopDrawingNewLinkForPorts(drawingNewLinkData);
481
+ }
482
+
483
+ stopDrawingNewLinkForPorts(drawingNewLinkData) {
484
+ const saveX1 = drawingNewLinkData.linkArray[0].x1;
485
+ const saveY1 = drawingNewLinkData.linkArray[0].y1;
486
+ const saveX2 = drawingNewLinkData.linkArray[0].x2;
487
+ const saveY2 = drawingNewLinkData.linkArray[0].y2;
488
+
489
+ const saveNewLinkData = Object.assign({}, drawingNewLinkData);
490
+
491
+ // If we completed a connection successfully just remove the new line
492
+ // objects.
493
+ let newPath = "";
494
+ let duration = 350;
495
+
496
+ if (this.ren.canvasLayout.linkType === LINK_TYPE_CURVE) {
497
+ newPath = "M " + saveX1 + " " + saveY1 +
498
+ "C " + saveX2 + " " + saveY2 +
499
+ " " + saveX2 + " " + saveY2 +
500
+ " " + saveX2 + " " + saveY2;
501
+
502
+ } else if (this.ren.canvasLayout.linkType === LINK_TYPE_STRAIGHT) {
503
+ if (saveX1 < saveX2) {
504
+ duration = 0;
505
+ }
506
+ newPath = "M " + saveX1 + " " + saveY1 +
507
+ "L " + saveX2 + " " + saveY2 +
508
+ " " + saveX2 + " " + saveY2 +
509
+ " " + saveX2 + " " + saveY2;
510
+
511
+ } else {
512
+ newPath = "M " + saveX1 + " " + saveY1 +
513
+ "L " + saveX2 + " " + saveY2 +
514
+ "Q " + saveX2 + " " + saveY2 + " " + saveX2 + " " + saveY2 +
515
+ "L " + saveX2 + " " + saveY2 +
516
+ "Q " + saveX2 + " " + saveY2 + " " + saveX2 + " " + saveY2 +
517
+ "L " + saveX2 + " " + saveY2 +
518
+ "Q " + saveX2 + " " + saveY2 + " " + saveX2 + " " + saveY2 +
519
+ "L " + saveX2 + " " + saveY2 +
520
+ "Q " + saveX2 + " " + saveY2 + " " + saveX2 + " " + saveY2 +
521
+ "L " + saveX2 + " " + saveY2;
522
+ }
523
+
524
+ this.ren.nodesLinksGrp.selectAll(".d3-new-connection-line")
525
+ .transition()
526
+ .duration(duration)
527
+ .attr("d", newPath)
528
+ .on("end", () => {
529
+ this.ren.nodesLinksGrp.selectAll(".d3-new-connection-arrow").remove();
530
+
531
+ this.ren.nodesLinksGrp.selectAll(".d3-new-connection-guide")
532
+ .transition()
533
+ .duration(1000)
534
+ .ease(d3.easeElastic)
535
+ // The lines below set all attributes for images AND circles even
536
+ // though some attributes will not be relevant. This is done
537
+ // because I could not get the .each() method to work here (which
538
+ // would be necessary to have an if statement based on guide object)
539
+ .attr("x", saveX1 - (saveNewLinkData.portWidth / 2))
540
+ .attr("y", saveY1 - (saveNewLinkData.portHeight / 2))
541
+ .attr("cx", saveX1)
542
+ .attr("cy", saveY1)
543
+ .attr("transform", null);
544
+ this.ren.nodesLinksGrp.selectAll(".d3-new-connection-line")
545
+ .transition()
546
+ .duration(1000)
547
+ .ease(d3.easeElastic)
548
+ .attr("d", "M " + saveX1 + " " + saveY1 +
549
+ "L " + saveX1 + " " + saveY1)
550
+ .on("end", this.removeNewLink.bind(this));
551
+ });
552
+ }
553
+
554
+ removeNewLink() {
555
+ this.ren.nodesLinksGrp.selectAll(".d3-new-connection-line").remove();
556
+ this.ren.nodesLinksGrp.selectAll(".d3-new-connection-start").remove();
557
+ this.ren.nodesLinksGrp.selectAll(".d3-new-connection-guide").remove();
558
+ this.ren.nodesLinksGrp.selectAll(".d3-new-connection-arrow").remove();
559
+ }
560
+
561
+ // Switches on or off node highlighting depending on whether a node is
562
+ // close to teh new link being dragged.
563
+ setNewLinkOverNode(d3Event) {
564
+ const nodeNearMouse = this.ren.getNodeNearMousePos(d3Event, this.ren.canvasLayout.nodeProximity);
565
+ const highlightState = nodeNearMouse && this.isNewLinkAllowedToNode(nodeNearMouse);
566
+ this.ren.setHighlightingOverNode(highlightState, nodeNearMouse);
567
+ }
568
+
569
+ // Returns true if a connection is allowed to the node passed in based on the
570
+ // this.drawingNewLinkData object which describes a new link being dragged.
571
+ isNewLinkAllowedToNode(node) {
572
+ if (this.drawingNewLinkData) {
573
+ if (this.drawingNewLinkData.action === NODE_LINK) {
574
+ const srcNode = this.drawingNewLinkData.srcNode;
575
+ const trgNode = node;
576
+ const srcNodePortId = this.drawingNewLinkData.srcPortId;
577
+ const trgNodePortId = CanvasUtils.getDefaultInputPortId(trgNode); // TODO - make specific to nodes.
578
+ return CanvasUtils.isDataConnectionAllowed(srcNodePortId, trgNodePortId, srcNode, trgNode, this.ren.activePipeline.links);
579
+
580
+ } else if (this.drawingNewLinkData.action === ASSOCIATION_LINK) {
581
+ const srcNode = this.drawingNewLinkData.srcNode;
582
+ const trgNode = node;
583
+ return CanvasUtils.isAssocConnectionAllowed(srcNode, trgNode, this.ren.activePipeline.links);
584
+
585
+ } else if (this.drawingNewLinkData.action === COMMENT_LINK) {
586
+ const srcObjId = this.drawingNewLinkData.srcObjId;
587
+ const trgNodeId = node.id;
588
+ return CanvasUtils.isCommentLinkConnectionAllowed(srcObjId, trgNodeId, this.ren.activePipeline.links);
589
+ }
590
+ }
591
+ return false;
592
+ }
593
+
594
+
595
+ }