]> source.dussan.org Git - vaadin-framework.git/commitdiff
Implement programmatic scrolling (#13327)
authorPatrik Lindström <patrik@vaadin.com>
Tue, 11 Feb 2014 13:36:24 +0000 (15:36 +0200)
committerHenrik Paul <henrik@vaadin.com>
Tue, 18 Feb 2014 15:47:40 +0000 (15:47 +0000)
Further changes required for this, included in the same patch:
- created GridClientRpc interface
- created test case UI for server-side controlled Grid programmatic
scrolling
- refactored getScrollPos logic into Escalator and moved
ScrollDestination enum to shared package

Change-Id: Ibf72a4f75831807d83fb5941597a6ce3fda08e17

client/src/com/vaadin/client/ui/grid/Escalator.java
client/src/com/vaadin/client/ui/grid/Grid.java
client/src/com/vaadin/client/ui/grid/GridConnector.java
client/src/com/vaadin/client/ui/grid/ScrollDestination.java [deleted file]
client/src/com/vaadin/shared/ui/grid/ScrollDestination.java [new file with mode: 0644]
server/src/com/vaadin/ui/components/grid/Grid.java
shared/src/com/vaadin/shared/ui/grid/GridClientRpc.java [new file with mode: 0644]
shared/src/com/vaadin/shared/ui/grid/GridConstants.java [new file with mode: 0644]
uitest/src/com/vaadin/tests/components/grid/GridScrolling.java [new file with mode: 0644]
uitest/src/com/vaadin/tests/widgetset/client/grid/TestGridConnector.java
uitest/src/com/vaadin/tests/widgetset/client/grid/VTestGrid.java

index a1d895c2ddfa346cc902a8f1bba52b9981efe938..77a8c2dbd9d6e8d6343eab203bb9a78ef302c762 100644 (file)
@@ -52,6 +52,7 @@ import com.vaadin.client.ui.grid.PositionFunction.WebkitTranslate3DPosition;
 import com.vaadin.client.ui.grid.ScrollbarBundle.HorizontalScrollbarBundle;
 import com.vaadin.client.ui.grid.ScrollbarBundle.VerticalScrollbarBundle;
 import com.vaadin.shared.ui.grid.Range;
+import com.vaadin.shared.ui.grid.ScrollDestination;
 import com.vaadin.shared.util.SharedUtil;
 
 /*-
@@ -548,6 +549,80 @@ public class Escalator extends Widget {
 
     private static final int ROW_HEIGHT_PX = 20;
 
+    /**
+     * ScrollDestination case-specific handling logic.
+     */
+    private static double getScrollPos(final ScrollDestination destination,
+            final double targetStartPx, final double targetEndPx,
+            final double viewportStartPx, final double viewportEndPx,
+            final int padding) {
+
+        final double viewportLength = viewportEndPx - viewportStartPx;
+
+        switch (destination) {
+
+        /*
+         * Scroll as little as possible to show the target element. If the
+         * element fits into view, this works as START or END depending on the
+         * current scroll position. If the element does not fit into view, this
+         * works as START.
+         */
+        case ANY: {
+            final double startScrollPos = targetStartPx - padding;
+            final double endScrollPos = targetEndPx + padding - viewportLength;
+
+            if (startScrollPos < viewportStartPx) {
+                return startScrollPos;
+            } else if (targetEndPx + padding > viewportEndPx) {
+                return endScrollPos;
+            } else {
+                // NOOP, it's already visible
+                return viewportStartPx;
+            }
+        }
+
+        /*
+         * Scrolls so that the element is shown at the end of the viewport. The
+         * viewport will, however, not scroll before its first element.
+         */
+        case END: {
+            return targetEndPx + padding - viewportLength;
+        }
+
+        /*
+         * Scrolls so that the element is shown in the middle of the viewport.
+         * The viewport will, however, not scroll beyond its contents, given
+         * more elements than what the viewport is able to show at once. Under
+         * no circumstances will the viewport scroll before its first element.
+         */
+        case MIDDLE: {
+            final double targetMiddle = targetStartPx
+                    + (targetEndPx - targetStartPx) / 2;
+            return targetMiddle - viewportLength / 2;
+        }
+
+        /*
+         * Scrolls so that the element is shown at the start of the viewport.
+         * The viewport will, however, not scroll beyond its contents.
+         */
+        case START: {
+            return targetStartPx - padding;
+        }
+
+        /*
+         * Throw an error if we're here. This can only mean that
+         * ScrollDestination has been carelessly amended..
+         */
+        default: {
+            throw new IllegalArgumentException(
+                    "Internal: ScrollDestination has been modified, "
+                            + "but Escalator.getScrollPos has not been updated "
+                            + "to match new values.");
+        }
+        }
+
+    }
+
     /** An inner class that handles all logic related to scrolling. */
     private class Scroller extends JsniWorkaround {
         private double lastScrollTop = 0;
@@ -900,7 +975,7 @@ public class Escalator extends Widget {
                 viewportEndPx -= Util.getNativeScrollbarSize();
             }
 
-            final double scrollLeft = destination.getScrollPos(targetStartPx,
+            final double scrollLeft = getScrollPos(destination, targetStartPx,
                     targetEndPx, viewportStartPx, viewportEndPx, padding);
 
             /*
@@ -921,7 +996,7 @@ public class Escalator extends Widget {
             final double viewportEndPx = viewportStartPx
                     + body.calculateHeight();
 
-            final double scrollTop = destination.getScrollPos(targetStartPx,
+            final double scrollTop = getScrollPos(destination, targetStartPx,
                     targetEndPx, viewportStartPx, viewportEndPx, padding);
 
             /*
@@ -3305,33 +3380,6 @@ public class Escalator extends Widget {
         horizontalScrollbar.setScrollPos(scrollLeft);
     }
 
-    /**
-     * Scrolls the body horizontally so that the column at the given index is
-     * visible.
-     * 
-     * @param columnIndex
-     *            the index of the column to scroll to
-     * @param destination
-     *            where the column should be aligned visually after scrolling
-     * @throws IndexOutOfBoundsException
-     *             if {@code columnIndex} is not a valid index for an existing
-     *             column
-     * @throws IllegalArgumentException
-     *             if the column is frozen
-     */
-    public void scrollToColumn(final int columnIndex,
-            final ScrollDestination destination)
-            throws IndexOutOfBoundsException, IllegalArgumentException {
-        verifyValidColumnIndex(columnIndex);
-
-        if (columnIndex < columnConfiguration.frozenColumns) {
-            throw new IllegalArgumentException("The given column index "
-                    + columnIndex + " is frozen.");
-        }
-
-        scroller.scrollToColumn(columnIndex, destination, 0);
-    }
-
     /**
      * Scrolls the body horizontally so that the column at the given index is
      * visible and there is at least {@code padding} pixels to the given scroll
@@ -3348,14 +3396,15 @@ public class Escalator extends Widget {
      *             if {@code columnIndex} is not a valid index for an existing
      *             column
      * @throws IllegalArgumentException
-     *             if {@code destination} is {@link ScrollDestination#MIDDLE},
-     *             because having a padding on a centered column is undefined
-     *             behavior or if the column is frozen
+     *             if {@code destination} is {@link ScrollDestination#MIDDLE}
+     *             and padding is nonzero, because having a padding on a
+     *             centered column is undefined behavior, or if the column is
+     *             frozen
      */
     public void scrollToColumn(final int columnIndex,
             final ScrollDestination destination, final int padding)
             throws IndexOutOfBoundsException, IllegalArgumentException {
-        if (destination == ScrollDestination.MIDDLE) {
+        if (destination == ScrollDestination.MIDDLE && padding != 0) {
             throw new IllegalArgumentException(
                     "You cannot have a padding with a MIDDLE destination");
         }
@@ -3378,26 +3427,6 @@ public class Escalator extends Widget {
         }
     }
 
-    /**
-     * Scrolls the body vertically so that the row at the given index is
-     * visible.
-     * 
-     * @param rowIndex
-     *            the index of the row to scroll to
-     * @param destination
-     *            where the row should be aligned visually after scrolling
-     * @throws IndexOutOfBoundsException
-     *             if {@code rowIndex} is not a valid index for an existing
-     *             logical row
-     */
-    public void scrollToRow(final int rowIndex,
-            final ScrollDestination destination)
-            throws IndexOutOfBoundsException {
-        verifyValidRowIndex(rowIndex);
-
-        scroller.scrollToRow(rowIndex, destination, 0);
-    }
-
     /**
      * Scrolls the body vertically so that the row at the given index is visible
      * and there is at least {@literal padding} pixels to the given scroll
@@ -3413,14 +3442,14 @@ public class Escalator extends Widget {
      * @throws IndexOutOfBoundsException
      *             if {@code rowIndex} is not a valid index for an existing row
      * @throws IllegalArgumentException
-     *             if {@code destination} is {@link ScrollDestination#MIDDLE},
-     *             because having a padding on a centered row is undefined
-     *             behavior
+     *             if {@code destination} is {@link ScrollDestination#MIDDLE}
+     *             and padding is nonzero, because having a padding on a
+     *             centered row is undefined behavior
      */
     public void scrollToRow(final int rowIndex,
             final ScrollDestination destination, final int padding)
             throws IndexOutOfBoundsException, IllegalArgumentException {
-        if (destination == ScrollDestination.MIDDLE) {
+        if (destination == ScrollDestination.MIDDLE && padding != 0) {
             throw new IllegalArgumentException(
                     "You cannot have a padding with a MIDDLE destination");
         }
index 015028765bb368a8f64fd5a67d0c63e3615cf3b3..02aa194655176c127f4183d991d904fd5f087f44 100644 (file)
@@ -18,6 +18,7 @@ package com.vaadin.client.ui.grid;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.logging.Logger;
 
 import com.google.gwt.core.shared.GWT;
 import com.google.gwt.dom.client.Element;
@@ -28,6 +29,8 @@ import com.google.gwt.user.client.ui.Widget;
 import com.vaadin.client.data.DataChangeHandler;
 import com.vaadin.client.data.DataSource;
 import com.vaadin.client.ui.grid.renderers.TextRenderer;
+import com.vaadin.shared.ui.grid.GridConstants;
+import com.vaadin.shared.ui.grid.ScrollDestination;
 import com.vaadin.shared.util.SharedUtil;
 
 /**
@@ -1225,4 +1228,91 @@ public class Grid<T> extends Composite {
          */
         return escalator.addRowVisibilityChangeHandler(handler);
     }
+
+    /**
+     * Scrolls to a certain row, using {@link ScrollDestination#ANY}.
+     * 
+     * @param rowIndex
+     *            zero-based index of the row to scroll to.
+     * @throws IllegalArgumentException
+     *             if rowIndex is below zero, or above the maximum value
+     *             supported by the data source.
+     */
+    public void scrollToRow(int rowIndex) throws IllegalArgumentException {
+        scrollToRow(rowIndex, ScrollDestination.ANY,
+                GridConstants.DEFAULT_PADDING);
+    }
+
+    /**
+     * Scrolls to a certain row, using user-specified scroll destination.
+     * 
+     * @param rowIndex
+     *            zero-based index of the row to scroll to.
+     * @param destination
+     *            desired destination placement of scrolled-to-row. See
+     *            {@link ScrollDestination} for more information.
+     * @throws IllegalArgumentException
+     *             if rowIndex is below zero, or above the maximum value
+     *             supported by the data source.
+     */
+    public void scrollToRow(int rowIndex, ScrollDestination destination)
+            throws IllegalArgumentException {
+        scrollToRow(rowIndex, destination,
+                destination == ScrollDestination.MIDDLE ? 0
+                        : GridConstants.DEFAULT_PADDING);
+    }
+
+    /**
+     * Scrolls to a certain row using only user-specified parameters.
+     * 
+     * @param rowIndex
+     *            zero-based index of the row to scroll to.
+     * @param destination
+     *            desired destination placement of scrolled-to-row. See
+     *            {@link ScrollDestination} for more information.
+     * @param paddingPx
+     *            number of pixels to overscroll. Behavior depends on
+     *            destination.
+     * @throws IllegalArgumentException
+     *             if {@code destination} is {@link ScrollDestination#MIDDLE}
+     *             and padding is nonzero, because having a padding on a
+     *             centered row is undefined behavior, or if rowIndex is below
+     *             zero or above the row count of the data source.
+     */
+    private void scrollToRow(int rowIndex, ScrollDestination destination,
+            int paddingPx) throws IllegalArgumentException {
+        int maxsize = escalator.getBody().getRowCount() - 1;
+
+        if (rowIndex < 0) {
+            throw new IllegalArgumentException("Row index (" + rowIndex
+                    + ") is below zero!");
+        }
+
+        if (rowIndex > maxsize) {
+            throw new IllegalArgumentException("Row index (" + rowIndex
+                    + ") is above maximum (" + maxsize + ")!");
+        }
+
+        escalator.scrollToRow(rowIndex, destination, paddingPx);
+    }
+
+    /**
+     * Scrolls to the beginning of the very first row.
+     */
+    public void scrollToStart() {
+        scrollToRow(0, ScrollDestination.START);
+    }
+
+    /**
+     * Scrolls to the end of the very last row.
+     */
+    public void scrollToEnd() {
+        scrollToRow(escalator.getBody().getRowCount() - 1,
+                ScrollDestination.END);
+    }
+
+    private static final Logger getLogger() {
+        return Logger.getLogger(Grid.class.getName());
+    }
+
 }
index f04326c7e63265de3acfbac12de987596639eaa4..5e0664667d0813159037ce72173ce09d6635eeab 100644 (file)
@@ -29,9 +29,11 @@ import com.vaadin.client.ui.AbstractComponentConnector;
 import com.vaadin.shared.ui.Connect;
 import com.vaadin.shared.ui.grid.ColumnGroupRowState;
 import com.vaadin.shared.ui.grid.ColumnGroupState;
+import com.vaadin.shared.ui.grid.GridClientRpc;
 import com.vaadin.shared.ui.grid.GridColumnState;
 import com.vaadin.shared.ui.grid.GridServerRpc;
 import com.vaadin.shared.ui.grid.GridState;
+import com.vaadin.shared.ui.grid.ScrollDestination;
 
 /**
  * Connects the client side {@link Grid} widget with the server side
@@ -96,6 +98,23 @@ public class GridConnector extends AbstractComponentConnector {
                                 event.getVisibleRowCount());
                     }
                 });
+
+        registerRpc(GridClientRpc.class, new GridClientRpc() {
+            @Override
+            public void scrollToStart() {
+                getWidget().scrollToStart();
+            }
+
+            @Override
+            public void scrollToEnd() {
+                getWidget().scrollToEnd();
+            }
+
+            @Override
+            public void scrollToRow(int row, ScrollDestination destination) {
+                getWidget().scrollToRow(row, destination);
+            }
+        });
     }
 
     @Override
diff --git a/client/src/com/vaadin/client/ui/grid/ScrollDestination.java b/client/src/com/vaadin/client/ui/grid/ScrollDestination.java
deleted file mode 100644 (file)
index e14f50f..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2000-2013 Vaadin Ltd.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.vaadin.client.ui.grid;
-
-/**
- * The destinations that are supported in an Escalator when scrolling rows or
- * columns into view.
- * 
- * @since 7.2
- * @author Vaadin Ltd
- */
-public enum ScrollDestination {
-
-    /**
-     * Scroll as little as possible to show the target element. If the element
-     * fits into view, this works as START or END depending on the current
-     * scroll position. If the element does not fit into view, this works as
-     * START.
-     */
-    ANY {
-        @Override
-        double getScrollPos(final double targetStartPx,
-                final double targetEndPx, final double viewportStartPx,
-                final double viewportEndPx, final int padding) {
-
-            final double startScrollPos = targetStartPx - padding;
-            final double viewportLength = viewportEndPx - viewportStartPx;
-            final double endScrollPos = targetEndPx + padding - viewportLength;
-
-            if (startScrollPos < viewportStartPx) {
-                return startScrollPos;
-            } else if (targetEndPx + padding > viewportEndPx) {
-                return endScrollPos;
-            } else {
-                // NOOP, it's already visible
-                return viewportStartPx;
-            }
-        }
-    },
-
-    /**
-     * Scrolls so that the element is shown at the start of the viewport. The
-     * viewport will, however, not scroll beyond its contents.
-     */
-    START {
-        @Override
-        double getScrollPos(final double targetStartPx,
-                final double targetEndPx, final double viewportStartPx,
-                final double viewportEndPx, final int padding) {
-            return targetStartPx - padding;
-        }
-    },
-
-    /**
-     * Scrolls so that the element is shown in the middle of the viewport. The
-     * viewport will, however, not scroll beyond its contents, given more
-     * elements than what the viewport is able to show at once. Under no
-     * circumstances will the viewport scroll before its first element.
-     */
-    MIDDLE {
-        @Override
-        double getScrollPos(final double targetStartPx,
-                final double targetEndPx, final double viewportStartPx,
-                final double viewportEndPx, final int padding) {
-            final double targetMiddle = targetStartPx
-                    + (targetEndPx - targetStartPx) / 2;
-            final double viewportLength = viewportEndPx - viewportStartPx;
-            return targetMiddle - viewportLength / 2;
-        }
-    },
-
-    /**
-     * Scrolls so that the element is shown at the end of the viewport. The
-     * viewport will, however, not scroll before its first element.
-     */
-    END {
-        @Override
-        double getScrollPos(final double targetStartPx,
-                final double targetEndPx, final double viewportStartPx,
-                final double viewportEndPx, final int padding) {
-            final double viewportLength = viewportEndPx - viewportStartPx;
-            return targetEndPx + padding - viewportLength;
-        }
-    };
-
-    abstract double getScrollPos(final double targetStartPx,
-            final double targetEndPx, final double viewportStartPx,
-            final double viewportEndPx, final int padding);
-}
diff --git a/client/src/com/vaadin/shared/ui/grid/ScrollDestination.java b/client/src/com/vaadin/shared/ui/grid/ScrollDestination.java
new file mode 100644 (file)
index 0000000..decc2fa
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.shared.ui.grid;
+
+/**
+ * Enumeration, specifying the destinations that are supported when scrolling
+ * rows or columns into view.
+ * 
+ * @since 7.2
+ * @author Vaadin Ltd
+ */
+public enum ScrollDestination {
+
+    /**
+     * Scroll as little as possible to show the target element. If the element
+     * fits into view, this works as START or END depending on the current
+     * scroll position. If the element does not fit into view, this works as
+     * START.
+     */
+    ANY,
+
+    /**
+     * Scrolls so that the element is shown at the start of the viewport. The
+     * viewport will, however, not scroll beyond its contents.
+     */
+    START,
+
+    /**
+     * Scrolls so that the element is shown in the middle of the viewport. The
+     * viewport will, however, not scroll beyond its contents, given more
+     * elements than what the viewport is able to show at once. Under no
+     * circumstances will the viewport scroll before its first element.
+     */
+    MIDDLE,
+
+    /**
+     * Scrolls so that the element is shown at the end of the viewport. The
+     * viewport will, however, not scroll before its first element.
+     */
+    END
+
+}
index 08685874c148c11c82e5847b8299e1eec4e0aec9..4126ec6d93f16922bc1b0d706806cf67834df4a9 100644 (file)
@@ -42,10 +42,12 @@ import com.vaadin.data.Property.ValueChangeNotifier;
 import com.vaadin.data.RpcDataProviderExtension;
 import com.vaadin.server.KeyMapper;
 import com.vaadin.shared.ui.grid.ColumnGroupRowState;
+import com.vaadin.shared.ui.grid.GridClientRpc;
 import com.vaadin.shared.ui.grid.GridColumnState;
 import com.vaadin.shared.ui.grid.GridServerRpc;
 import com.vaadin.shared.ui.grid.GridState;
 import com.vaadin.shared.ui.grid.Range;
+import com.vaadin.shared.ui.grid.ScrollDestination;
 import com.vaadin.ui.AbstractComponent;
 import com.vaadin.ui.Component;
 
@@ -804,4 +806,56 @@ public class Grid extends AbstractComponent {
     public Object getLastFrozenPropertyId() {
         return columnKeys.get(getState().lastFrozenColumnId);
     }
+
+    /**
+     * Scrolls to a certain item, using {@link ScrollDestination#ANY}.
+     * 
+     * @param itemId
+     *            id of item to scroll to.
+     * @throws IllegalArgumentException
+     *             if the provided id is not recognized by the data source.
+     */
+    public void scrollToItem(Object itemId) throws IllegalArgumentException {
+        scrollToItem(itemId, ScrollDestination.ANY);
+    }
+
+    /**
+     * Scrolls to a certain item, using user-specified scroll destination.
+     * 
+     * @param itemId
+     *            id of item to scroll to.
+     * @param destination
+     *            value specifying desired position of scrolled-to row.
+     * @throws IllegalArgumentException
+     *             if the provided id is not recognized by the data source.
+     */
+    public void scrollToItem(Object itemId, ScrollDestination destination)
+            throws IllegalArgumentException {
+
+        int row = datasource.indexOfId(itemId);
+
+        if (row == -1) {
+            throw new IllegalArgumentException(
+                    "Item with specified ID does not exist in data source");
+        }
+
+        GridClientRpc clientRPC = getRpcProxy(GridClientRpc.class);
+        clientRPC.scrollToRow(row, destination);
+    }
+
+    /**
+     * Scrolls to the beginning of the first data row.
+     */
+    public void scrollToStart() {
+        GridClientRpc clientRPC = getRpcProxy(GridClientRpc.class);
+        clientRPC.scrollToStart();
+    }
+
+    /**
+     * Scrolls to the end of the last data row.
+     */
+    public void scrollToEnd() {
+        GridClientRpc clientRPC = getRpcProxy(GridClientRpc.class);
+        clientRPC.scrollToEnd();
+    }
 }
diff --git a/shared/src/com/vaadin/shared/ui/grid/GridClientRpc.java b/shared/src/com/vaadin/shared/ui/grid/GridClientRpc.java
new file mode 100644 (file)
index 0000000..00cc93d
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.shared.ui.grid;
+
+import com.vaadin.shared.communication.ClientRpc;
+
+/**
+ * Server-to-client RPC interface for the Grid component.
+ * 
+ * @since 7.2
+ * @author Vaadin Ltd
+ */
+public interface GridClientRpc extends ClientRpc {
+
+    /**
+     * Command client Grid to scroll to a specific data row.
+     * 
+     * @param row
+     *            zero-based row index. If the row index is below zero or above
+     *            the row count of the client-side data source, a client-side
+     *            exception will be triggered. Since this exception has no
+     *            handling by default, an out-of-bounds value will cause a
+     *            client-side crash.
+     * @param destination
+     *            desired placement of scrolled-to row. See the documentation
+     *            for {@link ScrollDestination} for more information.
+     */
+    public void scrollToRow(int row, ScrollDestination destination);
+
+    /**
+     * Command client Grid to scroll to the first row.
+     */
+    public void scrollToStart();
+
+    /**
+     * Command client Grid to scroll to the last row.
+     */
+    public void scrollToEnd();
+
+}
diff --git a/shared/src/com/vaadin/shared/ui/grid/GridConstants.java b/shared/src/com/vaadin/shared/ui/grid/GridConstants.java
new file mode 100644 (file)
index 0000000..5b88fad
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.shared.ui.grid;
+
+/**
+ * Container class for common constants and default values used by the Grid
+ * component.
+ * 
+ * @since 7.2
+ * @author Vaadin Ltd
+ */
+public final class GridConstants {
+
+    /**
+     * Default padding in pixels when scrolling programmatically, without an
+     * explicitly defined padding value.
+     */
+    public static final int DEFAULT_PADDING = 0;
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridScrolling.java b/uitest/src/com/vaadin/tests/components/grid/GridScrolling.java
new file mode 100644 (file)
index 0000000..d514fbd
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.data.Item;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.shared.ui.grid.ScrollDestination;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.components.grid.Grid;
+
+/**
+ * 
+ */
+@SuppressWarnings("serial")
+public class GridScrolling extends AbstractTestUI {
+
+    private Grid grid;
+
+    private IndexedContainer ds;
+
+    @Override
+    @SuppressWarnings("unchecked")
+    protected void setup(VaadinRequest request) {
+        // Build data source
+        ds = new IndexedContainer();
+
+        for (int col = 0; col < 5; col++) {
+            ds.addContainerProperty("col" + col, String.class, "");
+        }
+
+        for (int row = 0; row < 65536; row++) {
+            Item item = ds.addItem(Integer.valueOf(row));
+            for (int col = 0; col < 5; col++) {
+                item.getItemProperty("col" + col).setValue(
+                        "(" + row + ", " + col + ")");
+            }
+        }
+
+        grid = new Grid(ds);
+
+        HorizontalLayout hl = new HorizontalLayout();
+        hl.addComponent(grid);
+        hl.setMargin(true);
+        hl.setSpacing(true);
+
+        VerticalLayout vl = new VerticalLayout();
+        vl.setSpacing(true);
+
+        // Add scroll buttons
+        Button scrollUpButton = new Button("Top", new ClickListener() {
+            @Override
+            public void buttonClick(ClickEvent event) {
+                grid.scrollToStart();
+            }
+        });
+        scrollUpButton.setSizeFull();
+        vl.addComponent(scrollUpButton);
+
+        for (int i = 1; i < 7; ++i) {
+            final int row = (ds.size() / 7) * i;
+            Button scrollButton = new Button("Scroll to row " + row,
+                    new ClickListener() {
+                        @Override
+                        public void buttonClick(ClickEvent event) {
+                            grid.scrollToItem(Integer.valueOf(row),
+                                    ScrollDestination.MIDDLE);
+                        }
+                    });
+            scrollButton.setSizeFull();
+            vl.addComponent(scrollButton);
+        }
+
+        Button scrollDownButton = new Button("Bottom", new ClickListener() {
+            @Override
+            public void buttonClick(ClickEvent event) {
+                grid.scrollToEnd();
+            }
+        });
+        scrollDownButton.setSizeFull();
+        vl.addComponent(scrollDownButton);
+
+        hl.addComponent(vl);
+        addComponent(hl);
+    }
+
+    @Override
+    protected String getTestDescription() {
+        return "Test Grid programmatic scrolling features";
+    }
+
+    @Override
+    protected Integer getTicketNumber() {
+        return 13327;
+    }
+
+}
index f9286091c00888bcf1e04a73867dd59bc784bd5f..b8ea380301eec7b210d3a8102df3db842b8c840b 100644 (file)
@@ -16,8 +16,8 @@
 package com.vaadin.tests.widgetset.client.grid;
 
 import com.vaadin.client.ui.AbstractComponentConnector;
-import com.vaadin.client.ui.grid.ScrollDestination;
 import com.vaadin.shared.ui.Connect;
+import com.vaadin.shared.ui.grid.ScrollDestination;
 import com.vaadin.tests.widgetset.server.grid.TestGrid;
 
 /**
index 5c8dd4a6098588e0aeba4cbac9c27ff8ff9b4fdf..0230367b858f516ce766349380ee637f0d2fcbc5 100644 (file)
@@ -10,7 +10,7 @@ import com.vaadin.client.ui.grid.Escalator;
 import com.vaadin.client.ui.grid.EscalatorUpdater;
 import com.vaadin.client.ui.grid.Row;
 import com.vaadin.client.ui.grid.RowContainer;
-import com.vaadin.client.ui.grid.ScrollDestination;
+import com.vaadin.shared.ui.grid.ScrollDestination;
 
 public class VTestGrid extends Composite {
 
@@ -174,20 +174,12 @@ public class VTestGrid extends Composite {
 
     public void scrollToRow(final int index,
             final ScrollDestination destination, final int padding) {
-        if (padding != 0) {
-            escalator.scrollToRow(index, destination, padding);
-        } else {
-            escalator.scrollToRow(index, destination);
-        }
+        escalator.scrollToRow(index, destination, padding);
     }
 
     public void scrollToColumn(final int index,
             final ScrollDestination destination, final int padding) {
-        if (padding != 0) {
-            escalator.scrollToColumn(index, destination, padding);
-        } else {
-            escalator.scrollToColumn(index, destination);
-        }
+        escalator.scrollToColumn(index, destination, padding);
     }
 
     public void removeRows(final int offset, final int amount) {