@elyra/canvas 12.21.0 → 12.23.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 (159) hide show
  1. package/dist/canvas-constants-09ffa4d4.js +2 -0
  2. package/dist/canvas-constants-09ffa4d4.js.map +1 -0
  3. package/dist/canvas-constants-ab55d0fd.js +2 -0
  4. package/dist/canvas-constants-ab55d0fd.js.map +1 -0
  5. package/dist/canvas-controller-017926a9.js +2 -0
  6. package/dist/canvas-controller-017926a9.js.map +1 -0
  7. package/dist/canvas-controller-51626884.js +2 -0
  8. package/dist/canvas-controller-51626884.js.map +1 -0
  9. package/dist/{canvas-logger-a0f1beaa.js → canvas-logger-3459dfc2.js} +2 -2
  10. package/dist/{canvas-logger-a0f1beaa.js.map → canvas-logger-3459dfc2.js.map} +1 -1
  11. package/dist/{canvas-logger-815781bb.js → canvas-logger-fa8cef5b.js} +2 -2
  12. package/dist/{canvas-logger-815781bb.js.map → canvas-logger-fa8cef5b.js.map} +1 -1
  13. package/dist/common-canvas-3330e83f.js +2 -0
  14. package/dist/common-canvas-3330e83f.js.map +1 -0
  15. package/dist/common-canvas-b2956514.js +2 -0
  16. package/dist/common-canvas-b2956514.js.map +1 -0
  17. package/dist/common-canvas.es.js +1 -1
  18. package/dist/common-canvas.es.js.map +1 -1
  19. package/dist/common-canvas.js +1 -1
  20. package/dist/common-canvas.js.map +1 -1
  21. package/dist/common-properties-9d77f8e1.js +2 -0
  22. package/dist/common-properties-9d77f8e1.js.map +1 -0
  23. package/dist/common-properties-a31de521.js +2 -0
  24. package/dist/common-properties-a31de521.js.map +1 -0
  25. package/dist/{createClass-6db89a23.js → createClass-72b049bc.js} +1 -1
  26. package/dist/createClass-72b049bc.js.map +1 -0
  27. package/dist/{createClass-32a0cf0f.js → createClass-d5cac0b7.js} +1 -1
  28. package/dist/createClass-d5cac0b7.js.map +1 -0
  29. package/dist/{datarecord-metadata-v3-schema-6b6384ff.js → datarecord-metadata-v3-schema-03db5d5d.js} +2 -2
  30. package/dist/{datarecord-metadata-v3-schema-6b6384ff.js.map → datarecord-metadata-v3-schema-03db5d5d.js.map} +1 -1
  31. package/dist/{datarecord-metadata-v3-schema-81228a9a.js → datarecord-metadata-v3-schema-07d7682c.js} +2 -2
  32. package/dist/{datarecord-metadata-v3-schema-81228a9a.js.map → datarecord-metadata-v3-schema-07d7682c.js.map} +1 -1
  33. package/dist/extends-87da7df3.js +7 -0
  34. package/dist/extends-87da7df3.js.map +1 -0
  35. package/dist/{extends-12382a72.js → extends-dc95dba8.js} +2 -2
  36. package/dist/extends-dc95dba8.js.map +1 -0
  37. package/dist/flexible-table-59ad2c83.js +2 -0
  38. package/dist/flexible-table-59ad2c83.js.map +1 -0
  39. package/dist/flexible-table-5c4fbb7b.js +2 -0
  40. package/dist/flexible-table-5c4fbb7b.js.map +1 -0
  41. package/dist/{getPrototypeOf-bf88242f.js → getPrototypeOf-4e282dd3.js} +1 -1
  42. package/dist/getPrototypeOf-4e282dd3.js.map +1 -0
  43. package/dist/{getPrototypeOf-a1c3fe64.js → getPrototypeOf-b3806813.js} +1 -1
  44. package/dist/getPrototypeOf-b3806813.js.map +1 -0
  45. package/dist/{icon-1ef0f3b9.js → icon-2c16236a.js} +2 -2
  46. package/dist/{icon-162ec1ee.js.map → icon-2c16236a.js.map} +1 -1
  47. package/dist/{icon-162ec1ee.js → icon-816af0e7.js} +2 -2
  48. package/dist/{icon-1ef0f3b9.js.map → icon-816af0e7.js.map} +1 -1
  49. package/dist/index-2f6be19d.js +2 -0
  50. package/dist/index-2f6be19d.js.map +1 -0
  51. package/dist/index-6f739fa1.js +2 -0
  52. package/dist/index-6f739fa1.js.map +1 -0
  53. package/dist/lib/canvas-controller.es.js +1 -1
  54. package/dist/lib/canvas-controller.js +1 -1
  55. package/dist/lib/canvas.es.js +1 -1
  56. package/dist/lib/canvas.js +1 -1
  57. package/dist/lib/command-stack.es.js +1 -1
  58. package/dist/lib/command-stack.es.js.map +1 -1
  59. package/dist/lib/command-stack.js +1 -1
  60. package/dist/lib/command-stack.js.map +1 -1
  61. package/dist/lib/context-menu.es.js +1 -1
  62. package/dist/lib/context-menu.es.js.map +1 -1
  63. package/dist/lib/context-menu.js +1 -1
  64. package/dist/lib/context-menu.js.map +1 -1
  65. package/dist/lib/properties/field-picker.es.js +1 -1
  66. package/dist/lib/properties/field-picker.js +1 -1
  67. package/dist/lib/properties/flexible-table.es.js +1 -1
  68. package/dist/lib/properties/flexible-table.js +1 -1
  69. package/dist/lib/properties.es.js +1 -1
  70. package/dist/lib/properties.js +1 -1
  71. package/dist/lib/tooltip.es.js +1 -1
  72. package/dist/lib/tooltip.es.js.map +1 -1
  73. package/dist/lib/tooltip.js +1 -1
  74. package/dist/lib/tooltip.js.map +1 -1
  75. package/dist/styles/common-canvas.min.css +1 -1
  76. package/dist/styles/common-canvas.min.css.map +1 -1
  77. package/dist/{toolbar-bb5bee87.js → toolbar-2ef99bd8.js} +2 -2
  78. package/dist/{toolbar-59ce5251.js.map → toolbar-2ef99bd8.js.map} +1 -1
  79. package/dist/{toolbar-59ce5251.js → toolbar-cb967e26.js} +2 -2
  80. package/dist/{toolbar-bb5bee87.js.map → toolbar-cb967e26.js.map} +1 -1
  81. package/locales/common-properties/locales/en.json +2 -0
  82. package/package.json +1 -1
  83. package/src/common-canvas/cc-contents.jsx +14 -2
  84. package/src/common-canvas/constants/canvas-constants.js +1 -0
  85. package/src/common-canvas/svg-canvas-d3.js +8 -0
  86. package/src/common-canvas/svg-canvas-d3.scss +1 -1
  87. package/src/common-canvas/svg-canvas-renderer.js +165 -130
  88. package/src/common-canvas/svg-canvas-utils-decs.js +3 -2
  89. package/src/common-canvas/svg-canvas-utils-textarea.js +19 -5
  90. package/src/common-properties/components/editor-form/editor-form.jsx +52 -21
  91. package/src/common-properties/components/flexible-table/flexible-table.scss +3 -2
  92. package/src/common-properties/components/virtualized-table/virtualized-table.jsx +38 -34
  93. package/src/common-properties/components/virtualized-table/virtualized-table.scss +17 -0
  94. package/src/common-properties/constants/constants.js +3 -0
  95. package/src/common-properties/controls/datefield/datefield.jsx +1 -1
  96. package/src/common-properties/controls/dropdown/dropdown.jsx +3 -3
  97. package/src/common-properties/controls/expression/expression-builder/expression-select-field-function.jsx +25 -18
  98. package/src/common-properties/controls/expression/expression.jsx +1 -1
  99. package/src/common-properties/controls/expression/expressionInfo-parser.js +11 -0
  100. package/src/common-properties/controls/list/list.jsx +1 -1
  101. package/src/common-properties/controls/multiselect/multiselect.jsx +2 -2
  102. package/src/common-properties/controls/numberfield/numberfield.jsx +1 -1
  103. package/src/common-properties/controls/passwordfield/passwordfield.jsx +3 -3
  104. package/src/common-properties/controls/selectcolumns/selectcolumns.jsx +1 -1
  105. package/src/common-properties/controls/someofselect/someofselect.jsx +1 -1
  106. package/src/common-properties/controls/textarea/textarea.jsx +2 -2
  107. package/src/common-properties/controls/textfield/textfield.jsx +1 -1
  108. package/src/common-properties/controls/timefield/timefield.jsx +1 -1
  109. package/src/common-properties/controls/toggle/toggle.jsx +1 -3
  110. package/src/common-properties/controls/toggle/toggle.scss +7 -4
  111. package/src/common-properties/form/ControlInfo.js +1 -0
  112. package/src/common-properties/form/EditorForm.js +18 -11
  113. package/src/common-properties/index.scss +5 -0
  114. package/src/common-properties/panels/tearsheet/tearsheet.jsx +9 -22
  115. package/src/common-properties/panels/tearsheet/tearsheet.scss +7 -1
  116. package/src/common-properties/properties-controller.js +6 -2
  117. package/src/common-properties/ui-conditions/ui-conditions-parser.js +1 -0
  118. package/src/common-properties/ui-conditions/ui-groups-parser.js +1 -0
  119. package/src/common-properties/util/property-utils.js +3 -0
  120. package/src/context-menu/common-context-menu.jsx +7 -0
  121. package/src/context-menu/context-menu-wrapper.jsx +30 -15
  122. package/src/object-model/api-pipeline.js +6 -9
  123. package/src/object-model/layout-dimensions.js +2 -2
  124. package/src/object-model/pipeline-out-handler.js +1 -1
  125. package/src/object-model/redux/reducers/canvasinfo.js +0 -1
  126. package/src/object-model/redux/reducers/nodes.js +0 -9
  127. package/src/palette/palette.scss +1 -1
  128. package/stats.html +1 -1
  129. package/dist/canvas-constants-34cdb7df.js +0 -2
  130. package/dist/canvas-constants-34cdb7df.js.map +0 -1
  131. package/dist/canvas-constants-3c09c7f6.js +0 -2
  132. package/dist/canvas-constants-3c09c7f6.js.map +0 -1
  133. package/dist/canvas-controller-ccb05f9f.js +0 -2
  134. package/dist/canvas-controller-ccb05f9f.js.map +0 -1
  135. package/dist/canvas-controller-feabad26.js +0 -2
  136. package/dist/canvas-controller-feabad26.js.map +0 -1
  137. package/dist/common-canvas-bcfe04ef.js +0 -2
  138. package/dist/common-canvas-bcfe04ef.js.map +0 -1
  139. package/dist/common-canvas-c4f77878.js +0 -2
  140. package/dist/common-canvas-c4f77878.js.map +0 -1
  141. package/dist/common-properties-267a9a6c.js +0 -2
  142. package/dist/common-properties-267a9a6c.js.map +0 -1
  143. package/dist/common-properties-6520f90b.js +0 -2
  144. package/dist/common-properties-6520f90b.js.map +0 -1
  145. package/dist/createClass-32a0cf0f.js.map +0 -1
  146. package/dist/createClass-6db89a23.js.map +0 -1
  147. package/dist/extends-12382a72.js.map +0 -1
  148. package/dist/extends-195c6b49.js +0 -7
  149. package/dist/extends-195c6b49.js.map +0 -1
  150. package/dist/flexible-table-056c538e.js +0 -2
  151. package/dist/flexible-table-056c538e.js.map +0 -1
  152. package/dist/flexible-table-7fb8a62e.js +0 -2
  153. package/dist/flexible-table-7fb8a62e.js.map +0 -1
  154. package/dist/getPrototypeOf-a1c3fe64.js.map +0 -1
  155. package/dist/getPrototypeOf-bf88242f.js.map +0 -1
  156. package/dist/index-61be3509.js +0 -2
  157. package/dist/index-61be3509.js.map +0 -1
  158. package/dist/index-8076376e.js +0 -2
  159. package/dist/index-8076376e.js.map +0 -1
@@ -41,7 +41,7 @@ import { ASSOC_RIGHT_SIDE_CURVE, ASSOCIATION_LINK, NODE_LINK, COMMENT_LINK,
41
41
  CONTEXT_MENU_BUTTON, DEC_LINK, DEC_NODE, LEFT_ARROW_ICON, EDIT_ICON,
42
42
  NODE_MENU_ICON, SUPER_NODE_EXPAND_ICON, PORT_OBJECT_CIRCLE, PORT_OBJECT_IMAGE,
43
43
  TIP_TYPE_NODE, TIP_TYPE_PORT, TIP_TYPE_DEC, TIP_TYPE_LINK,
44
- INTERACTION_MOUSE, INTERACTION_TRACKPAD,
44
+ INTERACTION_MOUSE, INTERACTION_TRACKPAD, INTERACTION_CARBON,
45
45
  USE_DEFAULT_ICON, USE_DEFAULT_EXT_ICON,
46
46
  SUPER_NODE, SNAP_TO_GRID_AFTER, SNAP_TO_GRID_DURING,
47
47
  NORTH, SOUTH, EAST, WEST }
@@ -178,6 +178,12 @@ export default class SVGCanvasRenderer {
178
178
  // no need to re-render whole canvas
179
179
  this.selecting = false;
180
180
 
181
+ // Flag to indicate when the space key is down (used when dragging).
182
+ this.spaceKeyPressed = false;
183
+
184
+ // Flag to indicate when a zoom is invoked programmatically.
185
+ this.zoomingAction = false;
186
+
181
187
  // Allows us to track when the binding nodes in a subflow are being moved.
182
188
  this.movingBindingNodes = false;
183
189
 
@@ -187,7 +193,9 @@ export default class SVGCanvasRenderer {
187
193
 
188
194
  // Used to monitor the region selection rectangle.
189
195
  this.regionSelect = false;
190
- this.region = { startX: 0, startY: 0, width: 0, height: 0 };
196
+
197
+ // Used to track the start of the zoom.
198
+ this.zoomStartPoint = { x: 0, y: 0, k: 0, startX: 0, startY: 0 };
191
199
 
192
200
  // I was not able to figure out how to use the zoom filter method to
193
201
  // allow mousedown and mousemove messages to go through to the canvas to
@@ -273,6 +281,27 @@ export default class SVGCanvasRenderer {
273
281
  this.logger.logEndTimer("constructor" + pipelineId.substring(0, 5));
274
282
  }
275
283
 
284
+ setSpaceKeyPressed(state) {
285
+ this.spaceKeyPressed = state;
286
+ this.resetCanvasCursor();
287
+ }
288
+
289
+ // Returns true if the space bar is pressed and held down. This is called
290
+ // from outside canvas via svg-canvas-d3 as well as internally.
291
+ isSpaceKeyPressed() {
292
+ return this.spaceKeyPressed;
293
+ }
294
+
295
+ // Returns true if the event indicates that a drag is in action. This means
296
+ // with regular Mouse interation that the space bar is pressed or with
297
+ // legacy interation it means the shift key is NOT pressed.
298
+ isDragActivated(d3Event) {
299
+ if (this.config.enableInteractionType === INTERACTION_CARBON) {
300
+ return this.isSpaceKeyPressed();
301
+ }
302
+ return (d3Event && d3Event.sourceEvent && !d3Event.sourceEvent.shiftKey);
303
+ }
304
+
276
305
  // Returns the data object for the parent supernode that references the
277
306
  // active pipeline (managed by this renderer). We get the supernode by
278
307
  // looking through the overall canvas info objects.
@@ -300,9 +329,6 @@ export default class SVGCanvasRenderer {
300
329
  initializeZoomVariables() {
301
330
  // Allows us to record the current zoom amounts.
302
331
  this.zoomTransform = d3.zoomIdentity.translate(0, 0).scale(1);
303
-
304
- // Allows us to record the start point of the current zoom.
305
- this.zoomStartPoint = { x: 0, y: 0, k: 0 };
306
332
  }
307
333
 
308
334
  setCanvasInfoRenderer(canvasInfo) {
@@ -322,10 +348,6 @@ export default class SVGCanvasRenderer {
322
348
  // need the zoom behavior, or vice versa.
323
349
  this.resetCanvasSVGBehaviors();
324
350
 
325
- // Reset the canvas cursor, in case we went from an empty canvas
326
- // (default cursor) to one with nodes and/or comments (hand cursor).
327
- this.resetCanvasCursor();
328
-
329
351
  // If a supernode and its corresponding pipeline has been deleted in the
330
352
  // object model we need to make sure the renderer is removed.
331
353
  this.superRenderers = this.cleanUpSuperRenderers();
@@ -1364,7 +1386,7 @@ export default class SVGCanvasRenderer {
1364
1386
  .attr("data-pipeline-id", this.activePipeline.id)
1365
1387
  .attr("class", "d3-svg-background")
1366
1388
  .attr("pointer-events", "all")
1367
- .style("cursor", this.getCanvasCursor());
1389
+ .style("cursor", "default");
1368
1390
 
1369
1391
  // Only attach the 'defs' to the top most SVG area when we are displaying
1370
1392
  // either the primary pipeline full page or a sub-pipeline full page.
@@ -1433,15 +1455,7 @@ export default class SVGCanvasRenderer {
1433
1455
  })
1434
1456
  .on("click.zoom", (d3Event) => {
1435
1457
  this.logger.log("Canvas - click-zoom");
1436
- this.selecting = true;
1437
- // Only clear selections if clicked on the canvas of the current active pipeline.
1438
- // Clicking the canvas of an expanded supernode will select that node.
1439
- if (this.dispUtils.isDisplayingCurrentPipeline() && !this.contextMenuClosedOnZoom) {
1440
- this.canvasController.clearSelections();
1441
- }
1442
- this.contextMenuClosedOnZoom = false;
1443
- // Ensure 'selecting' flag is off before calling click action callback.
1444
- this.selecting = false;
1458
+
1445
1459
  this.canvasController.clickActionHandler({
1446
1460
  clickType: d3Event.type === "contextmenu" ? "SINGLE_CLICK_CONTEXTMENU" : "SINGLE_CLICK",
1447
1461
  objectType: "canvas",
@@ -1464,19 +1478,7 @@ export default class SVGCanvasRenderer {
1464
1478
  // Resets the pointer cursor on the background rectangle in the Canvas SVG area.
1465
1479
  resetCanvasCursor() {
1466
1480
  const selector = ".d3-svg-background[data-pipeline-id='" + this.activePipeline.id + "']";
1467
- this.canvasSVG.select(selector).style("cursor", this.getCanvasCursor());
1468
- }
1469
-
1470
- // Retuens the appropriate cursor for the canvas SVG area.
1471
- getCanvasCursor() {
1472
- if (this.dispUtils.isDisplayingFullPage()) {
1473
- if (this.config.enableInteractionType === INTERACTION_TRACKPAD ||
1474
- this.activePipeline.isEmptyOrBindingsOnly()) {
1475
- return "default";
1476
- }
1477
- return "grab";
1478
- }
1479
- return "pointer";
1481
+ this.canvasSVG.select(selector).style("cursor", this.isDragActivated() && this.dispUtils.isDisplayingFullPage() ? "grab" : "default");
1480
1482
  }
1481
1483
 
1482
1484
  createCanvasGroup(canvasObj, className) {
@@ -1622,6 +1624,7 @@ export default class SVGCanvasRenderer {
1622
1624
  if (isFinite(newZoomTransform.x) &&
1623
1625
  isFinite(newZoomTransform.y) &&
1624
1626
  isFinite(newZoomTransform.k)) {
1627
+ this.zoomingAction = true;
1625
1628
  const zoomTransform = d3.zoomIdentity.translate(newZoomTransform.x, newZoomTransform.y).scale(newZoomTransform.k);
1626
1629
  if (animateTime) {
1627
1630
  this.canvasSVG.call(this.zoom).transition()
@@ -1630,6 +1633,7 @@ export default class SVGCanvasRenderer {
1630
1633
  } else {
1631
1634
  this.canvasSVG.call(this.zoom.transform, zoomTransform);
1632
1635
  }
1636
+ this.zoomingAction = false;
1633
1637
  }
1634
1638
  }
1635
1639
 
@@ -1649,9 +1653,7 @@ export default class SVGCanvasRenderer {
1649
1653
  x -= newScale * canvasDimensions.left;
1650
1654
  y -= newScale * canvasDimensions.top;
1651
1655
 
1652
- this.zoomingToFit = true;
1653
1656
  this.zoomCanvasInvokeZoomBehavior({ x: x, y: y, k: newScale });
1654
- this.zoomingToFit = false;
1655
1657
  }
1656
1658
  }
1657
1659
 
@@ -1795,47 +1797,28 @@ export default class SVGCanvasRenderer {
1795
1797
  this.contextMenuClosedOnZoom = true;
1796
1798
  }
1797
1799
 
1798
- // this.zoomingToFit flag is used to avoid redo actions initialized
1799
- // by Cmd+Shift+Z (where the shift key has been pressed) causing a region
1800
- // selection to start. So whenever it is set, make sure we do a scale
1801
- // operation.
1802
- // Also, below, we must check the d3Event.sourceEvent because for a zoom
1803
- // operation d3Event does not contain info about the shift key.
1804
- if (this.zoomingToFit) {
1805
- this.regionSelect = false;
1806
- } else if ((this.config.enableInteractionType === INTERACTION_TRACKPAD &&
1807
- d3Event.sourceEvent && d3Event.sourceEvent.buttons === 1) || // Main button is pressed
1808
- (this.config.enableInteractionType === INTERACTION_MOUSE &&
1809
- d3Event.sourceEvent && d3Event.sourceEvent.shiftKey)) { // Shift key is pressed
1810
- this.regionSelect = true;
1811
- } else {
1812
- this.regionSelect = false;
1813
- }
1800
+ this.regionSelect = this.shouldDoRegionSelect(d3Event);
1814
1801
 
1815
1802
  if (this.regionSelect) {
1803
+ // Add a delay so, if the user just clicks, they don't see the crosshair.
1804
+ // This will be cleared in zoomEnd if the user's click takes less than 200 ms.
1805
+ this.addingCrossHairCursor = setTimeout(() => this.addTempCursorOverlay("crosshair"), 200);
1816
1806
  this.regionStartTransformX = d3Event.transform.x;
1817
1807
  this.regionStartTransformY = d3Event.transform.y;
1818
- const transPos = this.getTransformedMousePos(d3Event);
1819
- this.region = {
1820
- startX: transPos.x,
1821
- startY: transPos.y,
1822
- width: 0,
1823
- height: 0
1824
- };
1825
- }
1826
1808
 
1827
- // To make the new cursor style appear *immediately* on mousedown we set the
1828
- // appropriate cursor style on the SVG background rectanagle. The cursor
1829
- // overlay will handle the cursor style as the mouse is moved.
1830
- const selector = ".d3-svg-background[data-pipeline-id='" + this.activePipeline.id + "']";
1831
- if (this.regionSelect) {
1832
- this.canvasSVG.select(selector).style("cursor", "crosshair");
1833
1809
  } else {
1834
- this.canvasSVG.select(selector).style("cursor", "grabbing");
1810
+ if (this.isDragActivated(d3Event)) {
1811
+ this.addTempCursorOverlay("grabbing");
1812
+ } else {
1813
+ this.addTempCursorOverlay("default");
1814
+ }
1835
1815
  }
1836
1816
 
1837
- this.zoomStartPoint = { x: d3Event.transform.x, y: d3Event.transform.y, k: d3Event.transform.k };
1817
+ const transPos = this.getTransformedMousePos(d3Event);
1818
+ this.zoomStartPoint = { x: d3Event.transform.x, y: d3Event.transform.y, k: d3Event.transform.k, startX: transPos.x, startY: transPos.y };
1838
1819
  this.previousD3Event = { x: d3Event.transform.x, y: d3Event.transform.y, k: d3Event.transform.k };
1820
+ // Calculate the canvas dimensions here, so we don't have to recalculate
1821
+ // them for every zoom action event.
1839
1822
  this.zoomCanvasDimensions = CanvasUtils.getCanvasDimensions(
1840
1823
  this.activePipeline.nodes, this.activePipeline.comments,
1841
1824
  this.activePipeline.links, this.canvasLayout.commentHighlightGap);
@@ -1847,14 +1830,13 @@ export default class SVGCanvasRenderer {
1847
1830
  // If the scale amount is the same we are not zooming, so we must be panning.
1848
1831
  if (d3Event.transform.k === this.zoomStartPoint.k) {
1849
1832
  if (this.regionSelect) {
1850
- this.addTempCursorOverlay("crosshair");
1851
1833
  this.drawRegionSelector(d3Event);
1852
1834
 
1853
1835
  } else {
1854
- this.addTempCursorOverlay("grabbing");
1855
1836
  this.zoomCanvasBackground(d3Event);
1856
1837
  }
1857
1838
  } else {
1839
+ this.addTempCursorOverlay("default");
1858
1840
  this.zoomCanvasBackground(d3Event);
1859
1841
  this.zoomCommentToolbar();
1860
1842
  }
@@ -1863,62 +1845,60 @@ export default class SVGCanvasRenderer {
1863
1845
  zoomEnd(d3Event) {
1864
1846
  this.logger.log("zoomEnd - " + JSON.stringify(d3Event.transform));
1865
1847
 
1848
+ // Clears the display of the crosshair cursor if the user clicks within 200 ms
1849
+ clearTimeout(this.addingCrossHairCursor);
1850
+
1851
+ const transPos = this.getTransformedMousePos(d3Event);
1852
+
1866
1853
  if (this.drawingNewLinkData) {
1867
1854
  this.stopDrawingNewLink();
1868
- this.drawingNewLinkData = null;
1869
- }
1870
1855
 
1871
- if (this.draggingLinkData) {
1856
+ } else if (this.draggingLinkData) {
1872
1857
  this.stopDraggingLink();
1873
- this.draggingLinkData = null;
1874
- }
1875
-
1876
- if (d3Event.transform.k === this.zoomStartPoint.k &&
1877
- this.regionSelect === true) {
1878
- this.removeRegionSelector();
1879
-
1880
- // Reset the transform x and y to what they were before the region
1881
- // selection action was started. This directly sets the x and y values
1882
- // in the __zoom property of the svgCanvas DOM object.
1883
- d3Event.transform.x = this.regionStartTransformX;
1884
- d3Event.transform.y = this.regionStartTransformY;
1885
-
1886
- var { startX, startY, width, height } = this.getRegionDimensions();
1887
- this.isSelecting = true;
1888
1858
 
1889
- // Ensure the link objects in the active pipeline have their coordinate
1890
- // positions set. The coords might not be set if the last object model
1891
- // update was a change in selections or some other operation that does
1892
- // not redraw link lines.
1893
- this.buildLinksArray();
1859
+ // The user just clicked -- with no drag.
1860
+ } else if (transPos.x === this.zoomStartPoint.startX &&
1861
+ transPos.y === this.zoomStartPoint.startY &&
1862
+ !this.zoomChanged()) {
1863
+ this.zoomClick();
1894
1864
 
1895
- const region = { x1: startX, y1: startY, x2: startX + width, y2: startY + height };
1896
- const selections =
1897
- CanvasUtils.selectInRegion(region, this.activePipeline,
1898
- this.config.enableLinkSelection !== LINK_SELECTION_NONE,
1899
- this.config.enableLinkType,
1900
- this.config.enableAssocLinkType);
1901
- this.canvasController.setSelections(selections, this.activePipeline.id);
1902
- this.regionSelect = false;
1865
+ } else if (this.regionSelect) {
1866
+ this.zoomEndRegionSelect(d3Event);
1903
1867
 
1904
1868
  } else if (this.dispUtils.isDisplayingFullPage() && this.zoomChanged()) {
1905
- // Set the internal zoom value for canvasSVG used by D3. This will be
1906
- // used by d3Event next time a zoom action is initiated.
1907
- this.canvasSVG.property("__zoom", this.zoomTransform);
1908
-
1909
- const data = {
1910
- editType: "setZoom",
1911
- editSource: "canvas",
1912
- zoom: this.zoomTransform,
1913
- pipelineId: this.activePipeline.id
1914
- };
1915
- this.canvasController.editActionHandler(data);
1869
+ this.zoomSave();
1916
1870
  }
1917
1871
 
1918
1872
  // Remove the cursor overlay and reset the SVG background rectangle
1919
1873
  // cursor style, which was set in the zoom start method.
1920
- this.resetCanvasCursor();
1874
+ this.resetCanvasCursor(d3Event);
1921
1875
  this.removeTempCursorOverlay();
1876
+ this.contextMenuClosedOnZoom = false;
1877
+ this.regionSelect = false;
1878
+ }
1879
+
1880
+ // Returns true if the region select gesture is requested by the user.
1881
+ shouldDoRegionSelect(d3Event) {
1882
+ // The this.zoomingAction flag indicates zooming is being invoked
1883
+ // programmatically.
1884
+ if (this.zoomingAction) {
1885
+ return false;
1886
+
1887
+ } else if (this.config.enableInteractionType === INTERACTION_MOUSE &&
1888
+ (d3Event && d3Event.sourceEvent && d3Event.sourceEvent.shiftKey)) {
1889
+ return true;
1890
+
1891
+ } else if (this.config.enableInteractionType === INTERACTION_CARBON &&
1892
+ !this.isSpaceKeyPressed(d3Event)) {
1893
+ return true;
1894
+
1895
+ } else if (this.config.enableInteractionType === INTERACTION_TRACKPAD &&
1896
+ (d3Event.sourceEvent && d3Event.sourceEvent.buttons === 1) && // Main button is pressed
1897
+ !this.spaceKeyPressed) {
1898
+ return true;
1899
+ }
1900
+
1901
+ return false;
1922
1902
  }
1923
1903
 
1924
1904
  // Returns true if the current zoom transform is different from the
@@ -1957,6 +1937,63 @@ export default class SVGCanvasRenderer {
1957
1937
  }
1958
1938
  }
1959
1939
 
1940
+ // Handles a zoom operation that is just a click on the canvas background.
1941
+ zoomClick() {
1942
+ // Only clear selections if clicked on the canvas of the current active pipeline.
1943
+ // Clicking the canvas of an expanded supernode will select that node.
1944
+ if (this.dispUtils.isDisplayingCurrentPipeline() && !this.contextMenuClosedOnZoom) {
1945
+ this.selecting = true;
1946
+ this.canvasController.clearSelections();
1947
+ this.selecting = false;
1948
+ }
1949
+ }
1950
+
1951
+ // Handles the behavior when the user stops doing a region select.
1952
+ zoomEndRegionSelect(d3Event) {
1953
+ this.removeRegionSelector();
1954
+
1955
+ // Reset the transform x and y to what they were before the region
1956
+ // selection action was started. This directly sets the x and y values
1957
+ // in the __zoom property of the svgCanvas DOM object.
1958
+ d3Event.transform.x = this.regionStartTransformX;
1959
+ d3Event.transform.y = this.regionStartTransformY;
1960
+
1961
+ const { startX, startY, width, height } = this.getRegionDimensions(d3Event);
1962
+
1963
+ // Ensure the link objects in the active pipeline have their coordinate
1964
+ // positions set. The coords might not be set if the last object model
1965
+ // update was a change in selections or some other operation that does
1966
+ // not redraw link lines.
1967
+ this.buildLinksArray();
1968
+
1969
+ const region = { x1: startX, y1: startY, x2: startX + width, y2: startY + height };
1970
+ const selections =
1971
+ CanvasUtils.selectInRegion(region, this.activePipeline,
1972
+ this.config.enableLinkSelection !== LINK_SELECTION_NONE,
1973
+ this.config.enableLinkType,
1974
+ this.config.enableAssocLinkType);
1975
+ this.selecting = true;
1976
+ this.canvasController.setSelections(selections, this.activePipeline.id);
1977
+ this.selecting = false;
1978
+ }
1979
+
1980
+ // Save the zoom amount. The canvas controller/object model will decide
1981
+ // how this info is saved.
1982
+ zoomSave() {
1983
+ // Set the internal zoom value for canvasSVG used by D3. This will be
1984
+ // used by d3Event next time a zoom action is initiated.
1985
+ this.canvasSVG.property("__zoom", this.zoomTransform);
1986
+
1987
+ const data = {
1988
+ editType: "setZoom",
1989
+ editSource: "canvas",
1990
+ zoom: this.zoomTransform,
1991
+ pipelineId: this.activePipeline.id
1992
+ };
1993
+ this.canvasController.editActionHandler(data);
1994
+
1995
+ }
1996
+
1960
1997
  // Repositions the comment toolbar so it is always over the top of the
1961
1998
  // comment being edited.
1962
1999
  zoomCommentToolbar() {
@@ -2061,12 +2098,8 @@ export default class SVGCanvasRenderer {
2061
2098
  }
2062
2099
 
2063
2100
  drawRegionSelector(d3Event) {
2064
- const transPos = this.getTransformedMousePos(d3Event);
2065
- this.region.width = transPos.x - this.region.startX;
2066
- this.region.height = transPos.y - this.region.startY;
2067
-
2068
2101
  this.removeRegionSelector();
2069
- var { startX, startY, width, height } = this.getRegionDimensions();
2102
+ const { startX, startY, width, height } = this.getRegionDimensions(d3Event);
2070
2103
 
2071
2104
  this.canvasGrp
2072
2105
  .append("rect")
@@ -2081,22 +2114,23 @@ export default class SVGCanvasRenderer {
2081
2114
  this.canvasGrp.selectAll(".d3-region-selector").remove();
2082
2115
  }
2083
2116
 
2084
- // Returns the startX, startY, width and height of the selction region
2117
+ // Returns the startX, startY, width and height of the selection region
2085
2118
  // where startX and startY are always the top left corner of the region
2086
2119
  // and width and height are therefore always positive.
2087
- getRegionDimensions() {
2088
- var startX = this.region.startX;
2089
- var startY = this.region.startY;
2090
- var width = this.region.width;
2091
- var height = this.region.height;
2120
+ getRegionDimensions(d3Event) {
2121
+ const transPos = this.getTransformedMousePos(d3Event);
2122
+ let startX = this.zoomStartPoint.startX;
2123
+ let startY = this.zoomStartPoint.startY;
2124
+ let width = transPos.x - startX;
2125
+ let height = transPos.y - startY;
2092
2126
 
2093
2127
  if (width < 0) {
2094
2128
  width = Math.abs(width);
2095
- startX = this.region.startX - width;
2129
+ startX -= width;
2096
2130
  }
2097
2131
  if (height < 0) {
2098
2132
  height = Math.abs(height);
2099
- startY = this.region.startY - height;
2133
+ startY -= height;
2100
2134
  }
2101
2135
 
2102
2136
  return { startX, startY, width, height };
@@ -2489,7 +2523,7 @@ export default class SVGCanvasRenderer {
2489
2523
  } else if ((this.dragging && !this.nodeSizing && !this.commentSizing) || this.movingBindingNodes) {
2490
2524
  this.displayMovedNodes();
2491
2525
 
2492
- } else if (this.selecting || this.regionSelect) {
2526
+ } else if (this.selecting) {
2493
2527
  this.displayNodesSelectionStatus();
2494
2528
 
2495
2529
  } else {
@@ -2922,7 +2956,7 @@ export default class SVGCanvasRenderer {
2922
2956
  .on("mousemove mouseenter", (d3Event, d) => {
2923
2957
  if (this.isNodeResizable(d) &&
2924
2958
  !this.isRegionSelectOrSizingInProgress()) { // Don't switch sizing direction if we are already sizing
2925
- let cursorType = "pointer";
2959
+ let cursorType = "default";
2926
2960
  if (!this.isPointerCloseToBodyEdge(d3Event, d)) {
2927
2961
  this.nodeSizingDirection = this.getSizingDirection(d3Event, d, d.layout.nodeCornerResizeArea);
2928
2962
  this.nodeSizingCursor = this.getCursorBasedOnDirection(this.nodeSizingDirection);
@@ -2932,7 +2966,7 @@ export default class SVGCanvasRenderer {
2932
2966
  }
2933
2967
  })
2934
2968
  .on("mouseleave", (d3Event, d) => {
2935
- d3.select(d3Event.currentTarget).style("cursor", "pointer");
2969
+ d3.select(d3Event.currentTarget).style("cursor", "default");
2936
2970
  });
2937
2971
  }
2938
2972
 
@@ -4193,6 +4227,7 @@ export default class SVGCanvasRenderer {
4193
4227
  }
4194
4228
 
4195
4229
  this.stopDrawingNewLinkForPorts();
4230
+ this.drawingNewLinkData = null;
4196
4231
  }
4197
4232
 
4198
4233
  stopDrawingNewLinkForPorts() {
@@ -5006,7 +5041,7 @@ export default class SVGCanvasRenderer {
5006
5041
  if (this.dragging && !this.commentSizing && !this.nodeSizing && !this.isCommentBeingUpdated) {
5007
5042
  this.displayMovedComments();
5008
5043
 
5009
- } else if (this.selecting || this.regionSelect) {
5044
+ } else if (this.selecting) {
5010
5045
  this.displayCommentsSelectionStatus();
5011
5046
 
5012
5047
  } else {
@@ -5204,7 +5239,7 @@ export default class SVGCanvasRenderer {
5204
5239
  if (this.config.enableEditingActions && // Only set cursor when we are able to edit comments
5205
5240
  !this.isRegionSelectOrSizingInProgress()) // Don't switch sizing direction if we are already sizing
5206
5241
  {
5207
- let cursorType = "pointer";
5242
+ let cursorType = "default";
5208
5243
  if (!this.isPointerCloseToBodyEdge(d3Event, d)) {
5209
5244
  this.commentSizingDirection = this.getSizingDirection(d3Event, d, this.canvasLayout.commentCornerResizeArea);
5210
5245
  this.commentSizingCursor = this.getCursorBasedOnDirection(this.commentSizingDirection);
@@ -5656,7 +5691,7 @@ export default class SVGCanvasRenderer {
5656
5691
  displayLinks() {
5657
5692
  this.logger.logStartTimer("displayLinks " + this.getFlags());
5658
5693
 
5659
- if (this.selecting || this.regionSelect) {
5694
+ if (this.selecting) {
5660
5695
  this.displayLinksSelectionStatus();
5661
5696
 
5662
5697
  } else {
@@ -183,11 +183,12 @@ export default class SvgCanvasDecs {
183
183
  }
184
184
 
185
185
  getDecLabelEditIconPosX(dec, obj, objType, spanObj, zoomScale) {
186
+ const minWidth = Math.min(spanObj.getBoundingClientRect().width, this.getDecLabelWidth(dec, obj, objType));
186
187
  if (dec.label_align === "center") {
187
188
  const halfWid = this.getDecLabelWidth(dec, obj, objType) / 2;
188
- return halfWid + (spanObj.getBoundingClientRect().width / 2) / zoomScale;
189
+ return halfWid + (minWidth / 2) / zoomScale;
189
190
  }
190
- return spanObj.getBoundingClientRect().width / zoomScale;
191
+ return minWidth / zoomScale;
191
192
  }
192
193
 
193
194
  getDecLabelEditIconPosY(dec) {
@@ -365,11 +365,18 @@ export default class SvgCanvasTextArea {
365
365
  .attr("class", data.className)
366
366
  .text(unescapeText(data.text))
367
367
  .on("keydown", (d3Event) => {
368
- // Don't accept return key press when text is all on one line or
369
- // if application doesn't want line feeds inserted in the label.
370
- if ((data.singleLine || !data.allowReturnKey) &&
371
- d3Event.keyCode === RETURN_KEY) {
372
- CanvasUtils.stopPropagationAndPreventDefault(d3Event);
368
+ // If user hits return/enter
369
+ if (d3Event.keyCode === RETURN_KEY) {
370
+ if (data.allowReturnKey === "save") {
371
+ this.textAreaLabelSaved = true;
372
+ this.saveAndCloseTextArea(foreignObject, data, d3Event.target.value, d3Event);
373
+ return;
374
+
375
+ // Don't accept return key press when text is all on one line or
376
+ // if application doesn't want line feeds inserted in the label.
377
+ } else if (data.singleLine || !data.allowReturnKey) {
378
+ CanvasUtils.stopPropagationAndPreventDefault(d3Event);
379
+ }
373
380
  }
374
381
  // If user presses ESC key revert back to original text by just
375
382
  // closing the text area.
@@ -409,6 +416,13 @@ export default class SvgCanvasTextArea {
409
416
  return;
410
417
  }
411
418
 
419
+ // If the text label has been saved by the user hitting the return key
420
+ // we just return since there's nothing further to do.
421
+ if (this.textAreaLabelSaved) {
422
+ this.textAreaLabelSaved = false;
423
+ return;
424
+ }
425
+
412
426
  // If the user clicked on an element in the text toolbar to cause the
413
427
  // blur event, just return.
414
428
  if (d3Event.relatedTarget && CanvasUtils.getParentElementWithClass(d3Event.relatedTarget, "text-toolbar")) {
@@ -41,9 +41,9 @@ import ActionPanel from "./../../panels/action-panel";
41
41
 
42
42
  import ActionFactory from "./../../actions/action-factory";
43
43
  import Icon from "./../../../icons/icon";
44
+ import { ItemType } from "../../constants/form-constants";
44
45
 
45
46
  const ALERT_TAB_GROUP = "alertMsgs";
46
-
47
47
  class EditorForm extends React.Component {
48
48
 
49
49
  constructor(props) {
@@ -70,6 +70,10 @@ class EditorForm extends React.Component {
70
70
 
71
71
  this.actionFactory = new ActionFactory(this.props.controller);
72
72
 
73
+ this.FIRST_TEARSHEET_ID = null;
74
+ this.TEARSHEETS = {};
75
+ this.visibleTearsheet = null;
76
+
73
77
  }
74
78
 
75
79
  shouldComponentUpdate(nextProps, nextState) {
@@ -129,9 +133,12 @@ class EditorForm extends React.Component {
129
133
  const tabContent = [];
130
134
  let hasAlertsTab = false;
131
135
  let modalSelected = 0;
136
+ const nonTearsheetTabs = tabs.filter((t) => t.content.itemType !== ItemType.TEARSHEET);
137
+ const tearsheetTabs = tabs.filter((t) => t.content.itemType === ItemType.TEARSHEET);
138
+ const totalTabs = tearsheetTabs.concat(nonTearsheetTabs);
132
139
 
133
- for (let i = 0; i < tabs.length; i++) {
134
- const tab = tabs[i];
140
+ for (let i = 0; i < totalTabs.length; i++) {
141
+ const tab = totalTabs[i];
135
142
  const tabState = this.props.controller.getPanelState({ name: tab.group });
136
143
  if (tabState === STATES.HIDDEN) {
137
144
  continue;
@@ -144,8 +151,9 @@ class EditorForm extends React.Component {
144
151
  if (this.props.additionalComponents) {
145
152
  additionalComponent = this.props.additionalComponents[tab.group];
146
153
  }
147
- // if only 1 tab don't show any tabs
148
- if (tabs.length === 1) {
154
+ // if only 1 tab AND
155
+ // if total non-tearsheet tabs is 1; don't show any tabs
156
+ if (totalTabs.length === 1 && nonTearsheetTabs.length === 1) {
149
157
  return (
150
158
  <div key={"cat." + key} className="properties-category">
151
159
  {panelItems}
@@ -160,20 +168,31 @@ class EditorForm extends React.Component {
160
168
  panelArrow = <Icon type={CARBON_ICONS.CHEVRONARROWS.UP} className="properties-category-caret-up" />;
161
169
  categoryOpen = true;
162
170
  }
163
- tabContent.push(
164
- <div key={this._getContainerIndex(hasAlertsTab, i) + "-" + key} className="properties-category-container">
165
- <button type="button" onClick={this._showCategoryPanel.bind(this, tab.group)}
166
- className={classNames("properties-category-title", { "properties-light-enabled": this.props.controller.getLight() }) }
167
- >
168
- {tab.text}{this._getMessageCountForCategory(tab)}
169
- {panelArrow}
170
- </button>
171
- <div className={classNames("properties-category-content", { "show": categoryOpen }) }>
171
+ if (tab.content.itemType !== ItemType.TEARSHEET && nonTearsheetTabs.length === 1) {
172
+ tabContent.push(
173
+ <div key={"cat." + key} className="properties-category">
172
174
  {panelItems}
173
175
  {additionalComponent}
174
176
  </div>
175
- </div>
176
- );
177
+ );
178
+ } else {
179
+ tabContent.push(
180
+ <div key={this._getContainerIndex(hasAlertsTab, i) + "-" + key}
181
+ className={classNames("properties-category-container", { "properties-hidden-container": tab.content.itemType === ItemType.TEARSHEET })}
182
+ >
183
+ <button type="button" onClick={this._showCategoryPanel.bind(this, tab.group)}
184
+ className={classNames("properties-category-title", { "properties-light-enabled": this.props.controller.getLight() }) }
185
+ >
186
+ {tab.text}{this._getMessageCountForCategory(tab)}
187
+ {panelArrow}
188
+ </button>
189
+ <div className={classNames("properties-category-content", { "show": categoryOpen }) }>
190
+ {panelItems}
191
+ {additionalComponent}
192
+ </div>
193
+ </div>
194
+ );
195
+ }
177
196
  } else {
178
197
  if (this.props.activeTab === tab.group) {
179
198
  modalSelected = i;
@@ -183,6 +202,7 @@ class EditorForm extends React.Component {
183
202
  key={this._getContainerIndex(hasAlertsTab, i) + "-" + key}
184
203
  tabIndex={i}
185
204
  label={tab.text}
205
+ className={classNames({ "properties-hidden-container": tab.content.itemType === ItemType.TEARSHEET })}
186
206
  onClick={this._modalTabsOnClick.bind(this, tab.group)}
187
207
  >
188
208
  {panelItems}
@@ -434,15 +454,26 @@ class EditorForm extends React.Component {
434
454
  {content}
435
455
  </TwistyPanel>);
436
456
  case ("tearsheet"):
437
- if (this.props.controller.getActiveTearsheet() === panel.id) {
457
+ this.TEARSHEETS[panel.id] = {
458
+ panel: panel,
459
+ title: panel.label,
460
+ description: panel.description ? panel.description.text : null,
461
+ content: content
462
+ };
463
+ if (this.props.controller.getActiveTearsheet() !== null) {
464
+ this.visibleTearsheet = this.TEARSHEETS[this.props.controller.getActiveTearsheet()];
465
+ } else {
466
+ this.visibleTearsheet = null;
467
+ }
468
+ if (!this.FIRST_TEARSHEET_ID || this.FIRST_TEARSHEET_ID === panel.id) {
469
+ this.FIRST_TEARSHEET_ID = panel.id;
438
470
  return (
439
471
  <TearSheet
472
+ open={this.props.controller.getActiveTearsheet() !== null}
440
473
  key={panel.id}
441
474
  controller={this.props.controller}
442
- panel={panel}
443
- >
444
- {content}
445
- </TearSheet>
475
+ tearsheet={this.visibleTearsheet}
476
+ />
446
477
  );
447
478
  }
448
479
  return null;