aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtur Signell <artur@vaadin.com>2012-03-23 09:47:23 +0200
committerArtur Signell <artur@vaadin.com>2012-03-23 09:47:23 +0200
commitdd06b3cb695567379b381e4be28fb609d0c70074 (patch)
tree0a8d51b65e479806d30e6f1bec811cde5b296691
parentff5cbf06457cf483c7a68d28fa3a876e673ec242 (diff)
parent8da6b1a0c3293c7de05ebc3d451a2f2e272a13b8 (diff)
downloadvaadin-framework-dd06b3cb695567379b381e4be28fb609d0c70074.tar.gz
vaadin-framework-dd06b3cb695567379b381e4be28fb609d0c70074.zip
Merge commit '8da6b1a0c3293c7de05ebc3d451a2f2e272a13b8' from origin/6.8
Conflicts: src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java12
-rw-r--r--src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java14
-rw-r--r--src/com/vaadin/ui/GridLayout.java256
-rw-r--r--src/com/vaadin/ui/Table.java10
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/SetCurrentPageFirstItemId.html62
-rw-r--r--tests/testbench/com/vaadin/tests/components/table/SetCurrentPageFirstItemId.java55
-rw-r--r--tests/testbench/com/vaadin/tests/components/tabsheet/TabKeyboardNavigation.html97
7 files changed, 379 insertions, 127 deletions
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java
index 3ef5ba1dfd..4e2c43dcc4 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java
@@ -1810,15 +1810,9 @@ public class VScrollTable extends FlowPanel implements HasWidgets,
isNewBody = false;
if (firstvisible > 0) {
- // Deferred due some Firefox oddities. IE & Safari could survive
- // without
- Scheduler.get().scheduleDeferred(new Command() {
- public void execute() {
- scrollBodyPanel
- .setScrollPosition(measureRowHeightOffset(firstvisible));
- firstRowInViewPort = firstvisible;
- }
- });
+ scrollBodyPanel
+ .setScrollPosition(measureRowHeightOffset(firstvisible));
+ firstRowInViewPort = firstvisible;
}
if (enabled) {
diff --git a/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java b/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java
index d2064c8d5e..ffef5825f4 100644
--- a/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java
+++ b/src/com/vaadin/terminal/gwt/client/ui/VTabsheet.java
@@ -161,16 +161,16 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
* true if the Tab is the first visible Tab
*/
public void setStyleNames(boolean selected, boolean first) {
- // TODO #5100 doesn't belong here
- focusImpl.setTabIndex(td, selected ? getTabsheet().tabulatorIndex
- : -1);
-
setStyleName(td, TD_FIRST_CLASSNAME, first);
setStyleName(td, TD_SELECTED_CLASSNAME, selected);
setStyleName(td, TD_SELECTED_FIRST_CLASSNAME, selected && first);
setStyleName(div, DIV_SELECTED_CLASSNAME, selected);
}
+ public void setTabulatorIndex(int tabIndex) {
+ focusImpl.setTabIndex(td, tabIndex);
+ }
+
public boolean isClosable() {
return tabCaption.isClosable();
}
@@ -414,10 +414,12 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
final Tab oldSelected = selected;
newSelected.setStyleNames(true, isFirstVisibleTab(index));
+ newSelected.setTabulatorIndex(getTabsheet().tabulatorIndex);
if (oldSelected != null && oldSelected != newSelected) {
oldSelected.setStyleNames(false,
isFirstVisibleTab(getWidgetIndex(oldSelected)));
+ oldSelected.setTabulatorIndex(-1);
}
// Update the field holding the currently selected tab
@@ -529,6 +531,10 @@ public class VTabsheet extends VTabsheetBase implements Focusable,
final Element tabs; // tabbar and 'scroller' container
Tab focusedTab;
+ /**
+ * The tabindex property (position in the browser's focus cycle.) Named like
+ * this to avoid confusion with activeTabIndex.
+ */
int tabulatorIndex = 0;
private static final FocusImpl focusImpl = FocusImpl.getFocusImplForPanel();
diff --git a/src/com/vaadin/ui/GridLayout.java b/src/com/vaadin/ui/GridLayout.java
index 596773b870..bc5f1a1999 100644
--- a/src/com/vaadin/ui/GridLayout.java
+++ b/src/com/vaadin/ui/GridLayout.java
@@ -21,18 +21,24 @@ import com.vaadin.terminal.gwt.client.EventId;
import com.vaadin.terminal.gwt.client.ui.GridLayoutConnector;
/**
+ * A layout where the components are laid out on a grid using cell coordinates.
+ *
+ * <p>
+ * The GridLayout also maintains a cursor for adding components in
+ * left-to-right, top-to-bottom order.
+ * </p>
+ *
* <p>
- * A container that consists of components with certain coordinates (cell
- * position) on a grid. It also maintains cursor for adding component in left to
- * right, top to bottom order.
+ * Each component in a <code>GridLayout</code> uses a defined
+ * {@link GridLayout.Area area} (column1,row1,column2,row2) from the grid. The
+ * components may not overlap with the existing components - if you try to do so
+ * you will get an {@link OverlapsException}. Adding a component with cursor
+ * automatically extends the grid by increasing the grid height.
* </p>
*
* <p>
- * Each component in a <code>GridLayout</code> uses a certain
- * {@link GridLayout.Area area} (column1,row1,column2,row2) from the grid. One
- * should not add components that would overlap with the existing components
- * because in such case an {@link OverlapsException} is thrown. Adding component
- * with cursor automatically extends the grid by increasing the grid height.
+ * The grid coordinates, which are specified by a row and column index, always
+ * start from 0 for the topmost row and the leftmost column.
* </p>
*
* @author Vaadin Ltd.
@@ -102,9 +108,10 @@ public class GridLayout extends AbstractLayout implements
private Map<Integer, Float> rowExpandRatio = new HashMap<Integer, Float>();
/**
- * Constructor for grid of given size (number of cells). Note that grid's
- * final size depends on the items that are added into the grid. Grid grows
- * if you add components outside the grid's area.
+ * Constructor for a grid of given size (number of columns and rows).
+ *
+ * The grid may grow or shrink later. Grid grows automatically if you add
+ * components outside its area.
*
* @param columns
* Number of columns in the grid.
@@ -117,7 +124,7 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * Constructs an empty grid layout that is extended as needed.
+ * Constructs an empty (1x1) grid layout that is extended as needed.
*/
public GridLayout() {
this(1, 1);
@@ -125,25 +132,25 @@ public class GridLayout extends AbstractLayout implements
/**
* <p>
- * Adds a component with a specified area to the grid. The area the new
- * component should take is defined by specifying the upper left corner
- * (column1, row1) and the lower right corner (column2, row2) of the area.
+ * Adds a component to the grid in the specified area. The area is defined
+ * by specifying the upper left corner (column1, row1) and the lower right
+ * corner (column2, row2) of the area. The coordinates are zero-based.
* </p>
*
* <p>
- * If the new component overlaps with any of the existing components already
- * present in the grid the operation will fail and an
- * {@link OverlapsException} is thrown.
+ * If the area overlaps with any of the existing components already present
+ * in the grid, the operation will fail and an {@link OverlapsException} is
+ * thrown.
* </p>
*
- * @param c
+ * @param component
* the component to be added.
* @param column1
* the column of the upper left corner of the area <code>c</code>
- * is supposed to occupy.
+ * is supposed to occupy. The leftmost column has index 0.
* @param row1
* the row of the upper left corner of the area <code>c</code> is
- * supposed to occupy.
+ * supposed to occupy. The topmost row has index 0.
* @param column2
* the column of the lower right corner of the area
* <code>c</code> is supposed to occupy.
@@ -254,31 +261,39 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * Adds the component into this container to cells column1,row1 (NortWest
- * corner of the area.) End coordinates (SouthEast corner of the area) are
- * the same as column1,row1. Component width and height is 1.
+ * Adds the component to the grid in cells column1,row1 (NortWest corner of
+ * the area.) End coordinates (SouthEast corner of the area) are the same as
+ * column1,row1. The coordinates are zero-based. Component width and height
+ * is 1.
*
- * @param c
+ * @param component
* the component to be added.
* @param column
- * the column index.
+ * the column index, starting from 0.
* @param row
- * the row index.
+ * the row index, starting from 0.
* @throws OverlapsException
* if the new component overlaps with any of the components
* already in the grid.
* @throws OutOfBoundsException
* if the cell is outside the grid area.
*/
- public void addComponent(Component c, int column, int row)
+ public void addComponent(Component component, int column, int row)
throws OverlapsException, OutOfBoundsException {
- this.addComponent(c, column, row, column, row);
+ this.addComponent(component, column, row, column, row);
}
/**
- * Force the next component to be added to the beginning of the next line.
- * By calling this function user can ensure that no more components are
- * added to the right of the previous component.
+ * Forces the next component to be added at the beginning of the next line.
+ *
+ * <p>
+ * Sets the cursor column to 0 and increments the cursor row by one.
+ * </p>
+ *
+ * <p>
+ * By calling this function you can ensure that no more components are added
+ * right of the previous component.
+ * </p>
*
* @see #space()
*/
@@ -288,8 +303,8 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * Moves the cursor forwards by one. If the cursor goes out of the right
- * grid border, move it to next line.
+ * Moves the cursor forward by one. If the cursor goes out of the right grid
+ * border, it is moved to the first column of the next row.
*
* @see #newLine()
*/
@@ -307,7 +322,7 @@ public class GridLayout extends AbstractLayout implements
* free position. If the cursor goes out from the bottom of the grid, the
* grid is automatically extended.
*
- * @param c
+ * @param component
* the component to be added.
*/
@Override
@@ -334,9 +349,9 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * Removes the given component from this container.
+ * Removes the specified component from the layout.
*
- * @param c
+ * @param component
* the component to be removed.
*/
@Override
@@ -369,12 +384,12 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * Removes the component specified with it's cell index.
+ * Removes the component specified by its cell coordinates.
*
* @param column
- * the Component's column.
+ * the component's column, starting from 0.
* @param row
- * the Component's row.
+ * the component's row, starting from 0.
*/
public void removeComponent(int column, int row) {
@@ -389,18 +404,18 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * Gets an Iterator to the component container contents. Using the Iterator
- * it's possible to step through the contents of the container.
+ * Gets an Iterator for the components contained in the layout. By using the
+ * Iterator it is possible to step through the contents of the layout.
*
- * @return the Iterator of the components inside the container.
+ * @return the Iterator of the components inside the layout.
*/
public Iterator<Component> getComponentIterator() {
return Collections.unmodifiableCollection(components).iterator();
}
/**
- * Gets the number of contained components. Consistent with the iterator
- * returned by {@link #getComponentIterator()}.
+ * Gets the number of components contained in the layout. Consistent with
+ * the iterator returned by {@link #getComponentIterator()}.
*
* @return the number of contained components
*/
@@ -662,9 +677,17 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * This class defines an area on a grid. An Area is defined by the cells of
- * its upper left corner (column1,row1) and lower right corner
- * (column2,row2).
+ * Defines a rectangular area of cells in a GridLayout.
+ *
+ * <p>
+ * Also maintains a reference to the component contained in the area.
+ * </p>
+ *
+ * <p>
+ * The area is specified by the cell coordinates of its upper left corner
+ * (column1,row1) and lower right corner (column2,row2). As otherwise with
+ * GridLayout, the column and row coordinates start from zero.
+ * </p>
*
* @author Vaadin Ltd.
* @version
@@ -694,7 +717,7 @@ public class GridLayout extends AbstractLayout implements
private int row2;
/**
- * Component painted on the area.
+ * Component painted in the area.
*/
private Component component;
@@ -706,20 +729,17 @@ public class GridLayout extends AbstractLayout implements
* @param component
* the component connected to the area.
* @param column1
- * The column of the upper left corner cell of the area
- * <code>c</code> is supposed to occupy.
+ * The column of the upper left corner cell of the area. The
+ * leftmost column has index 0.
* @param row1
- * The row of the upper left corner cell of the area
- * <code>c</code> is supposed to occupy.
+ * The row of the upper left corner cell of the area. The
+ * topmost row has index 0.
* @param column2
- * The column of the lower right corner cell of the area
- * <code>c</code> is supposed to occupy.
+ * The column of the lower right corner cell of the area. The
+ * leftmost column has index 0.
* @param row2
- * The row of the lower right corner cell of the area
- * <code>c</code> is supposed to occupy.
- * @throws OverlapsException
- * if the new component overlaps with any of the components
- * already in the grid
+ * The row of the lower right corner cell of the area. The
+ * topmost row has index 0.
*/
public Area(Component component, int column1, int row1, int column2,
int row2) {
@@ -731,13 +751,13 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * Tests if the given Area overlaps with an another Area.
+ * Tests if this Area overlaps with another Area.
*
* @param other
- * the Another Area that's to be tested for overlap with this
- * area.
- * @return <code>true</code> if <code>other</code> overlaps with this
- * area, <code>false</code> if it doesn't.
+ * the other Area that is to be tested for overlap with this
+ * area
+ * @return <code>true</code> if <code>other</code> area overlaps with
+ * this on, <code>false</code> if it does not.
*/
public boolean overlaps(Area other) {
return column1 <= other.getColumn2() && row1 <= other.getRow2()
@@ -758,7 +778,7 @@ public class GridLayout extends AbstractLayout implements
* Sets the component connected to the area.
*
* <p>
- * This function only sets the value in the datastructure and does not
+ * This function only sets the value in the data structure and does not
* send any events or set parents.
* </p>
*
@@ -770,9 +790,7 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * @deprecated Use getColumn1() instead.
- *
- * @see com.vaadin.ui.GridLayout#getColumn1()
+ * @deprecated Use {@link #getColumn1()} instead.
*/
@Deprecated
public int getX1() {
@@ -789,9 +807,7 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * @deprecated Use getColumn2() instead.
- *
- * @see com.vaadin.ui.GridLayout#getColumn2()
+ * @deprecated Use {@link #getColumn2()} instead.
*/
@Deprecated
public int getX2() {
@@ -808,9 +824,7 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * @deprecated Use getRow1() instead.
- *
- * @see com.vaadin.ui.GridLayout#getRow1()
+ * @deprecated Use {@link #getRow1()} instead.
*/
@Deprecated
public int getY1() {
@@ -827,9 +841,7 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * @deprecated Use getRow2() instead.
- *
- * @see com.vaadin.ui.GridLayout#getRow2()
+ * @deprecated Use {@link #getRow2()} instead.
*/
@Deprecated
public int getY2() {
@@ -1028,12 +1040,16 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * Gets the current cursor x-position. The cursor position points the
- * position for the next component that is added without specifying its
- * coordinates (grid cell). When the cursor position is occupied, the next
- * component will be added to first free position after the cursor.
+ * Gets the current x-position (column) of the cursor.
*
- * @return the grid column the Cursor is on.
+ * <p>
+ * The cursor position points the position for the next component that is
+ * added without specifying its coordinates (grid cell). When the cursor
+ * position is occupied, the next component will be added to first free
+ * position after the cursor.
+ * </p>
+ *
+ * @return the grid column the cursor is on, starting from 0.
*/
public int getCursorX() {
return cursorX;
@@ -1050,10 +1066,14 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * Gets the current cursor y-position. The cursor position points the
- * position for the next component that is added without specifying its
- * coordinates (grid cell). When the cursor position is occupied, the next
- * component will be added to first free position after the cursor.
+ * Gets the current y-position (row) of the cursor.
+ *
+ * <p>
+ * The cursor position points the position for the next component that is
+ * added without specifying its coordinates (grid cell). When the cursor
+ * position is occupied, the next component will be added to the first free
+ * position after the cursor.
+ * </p>
*
* @return the grid row the Cursor is on.
*/
@@ -1062,10 +1082,11 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * Sets the current cursor y-position. This is usually handled automatically
- * by GridLayout.
+ * Sets the current y-coordinate (row) of the cursor. This is usually
+ * handled automatically by GridLayout.
*
* @param cursorY
+ * the row number, starting from 0 for the topmost row.
*/
public void setCursorY(int cursorY) {
this.cursorY = cursorY;
@@ -1164,10 +1185,11 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * Inserts an empty row at the chosen position in the grid.
+ * Inserts an empty row at the specified position in the grid.
*
* @param row
- * Number of the row the new row will be inserted before
+ * Index of the row before which the new row will be inserted.
+ * The leftmost row has index 0.
*/
public void insertRow(int row) {
if (row > rows) {
@@ -1199,9 +1221,13 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * Removes row and all components in the row. Components which span over
- * several rows are removed if the selected row is the component's first
- * row.
+ * Removes a row and all the components in the row.
+ *
+ * <p>
+ * Components which span over several rows are removed if the selected row
+ * is on the first row of such a component.
+ * </p>
+ *
* <p>
* If the last row is removed then all remaining components will be removed
* and the grid will be reduced to one row. The cursor will be moved to the
@@ -1209,7 +1235,7 @@ public class GridLayout extends AbstractLayout implements
* </p>
*
* @param row
- * The row number to remove
+ * Index of the row to remove. The leftmost row has index 0.
*/
public void removeRow(int row) {
if (row >= rows) {
@@ -1255,15 +1281,18 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * Sets the expand ratio of given column. Expand ratio defines how excess
- * space is distributed among columns. Excess space means the space not
- * consumed by non relatively sized components.
+ * Sets the expand ratio of given column.
*
* <p>
- * By default excess space is distributed evenly.
+ * The expand ratio defines how excess space is distributed among columns.
+ * Excess space means space that is left over from components that are not
+ * sized relatively. By default, the excess space is distributed evenly.
+ * </p>
*
* <p>
- * Note, that width needs to be defined for this method to have any effect.
+ * Note that the component width of the GridLayout must be defined (fixed or
+ * relative, as opposed to undefined) for this method to have any effect.
+ * </p>
*
* @see #setWidth(float, int)
*
@@ -1289,19 +1318,23 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * Sets the expand ratio of given row. Expand ratio defines how excess space
- * is distributed among rows. Excess space means the space not consumed by
- * non relatively sized components.
+ * Sets the expand ratio of given row.
*
* <p>
- * By default excess space is distributed evenly.
+ * Expand ratio defines how excess space is distributed among rows. Excess
+ * space means the space left over from components that are not sized
+ * relatively. By default, the excess space is distributed evenly.
+ * </p>
*
* <p>
- * Note, that height needs to be defined for this method to have any effect.
+ * Note, that height needs to be defined (fixed or relative, as opposed to
+ * undefined height) for this method to have any effect.
+ * </p>
*
* @see #setHeight(float, int)
*
* @param rowIndex
+ * The row index, starting from 0 for the topmost row.
* @param ratio
*/
public void setRowExpandRatio(int rowIndex, float ratio) {
@@ -1315,6 +1348,7 @@ public class GridLayout extends AbstractLayout implements
* @see #setRowExpandRatio(int, float)
*
* @param rowIndex
+ * The row index, starting from 0 for the topmost row.
* @return the expand ratio, 0.0f by default
*/
public float getRowExpandRatio(int rowIndex) {
@@ -1326,9 +1360,9 @@ public class GridLayout extends AbstractLayout implements
* Gets the Component at given index.
*
* @param x
- * x-index
+ * The column index, starting from 0 for the leftmost column.
* @param y
- * y-index
+ * The row index, starting from 0 for the topmost row.
* @return Component in given cell or null if empty
*/
public Component getComponent(int x, int y) {
@@ -1344,13 +1378,13 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * Returns information about the area where given component is layed in the
+ * Returns information about the area where given component is laid in the
* GridLayout.
*
* @param component
* the component whose area information is requested.
- * @return an Area object that contains information how component is layed
- * in the grid
+ * @return an Area object that contains information how component is laid in
+ * the grid
*/
public Area getComponentArea(Component component) {
for (final Iterator<Area> iterator = areas.iterator(); iterator
@@ -1364,7 +1398,7 @@ public class GridLayout extends AbstractLayout implements
}
/**
- * Sets the component alignment using a short hand string notation.
+ * Sets the component alignment using a shorthand string notation.
*
* @deprecated Replaced by
* {@link #setComponentAlignment(Component, Alignment)}
diff --git a/src/com/vaadin/ui/Table.java b/src/com/vaadin/ui/Table.java
index 5085f5b568..ff83a9ef2e 100644
--- a/src/com/vaadin/ui/Table.java
+++ b/src/com/vaadin/ui/Table.java
@@ -1091,7 +1091,9 @@ public class Table extends AbstractSelect implements Action.Container,
}
if (index > maxIndex) {
- setCurrentPageFirstItemIndex(maxIndex);
+ // Note that we pass index, not maxIndex, letting
+ // setCurrentPageFirstItemIndex handle the situation.
+ setCurrentPageFirstItemIndex(index);
return;
}
@@ -1370,9 +1372,11 @@ public class Table extends AbstractSelect implements Action.Container,
maxIndex = 0;
}
- // Ensures that the new value is valid
+ // Assume that we want to scroll to the very bottom (so that the bottom
+ // row is completely visible even if (table height) / (row height) is
+ // not an integer.)
if (newIndex > maxIndex) {
- newIndex = maxIndex;
+ newIndex = maxIndex + 1;
}
// Refresh first item id
diff --git a/tests/testbench/com/vaadin/tests/components/table/SetCurrentPageFirstItemId.html b/tests/testbench/com/vaadin/tests/components/table/SetCurrentPageFirstItemId.html
new file mode 100644
index 0000000000..8881c0d2f5
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/table/SetCurrentPageFirstItemId.html
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8067/" />
+<title>SetCurrentPageFirstItemId</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">SetCurrentPageFirstItemId</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/SetCurrentPageFirstItemId?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runSetCurrentPageFirstItemId::/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runSetCurrentPageFirstItemId::/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runSetCurrentPageFirstItemId::/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runSetCurrentPageFirstItemId::/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runSetCurrentPageFirstItemId::/VVerticalLayout[0]/ChildComponentContainer[1]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>pause</td>
+ <td>300</td>
+ <td></td>
+</tr>
+<tr>
+ <td>assertText</td>
+ <td>vaadin=runSetCurrentPageFirstItemId::/VVerticalLayout[0]/ChildComponentContainer[0]/VScrollTable[0]/domChild[1]/domChild[0]/domChild[1]/domChild[0]/domChild[24]/domChild[0]/domChild[0]</td>
+ <td>24</td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>scrolled-to-bottom</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/tests/testbench/com/vaadin/tests/components/table/SetCurrentPageFirstItemId.java b/tests/testbench/com/vaadin/tests/components/table/SetCurrentPageFirstItemId.java
new file mode 100644
index 0000000000..536348a393
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/table/SetCurrentPageFirstItemId.java
@@ -0,0 +1,55 @@
+package com.vaadin.tests.components.table;
+
+import com.vaadin.tests.components.TestBase;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.VerticalLayout;
+
+public class SetCurrentPageFirstItemId extends TestBase {
+ int index = 0;
+
+ private final Table table = new Table();
+
+ @Override
+ public void setup() {
+
+ VerticalLayout mainLayout = new VerticalLayout();
+ mainLayout.setHeight("100%");
+ mainLayout.setMargin(true);
+
+ getMainWindow().setContent(mainLayout);
+
+ mainLayout.addComponent(table);
+ table.setSizeFull();
+ table.addContainerProperty("rowID", Integer.class, null);
+ for (int i = 0; i < 20; i++) {
+ addRow();
+ }
+
+ Button addrowButton = new Button("Add row");
+ addrowButton.addListener(new ClickListener() {
+ public void buttonClick(ClickEvent pEvent) {
+ Object id = addRow();
+ table.setCurrentPageFirstItemId(id);
+ }
+ });
+
+ mainLayout.addComponent(addrowButton);
+ }
+
+ private Object addRow() {
+ return table.addItem(new Object[] { index++ }, null);
+ }
+
+ @Override
+ protected String getDescription() {
+ return "Table.setCurrentPageFirstItemId doesn't always work with full sized Table";
+ }
+
+ @Override
+ protected Integer getTicketNumber() {
+ return 7607;
+ }
+} \ No newline at end of file
diff --git a/tests/testbench/com/vaadin/tests/components/tabsheet/TabKeyboardNavigation.html b/tests/testbench/com/vaadin/tests/components/tabsheet/TabKeyboardNavigation.html
new file mode 100644
index 0000000000..d7876ba646
--- /dev/null
+++ b/tests/testbench/com/vaadin/tests/components/tabsheet/TabKeyboardNavigation.html
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8068/" />
+<title>TabKeyboardNavigation</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">TabKeyboardNavigation</td></tr>
+</thead><tbody>
+<tr>
+ <td>open</td>
+ <td>/run/TabKeyboardNavigation?restartApplication</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>9,8</td>
+</tr>
+<tr>
+ <td>pressSpecialKey</td>
+ <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>right</td>
+</tr>
+<tr>
+ <td>assertTextPresent</td>
+ <td>Tab 2</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>tab2</td>
+</tr>
+<tr>
+ <td>pressSpecialKey</td>
+ <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[1]</td>
+ <td>right</td>
+</tr>
+<tr>
+ <td>pressSpecialKey</td>
+ <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[2]</td>
+ <td>right</td>
+</tr>
+<tr>
+ <td>assertTextPresent</td>
+ <td>Tab 5</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>skip-disabled-to-tab5</td>
+</tr>
+<tr>
+ <td>pressSpecialKey</td>
+ <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[4]</td>
+ <td>right</td>
+</tr>
+<tr>
+ <td>assertTextPresent</td>
+ <td>Tab 1</td>
+ <td>wraparound-to-tab1</td>
+</tr>
+<tr>
+ <td>click</td>
+ <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[0]/VButton[0]/domChild[0]/domChild[0]</td>
+ <td></td>
+</tr>
+<tr>
+ <td>mouseClick</td>
+ <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>14,9</td>
+</tr>
+<tr>
+ <td>pressSpecialKey</td>
+ <td>vaadin=runTabKeyboardNavigation::/VVerticalLayout[0]/ChildComponentContainer[1]/VVerticalLayout[0]/ChildComponentContainer[4]/VTabsheet[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]/domChild[0]</td>
+ <td>left</td>
+</tr>
+<tr>
+ <td>assertTextPresent</td>
+ <td>Tab 6</td>
+ <td></td>
+</tr>
+<tr>
+ <td>screenCapture</td>
+ <td></td>
+ <td>moved-left-to-tab6</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>