]> source.dussan.org Git - vaadin-framework.git/commitdiff
Adjust column reorder drop marker when auto scrolling grid. (#16643)
authorPekka Hyvönen <pekka@vaadin.com>
Wed, 25 Feb 2015 07:22:06 +0000 (09:22 +0200)
committerPekka Hyvönen <pekka@vaadin.com>
Wed, 25 Feb 2015 13:12:26 +0000 (15:12 +0200)
Change-Id: I11377fb8b007c3c50c3e3bd1c29afcf8485431f0

client/src/com/vaadin/client/widget/grid/AutoScroller.java
client/src/com/vaadin/client/widgets/Escalator.java
client/src/com/vaadin/client/widgets/Grid.java

index 8f4e2036fc4704361575b829ec0d34e8565a96b0..60c9535ca78c5b4a527ca90cd0d167fa777803bd 100644 (file)
@@ -43,28 +43,34 @@ public class AutoScroller {
     /**
      * Callback that notifies when the cursor is on top of a new row or column
      * because of the automatic scrolling.
-     * 
-     * @since
      */
     public interface AutoScrollerCallback {
 
         /**
-         * Triggered when doing automatic horizontal scrolling.
+         * Triggered when doing automatic scrolling.
+         * <p>
+         * Because the auto scroller currently only supports scrolling in one
+         * axis, this method is used for both vertical and horizontal scrolling.
          * 
          * @param scrollDiff
          *            the amount of pixels that have been auto scrolled since
          *            last call
          */
-        void onHorizontalAutoScroll(int scrollDiff);
+        void onAutoScroll(int scrollDiff);
 
         /**
-         * Triggered when doing automatic vertical scrolling.
-         * 
-         * @param scrollDiff
-         *            the amount of pixels that have been auto scrolled since
-         *            last call
+         * Triggered when the grid scroll has reached the minimum scroll
+         * position. Depending on the scroll axis, either scrollLeft or
+         * scrollTop is 0.
          */
-        void onVerticalAutoScroll(int scrollDiff);
+        void onAutoScrollReachedMin();
+
+        /**
+         * Triggered when the grid scroll has reached the max scroll position.
+         * Depending on the scroll axis, either scrollLeft or scrollTop is at
+         * its maximum value.
+         */
+        void onAutoScrollReachedMax();
     }
 
     public enum ScrollAxis {
@@ -229,12 +235,30 @@ public class AutoScroller {
             pixelsToScroll -= intPixelsToScroll;
 
             if (intPixelsToScroll != 0) {
+                double scrollPos;
+                double maxScrollPos;
+                double newScrollPos;
                 if (scrollDirection == ScrollAxis.VERTICAL) {
-                    grid.setScrollTop(grid.getScrollTop() + intPixelsToScroll);
-                    callback.onVerticalAutoScroll(intPixelsToScroll);
+                    scrollPos = grid.getScrollTop();
+                    maxScrollPos = getMaxScrollTop();
                 } else {
-                    grid.setScrollLeft(grid.getScrollLeft() + intPixelsToScroll);
-                    callback.onHorizontalAutoScroll(intPixelsToScroll);
+                    scrollPos = grid.getScrollLeft();
+                    maxScrollPos = getMaxScrollLeft();
+                }
+                if (intPixelsToScroll > 0 && scrollPos < maxScrollPos
+                        || intPixelsToScroll < 0 && scrollPos > 0) {
+                    newScrollPos = scrollPos + intPixelsToScroll;
+                    if (scrollDirection == ScrollAxis.VERTICAL) {
+                        grid.setScrollTop(newScrollPos);
+                    } else {
+                        grid.setScrollLeft(newScrollPos);
+                    }
+                    callback.onAutoScroll(intPixelsToScroll);
+                    if (newScrollPos <= 0) {
+                        callback.onAutoScrollReachedMin();
+                    } else if (newScrollPos >= maxScrollPos) {
+                        callback.onAutoScrollReachedMax();
+                    }
                 }
             }
 
@@ -521,10 +545,7 @@ public class AutoScroller {
     private void updateScrollBounds() {
         double startBorder = getBodyClientStart();
         final int endBorder = getBodyClientEnd();
-
-        for (int i = 0; i < grid.getFrozenColumnCount(); i++) {
-            startBorder += grid.getColumn(i).getWidthActual();
-        }
+        startBorder += getFrozenColumnsWidth();
 
         final int scrollCompensation = getScrollCompensation();
         startingBound = scrollCompensation + startBorder + scrollAreaPX;
@@ -646,4 +667,22 @@ public class AutoScroller {
             return getClientLeft(getTbodyElement());
         }
     }
+
+    private double getFrozenColumnsWidth() {
+        double value = 0;
+        for (int i = 0; i < grid.getFrozenColumnCount(); i++) {
+            value += grid.getColumn(i).getWidthActual();
+        }
+        return value;
+    }
+
+    private double getMaxScrollLeft() {
+        return grid.getScrollWidth()
+                - (getTableElement().getParentElement().getOffsetWidth() - getFrozenColumnsWidth());
+    }
+
+    private double getMaxScrollTop() {
+        return grid.getScrollHeight() - getTfootElement().getOffsetHeight()
+                - getTheadElement().getOffsetHeight();
+    }
 }
index ca54b97ca5bc9da83ad03f9bf39c57d5d6916ea3..c9a1efde98b1932eb3d24dcd990053875982a05f 100644 (file)
@@ -4713,6 +4713,28 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker
         horizontalScrollbar.setScrollPos(scrollLeft);
     }
 
+    /**
+     * Returns the scroll width for the escalator. Note that this is not
+     * necessary the same as {@code Element.scrollWidth} in the DOM.
+     * 
+     * @since
+     * @return the scroll width in pixels
+     */
+    public double getScrollWidth() {
+        return horizontalScrollbar.getScrollSize();
+    }
+
+    /**
+     * Returns the scroll height for the escalator. Note that this is not
+     * necessary the same as {@code Element.scrollHeight} in the DOM.
+     * 
+     * @since
+     * @return the scroll height in pixels
+     */
+    public double getScrollHeight() {
+        return verticalScrollbar.getScrollSize();
+    }
+
     /**
      * Scrolls the body horizontally so that the column at the given index is
      * visible and there is at least {@code padding} pixels in the direction of
index 514cb6185c187b9b75534f72d790b51cc9b5e4e8..1d3f090a626b6c114adf794e1097bb11ce93fd11 100644 (file)
@@ -2875,13 +2875,23 @@ public class Grid<T> extends ResizeComposite implements
         private final AutoScrollerCallback autoScrollerCallback = new AutoScrollerCallback() {
 
             @Override
-            public void onVerticalAutoScroll(int scrollDiff) {
-                // NOP
+            public void onAutoScroll(int scrollDiff) {
+                autoScrollX = scrollDiff;
+                onDragUpdate(null);
             }
 
             @Override
-            public void onHorizontalAutoScroll(int scrollDiff) {
-                onDragUpdate(null);
+            public void onAutoScrollReachedMin() {
+                // make sure the drop marker is visible on the left
+                autoScrollX = 0;
+                updateDragDropMarker(clientX);
+            }
+
+            @Override
+            public void onAutoScrollReachedMax() {
+                // make sure the drop marker is visible on the right
+                autoScrollX = 0;
+                updateDragDropMarker(clientX);
             }
         };
         /**
@@ -2903,6 +2913,9 @@ public class Grid<T> extends ResizeComposite implements
 
         private int clientX;
 
+        /** How much the grid is being auto scrolled while dragging. */
+        private int autoScrollX;
+
         private void initHeaderDragElementDOM() {
             if (table == null) {
                 tableHeader = DOM.createTHead();
@@ -2925,6 +2938,7 @@ public class Grid<T> extends ResizeComposite implements
             if (event != null) {
                 clientX = WidgetUtil.getTouchOrMouseClientX(event
                         .getNativeEvent());
+                autoScrollX = 0;
             }
             resolveDragElementHorizontalPosition(clientX);
             updateDragDropMarker(clientX);
@@ -2946,6 +2960,7 @@ public class Grid<T> extends ResizeComposite implements
                     dropMarkerLeft += cellWidth;
                 }
             }
+            dropMarkerLeft += autoScrollX;
             if (dropMarkerLeft > header.getElement().getOffsetWidth()
                     || dropMarkerLeft < 0) {
                 dropMarkerLeft = -10000000;
@@ -3014,10 +3029,6 @@ public class Grid<T> extends ResizeComposite implements
                 final int focusedRowIndex = focusedCell.getRow();
                 final int draggedColumnIndex = eventCell.getColumnIndex();
                 // transfer focus if it was effected by the new column order
-                // FIXME if the dragged column is partly outside of the view
-                // port and the focused cell is +-1 of the dragged column, the
-                // grid scrolls to the right end. maybe fixed when the automatic
-                // scroll handling is implemented?
                 final RowContainer rowContainer = escalator
                         .findRowContainer(focusedCell.getElement());
                 if (focusedCellColumnIndex == draggedColumnIndex) {
@@ -3032,9 +3043,6 @@ public class Grid<T> extends ResizeComposite implements
                         && draggedColumnIndex < focusedCellColumnIndex) {
                     cellFocusHandler.setCellFocus(focusedRowIndex,
                             focusedCellColumnIndex - 1, rowContainer);
-                } else {
-                    cellFocusHandler.setCellFocus(focusedRowIndex,
-                            focusedCellColumnIndex, rowContainer);
                 }
             }
         }
@@ -5022,6 +5030,26 @@ public class Grid<T> extends ResizeComposite implements
         return escalator.getScrollLeft();
     }
 
+    /**
+     * Returns the height of the scrollable area in pixels.
+     * 
+     * @since
+     * @return the height of the scrollable area in pixels
+     */
+    public double getScrollHeight() {
+        return escalator.getScrollHeight();
+    }
+
+    /**
+     * Returns the width of the scrollable area in pixels.
+     * 
+     * @since
+     * @return the width of the scrollable area in pixels.
+     */
+    public double getScrollWidth() {
+        return escalator.getScrollWidth();
+    }
+
     private static final Logger getLogger() {
         return Logger.getLogger(Grid.class.getName());
     }