You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by mc...@apache.org on 2019/04/12 19:27:42 UTC

[nifi] branch master updated: NIFI-4230 - Use a better default location when pasting via keystokes and the original copied item is not fully in view. - handle multi-select copy/paste better. - remove dimension info from getOrigin function - handle pasting better when pasted items should be centered and not offset from the original. - fixed strict mode and removed console.logs - Fixing pasting logic when trying to center the items on the canvas.

This is an automated email from the ASF dual-hosted git repository.

mcgilman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nifi.git


The following commit(s) were added to refs/heads/master by this push:
     new b5ff622  NIFI-4230 - Use a better default location when pasting via keystokes and the original copied item is not fully in view. - handle multi-select copy/paste better. - remove dimension info from getOrigin function - handle pasting better when pasted items should be centered and not offset from the original. - fixed strict mode and removed console.logs - Fixing pasting logic when trying to center the items on the canvas.
b5ff622 is described below

commit b5ff62211808afbb427ece220e55ddfba048cf8a
Author: Rob Fellows <ro...@gmail.com>
AuthorDate: Thu Mar 21 09:24:14 2019 -0400

    NIFI-4230 - Use a better default location when pasting via keystokes and the original copied item is not fully in view.
    - handle multi-select copy/paste better.
    - remove dimension info from getOrigin function
    - handle pasting better when pasted items should be centered and not offset from the original.
    - fixed strict mode and removed console.logs
    - Fixing pasting logic when trying to center the items on the canvas.
    
    This closes #3383
---
 .../src/main/webapp/js/nf/canvas/nf-actions.js     |  26 ++++-
 .../main/webapp/js/nf/canvas/nf-canvas-utils.js    | 124 ++++++++++++++++++++-
 2 files changed, 144 insertions(+), 6 deletions(-)

diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
index bf32d5b..cb33ccc 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-actions.js
@@ -1722,12 +1722,14 @@
 
             // determine the origin of the bounding box of the selection
             var origin = nfCanvasUtils.getOrigin(selection);
+            var selectionDimensions = nfCanvasUtils.getSelectionBoundingClientRect(selection);
 
             // copy the snippet details
             var parentGroupId = nfCanvasUtils.getGroupId();
             nfClipboard.copy({
                 snippet: nfSnippet.marshal(selection, parentGroupId),
-                origin: origin
+                origin: origin,
+                dimensions: selectionDimensions
             });
         },
 
@@ -1771,12 +1773,28 @@
                         // determine the origin of the bounding box of the copy
                         var origin = pasteLocation;
                         var snippetOrigin = data['origin'];
+                        var dimensions = data['dimensions'];
 
                         // determine the appropriate origin
                         if (!nfCommon.isDefinedAndNotNull(origin)) {
-                            snippetOrigin.x += 25;
-                            snippetOrigin.y += 25;
-                            origin = snippetOrigin;
+                            // if the copied item(s) are from a different group or the origin item is not in the viewport, center the pasted item(s)
+                            if (nfCanvasUtils.getGroupId() !== data['snippet'].parentGroupId || !nfCanvasUtils.isBoundingBoxInViewport(dimensions, false)) {
+                                var scale = nfCanvasUtils.getCanvasScale();
+
+                                // put it in the center of the screen
+                                var center = nfCanvasUtils.getCenterForBoundingBox(dimensions);
+                                var translate = nfCanvasUtils.getCanvasTranslate();
+                                origin = {
+                                    x: center[0] - (translate[0] / scale),
+                                    y: center[1] - (translate[1] / scale)
+                                };
+
+                            } else {
+                                // paste it just offset from the original
+                                snippetOrigin.x += 25;
+                                snippetOrigin.y += 25;
+                                origin = snippetOrigin;
+                            }
                         }
 
                         // copy the snippet to the new location
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js
index b41cbfb..6d908d8 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-canvas-utils.js
@@ -575,11 +575,12 @@
         },
 
         /**
-         * Centers the specified bounding box.
+         * Gets the coordinates neccessary to center a bounding box on the screen.
          *
          * @param {type} boundingBox
+         * @returns {number[]}
          */
-        centerBoundingBox: function (boundingBox) {
+        getCenterForBoundingBox: function (boundingBox) {
             var scale = nfCanvas.View.getScale();
             if (nfCommon.isDefinedAndNotNull(boundingBox.scale)) {
                 scale = boundingBox.scale;
@@ -592,6 +593,56 @@
 
             // determine the center location for this component in canvas space
             var center = [(screenWidth / 2) - (boundingBox.width / 2), (screenHeight / 2) - (boundingBox.height / 2)];
+            return center;
+        },
+
+        /**
+         * Determines if a bounding box is fully in the current viewable canvas area.
+         *
+         * @param {type} boundingBox       Bounding box to check.
+         * @param {boolean} strict         If true, the entire bounding box must be in the viewport.
+         *                                 If false, only part of the bounding box must be in the viewport.
+         * @returns {boolean}
+         */
+        isBoundingBoxInViewport: function (boundingBox, strict) {
+            var scale = nfCanvas.View.getScale();
+            var translate = nfCanvas.View.getTranslate();
+            var offset = nfCanvas.CANVAS_OFFSET;
+
+            // get the canvas normalized width and height
+            var canvasContainer = $('#canvas-container');
+            var screenWidth = Math.floor(canvasContainer.width() / scale);
+            var screenHeight = Math.floor(canvasContainer.height() / scale);
+            var screenLeft = Math.ceil(-translate[0] / scale);
+            var screenTop = Math.ceil(-translate[1] / scale);
+            var screenRight = screenLeft + screenWidth;
+            var screenBottom = screenTop + screenHeight;
+
+            var left = Math.ceil(boundingBox.x);
+            var right = Math.floor(boundingBox.x + boundingBox.width);
+            var top = Math.ceil(boundingBox.y - (offset) / scale);
+            var bottom = Math.floor(boundingBox.y - (offset / scale) + boundingBox.height);
+
+            if (strict) {
+                return !(left < screenLeft || right > screenRight || top < screenTop || bottom > screenBottom);
+            } else {
+                return ((left > screenLeft && left < screenRight) || (right < screenRight && right > screenLeft)) &&
+                    ((top > screenTop && top < screenBottom) || (bottom < screenBottom && bottom > screenTop));
+            }
+        },
+
+        /**
+         * Centers the specified bounding box.
+         *
+         * @param {type} boundingBox
+         */
+        centerBoundingBox: function (boundingBox) {
+            var scale = nfCanvas.View.getScale();
+            if (nfCommon.isDefinedAndNotNull(boundingBox.scale)) {
+                scale = boundingBox.scale;
+            }
+
+            var center = nfCanvasUtils.getCenterForBoundingBox(boundingBox);
 
             // calculate the difference between the center point and the position of this component and convert to screen space
             nfCanvas.View.transform([(center[0] - boundingBox.x) * scale, (center[1] - boundingBox.y) * scale], scale);
@@ -1764,6 +1815,75 @@
         },
 
         /**
+         * Get a BoundingClientRect, normalized to the canvas, that encompasses all nodes in a given selection.
+         *
+         * @param selection
+         * @returns {*} BoundingClientRect
+         */
+        getSelectionBoundingClientRect: function (selection) {
+            var scale = nfCanvas.View.getScale();
+            var translate = nfCanvas.View.getTranslate();
+
+            var initialBBox = {
+                x: Number.MAX_VALUE,
+                y: Number.MAX_VALUE,
+                right: Number.MIN_VALUE,
+                bottom: Number.MIN_VALUE,
+                translate: nfCanvas.View.getTranslate()
+            };
+
+            var bbox = selection.nodes().reduce(function (aggregateBBox, node) {
+                var rect = node.getBoundingClientRect();
+                aggregateBBox.x = Math.min(rect.x, aggregateBBox.x);
+                aggregateBBox.y = Math.min(rect.y, aggregateBBox.y);
+                aggregateBBox.right = Math.max(rect.right, aggregateBBox.right);
+                aggregateBBox.bottom = Math.max(rect.bottom, aggregateBBox.bottom);
+
+                return aggregateBBox;
+            }, initialBBox);
+
+            // normalize the bounding box with scale and translate
+            bbox.x = (bbox.x - translate[0]) / scale;
+            bbox.y = (bbox.y - translate[1]) / scale;
+            bbox.right = (bbox.right - translate[0]) / scale;
+            bbox.bottom = (bbox.bottom - translate[1]) / scale;
+
+            bbox.width = bbox.right - bbox.x;
+            bbox.height = bbox.bottom - bbox.y;
+            bbox.top = bbox.y;
+            bbox.left = bbox.x;
+
+            return bbox;
+        },
+
+        /**
+         * Applies a translation to BoundingClientRect.
+         *
+         * @param boundingClientRect
+         * @param translate
+         * @returns {{top: number, left: number, bottom: number, x: number, width: number, y: number, right: number, height: number}}
+         */
+        translateBoundingClientRect: function (boundingClientRect, translate) {
+            if (nfCommon.isUndefinedOrNull(translate)) {
+                if (nfCommon.isDefinedAndNotNull(boundingClientRect.translate)) {
+                    translate = boundingClientRect.translate;
+                } else {
+                    translate = nfCanvas.View.getTranslate();
+                }
+            }
+            return {
+                x: boundingClientRect.x - translate[0],
+                y: boundingClientRect.y - translate[1],
+                left: boundingClientRect.left - translate[0],
+                right: boundingClientRect.right - translate[0],
+                top: boundingClientRect.top - translate[1],
+                bottom: boundingClientRect.bottom - translate[1],
+                width: boundingClientRect.width,
+                height: boundingClientRect.height
+            }
+        },
+
+        /**
          * Moves the specified components into the current parent group.
          *
          * @param {selection} components