diff --git a/org.eclipse.osbp.fork.vaadin.addon.filteringtable/src/com/vaadin/client/ui/VCustomScrollTable.java b/org.eclipse.osbp.fork.vaadin.addon.filteringtable/src/com/vaadin/client/ui/VCustomScrollTable.java
new file mode 100644
index 0000000..7212104
--- /dev/null
+++ b/org.eclipse.osbp.fork.vaadin.addon.filteringtable/src/com/vaadin/client/ui/VCustomScrollTable.java
@@ -0,0 +1,9629 @@
+/*
+ * Copyright 2000-2014 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;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.dom.client.Node;
+import com.google.gwt.dom.client.NodeList;
+import com.google.gwt.dom.client.Style;
+import com.google.gwt.dom.client.Style.Display;
+import com.google.gwt.dom.client.Style.Overflow;
+import com.google.gwt.dom.client.Style.Position;
+import com.google.gwt.dom.client.Style.TextAlign;
+import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.dom.client.Style.Visibility;
+import com.google.gwt.dom.client.TableCellElement;
+import com.google.gwt.dom.client.TableRowElement;
+import com.google.gwt.dom.client.TableSectionElement;
+import com.google.gwt.dom.client.Touch;
+import com.google.gwt.event.dom.client.BlurEvent;
+import com.google.gwt.event.dom.client.BlurHandler;
+import com.google.gwt.event.dom.client.FocusEvent;
+import com.google.gwt.event.dom.client.FocusHandler;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
+import com.google.gwt.event.dom.client.KeyPressEvent;
+import com.google.gwt.event.dom.client.KeyPressHandler;
+import com.google.gwt.event.dom.client.KeyUpEvent;
+import com.google.gwt.event.dom.client.KeyUpHandler;
+import com.google.gwt.event.dom.client.ScrollEvent;
+import com.google.gwt.event.dom.client.ScrollHandler;
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
+import com.google.gwt.event.shared.HandlerRegistration;
+import com.google.gwt.regexp.shared.MatchResult;
+import com.google.gwt.regexp.shared.RegExp;
+import com.google.gwt.user.client.Command;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.Event.NativePreviewEvent;
+import com.google.gwt.user.client.Event.NativePreviewHandler;
+import com.google.gwt.user.client.Timer;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.HasWidgets;
+import com.google.gwt.user.client.ui.Panel;
+import com.google.gwt.user.client.ui.PopupPanel;
+import com.google.gwt.user.client.ui.UIObject;
+import com.google.gwt.user.client.ui.Widget;
+import com.vaadin.client.ApplicationConnection;
+import com.vaadin.client.BrowserInfo;
+import com.vaadin.client.ComponentConnector;
+import com.vaadin.client.ConnectorMap;
+import com.vaadin.client.DeferredWorker;
+import com.vaadin.client.Focusable;
+import com.vaadin.client.MouseEventDetailsBuilder;
+import com.vaadin.client.StyleConstants;
+import com.vaadin.client.TooltipInfo;
+import com.vaadin.client.UIDL;
+import com.vaadin.client.Util;
+import com.vaadin.client.VConsole;
+import com.vaadin.client.VTooltip;
+import com.vaadin.client.ui.VCustomScrollTable.VScrollTableBody.VScrollTableRow;
+import com.vaadin.client.ui.dd.DDUtil;
+import com.vaadin.client.ui.dd.VAbstractDropHandler;
+import com.vaadin.client.ui.dd.VAcceptCallback;
+import com.vaadin.client.ui.dd.VDragAndDropManager;
+import com.vaadin.client.ui.dd.VDragEvent;
+import com.vaadin.client.ui.dd.VHasDropHandler;
+import com.vaadin.client.ui.dd.VTransferable;
+import com.vaadin.shared.AbstractComponentState;
+import com.vaadin.shared.MouseEventDetails;
+import com.vaadin.shared.ui.dd.VerticalDropLocation;
+import com.vaadin.shared.ui.table.TableConstants;
+
+// TODO: Auto-generated Javadoc
+/**
+ * VCustomScrollTable
+ * 
+ * VCustomScrollTable is a FlowPanel having two widgets in it: * TableHead
+ * component * ScrollPanel
+ * 
+ * TableHead contains table's header and widgets + logic for resizing,
+ * reordering and hiding columns.
+ * 
+ * ScrollPanel contains VScrollTableBody object which handles content. To save
+ * some bandwidth and to improve clients responsiveness with loads of data, in
+ * VScrollTableBody all rows are not necessary rendered. There are "spacers" in
+ * VScrollTableBody to use the exact same space as non-rendered rows would use.
+ * This way we can use seamlessly traditional scrollbars and scrolling to fetch
+ * more rows instead of "paging".
+ * 
+ * In VCustomScrollTable we listen to scroll events. On horizontal scrolling we
+ * also update TableHeads scroll position which has its scrollbars hidden. On
+ * vertical scroll events we will check if we are reaching the end of area where
+ * we have rows rendered and
+ * 
+ * TODO implement unregistering for child components in Cells
+ */
+@SuppressWarnings("deprecation")
+public class VCustomScrollTable extends FlowPanel implements HasWidgets,
+        ScrollHandler, VHasDropHandler, FocusHandler, BlurHandler, Focusable,
+        ActionOwner, SubPartAware, DeferredWorker {
+
+    /** Simple interface for parts of the table capable of owning a context
+	 * menu.
+	 *
+	 * @author Vaadin Ltd
+	 * @since 7.2
+	 */
+    private interface ContextMenuOwner {
+        
+        /** Show context menu.
+		 *
+		 * @param event
+		 *            the event
+		 */
+        public void showContextMenu(Event event);
+    }
+
+    /** Handles showing context menu on "long press" from a touch screen.
+	 *
+	 * @author Vaadin Ltd
+	 * @since 7.2
+	 */
+    private class TouchContextProvider {
+        
+        /** The Constant TOUCH_CONTEXT_MENU_TIMEOUT. */
+        private static final int TOUCH_CONTEXT_MENU_TIMEOUT = 500;
+        
+        /** The context touch timeout. */
+        private Timer contextTouchTimeout;
+
+        /** The touch start. */
+        private Event touchStart;
+        
+        /** The touch start y. */
+        private int touchStartY;
+        
+        /** The touch start x. */
+        private int touchStartX;
+
+        /** The target. */
+        private ContextMenuOwner target;
+
+        /**
+         * Initializes a handler for a certain context menu owner.
+         * 
+         * @param target
+         *            the owner of the context menu
+         */
+        public TouchContextProvider(ContextMenuOwner target) {
+            this.target = target;
+        }
+
+        /**
+         * Cancels the current context touch timeout.
+         */
+        public void cancel() {
+            if (contextTouchTimeout != null) {
+                contextTouchTimeout.cancel();
+                contextTouchTimeout = null;
+            }
+            touchStart = null;
+        }
+
+        /**
+         * A function to handle touch context events in a table.
+         * 
+         * @param event
+         *            browser event to handle
+         */
+        public void handleTouchEvent(final Event event) {
+            int type = event.getTypeInt();
+
+            switch (type) {
+            case Event.ONCONTEXTMENU:
+                target.showContextMenu(event);
+                break;
+            case Event.ONTOUCHSTART:
+                // save position to fields, touches in events are same
+                // instance during the operation.
+                touchStart = event;
+
+                Touch touch = event.getChangedTouches().get(0);
+                touchStartX = touch.getClientX();
+                touchStartY = touch.getClientY();
+
+                if (contextTouchTimeout == null) {
+                    contextTouchTimeout = new Timer() {
+
+                        @Override
+                        public void run() {
+                            if (touchStart != null) {
+                                // Open the context menu if finger
+                                // is held in place long enough.
+                                target.showContextMenu(touchStart);
+                                event.preventDefault();
+                                touchStart = null;
+                            }
+                        }
+                    };
+                }
+                contextTouchTimeout.schedule(TOUCH_CONTEXT_MENU_TIMEOUT);
+                break;
+            case Event.ONTOUCHCANCEL:
+            case Event.ONTOUCHEND:
+                cancel();
+                break;
+            case Event.ONTOUCHMOVE:
+                if (isSignificantMove(event)) {
+                    // Moved finger before the context menu timer
+                    // expired, so let the browser handle the event.
+                    cancel();
+                }
+            }
+        }
+
+        /**
+         * Calculates how many pixels away the user's finger has traveled. This
+         * reduces the chance of small non-intentional movements from canceling
+         * the long press detection.
+         * 
+         * @param event
+         *            the Event for which to check the move distance
+         * @return true if this is considered an intentional move by the user
+         */
+        protected boolean isSignificantMove(Event event) {
+            if (touchStart == null) {
+                // no touch start
+                return false;
+            }
+
+            // Calculate the distance between touch start and the current touch
+            // position
+            Touch touch = event.getChangedTouches().get(0);
+            int deltaX = touch.getClientX() - touchStartX;
+            int deltaY = touch.getClientY() - touchStartY;
+            int delta = deltaX * deltaX + deltaY * deltaY;
+
+            // Compare to the square of the significant move threshold to remove
+            // the need for a square root
+            if (delta > TouchScrollDelegate.SIGNIFICANT_MOVE_THRESHOLD
+                    * TouchScrollDelegate.SIGNIFICANT_MOVE_THRESHOLD) {
+                return true;
+            }
+            return false;
+        }
+    }
+
+    /** The Constant STYLENAME. */
+    public static final String STYLENAME = "v-table";
+
+    /** The Enum SelectMode.
+	 */
+    public enum SelectMode {
+        
+        /** The none. */
+        NONE(0), 
+ /** The single. */
+ SINGLE(1), 
+ /** The multi. */
+ MULTI(2);
+        
+        /** The id. */
+        private int id;
+
+        /** Instantiates a new select mode.
+		 *
+		 * @param id
+		 *            the id
+		 */
+        private SelectMode(int id) {
+            this.id = id;
+        }
+
+        /** Gets the id.
+		 *
+		 * @return the id
+		 */
+        public int getId() {
+            return id;
+        }
+    }
+
+    /** The Constant ROW_HEADER_COLUMN_KEY. */
+    private static final String ROW_HEADER_COLUMN_KEY = "0";
+
+    /** The Constant CACHE_RATE_DEFAULT. */
+    private static final double CACHE_RATE_DEFAULT = 2;
+
+    /**
+     * The default multi select mode where simple left clicks only selects one
+     * item, CTRL+left click selects multiple items and SHIFT-left click selects
+     * a range of items.
+     */
+    private static final int MULTISELECT_MODE_DEFAULT = 0;
+
+    /**
+     * The simple multiselect mode is what the table used to have before
+     * ctrl/shift selections were added. That is that when this is set clicking
+     * on an item selects/deselects the item and no ctrl/shift selections are
+     * available.
+     */
+    private static final int MULTISELECT_MODE_SIMPLE = 1;
+
+    /** multiple of pagelength which component will cache when requesting
+	 * more rows.
+	 */
+    private double cache_rate = CACHE_RATE_DEFAULT;
+    
+    /** fraction of pageLenght which can be scrolled without making new
+	 * request.
+	 */
+    private double cache_react_rate = 0.75 * cache_rate;
+
+    /** The Constant ALIGN_CENTER. */
+    public static final char ALIGN_CENTER = 'c';
+    
+    /** The Constant ALIGN_LEFT. */
+    public static final char ALIGN_LEFT = 'b';
+    
+    /** The Constant ALIGN_RIGHT. */
+    public static final char ALIGN_RIGHT = 'e';
+    
+    /** The Constant CHARCODE_SPACE. */
+    private static final int CHARCODE_SPACE = 32;
+    
+    /** The first row in view port. */
+    private int firstRowInViewPort = 0;
+    
+    /** The page length. */
+    private int pageLength = 15;
+    
+    /** The last requested firstvisible. */
+    private int lastRequestedFirstvisible = 0; // to detect "serverside scroll"
+    
+    /** The firstvisible on last page. */
+    private int firstvisibleOnLastPage = -1; // To detect if the first visible
+                                             // is on the last page
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public boolean showRowHeaders = false;
+
+    /** The column order. */
+    private String[] columnOrder;
+
+    /** The client. */
+    protected ApplicationConnection client;
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public String paintableId;
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public boolean immediate;
+
+    /** The updated req rows. */
+    private boolean updatedReqRows = true;
+
+    /** The null selection allowed. */
+    private boolean nullSelectionAllowed = true;
+
+    /** The select mode. */
+    private SelectMode selectMode = SelectMode.NONE;
+
+    /** The selected row keys. */
+    public final HashSet<String> selectedRowKeys = new HashSet<String>();
+
+    /** The un syncedselections before row fetch. */
+    /*
+     * When scrolling and selecting at the same time, the selections are not in
+     * sync with the server while retrieving new rows (until key is released).
+     */
+    private HashSet<Object> unSyncedselectionsBeforeRowFetch;
+
+    /*
+     * These are used when jumping between pages when pressing Home and End
+     */
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public boolean selectLastItemInNextRender = false;
+    /** For internal use only. May be removed or replaced in the future. */
+    public boolean selectFirstItemInNextRender = false;
+    /** For internal use only. May be removed or replaced in the future. */
+    public boolean focusFirstItemInNextRender = false;
+    /** For internal use only. May be removed or replaced in the future. */
+    public boolean focusLastItemInNextRender = false;
+
+    /**
+     * The currently focused row.
+     * <p>
+     * For internal use only. May be removed or replaced in the future.
+     */
+    public VScrollTableRow focusedRow;
+
+    /**
+     * Helper to store selection range start in when using the keyboard
+     * <p>
+     * For internal use only. May be removed or replaced in the future.
+     */
+    public VScrollTableRow selectionRangeStart;
+
+    /**
+     * Flag for notifying when the selection has changed and should be sent to
+     * the server
+     * <p>
+     * For internal use only. May be removed or replaced in the future.
+     */
+    public boolean selectionChanged = false;
+
+    /** The scrolling velocity. */
+    /*
+     * The speed (in pixels) which the scrolling scrolls vertically/horizontally
+     */
+    private int scrollingVelocity = 10;
+
+    /** The scrolling velocity timer. */
+    private Timer scrollingVelocityTimer = null;
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public String[] bodyActionKeys;
+
+    /** The enable debug. */
+    private boolean enableDebug = false;
+
+    /** The Constant hasNativeTouchScrolling. */
+    private static final boolean hasNativeTouchScrolling = BrowserInfo.get()
+            .isTouchDevice()
+            && !BrowserInfo.get().requiresTouchScrollDelegate();
+
+    /** The noncollapsible columns. */
+    private Set<String> noncollapsibleColumns;
+
+    /**
+     * The last known row height used to preserve the height of a table with
+     * custom row heights and a fixed page length after removing the last row
+     * from the table.
+     * 
+     * A new VScrollTableBody instance is created every time the number of rows
+     * changes causing {@link VScrollTableBody#rowHeight} to be discarded and
+     * the height recalculated by {@link VScrollTableBody#getRowHeight(boolean)}
+     * to avoid some rounding problems, e.g. round(2 * 19.8) / 2 = 20 but
+     * round(3 * 19.8) / 3 = 19.66.
+     */
+    private double lastKnownRowHeight = Double.NaN;
+
+    /**
+     * Remember scroll position when getting detached to properly scroll back to
+     * the location that there is data for if getting attached again.
+     */
+    private int detachedScrollPosition = 0;
+
+    /** Represents a select range of rows.
+	 */
+    private class SelectionRange {
+        
+        /** The start row. */
+        private VScrollTableRow startRow;
+        
+        /** The length. */
+        private final int length;
+
+        /** Constuctor.
+		 *
+		 * @param row1
+		 *            the row1
+		 * @param row2
+		 *            the row2
+		 */
+        public SelectionRange(VScrollTableRow row1, VScrollTableRow row2) {
+            VScrollTableRow endRow;
+            if (row2.isBefore(row1)) {
+                startRow = row2;
+                endRow = row1;
+            } else {
+                startRow = row1;
+                endRow = row2;
+            }
+            length = endRow.getIndex() - startRow.getIndex() + 1;
+        }
+
+        /** Instantiates a new selection range.
+		 *
+		 * @param row
+		 *            the row
+		 * @param length
+		 *            the length
+		 */
+        public SelectionRange(VScrollTableRow row, int length) {
+            startRow = row;
+            this.length = length;
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see java.lang.Object#toString()
+         */
+
+        @Override
+        public String toString() {
+            return startRow.getKey() + "-" + length;
+        }
+
+        /** In range.
+		 *
+		 * @param row
+		 *            the row
+		 * @return true, if successful
+		 */
+        private boolean inRange(VScrollTableRow row) {
+            return row.getIndex() >= startRow.getIndex()
+                    && row.getIndex() < startRow.getIndex() + length;
+        }
+
+        /** Split.
+		 *
+		 * @param row
+		 *            the row
+		 * @return the collection
+		 */
+        public Collection<SelectionRange> split(VScrollTableRow row) {
+            assert row.isAttached();
+            ArrayList<SelectionRange> ranges = new ArrayList<SelectionRange>(2);
+
+            int endOfFirstRange = row.getIndex() - 1;
+            if (endOfFirstRange >= startRow.getIndex()) {
+                // create range of first part unless its length is < 1
+                ranges.add(new SelectionRange(startRow, endOfFirstRange
+                        - startRow.getIndex() + 1));
+            }
+            int startOfSecondRange = row.getIndex() + 1;
+            if (getEndIndex() >= startOfSecondRange) {
+                // create range of second part unless its length is < 1
+                VScrollTableRow startOfRange = scrollBody
+                        .getRowByRowIndex(startOfSecondRange);
+                if (startOfRange != null) {
+                    ranges.add(new SelectionRange(startOfRange, getEndIndex()
+                            - startOfSecondRange + 1));
+                }
+            }
+            return ranges;
+        }
+
+        /** Gets the end index.
+		 *
+		 * @return the end index
+		 */
+        private int getEndIndex() {
+            return startRow.getIndex() + length - 1;
+        }
+
+    }
+
+    /** The selected row ranges. */
+    private final HashSet<SelectionRange> selectedRowRanges = new HashSet<SelectionRange>();
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public boolean initializedAndAttached = false;
+
+    /**
+     * Flag to indicate if a column width recalculation is needed due update.
+     * <p>
+     * For internal use only. May be removed or replaced in the future.
+     */
+    public boolean headerChangedDuringUpdate = false;
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public final TableHead tHead = new TableHead();
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public final TableFooter tFoot = new TableFooter();
+
+    /** Handles context menu for table body. */
+    private ContextMenuOwner contextMenuOwner = new ContextMenuOwner() {
+
+        @Override
+        public void showContextMenu(Event event) {
+            int left = Util.getTouchOrMouseClientX(event);
+            int top = Util.getTouchOrMouseClientY(event);
+            boolean menuShown = handleBodyContextMenu(left, top);
+            if (menuShown) {
+                event.stopPropagation();
+                event.preventDefault();
+            }
+        }
+    };
+
+    /** Handles touch events to display a context menu for table body. */
+    private TouchContextProvider touchContextProvider = new TouchContextProvider(
+            contextMenuOwner);
+
+    /** For internal use only. May be removed or replaced in the future.
+	 * 
+	 * Overwrites onBrowserEvent function on FocusableScrollPanel to give event
+	 * access to touchContextProvider. Has to be public to give TableConnector
+	 * access to the scrollBodyPanel field.
+	 *
+	 * @author Vaadin Ltd
+	 * @since 7.2
+	 */
+    public class FocusableScrollContextPanel extends FocusableScrollPanel {
+        
+        /* (non-Javadoc)
+         * @see com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt.user.client.Event)
+         */
+        @Override
+        public void onBrowserEvent(Event event) {
+            super.onBrowserEvent(event);
+            touchContextProvider.handleTouchEvent(event);
+        };
+
+        /** Instantiates a new focusable scroll context panel.
+		 *
+		 * @param useFakeFocusElement
+		 *            the use fake focus element
+		 */
+        public FocusableScrollContextPanel(boolean useFakeFocusElement) {
+            super(useFakeFocusElement);
+        }
+    }
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public final FocusableScrollContextPanel scrollBodyPanel = new FocusableScrollContextPanel(
+            true);
+
+    /** The nav key press handler. */
+    private KeyPressHandler navKeyPressHandler = new KeyPressHandler() {
+
+        @Override
+        public void onKeyPress(KeyPressEvent keyPressEvent) {
+            // This is used for Firefox only, since Firefox auto-repeat
+            // works correctly only if we use a key press handler, other
+            // browsers handle it correctly when using a key down handler
+            if (!BrowserInfo.get().isGecko()) {
+                return;
+            }
+
+            NativeEvent event = keyPressEvent.getNativeEvent();
+            if (!enabled) {
+                // Cancel default keyboard events on a disabled Table
+                // (prevents scrolling)
+                event.preventDefault();
+            } else if (hasFocus) {
+                // Key code in Firefox/onKeyPress is present only for
+                // special keys, otherwise 0 is returned
+                int keyCode = event.getKeyCode();
+                if (keyCode == 0 && event.getCharCode() == ' ') {
+                    // Provide a keyCode for space to be compatible with
+                    // FireFox keypress event
+                    keyCode = CHARCODE_SPACE;
+                }
+
+                if (handleNavigation(keyCode,
+                        event.getCtrlKey() || event.getMetaKey(),
+                        event.getShiftKey())) {
+                    event.preventDefault();
+                }
+
+                startScrollingVelocityTimer();
+            }
+        }
+
+    };
+
+    /** The nav key up handler. */
+    private KeyUpHandler navKeyUpHandler = new KeyUpHandler() {
+
+        @Override
+        public void onKeyUp(KeyUpEvent keyUpEvent) {
+            NativeEvent event = keyUpEvent.getNativeEvent();
+            int keyCode = event.getKeyCode();
+
+            if (!isFocusable()) {
+                cancelScrollingVelocityTimer();
+            } else if (isNavigationKey(keyCode)) {
+                if (keyCode == getNavigationDownKey()
+                        || keyCode == getNavigationUpKey()) {
+                    /*
+                     * in multiselect mode the server may still have value from
+                     * previous page. Clear it unless doing multiselection or
+                     * just moving focus.
+                     */
+                    if (!event.getShiftKey() && !event.getCtrlKey()) {
+                        instructServerToForgetPreviousSelections();
+                    }
+                    sendSelectedRows();
+                }
+                cancelScrollingVelocityTimer();
+                navKeyDown = false;
+            }
+        }
+    };
+
+    /** The nav key down handler. */
+    private KeyDownHandler navKeyDownHandler = new KeyDownHandler() {
+
+        @Override
+        public void onKeyDown(KeyDownEvent keyDownEvent) {
+            NativeEvent event = keyDownEvent.getNativeEvent();
+            // This is not used for Firefox
+            if (BrowserInfo.get().isGecko()) {
+                return;
+            }
+
+            if (!enabled) {
+                // Cancel default keyboard events on a disabled Table
+                // (prevents scrolling)
+                event.preventDefault();
+            } else if (hasFocus) {
+                if (handleNavigation(event.getKeyCode(), event.getCtrlKey()
+                        || event.getMetaKey(), event.getShiftKey())) {
+                    navKeyDown = true;
+                    event.preventDefault();
+                }
+
+                startScrollingVelocityTimer();
+            }
+        }
+    };
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public int totalRows;
+
+    /** The collapsed columns. */
+    private Set<String> collapsedColumns;
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public final RowRequestHandler rowRequestHandler;
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public VScrollTableBody scrollBody;
+
+    /** The firstvisible. */
+    private int firstvisible = 0;
+    
+    /** The sort ascending. */
+    private boolean sortAscending;
+    
+    /** The sort column. */
+    private String sortColumn;
+    
+    /** The old sort column. */
+    private String oldSortColumn;
+    
+    /** The column reordering. */
+    private boolean columnReordering;
+
+    /**
+     * This map contains captions and icon urls for actions like: * "33_c" ->
+     * "Edit" * "33_i" -> "http://dom.com/edit.png"
+     */
+    private final HashMap<Object, String> actionMap = new HashMap<Object, String>();
+    
+    /** The visible col order. */
+    private String[] visibleColOrder;
+    
+    /** The initial content received. */
+    private boolean initialContentReceived = false;
+    
+    /** The scroll position element. */
+    private Element scrollPositionElement;
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public boolean enabled;
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public boolean showColHeaders;
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public boolean showColFooters;
+
+    /** flag to indicate that table body has changed. */
+    private boolean isNewBody = true;
+
+    /**
+     * Read from the "recalcWidths" -attribute. When it is true, the table will
+     * recalculate the widths for columns - desirable in some cases. For #1983,
+     * marked experimental. See also variable <code>refreshContentWidths</code>
+     * in method {@link TableHead#updateCellsFromUIDL(UIDL)}.
+     * <p>
+     * For internal use only. May be removed or replaced in the future.
+     */
+    public boolean recalcWidths = false;
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public boolean rendering = false;
+
+    /** The has focus. */
+    private boolean hasFocus = false;
+    
+    /** The dragmode. */
+    private int dragmode;
+
+    /** The multiselectmode. */
+    private int multiselectmode;
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public int tabIndex;
+
+    /** The touch scroll delegate. */
+    private TouchScrollDelegate touchScrollDelegate;
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public int lastRenderedHeight;
+
+    /**
+     * Values (serverCacheFirst+serverCacheLast) sent by server that tells which
+     * rows (indexes) are in the server side cache (page buffer). -1 means
+     * unknown. The server side cache row MUST MATCH the client side cache rows.
+     * 
+     * If the client side cache contains additional rows with e.g. buttons, it
+     * will cause out of sync when such a button is pressed.
+     * 
+     * If the server side cache contains additional rows with e.g. buttons,
+     * scrolling in the client will cause empty buttons to be rendered
+     * (cached=true request for non-existing components)
+     * 
+     * For internal use only. May be removed or replaced in the future.
+     */
+    public int serverCacheFirst = -1;
+    
+    /** The server cache last. */
+    public int serverCacheLast = -1;
+
+    /**
+     * In several cases TreeTable depends on the scrollBody.lastRendered being
+     * 'out of sync' while the update is being done. In those cases the sanity
+     * check must be performed afterwards.
+     */
+    public boolean postponeSanityCheckForLastRendered;
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public boolean sizeNeedsInit = true;
+
+    /**
+     * Used to recall the position of an open context menu if we need to close
+     * and reopen it during a row update.
+     * <p>
+     * For internal use only. May be removed or replaced in the future.
+     */
+    public class ContextMenuDetails implements CloseHandler<PopupPanel> {
+        
+        /** The row key. */
+        public String rowKey;
+        
+        /** The left. */
+        public int left;
+        
+        /** The top. */
+        public int top;
+        
+        /** The close registration. */
+        HandlerRegistration closeRegistration;
+
+        /** Instantiates a new context menu details.
+		 *
+		 * @param menu
+		 *            the menu
+		 * @param rowKey
+		 *            the row key
+		 * @param left
+		 *            the left
+		 * @param top
+		 *            the top
+		 */
+        public ContextMenuDetails(VContextMenu menu, String rowKey, int left,
+                int top) {
+            this.rowKey = rowKey;
+            this.left = left;
+            this.top = top;
+            closeRegistration = menu.addCloseHandler(this);
+        }
+
+        /* (non-Javadoc)
+         * @see com.google.gwt.event.logical.shared.CloseHandler#onClose(com.google.gwt.event.logical.shared.CloseEvent)
+         */
+        @Override
+        public void onClose(CloseEvent<PopupPanel> event) {
+            contextMenu = null;
+            closeRegistration.removeHandler();
+        }
+    }
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public ContextMenuDetails contextMenu = null;
+
+    /** The had scroll bars. */
+    private boolean hadScrollBars = false;
+
+    /** The add close handler. */
+    private HandlerRegistration addCloseHandler;
+
+    /** Changes to manage mouseDown and mouseUp. */
+    /**
+     * The element where the last mouse down event was registered.
+     */
+    private Element lastMouseDownTarget;
+
+    /**
+     * Set to true by {@link #mouseUpPreviewHandler} if it gets a mouseup at the
+     * same element as {@link #lastMouseDownTarget}.
+     */
+    private boolean mouseUpPreviewMatched = false;
+
+    /** The mouse up event preview registration. */
+    private HandlerRegistration mouseUpEventPreviewRegistration;
+
+    /**
+     * Previews events after a mousedown to detect where the following mouseup
+     * hits.
+     */
+    private final NativePreviewHandler mouseUpPreviewHandler = new NativePreviewHandler() {
+
+        @Override
+        public void onPreviewNativeEvent(NativePreviewEvent event) {
+            if (event.getTypeInt() == Event.ONMOUSEUP) {
+                mouseUpEventPreviewRegistration.removeHandler();
+
+                // Event's reported target not always correct if event
+                // capture is in use
+                Element elementUnderMouse = Util.getElementUnderMouse(event
+                        .getNativeEvent());
+                if (lastMouseDownTarget != null
+                        && lastMouseDownTarget.isOrHasChild(elementUnderMouse)) {
+                    mouseUpPreviewMatched = true;
+                } else {
+                    getLogger().log(
+                            Level.FINEST,
+                            "Ignoring mouseup from " + elementUnderMouse
+                                    + " when mousedown was on "
+                                    + lastMouseDownTarget);
+                }
+            }
+        }
+    };
+
+    /** Instantiates a new v custom scroll table.
+	 */
+    public VCustomScrollTable() {
+        setMultiSelectMode(MULTISELECT_MODE_DEFAULT);
+
+        scrollBodyPanel.addFocusHandler(this);
+        scrollBodyPanel.addBlurHandler(this);
+
+        scrollBodyPanel.addScrollHandler(this);
+
+        /*
+         * Firefox auto-repeat works correctly only if we use a key press
+         * handler, other browsers handle it correctly when using a key down
+         * handler
+         */
+        if (BrowserInfo.get().isGecko()) {
+            scrollBodyPanel.addKeyPressHandler(navKeyPressHandler);
+        } else {
+            scrollBodyPanel.addKeyDownHandler(navKeyDownHandler);
+        }
+        scrollBodyPanel.addKeyUpHandler(navKeyUpHandler);
+
+        scrollBodyPanel.sinkEvents(Event.TOUCHEVENTS | Event.ONCONTEXTMENU);
+
+        setStyleName(STYLENAME);
+
+        add(tHead);
+        add(scrollBodyPanel);
+        add(tFoot);
+
+        rowRequestHandler = new RowRequestHandler();
+    }
+
+    /* (non-Javadoc)
+     * @see com.google.gwt.user.client.ui.UIObject#setStyleName(java.lang.String)
+     */
+    @Override
+    public void setStyleName(String style) {
+        updateStyleNames(style, false);
+    }
+
+    /* (non-Javadoc)
+     * @see com.google.gwt.user.client.ui.UIObject#setStylePrimaryName(java.lang.String)
+     */
+    @Override
+    public void setStylePrimaryName(String style) {
+        updateStyleNames(style, true);
+    }
+
+    /** Update style names.
+	 *
+	 * @param newStyle
+	 *            the new style
+	 * @param isPrimary
+	 *            the is primary
+	 */
+    private void updateStyleNames(String newStyle, boolean isPrimary) {
+        scrollBodyPanel
+                .removeStyleName(getStylePrimaryName() + "-body-wrapper");
+        scrollBodyPanel.removeStyleName(getStylePrimaryName() + "-body");
+
+        if (scrollBody != null) {
+            scrollBody.removeStyleName(getStylePrimaryName()
+                    + "-body-noselection");
+        }
+
+        if (isPrimary) {
+            super.setStylePrimaryName(newStyle);
+        } else {
+            super.setStyleName(newStyle);
+        }
+
+        scrollBodyPanel.addStyleName(getStylePrimaryName() + "-body-wrapper");
+        scrollBodyPanel.addStyleName(getStylePrimaryName() + "-body");
+
+        tHead.updateStyleNames(getStylePrimaryName());
+        tFoot.updateStyleNames(getStylePrimaryName());
+
+        if (scrollBody != null) {
+            scrollBody.updateStyleNames(getStylePrimaryName());
+        }
+    }
+
+    /** Inits the.
+	 *
+	 * @param client
+	 *            the client
+	 */
+    public void init(ApplicationConnection client) {
+        this.client = client;
+        // Add a handler to clear saved context menu details when the menu
+        // closes. See #8526.
+        addCloseHandler = client.getContextMenu().addCloseHandler(
+                new CloseHandler<PopupPanel>() {
+
+                    @Override
+                    public void onClose(CloseEvent<PopupPanel> event) {
+                        contextMenu = null;
+                    }
+                });
+    }
+
+    /**
+     * Handles a context menu event on table body.
+     * 
+     * @param left
+     *            left position of the context menu
+     * @param top
+     *            top position of the context menu
+     * @return true if a context menu was shown, otherwise false
+     */
+    private boolean handleBodyContextMenu(int left, int top) {
+        if (enabled && bodyActionKeys != null) {
+            top += Window.getScrollTop();
+            left += Window.getScrollLeft();
+            client.getContextMenu().showAt(this, left, top);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Fires a column resize event which sends the resize information to the
+     * server.
+     * 
+     * @param columnId
+     *            The columnId of the column which was resized
+     * @param originalWidth
+     *            The width in pixels of the column before the resize event
+     * @param newWidth
+     *            The width in pixels of the column after the resize event
+     */
+    private void fireColumnResizeEvent(String columnId, int originalWidth,
+            int newWidth) {
+        client.updateVariable(paintableId, "columnResizeEventColumn", columnId,
+                false);
+        client.updateVariable(paintableId, "columnResizeEventPrev",
+                originalWidth, false);
+        client.updateVariable(paintableId, "columnResizeEventCurr", newWidth,
+                immediate);
+
+    }
+
+    /**
+     * Non-immediate variable update of column widths for a collection of
+     * columns.
+     * 
+     * @param columns
+     *            the columns to trigger the events for.
+     */
+    private void sendColumnWidthUpdates(Collection<HeaderCell> columns) {
+        String[] newSizes = new String[columns.size()];
+        int ix = 0;
+        for (HeaderCell cell : columns) {
+            newSizes[ix++] = cell.getColKey() + ":" + cell.getWidth();
+        }
+        client.updateVariable(paintableId, "columnWidthUpdates", newSizes,
+                false);
+    }
+
+    /** Moves the focus one step down.
+	 *
+	 * @return Returns true if succeeded
+	 */
+    private boolean moveFocusDown() {
+        return moveFocusDown(0);
+    }
+
+    /** Moves the focus down by 1+offset rows.
+	 *
+	 * @param offset
+	 *            the offset
+	 * @return Returns true if succeeded, else false if the selection could not
+	 *         be move downwards
+	 */
+    private boolean moveFocusDown(int offset) {
+        if (isSelectable()) {
+            if (focusedRow == null && scrollBody.iterator().hasNext()) {
+                // FIXME should focus first visible from top, not first rendered
+                // ??
+                return setRowFocus((VScrollTableRow) scrollBody.iterator()
+                        .next());
+            } else {
+                VScrollTableRow next = getNextRow(focusedRow, offset);
+                if (next != null) {
+                    return setRowFocus(next);
+                }
+            }
+        }
+
+        return false;
+    }
+
+    /** Moves the selection one step up.
+	 *
+	 * @return Returns true if succeeded
+	 */
+    private boolean moveFocusUp() {
+        return moveFocusUp(0);
+    }
+
+    /** Moves the focus row upwards.
+	 *
+	 * @param offset
+	 *            the offset
+	 * @return Returns true if succeeded, else false if the selection could not
+	 *         be move upwards
+	 */
+    private boolean moveFocusUp(int offset) {
+        if (isSelectable()) {
+            if (focusedRow == null && scrollBody.iterator().hasNext()) {
+                // FIXME logic is exactly the same as in moveFocusDown, should
+                // be the opposite??
+                return setRowFocus((VScrollTableRow) scrollBody.iterator()
+                        .next());
+            } else {
+                VScrollTableRow prev = getPreviousRow(focusedRow, offset);
+                if (prev != null) {
+                    return setRowFocus(prev);
+                } else {
+                    VConsole.log("no previous available");
+                }
+            }
+        }
+
+        return false;
+    }
+
+    /** Selects a row where the current selection head is.
+	 *
+	 * @param ctrlSelect
+	 *            Is the selection a ctrl+selection
+	 * @param shiftSelect
+	 *            Is the selection a shift+selection
+	 * @return Returns truw
+	 */
+    private void selectFocusedRow(boolean ctrlSelect, boolean shiftSelect) {
+        if (focusedRow != null) {
+            // Arrows moves the selection and clears previous selections
+            if (isSelectable() && !ctrlSelect && !shiftSelect) {
+                deselectAll();
+                focusedRow.toggleSelection();
+                selectionRangeStart = focusedRow;
+            } else if (isSelectable() && ctrlSelect && !shiftSelect) {
+                // Ctrl+arrows moves selection head
+                selectionRangeStart = focusedRow;
+                // No selection, only selection head is moved
+            } else if (isMultiSelectModeAny() && !ctrlSelect && shiftSelect) {
+                // Shift+arrows selection selects a range
+                focusedRow.toggleShiftSelection(shiftSelect);
+            }
+        }
+    }
+
+    /**
+     * Sends the selection to the server if changed since the last update/visit.
+     */
+    protected void sendSelectedRows() {
+        sendSelectedRows(immediate);
+    }
+
+    /**
+     * Sends the selection to the server if it has been changed since the last
+     * update/visit.
+     * 
+     * @param immediately
+     *            set to true to immediately send the rows
+     */
+    protected void sendSelectedRows(boolean immediately) {
+        // Don't send anything if selection has not changed
+        if (!selectionChanged) {
+            return;
+        }
+
+        // Reset selection changed flag
+        selectionChanged = false;
+
+        // Note: changing the immediateness of this might require changes to
+        // "clickEvent" immediateness also.
+        if (isMultiSelectModeDefault()) {
+            // Convert ranges to a set of strings
+            Set<String> ranges = new HashSet<String>();
+            for (SelectionRange range : selectedRowRanges) {
+                ranges.add(range.toString());
+            }
+
+            // Send the selected row ranges
+            client.updateVariable(paintableId, "selectedRanges",
+                    ranges.toArray(new String[selectedRowRanges.size()]), false);
+            selectedRowRanges.clear();
+
+            // clean selectedRowKeys so that they don't contain excess values
+            for (Iterator<String> iterator = selectedRowKeys.iterator(); iterator
+                    .hasNext();) {
+                String key = iterator.next();
+                VScrollTableRow renderedRowByKey = getRenderedRowByKey(key);
+                if (renderedRowByKey != null) {
+                    for (SelectionRange range : selectedRowRanges) {
+                        if (range.inRange(renderedRowByKey)) {
+                            iterator.remove();
+                        }
+                    }
+                } else {
+                    // orphaned selected key, must be in a range, ignore
+                    iterator.remove();
+                }
+
+            }
+        }
+
+        // Send the selected rows
+        client.updateVariable(paintableId, "selected",
+                selectedRowKeys.toArray(new String[selectedRowKeys.size()]),
+                immediately);
+
+    }
+
+    /**
+     * Get the key that moves the selection head upwards. By default it is the
+     * up arrow key but by overriding this you can change the key to whatever
+     * you want.
+     * 
+     * @return The keycode of the key
+     */
+    protected int getNavigationUpKey() {
+        return KeyCodes.KEY_UP;
+    }
+
+    /**
+     * Get the key that moves the selection head downwards. By default it is the
+     * down arrow key but by overriding this you can change the key to whatever
+     * you want.
+     * 
+     * @return The keycode of the key
+     */
+    protected int getNavigationDownKey() {
+        return KeyCodes.KEY_DOWN;
+    }
+
+    /**
+     * Get the key that scrolls to the left in the table. By default it is the
+     * left arrow key but by overriding this you can change the key to whatever
+     * you want.
+     * 
+     * @return The keycode of the key
+     */
+    protected int getNavigationLeftKey() {
+        return KeyCodes.KEY_LEFT;
+    }
+
+    /**
+     * Get the key that scroll to the right on the table. By default it is the
+     * right arrow key but by overriding this you can change the key to whatever
+     * you want.
+     * 
+     * @return The keycode of the key
+     */
+    protected int getNavigationRightKey() {
+        return KeyCodes.KEY_RIGHT;
+    }
+
+    /** Get the key that selects an item in the table. By default it is the
+	 * space bar key but by overriding this you can change the key to whatever
+	 * you want.
+	 *
+	 * @return the navigation select key
+	 */
+    protected int getNavigationSelectKey() {
+        return CHARCODE_SPACE;
+    }
+
+    /** Get the key the moves the selection one page up in the table. By
+	 * default this is the Page Up key but by overriding this you can change the
+	 * key to whatever you want.
+	 *
+	 * @return the navigation page up key
+	 */
+    protected int getNavigationPageUpKey() {
+        return KeyCodes.KEY_PAGEUP;
+    }
+
+    /** Get the key the moves the selection one page down in the table. By
+	 * default this is the Page Down key but by overriding this you can change
+	 * the key to whatever you want.
+	 *
+	 * @return the navigation page down key
+	 */
+    protected int getNavigationPageDownKey() {
+        return KeyCodes.KEY_PAGEDOWN;
+    }
+
+    /** Get the key the moves the selection to the beginning of the table. By
+	 * default this is the Home key but by overriding this you can change the
+	 * key to whatever you want.
+	 *
+	 * @return the navigation start key
+	 */
+    protected int getNavigationStartKey() {
+        return KeyCodes.KEY_HOME;
+    }
+
+    /** Get the key the moves the selection to the end of the table. By
+	 * default this is the End key but by overriding this you can change the key
+	 * to whatever you want.
+	 *
+	 * @return the navigation end key
+	 */
+    protected int getNavigationEndKey() {
+        return KeyCodes.KEY_END;
+    }
+
+    /** For internal use only. May be removed or replaced in the future.
+	 *
+	 * @param uidl
+	 *            the uidl
+	 * @param rowData
+	 *            the row data
+	 */
+    public void initializeRows(UIDL uidl, UIDL rowData) {
+        if (scrollBody != null) {
+            scrollBody.removeFromParent();
+        }
+
+        // Without this call the scroll position is messed up in IE even after
+        // the lazy scroller has set the scroll position to the first visible
+        // item
+        scrollBodyPanel.getScrollPosition();
+
+        scrollBody = createScrollBody();
+
+        scrollBody.renderInitialRows(rowData, uidl.getIntAttribute("firstrow"),
+                uidl.getIntAttribute("rows"));
+        scrollBodyPanel.add(scrollBody);
+
+        // New body starts scrolled to the left, make sure the header and footer
+        // are also scrolled to the left
+        tHead.setHorizontalScrollPosition(0);
+        tFoot.setHorizontalScrollPosition(0);
+
+        initialContentReceived = true;
+        sizeNeedsInit = true;
+        scrollBody.restoreRowVisibility();
+    }
+
+    /** For internal use only. May be removed or replaced in the future.
+	 *
+	 * @param uidl
+	 *            the uidl
+	 */
+    public void updateColumnProperties(UIDL uidl) {
+        updateColumnOrder(uidl);
+
+        updateCollapsedColumns(uidl);
+
+        UIDL vc = uidl.getChildByTagName("visiblecolumns");
+        if (vc != null) {
+            tHead.updateCellsFromUIDL(vc);
+            tFoot.updateCellsFromUIDL(vc);
+        }
+
+        updateHeader(uidl.getStringArrayAttribute("vcolorder"));
+        updateFooter(uidl.getStringArrayAttribute("vcolorder"));
+        if (uidl.hasVariable("noncollapsiblecolumns")) {
+            noncollapsibleColumns = uidl
+                    .getStringArrayVariableAsSet("noncollapsiblecolumns");
+        }
+    }
+
+    /** Update collapsed columns.
+	 *
+	 * @param uidl
+	 *            the uidl
+	 */
+    private void updateCollapsedColumns(UIDL uidl) {
+        if (uidl.hasVariable("collapsedcolumns")) {
+            tHead.setColumnCollapsingAllowed(true);
+            collapsedColumns = uidl
+                    .getStringArrayVariableAsSet("collapsedcolumns");
+        } else {
+            tHead.setColumnCollapsingAllowed(false);
+        }
+    }
+
+    /** Update column order.
+	 *
+	 * @param uidl
+	 *            the uidl
+	 */
+    private void updateColumnOrder(UIDL uidl) {
+        if (uidl.hasVariable("columnorder")) {
+            columnReordering = true;
+            columnOrder = uidl.getStringArrayVariable("columnorder");
+        } else {
+            columnReordering = false;
+            columnOrder = null;
+        }
+    }
+
+    /** For internal use only. May be removed or replaced in the future.
+	 *
+	 * @param uidl
+	 *            the uidl
+	 * @return true, if successful
+	 */
+    public boolean selectSelectedRows(UIDL uidl) {
+        boolean keyboardSelectionOverRowFetchInProgress = false;
+
+        if (uidl.hasVariable("selected")) {
+            final Set<String> selectedKeys = uidl
+                    .getStringArrayVariableAsSet("selected");
+            removeUnselectedRowKeys(selectedKeys);
+
+            if (scrollBody != null) {
+                Iterator<Widget> iterator = scrollBody.iterator();
+                while (iterator.hasNext()) {
+                    /*
+                     * Make the focus reflect to the server side state unless we
+                     * are currently selecting multiple rows with keyboard.
+                     */
+                    VScrollTableRow row = (VScrollTableRow) iterator.next();
+                    boolean selected = selectedKeys.contains(row.getKey());
+                    if (!selected
+                            && unSyncedselectionsBeforeRowFetch != null
+                            && unSyncedselectionsBeforeRowFetch.contains(row
+                                    .getKey())) {
+                        selected = true;
+                        keyboardSelectionOverRowFetchInProgress = true;
+                    }
+                    if (selected && selectedKeys.size() == 1) {
+                        /*
+                         * If a single item is selected, move focus to the
+                         * selected row. (#10522)
+                         */
+                        setRowFocus(row);
+                    }
+
+                    if (selected != row.isSelected()) {
+                        row.toggleSelection();
+
+                        if (!isSingleSelectMode() && !selected) {
+                            // Update selection range in case a row is
+                            // unselected from the middle of a range - #8076
+                            removeRowFromUnsentSelectionRanges(row);
+                        }
+                    }
+                }
+
+            }
+        }
+        unSyncedselectionsBeforeRowFetch = null;
+        return keyboardSelectionOverRowFetchInProgress;
+    }
+
+    /** Removes the unselected row keys.
+	 *
+	 * @param selectedKeys
+	 *            the selected keys
+	 */
+    private void removeUnselectedRowKeys(final Set<String> selectedKeys) {
+        List<String> unselectedKeys = new ArrayList<String>(0);
+        for (String key : selectedRowKeys) {
+            if (!selectedKeys.contains(key)) {
+                unselectedKeys.add(key);
+            }
+        }
+        selectedRowKeys.removeAll(unselectedKeys);
+    }
+
+    /** For internal use only. May be removed or replaced in the future.
+	 *
+	 * @param uidl
+	 *            the uidl
+	 */
+    public void updateSortingProperties(UIDL uidl) {
+        oldSortColumn = sortColumn;
+        if (uidl.hasVariable("sortascending")) {
+            sortAscending = uidl.getBooleanVariable("sortascending");
+            sortColumn = uidl.getStringVariable("sortcolumn");
+        }
+    }
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public void resizeSortedColumnForSortIndicator() {
+        // Force recalculation of the captionContainer element inside the header
+        // cell to accomodate for the size of the sort arrow.
+        HeaderCell sortedHeader = tHead.getHeaderCell(sortColumn);
+        if (sortedHeader != null) {
+            // Mark header as sorted now. Any earlier marking would lead to
+            // columns with wrong sizes
+            sortedHeader.setSorted(true);
+            tHead.resizeCaptionContainer(sortedHeader);
+        }
+        // Also recalculate the width of the captionContainer element in the
+        // previously sorted header, since this now has more room.
+        HeaderCell oldSortedHeader = tHead.getHeaderCell(oldSortColumn);
+        if (oldSortedHeader != null) {
+            tHead.resizeCaptionContainer(oldSortedHeader);
+        }
+    }
+
+    /** The lazy scroller is active. */
+    private boolean lazyScrollerIsActive;
+
+    /** Disable lazy scroller.
+	 */
+    private void disableLazyScroller() {
+        lazyScrollerIsActive = false;
+        scrollBodyPanel.getElement().getStyle().clearOverflowX();
+        scrollBodyPanel.getElement().getStyle().clearOverflowY();
+    }
+
+    /** Enable lazy scroller.
+	 */
+    private void enableLazyScroller() {
+        Scheduler.get().scheduleDeferred(lazyScroller);
+        lazyScrollerIsActive = true;
+        // prevent scrolling to jump in IE11
+        scrollBodyPanel.getElement().getStyle().setOverflowX(Overflow.HIDDEN);
+        scrollBodyPanel.getElement().getStyle().setOverflowY(Overflow.HIDDEN);
+    }
+
+    /** Checks if is lazy scroller active.
+	 *
+	 * @return true, if is lazy scroller active
+	 */
+    private boolean isLazyScrollerActive() {
+        return lazyScrollerIsActive;
+    }
+
+    /** The lazy scroller. */
+    private ScheduledCommand lazyScroller = new ScheduledCommand() {
+
+        @Override
+        public void execute() {
+            if (firstvisible >= 0) {
+                firstRowInViewPort = firstvisible;
+                if (firstvisibleOnLastPage > -1) {
+                    scrollBodyPanel
+                            .setScrollPosition(measureRowHeightOffset(firstvisibleOnLastPage));
+                } else {
+                    scrollBodyPanel
+                            .setScrollPosition(measureRowHeightOffset(firstvisible));
+                }
+            }
+            disableLazyScroller();
+        }
+    };
+
+    /** For internal use only. May be removed or replaced in the future.
+	 *
+	 * @param uidl
+	 *            the uidl
+	 */
+    public void updateFirstVisibleAndScrollIfNeeded(UIDL uidl) {
+        firstvisible = uidl.hasVariable("firstvisible") ? uidl
+                .getIntVariable("firstvisible") : 0;
+        firstvisibleOnLastPage = uidl.hasVariable("firstvisibleonlastpage") ? uidl
+                .getIntVariable("firstvisibleonlastpage") : -1;
+        if (firstvisible != lastRequestedFirstvisible && scrollBody != null) {
+
+            // Update lastRequestedFirstvisible right away here
+            // (don't rely on update in the timer which could be cancelled).
+            lastRequestedFirstvisible = firstRowInViewPort;
+
+            // Only scroll if the first visible changes from the server side.
+            // Else we might unintentionally scroll even when the scroll
+            // position has not changed.
+            enableLazyScroller();
+        }
+    }
+
+    /** Measure row height offset.
+	 *
+	 * @param rowIx
+	 *            the row ix
+	 * @return the int
+	 */
+    protected int measureRowHeightOffset(int rowIx) {
+        return (int) (rowIx * scrollBody.getRowHeight());
+    }
+
+    /** For internal use only. May be removed or replaced in the future.
+	 *
+	 * @param uidl
+	 *            the uidl
+	 */
+    public void updatePageLength(UIDL uidl) {
+        int oldPageLength = pageLength;
+        if (uidl.hasAttribute("pagelength")) {
+            pageLength = uidl.getIntAttribute("pagelength");
+        } else {
+            // pagelenght is "0" meaning scrolling is turned off
+            pageLength = totalRows;
+        }
+
+        if (oldPageLength != pageLength && initializedAndAttached) {
+            // page length changed, need to update size
+            sizeNeedsInit = true;
+        }
+    }
+
+    /** For internal use only. May be removed or replaced in the future.
+	 *
+	 * @param uidl
+	 *            the uidl
+	 * @param state
+	 *            the state
+	 * @param readOnly
+	 *            the read only
+	 */
+    public void updateSelectionProperties(UIDL uidl,
+            AbstractComponentState state, boolean readOnly) {
+        setMultiSelectMode(uidl.hasAttribute("multiselectmode") ? uidl
+                .getIntAttribute("multiselectmode") : MULTISELECT_MODE_DEFAULT);
+
+        nullSelectionAllowed = uidl.hasAttribute("nsa") ? uidl
+                .getBooleanAttribute("nsa") : true;
+
+        if (uidl.hasAttribute("selectmode")) {
+            if (readOnly) {
+                selectMode = SelectMode.NONE;
+            } else if (uidl.getStringAttribute("selectmode").equals("multi")) {
+                selectMode = SelectMode.MULTI;
+            } else if (uidl.getStringAttribute("selectmode").equals("single")) {
+                selectMode = SelectMode.SINGLE;
+            } else {
+                selectMode = SelectMode.NONE;
+            }
+        }
+    }
+
+    /** For internal use only. May be removed or replaced in the future.
+	 *
+	 * @param uidl
+	 *            the uidl
+	 */
+    public void updateDragMode(UIDL uidl) {
+        dragmode = uidl.hasAttribute("dragmode") ? uidl
+                .getIntAttribute("dragmode") : 0;
+        if (BrowserInfo.get().isIE()) {
+            if (dragmode > 0) {
+                getElement().setPropertyJSO("onselectstart",
+                        getPreventTextSelectionIEHack());
+            } else {
+                getElement().setPropertyJSO("onselectstart", null);
+            }
+        }
+    }
+
+    /** For internal use only. May be removed or replaced in the future.
+	 *
+	 * @param uidl
+	 *            the uidl
+	 */
+    public void updateTotalRows(UIDL uidl) {
+        int newTotalRows = uidl.getIntAttribute("totalrows");
+        if (newTotalRows != getTotalRows()) {
+            if (scrollBody != null) {
+                if (getTotalRows() == 0) {
+                    tHead.clear();
+                    tFoot.clear();
+                }
+                initializedAndAttached = false;
+                initialContentReceived = false;
+                isNewBody = true;
+            }
+            setTotalRows(newTotalRows);
+        }
+    }
+
+    /** Sets the for internal use only.
+	 *
+	 * @param newTotalRows
+	 *            the new for internal use only
+	 */
+    protected void setTotalRows(int newTotalRows) {
+        totalRows = newTotalRows;
+    }
+
+    /** Gets the for internal use only.
+	 *
+	 * @return the for internal use only
+	 */
+    public int getTotalRows() {
+        return totalRows;
+    }
+
+    /**
+     * Returns the extra space that is given to the header column when column
+     * width is determined by header text.
+     * 
+     * @return extra space in pixels
+     */
+    private int getHeaderPadding() {
+        return scrollBody.getCellExtraWidth();
+    }
+
+    /**
+     * This method exists for the needs of {@link VTreeTable} only. Not part of
+     * the official API, <b>extend at your own risk</b>. May be removed or
+     * replaced in the future.
+     * 
+     * @return index of TreeTable's hierarchy column, or -1 if not applicable
+     */
+    protected int getHierarchyColumnIndex() {
+        return -1;
+    }
+
+    /**
+     * For internal use only. May be removed or replaced in the future.
+     */
+    public void updateMaxIndent() {
+        int oldIndent = scrollBody.getMaxIndent();
+        scrollBody.calculateMaxIndent();
+        if (oldIndent != scrollBody.getMaxIndent()) {
+            // indent updated, headers might need adjusting
+            triggerLazyColumnAdjustment(true);
+        }
+    }
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public void focusRowFromBody() {
+        if (selectedRowKeys.size() == 1) {
+            // try to focus a row currently selected and in viewport
+            String selectedRowKey = selectedRowKeys.iterator().next();
+            if (selectedRowKey != null) {
+                VScrollTableRow renderedRow = getRenderedRowByKey(selectedRowKey);
+                if (renderedRow == null || !renderedRow.isInViewPort()) {
+                    setRowFocus(scrollBody.getRowByRowIndex(firstRowInViewPort));
+                } else {
+                    setRowFocus(renderedRow);
+                }
+            }
+        } else {
+            // multiselect mode
+            setRowFocus(scrollBody.getRowByRowIndex(firstRowInViewPort));
+        }
+    }
+
+    /** Creates the scroll body.
+	 *
+	 * @return the v scroll table body
+	 */
+    protected VScrollTableBody createScrollBody() {
+        return new VScrollTableBody();
+    }
+
+    /**
+     * Selects the last row visible in the table
+     * <p>
+     * For internal use only. May be removed or replaced in the future.
+     * 
+     * @param focusOnly
+     *            Should the focus only be moved to the last row
+     */
+    public void selectLastRenderedRowInViewPort(boolean focusOnly) {
+        int index = firstRowInViewPort + getFullyVisibleRowCount();
+        VScrollTableRow lastRowInViewport = scrollBody.getRowByRowIndex(index);
+        if (lastRowInViewport == null) {
+            // this should not happen in normal situations (white space at the
+            // end of viewport). Select the last rendered as a fallback.
+            lastRowInViewport = scrollBody.getRowByRowIndex(scrollBody
+                    .getLastRendered());
+            if (lastRowInViewport == null) {
+                return; // empty table
+            }
+        }
+        setRowFocus(lastRowInViewport);
+        if (!focusOnly) {
+            selectFocusedRow(false, multiselectPending);
+            sendSelectedRows();
+        }
+    }
+
+    /**
+     * Selects the first row visible in the table
+     * <p>
+     * For internal use only. May be removed or replaced in the future.
+     * 
+     * @param focusOnly
+     *            Should the focus only be moved to the first row
+     */
+    public void selectFirstRenderedRowInViewPort(boolean focusOnly) {
+        int index = firstRowInViewPort;
+        VScrollTableRow firstInViewport = scrollBody.getRowByRowIndex(index);
+        if (firstInViewport == null) {
+            // this should not happen in normal situations
+            return;
+        }
+        setRowFocus(firstInViewport);
+        if (!focusOnly) {
+            selectFocusedRow(false, multiselectPending);
+            sendSelectedRows();
+        }
+    }
+
+    /** For internal use only. May be removed or replaced in the future.
+	 *
+	 * @param uidl
+	 *            the new cache rate from uidl
+	 */
+    public void setCacheRateFromUIDL(UIDL uidl) {
+        setCacheRate(uidl.hasAttribute("cr") ? uidl.getDoubleAttribute("cr")
+                : CACHE_RATE_DEFAULT);
+    }
+
+    /** Sets the cache rate.
+	 *
+	 * @param d
+	 *            the new cache rate
+	 */
+    private void setCacheRate(double d) {
+        if (cache_rate != d) {
+            cache_rate = d;
+            cache_react_rate = 0.75 * d;
+        }
+    }
+
+    /** For internal use only. May be removed or replaced in the future.
+	 *
+	 * @param mainUidl
+	 *            the main uidl
+	 */
+    public void updateActionMap(UIDL mainUidl) {
+        UIDL actionsUidl = mainUidl.getChildByTagName("actions");
+        if (actionsUidl == null) {
+            return;
+        }
+
+        final Iterator<?> it = actionsUidl.getChildIterator();
+        while (it.hasNext()) {
+            final UIDL action = (UIDL) it.next();
+            final String key = action.getStringAttribute("key");
+            final String caption = action.getStringAttribute("caption");
+            actionMap.put(key + "_c", caption);
+            if (action.hasAttribute("icon")) {
+                // TODO need some uri handling ??
+                actionMap.put(key + "_i", client.translateVaadinUri(action
+                        .getStringAttribute("icon")));
+            } else {
+                actionMap.remove(key + "_i");
+            }
+        }
+
+    }
+
+    /** Gets the action caption.
+	 *
+	 * @param actionKey
+	 *            the action key
+	 * @return the action caption
+	 */
+    public String getActionCaption(String actionKey) {
+        return actionMap.get(actionKey + "_c");
+    }
+
+    /** Gets the action icon.
+	 *
+	 * @param actionKey
+	 *            the action key
+	 * @return the action icon
+	 */
+    public String getActionIcon(String actionKey) {
+        return actionMap.get(actionKey + "_i");
+    }
+
+    /** Update header.
+	 *
+	 * @param strings
+	 *            the strings
+	 */
+    private void updateHeader(String[] strings) {
+        if (strings == null) {
+            return;
+        }
+
+        int visibleCols = strings.length;
+        int colIndex = 0;
+        if (showRowHeaders) {
+            tHead.enableColumn(ROW_HEADER_COLUMN_KEY, colIndex);
+            visibleCols++;
+            visibleColOrder = new String[visibleCols];
+            visibleColOrder[colIndex] = ROW_HEADER_COLUMN_KEY;
+            colIndex++;
+        } else {
+            visibleColOrder = new String[visibleCols];
+            tHead.removeCell(ROW_HEADER_COLUMN_KEY);
+        }
+
+        int i;
+        for (i = 0; i < strings.length; i++) {
+            final String cid = strings[i];
+            visibleColOrder[colIndex] = cid;
+            tHead.enableColumn(cid, colIndex);
+            colIndex++;
+        }
+
+        tHead.setVisible(showColHeaders);
+        setContainerHeight();
+
+    }
+
+    /** Updates footers.
+	 * <p>
+	 * Update headers whould be called before this method is called!
+	 * </p>
+	 *
+	 * @param strings
+	 *            the strings
+	 */
+    private void updateFooter(String[] strings) {
+        if (strings == null) {
+            return;
+        }
+
+        // Add dummy column if row headers are present
+        int colIndex = 0;
+        if (showRowHeaders) {
+            tFoot.enableColumn(ROW_HEADER_COLUMN_KEY, colIndex);
+            colIndex++;
+        } else {
+            tFoot.removeCell(ROW_HEADER_COLUMN_KEY);
+        }
+
+        int i;
+        for (i = 0; i < strings.length; i++) {
+            final String cid = strings[i];
+            tFoot.enableColumn(cid, colIndex);
+            colIndex++;
+        }
+
+        tFoot.setVisible(showColFooters);
+    }
+
+    /**
+     * For internal use only. May be removed or replaced in the future.
+     * 
+     * @param uidl
+     *            which contains row data
+     * @param firstRow
+     *            first row in data set
+     * @param reqRows
+     *            amount of rows in data set
+     */
+    public void updateBody(UIDL uidl, int firstRow, int reqRows) {
+        int oldIndent = scrollBody.getMaxIndent();
+        if (uidl == null || reqRows < 1) {
+            // container is empty, remove possibly existing rows
+            if (firstRow <= 0) {
+                postponeSanityCheckForLastRendered = true;
+                while (scrollBody.getLastRendered() > scrollBody
+                        .getFirstRendered()) {
+                    scrollBody.unlinkRow(false);
+                }
+                postponeSanityCheckForLastRendered = false;
+                scrollBody.unlinkRow(false);
+            }
+            return;
+        }
+
+        scrollBody.renderRows(uidl, firstRow, reqRows);
+
+        discardRowsOutsideCacheWindow();
+        scrollBody.calculateMaxIndent();
+        if (oldIndent != scrollBody.getMaxIndent()) {
+            // indent updated, headers might need adjusting
+            headerChangedDuringUpdate = true;
+        }
+    }
+
+    /** For internal use only. May be removed or replaced in the future.
+	 *
+	 * @param partialRowUpdates
+	 *            the partial row updates
+	 */
+    public void updateRowsInBody(UIDL partialRowUpdates) {
+        if (partialRowUpdates == null) {
+            return;
+        }
+        int firstRowIx = partialRowUpdates.getIntAttribute("firsturowix");
+        int count = partialRowUpdates.getIntAttribute("numurows");
+        scrollBody.unlinkRows(firstRowIx, count);
+        scrollBody.insertRows(partialRowUpdates, firstRowIx, count);
+    }
+
+    /**
+     * Updates the internal cache by unlinking rows that fall outside of the
+     * caching window.
+     */
+    protected void discardRowsOutsideCacheWindow() {
+        int firstRowToKeep = (int) (firstRowInViewPort - pageLength
+                * cache_rate);
+        int lastRowToKeep = (int) (firstRowInViewPort + pageLength + pageLength
+                * cache_rate);
+        // sanity checks:
+        if (firstRowToKeep < 0) {
+            firstRowToKeep = 0;
+        }
+        if (lastRowToKeep > totalRows) {
+            lastRowToKeep = totalRows - 1;
+        }
+        debug("Client side calculated cache rows to keep: " + firstRowToKeep
+                + "-" + lastRowToKeep);
+
+        if (serverCacheFirst != -1) {
+            firstRowToKeep = serverCacheFirst;
+            lastRowToKeep = serverCacheLast;
+            debug("Server cache rows that override: " + serverCacheFirst + "-"
+                    + serverCacheLast);
+            if (firstRowToKeep < scrollBody.getFirstRendered()
+                    || lastRowToKeep > scrollBody.getLastRendered()) {
+                debug("*** Server wants us to keep " + serverCacheFirst + "-"
+                        + serverCacheLast + " but we only have rows "
+                        + scrollBody.getFirstRendered() + "-"
+                        + scrollBody.getLastRendered() + " rendered!");
+            }
+        }
+        discardRowsOutsideOf(firstRowToKeep, lastRowToKeep);
+
+        scrollBody.fixSpacers();
+
+        scrollBody.restoreRowVisibility();
+    }
+
+    /** Discard rows outside of.
+	 *
+	 * @param optimalFirstRow
+	 *            the optimal first row
+	 * @param optimalLastRow
+	 *            the optimal last row
+	 */
+    private void discardRowsOutsideOf(int optimalFirstRow, int optimalLastRow) {
+        /*
+         * firstDiscarded and lastDiscarded are only calculated for debug
+         * purposes
+         */
+        int firstDiscarded = -1, lastDiscarded = -1;
+        boolean cont = true;
+        while (cont && scrollBody.getLastRendered() > optimalFirstRow
+                && scrollBody.getFirstRendered() < optimalFirstRow) {
+            if (firstDiscarded == -1) {
+                firstDiscarded = scrollBody.getFirstRendered();
+            }
+
+            // removing row from start
+            cont = scrollBody.unlinkRow(true);
+        }
+        if (firstDiscarded != -1) {
+            lastDiscarded = scrollBody.getFirstRendered() - 1;
+            debug("Discarded rows " + firstDiscarded + "-" + lastDiscarded);
+        }
+        firstDiscarded = lastDiscarded = -1;
+
+        cont = true;
+        while (cont && scrollBody.getLastRendered() > optimalLastRow) {
+            if (lastDiscarded == -1) {
+                lastDiscarded = scrollBody.getLastRendered();
+            }
+
+            // removing row from the end
+            cont = scrollBody.unlinkRow(false);
+        }
+        if (lastDiscarded != -1) {
+            firstDiscarded = scrollBody.getLastRendered() + 1;
+            debug("Discarded rows " + firstDiscarded + "-" + lastDiscarded);
+        }
+
+        debug("Now in cache: " + scrollBody.getFirstRendered() + "-"
+                + scrollBody.getLastRendered());
+    }
+
+    /**
+     * Inserts rows in the table body or removes them from the table body based
+     * on the commands in the UIDL.
+     * <p>
+     * For internal use only. May be removed or replaced in the future.
+     * 
+     * @param partialRowAdditions
+     *            the UIDL containing row updates.
+     */
+    public void addAndRemoveRows(UIDL partialRowAdditions) {
+        if (partialRowAdditions == null) {
+            return;
+        }
+        if (partialRowAdditions.hasAttribute("hide")) {
+            scrollBody.unlinkAndReindexRows(
+                    partialRowAdditions.getIntAttribute("firstprowix"),
+                    partialRowAdditions.getIntAttribute("numprows"));
+            scrollBody.ensureCacheFilled();
+        } else {
+            if (partialRowAdditions.hasAttribute("delbelow")) {
+                scrollBody.insertRowsDeleteBelow(partialRowAdditions,
+                        partialRowAdditions.getIntAttribute("firstprowix"),
+                        partialRowAdditions.getIntAttribute("numprows"));
+            } else {
+                scrollBody.insertAndReindexRows(partialRowAdditions,
+                        partialRowAdditions.getIntAttribute("firstprowix"),
+                        partialRowAdditions.getIntAttribute("numprows"));
+            }
+        }
+
+        discardRowsOutsideCacheWindow();
+    }
+
+    /** Gives correct column index for given column key ("cid" in UIDL).
+	 *
+	 * @param colKey
+	 *            the col key
+	 * @return column index of visible columns, -1 if column not visible
+	 */
+    private int getColIndexByKey(String colKey) {
+        // return 0 if asked for rowHeaders
+        if (ROW_HEADER_COLUMN_KEY.equals(colKey)) {
+            return 0;
+        }
+        for (int i = 0; i < visibleColOrder.length; i++) {
+            if (visibleColOrder[i].equals(colKey)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /** Checks if is multi select mode simple.
+	 *
+	 * @return true, if is multi select mode simple
+	 */
+    private boolean isMultiSelectModeSimple() {
+        return selectMode == SelectMode.MULTI
+                && multiselectmode == MULTISELECT_MODE_SIMPLE;
+    }
+
+    /** Checks if is single select mode.
+	 *
+	 * @return true, if is single select mode
+	 */
+    private boolean isSingleSelectMode() {
+        return selectMode == SelectMode.SINGLE;
+    }
+
+    /** Checks if is multi select mode any.
+	 *
+	 * @return true, if is multi select mode any
+	 */
+    private boolean isMultiSelectModeAny() {
+        return selectMode == SelectMode.MULTI;
+    }
+
+    /** Checks if is multi select mode default.
+	 *
+	 * @return true, if is multi select mode default
+	 */
+    private boolean isMultiSelectModeDefault() {
+        return selectMode == SelectMode.MULTI
+                && multiselectmode == MULTISELECT_MODE_DEFAULT;
+    }
+
+    /** Sets the multi select mode.
+	 *
+	 * @param multiselectmode
+	 *            the new multi select mode
+	 */
+    private void setMultiSelectMode(int multiselectmode) {
+        if (BrowserInfo.get().isTouchDevice()) {
+            // Always use the simple mode for touch devices that do not have
+            // shift/ctrl keys
+            this.multiselectmode = MULTISELECT_MODE_SIMPLE;
+        } else {
+            this.multiselectmode = multiselectmode;
+        }
+
+    }
+
+    /** For internal use only. May be removed or replaced in the future.
+	 *
+	 * @return true, if is selectable
+	 */
+    public boolean isSelectable() {
+        return selectMode.getId() > SelectMode.NONE.getId();
+    }
+
+    /** Checks if is collapsed column.
+	 *
+	 * @param colKey
+	 *            the col key
+	 * @return true, if is collapsed column
+	 */
+    private boolean isCollapsedColumn(String colKey) {
+        if (collapsedColumns == null) {
+            return false;
+        }
+        if (collapsedColumns.contains(colKey)) {
+            return true;
+        }
+        return false;
+    }
+
+    /** Gets the col key by index.
+	 *
+	 * @param index
+	 *            the index
+	 * @return the col key by index
+	 */
+    private String getColKeyByIndex(int index) {
+        return tHead.getHeaderCell(index).getColKey();
+    }
+
+    /**
+     * Note: not part of the official API, extend at your own risk. May be
+     * removed or replaced in the future.
+     * 
+     * Sets the indicated column's width for headers and scrollBody alike.
+     * 
+     * @param colIndex
+     *            index of the modified column
+     * @param w
+     *            new width (may be subject to modifications if doesn't meet
+     *            minimum requirements)
+     * @param isDefinedWidth
+     *            disables expand ratio if set true
+     */
+    protected void setColWidth(int colIndex, int w, boolean isDefinedWidth) {
+        final HeaderCell hcell = tHead.getHeaderCell(colIndex);
+
+        // Make sure that the column grows to accommodate the sort indicator if
+        // necessary.
+        // get min width with no indent or padding
+        int minWidth = hcell.getMinWidth(false, false);
+        if (w < minWidth) {
+            w = minWidth;
+        }
+
+        // Set header column width WITHOUT INDENT
+        hcell.setWidth(w, isDefinedWidth);
+
+        // Set footer column width likewise
+        FooterCell fcell = tFoot.getFooterCell(colIndex);
+        fcell.setWidth(w, isDefinedWidth);
+
+        // Ensure indicators have been taken into account
+        tHead.resizeCaptionContainer(hcell);
+
+        // Make sure that the body column grows to accommodate the indent if
+        // necessary.
+        // get min width with indent, no padding
+        minWidth = hcell.getMinWidth(true, false);
+        if (w < minWidth) {
+            w = minWidth;
+        }
+
+        // Set body column width
+        scrollBody.setColWidth(colIndex, w);
+    }
+
+    /** Gets the col width.
+	 *
+	 * @param colKey
+	 *            the col key
+	 * @return the col width
+	 */
+    private int getColWidth(String colKey) {
+        return tHead.getHeaderCell(colKey).getWidthWithIndent();
+    }
+
+    /** Get a rendered row by its key.
+	 *
+	 * @param key
+	 *            The key to search with
+	 * @return the rendered row by key
+	 */
+    public VScrollTableRow getRenderedRowByKey(String key) {
+        if (scrollBody != null) {
+            final Iterator<Widget> it = scrollBody.iterator();
+            VScrollTableRow r = null;
+            while (it.hasNext()) {
+                r = (VScrollTableRow) it.next();
+                if (r.getKey().equals(key)) {
+                    return r;
+                }
+            }
+        }
+        return null;
+    }
+
+    /** Returns the next row to the given row.
+	 *
+	 * @param row
+	 *            The row to calculate from
+	 * @param offset
+	 *            the offset
+	 * @return The next row or null if no row exists
+	 */
+    private VScrollTableRow getNextRow(VScrollTableRow row, int offset) {
+        final Iterator<Widget> it = scrollBody.iterator();
+        VScrollTableRow r = null;
+        while (it.hasNext()) {
+            r = (VScrollTableRow) it.next();
+            if (r == row) {
+                r = null;
+                while (offset >= 0 && it.hasNext()) {
+                    r = (VScrollTableRow) it.next();
+                    offset--;
+                }
+                return r;
+            }
+        }
+
+        return null;
+    }
+
+    /** Returns the previous row from the given row.
+	 *
+	 * @param row
+	 *            The row to calculate from
+	 * @param offset
+	 *            the offset
+	 * @return The previous row or null if no row exists
+	 */
+    private VScrollTableRow getPreviousRow(VScrollTableRow row, int offset) {
+        final Iterator<Widget> it = scrollBody.iterator();
+        final Iterator<Widget> offsetIt = scrollBody.iterator();
+        VScrollTableRow r = null;
+        VScrollTableRow prev = null;
+        while (it.hasNext()) {
+            r = (VScrollTableRow) it.next();
+            if (offset < 0) {
+                prev = (VScrollTableRow) offsetIt.next();
+            }
+            if (r == row) {
+                return prev;
+            }
+            offset--;
+        }
+
+        return null;
+    }
+
+    /** Re order column.
+	 *
+	 * @param columnKey
+	 *            the column key
+	 * @param newIndex
+	 *            the new index
+	 */
+    protected void reOrderColumn(String columnKey, int newIndex) {
+
+        final int oldIndex = getColIndexByKey(columnKey);
+
+        // Change header order
+        tHead.moveCell(oldIndex, newIndex);
+
+        // Change body order
+        scrollBody.moveCol(oldIndex, newIndex);
+
+        // Change footer order
+        tFoot.moveCell(oldIndex, newIndex);
+
+        /*
+         * Build new columnOrder and update it to server Note that columnOrder
+         * also contains collapsed columns so we cannot directly build it from
+         * cells vector Loop the old columnOrder and append in order to new
+         * array unless on moved columnKey. On new index also put the moved key
+         * i == index on columnOrder, j == index on newOrder
+         */
+        final String oldKeyOnNewIndex = visibleColOrder[newIndex];
+        if (showRowHeaders) {
+            newIndex--; // columnOrder don't have rowHeader
+        }
+        // add back hidden rows,
+        for (int i = 0; i < columnOrder.length; i++) {
+            if (columnOrder[i].equals(oldKeyOnNewIndex)) {
+                break; // break loop at target
+            }
+            if (isCollapsedColumn(columnOrder[i])) {
+                newIndex++;
+            }
+        }
+        // finally we can build the new columnOrder for server
+        final String[] newOrder = new String[columnOrder.length];
+        for (int i = 0, j = 0; j < newOrder.length; i++) {
+            if (j == newIndex) {
+                newOrder[j] = columnKey;
+                j++;
+            }
+            if (i == columnOrder.length) {
+                break;
+            }
+            if (columnOrder[i].equals(columnKey)) {
+                continue;
+            }
+            newOrder[j] = columnOrder[i];
+            j++;
+        }
+        columnOrder = newOrder;
+        // also update visibleColumnOrder
+        int i = showRowHeaders ? 1 : 0;
+        for (int j = 0; j < newOrder.length; j++) {
+            final String cid = newOrder[j];
+            if (!isCollapsedColumn(cid)) {
+                visibleColOrder[i++] = cid;
+            }
+        }
+        client.updateVariable(paintableId, "columnorder", columnOrder, false);
+        if (client.hasEventListeners(this,
+                TableConstants.COLUMN_REORDER_EVENT_ID)) {
+            client.sendPendingVariableChanges();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see com.google.gwt.user.client.ui.Widget#onDetach()
+     */
+    @Override
+    protected void onDetach() {
+        detachedScrollPosition = scrollBodyPanel.getScrollPosition();
+        rowRequestHandler.cancel();
+        super.onDetach();
+        // ensure that scrollPosElement will be detached
+        if (scrollPositionElement != null) {
+            final Element parent = DOM.getParent(scrollPositionElement);
+            if (parent != null) {
+                DOM.removeChild(parent, scrollPositionElement);
+            }
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see com.google.gwt.user.client.ui.Widget#onAttach()
+     */
+    @Override
+    public void onAttach() {
+        super.onAttach();
+        scrollBodyPanel.setScrollPosition(detachedScrollPosition);
+    }
+
+    /**
+     * Run only once when component is attached and received its initial
+     * content. This function:
+     * 
+     * * Syncs headers and bodys "natural widths and saves the values.
+     * 
+     * * Sets proper width and height
+     * 
+     * * Makes deferred request to get some cache rows
+     * 
+     * For internal use only. May be removed or replaced in the future.
+     */
+    public void sizeInit() {
+        sizeNeedsInit = false;
+
+        scrollBody.setContainerHeight();
+
+        /*
+         * We will use browsers table rendering algorithm to find proper column
+         * widths. If content and header take less space than available, we will
+         * divide extra space relatively to each column which has not width set.
+         * 
+         * Overflow pixels are added to last column.
+         */
+
+        Iterator<Widget> headCells = tHead.iterator();
+        Iterator<Widget> footCells = tFoot.iterator();
+        int i = 0;
+        int totalExplicitColumnsWidths = 0;
+        int total = 0;
+        float expandRatioDivider = 0;
+
+        final int[] widths = new int[tHead.visibleCells.size()];
+
+        tHead.enableBrowserIntelligence();
+        tFoot.enableBrowserIntelligence();
+
+        int hierarchyColumnIndent = scrollBody != null ? scrollBody
+                .getMaxIndent() : 0;
+        HeaderCell hierarchyHeaderWithExpandRatio = null;
+
+        // first loop: collect natural widths
+        while (headCells.hasNext()) {
+            final HeaderCell hCell = (HeaderCell) headCells.next();
+            final FooterCell fCell = (FooterCell) footCells.next();
+            boolean needsIndent = hierarchyColumnIndent > 0
+                    && hCell.isHierarchyColumn();
+            int w = hCell.getWidth();
+            if (hCell.isDefinedWidth()) {
+                // server has defined column width explicitly
+                if (needsIndent && w < hierarchyColumnIndent) {
+                    // hierarchy indent overrides explicitly set width
+                    w = hierarchyColumnIndent;
+                }
+                totalExplicitColumnsWidths += w;
+            } else {
+                if (hCell.getExpandRatio() > 0) {
+                    expandRatioDivider += hCell.getExpandRatio();
+                    w = 0;
+                    if (needsIndent && w < hierarchyColumnIndent) {
+                        hierarchyHeaderWithExpandRatio = hCell;
+                        // don't add to widths here, because will be included in
+                        // the expand ratio space if there's enough of it
+                    }
+                } else {
+                    // get and store greater of header width and column width,
+                    // and store it as a minimum natural column width (these
+                    // already contain the indent if any)
+                    int headerWidth = hCell.getNaturalColumnWidth(i);
+                    int footerWidth = fCell.getNaturalColumnWidth(i);
+                    w = headerWidth > footerWidth ? headerWidth : footerWidth;
+                }
+                hCell.setNaturalMinimumColumnWidth(w);
+                fCell.setNaturalMinimumColumnWidth(w);
+            }
+            widths[i] = w;
+            total += w;
+            i++;
+        }
+        if (hierarchyHeaderWithExpandRatio != null) {
+            total += hierarchyColumnIndent;
+        }
+
+        tHead.disableBrowserIntelligence();
+        tFoot.disableBrowserIntelligence();
+
+        boolean willHaveScrollbarz = willHaveScrollbars();
+
+        // fix "natural" width if width not set
+        if (isDynamicWidth()) {
+            int w = total;
+            w += scrollBody.getCellExtraWidth() * visibleColOrder.length;
+            if (willHaveScrollbarz) {
+                w += Util.getNativeScrollbarSize();
+            }
+            setContentWidth(w);
+        }
+
+        int availW = scrollBody.getAvailableWidth();
+        if (BrowserInfo.get().isIE()) {
+            // Hey IE, are you really sure about this?
+            availW = scrollBody.getAvailableWidth();
+        }
+        availW -= scrollBody.getCellExtraWidth() * visibleColOrder.length;
+
+        if (willHaveScrollbarz) {
+            availW -= Util.getNativeScrollbarSize();
+        }
+
+        // TODO refactor this code to be the same as in resize timer
+
+        if (availW > total) {
+            // natural size is smaller than available space
+            int extraSpace = availW - total;
+            if (hierarchyHeaderWithExpandRatio != null) {
+                /*
+                 * add the indent's space back to ensure each column gets an
+                 * even share according to the expand ratios (note: if the
+                 * allocated space isn't enough for the hierarchy column it
+                 * shall be treated like a defined width column and the indent
+                 * space gets removed from the extra space again)
+                 */
+                extraSpace += hierarchyColumnIndent;
+            }
+            final int totalWidthR = total - totalExplicitColumnsWidths;
+            int checksum = 0;
+
+            if (extraSpace == 1) {
+                // We cannot divide one single pixel so we give it the first
+                // undefined column
+                // no need to worry about indent here
+                headCells = tHead.iterator();
+                i = 0;
+                checksum = availW;
+                while (headCells.hasNext()) {
+                    HeaderCell hc = (HeaderCell) headCells.next();
+                    if (!hc.isDefinedWidth()) {
+                        widths[i]++;
+                        break;
+                    }
+                    i++;
+                }
+
+            } else if (expandRatioDivider > 0) {
+                boolean setIndentToHierarchyHeader = false;
+                if (hierarchyHeaderWithExpandRatio != null) {
+                    // ensure first that the hierarchyColumn gets at least the
+                    // space allocated for indent
+                    final int newSpace = Math
+                            .round((extraSpace * (hierarchyHeaderWithExpandRatio
+                                    .getExpandRatio() / expandRatioDivider)));
+                    if (newSpace < hierarchyColumnIndent) {
+                        // not enough space for indent, remove indent from the
+                        // extraSpace again and handle hierarchy column's header
+                        // separately
+                        setIndentToHierarchyHeader = true;
+                        extraSpace -= hierarchyColumnIndent;
+                    }
+                }
+
+                // visible columns have some active expand ratios, excess
+                // space is divided according to them
+                headCells = tHead.iterator();
+                i = 0;
+                while (headCells.hasNext()) {
+                    HeaderCell hCell = (HeaderCell) headCells.next();
+                    if (hCell.getExpandRatio() > 0) {
+                        int w = widths[i];
+                        if (setIndentToHierarchyHeader
+                                && hierarchyHeaderWithExpandRatio.equals(hCell)) {
+                            // hierarchy column's header is no longer part of
+                            // the expansion divide and only gets indent
+                            w += hierarchyColumnIndent;
+                        } else {
+                            final int newSpace = Math
+                                    .round((extraSpace * (hCell
+                                            .getExpandRatio() / expandRatioDivider)));
+                            w += newSpace;
+                        }
+                        widths[i] = w;
+                    }
+                    checksum += widths[i];
+                    i++;
+                }
+            } else if (totalWidthR > 0) {
+                // no expand ratios defined, we will share extra space
+                // relatively to "natural widths" among those without
+                // explicit width
+                // no need to worry about indent here, it's already included
+                headCells = tHead.iterator();
+                i = 0;
+                while (headCells.hasNext()) {
+                    HeaderCell hCell = (HeaderCell) headCells.next();
+                    if (!hCell.isDefinedWidth()) {
+                        int w = widths[i];
+                        final int newSpace = Math.round((float) extraSpace
+                                * (float) w / totalWidthR);
+                        w += newSpace;
+                        widths[i] = w;
+                    }
+                    checksum += widths[i];
+                    i++;
+                }
+            }
+
+            if (extraSpace > 0 && checksum != availW) {
+                /*
+                 * There might be in some cases a rounding error of 1px when
+                 * extra space is divided so if there is one then we give the
+                 * first undefined column 1 more pixel
+                 */
+                headCells = tHead.iterator();
+                i = 0;
+                while (headCells.hasNext()) {
+                    HeaderCell hc = (HeaderCell) headCells.next();
+                    if (!hc.isDefinedWidth()) {
+                        widths[i] += availW - checksum;
+                        break;
+                    }
+                    i++;
+                }
+            }
+
+        } else {
+            // body's size will be more than available and scrollbar will appear
+        }
+
+        // last loop: set possibly modified values or reset if new tBody
+        i = 0;
+        headCells = tHead.iterator();
+        while (headCells.hasNext()) {
+            final HeaderCell hCell = (HeaderCell) headCells.next();
+            if (isNewBody || hCell.getWidth() == -1) {
+                final int w = widths[i];
+                setColWidth(i, w, false);
+            }
+            i++;
+        }
+
+        initializedAndAttached = true;
+
+        updatePageLength();
+
+        /*
+         * Fix "natural" height if height is not set. This must be after width
+         * fixing so the components' widths have been adjusted.
+         */
+        if (isDynamicHeight()) {
+            /*
+             * We must force an update of the row height as this point as it
+             * might have been (incorrectly) calculated earlier
+             */
+
+            /*
+             * TreeTable updates stuff in a funky order, so we must set the
+             * height as zero here before doing the real update to make it
+             * realize that there is no content,
+             */
+            if (pageLength == totalRows && pageLength == 0) {
+                scrollBody.setHeight("0px");
+            }
+
+            int bodyHeight;
+            if (pageLength == totalRows) {
+                /*
+                 * A hack to support variable height rows when paging is off.
+                 * Generally this is not supported by scrolltable. We want to
+                 * show all rows so the bodyHeight should be equal to the table
+                 * height.
+                 */
+                // int bodyHeight = scrollBody.getOffsetHeight();
+                bodyHeight = scrollBody.getRequiredHeight();
+            } else {
+                bodyHeight = (int) Math.round(scrollBody.getRowHeight(true)
+                        * pageLength);
+            }
+            boolean needsSpaceForHorizontalSrollbar = (total > availW);
+            if (needsSpaceForHorizontalSrollbar) {
+                bodyHeight += Util.getNativeScrollbarSize();
+            }
+            scrollBodyPanel.setHeight(bodyHeight + "px");
+            Util.runWebkitOverflowAutoFix(scrollBodyPanel.getElement());
+        }
+
+        isNewBody = false;
+
+        if (firstvisible > 0) {
+            enableLazyScroller();
+        }
+
+        if (enabled) {
+            // Do we need cache rows
+            if (scrollBody.getLastRendered() + 1 < firstRowInViewPort
+                    + pageLength + (int) cache_react_rate * pageLength) {
+                if (totalRows - 1 > scrollBody.getLastRendered()) {
+                    // fetch cache rows
+                    int firstInNewSet = scrollBody.getLastRendered() + 1;
+                    int lastInNewSet = (int) (firstRowInViewPort + pageLength + cache_rate
+                            * pageLength);
+                    if (lastInNewSet > totalRows - 1) {
+                        lastInNewSet = totalRows - 1;
+                    }
+                    rowRequestHandler.triggerRowFetch(firstInNewSet,
+                            lastInNewSet - firstInNewSet + 1, 1);
+                }
+            }
+        }
+
+        /*
+         * Ensures the column alignments are correct at initial loading. <br>
+         * (child components widths are correct)
+         */
+        Util.runWebkitOverflowAutoFixDeferred(scrollBodyPanel.getElement());
+
+        hadScrollBars = willHaveScrollbarz;
+    }
+
+    /**
+     * Note: this method is not part of official API although declared as
+     * protected. Extend at your own risk.
+     * 
+     * @return true if content area will have scrollbars visible.
+     */
+    protected boolean willHaveScrollbars() {
+        if (isDynamicHeight()) {
+            if (pageLength < totalRows) {
+                return true;
+            }
+        } else {
+            int fakeheight = (int) Math.round(scrollBody.getRowHeight()
+                    * totalRows);
+            int availableHeight = scrollBodyPanel.getElement().getPropertyInt(
+                    "clientHeight");
+            if (fakeheight > availableHeight) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /** Announce scroll position.
+	 */
+    private void announceScrollPosition() {
+        if (scrollPositionElement == null) {
+            scrollPositionElement = DOM.createDiv();
+            scrollPositionElement.setClassName(getStylePrimaryName()
+                    + "-scrollposition");
+            scrollPositionElement.getStyle().setPosition(Position.ABSOLUTE);
+            scrollPositionElement.getStyle().setDisplay(Display.NONE);
+            getElement().appendChild(scrollPositionElement);
+        }
+
+        Style style = scrollPositionElement.getStyle();
+        style.setMarginLeft(getElement().getOffsetWidth() / 2 - 80, Unit.PX);
+        style.setMarginTop(-scrollBodyPanel.getOffsetHeight(), Unit.PX);
+
+        // indexes go from 1-totalRows, as rowheaders in index-mode indicate
+        int last = (firstRowInViewPort + pageLength);
+        if (last > totalRows) {
+            last = totalRows;
+        }
+        scrollPositionElement.setInnerHTML("<span>" + (firstRowInViewPort + 1)
+                + " &ndash; " + (last) + "..." + "</span>");
+        style.setDisplay(Display.BLOCK);
+    }
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public void hideScrollPositionAnnotation() {
+        if (scrollPositionElement != null) {
+            scrollPositionElement.getStyle().setDisplay(Display.NONE);
+        }
+    }
+
+    /** For internal use only. May be removed or replaced in the future.
+	 *
+	 * @return true, if is scroll position visible
+	 */
+    public boolean isScrollPositionVisible() {
+        return scrollPositionElement != null
+                && !scrollPositionElement.getStyle().getDisplay()
+                        .equals(Display.NONE.toString());
+    }
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public class RowRequestHandler extends Timer {
+
+        /** The req first row. */
+        private int reqFirstRow = 0;
+        
+        /** The req rows. */
+        private int reqRows = 0;
+        
+        /** The is request handler running. */
+        private boolean isRequestHandlerRunning = false;
+
+        /** Trigger row fetch.
+		 *
+		 * @param first
+		 *            the first
+		 * @param rows
+		 *            the rows
+		 */
+        public void triggerRowFetch(int first, int rows) {
+            setReqFirstRow(first);
+            setReqRows(rows);
+            deferRowFetch();
+        }
+
+        /** Trigger row fetch.
+		 *
+		 * @param first
+		 *            the first
+		 * @param rows
+		 *            the rows
+		 * @param delay
+		 *            the delay
+		 */
+        public void triggerRowFetch(int first, int rows, int delay) {
+            setReqFirstRow(first);
+            setReqRows(rows);
+            deferRowFetch(delay);
+        }
+
+        /** Defer row fetch.
+		 */
+        public void deferRowFetch() {
+            deferRowFetch(250);
+        }
+
+        /** Checks if is request handler running.
+		 *
+		 * @return true, if is request handler running
+		 */
+        public boolean isRequestHandlerRunning() {
+            return isRequestHandlerRunning;
+        }
+
+        /** Defer row fetch.
+		 *
+		 * @param msec
+		 *            the msec
+		 */
+        public void deferRowFetch(int msec) {
+            isRequestHandlerRunning = true;
+            if (reqRows > 0 && reqFirstRow < totalRows) {
+                schedule(msec);
+
+                // tell scroll position to user if currently "visible" rows are
+                // not rendered
+                if (totalRows > pageLength
+                        && ((firstRowInViewPort + pageLength > scrollBody
+                                .getLastRendered()) || (firstRowInViewPort < scrollBody
+                                .getFirstRendered()))) {
+                    announceScrollPosition();
+                } else {
+                    hideScrollPositionAnnotation();
+                }
+            }
+        }
+
+        /** Gets the req first row.
+		 *
+		 * @return the req first row
+		 */
+        public int getReqFirstRow() {
+            return reqFirstRow;
+        }
+
+        /** Sets the req first row.
+		 *
+		 * @param reqFirstRow
+		 *            the new req first row
+		 */
+        public void setReqFirstRow(int reqFirstRow) {
+            if (reqFirstRow < 0) {
+                this.reqFirstRow = 0;
+            } else if (reqFirstRow >= totalRows) {
+                this.reqFirstRow = totalRows - 1;
+            } else {
+                this.reqFirstRow = reqFirstRow;
+            }
+        }
+
+        /** Sets the req rows.
+		 *
+		 * @param reqRows
+		 *            the new req rows
+		 */
+        public void setReqRows(int reqRows) {
+            if (reqRows < 0) {
+                this.reqRows = 0;
+            } else if (reqFirstRow + reqRows > totalRows) {
+                this.reqRows = totalRows - reqFirstRow;
+            } else {
+                this.reqRows = reqRows;
+            }
+        }
+
+        /* (non-Javadoc)
+         * @see com.google.gwt.user.client.Timer#run()
+         */
+        @Override
+        public void run() {
+            if (client.getMessageSender().hasActiveRequest() || navKeyDown) {
+                // if client connection is busy, don't bother loading it more
+                VConsole.log("Postponed rowfetch");
+                schedule(250);
+            } else if (!updatedReqRows && allRenderedRowsAreNew()) {
+
+                /*
+                 * If all rows are new, there might have been a server-side call
+                 * to Table.setCurrentPageFirstItemIndex(int) In this case,
+                 * scrolling event takes way too late, and all the rows from
+                 * previous viewport to this one were requested.
+                 * 
+                 * This should prevent requesting unneeded rows by updating
+                 * reqFirstRow and reqRows before needing them. See (#14135)
+                 */
+
+                setReqFirstRow((firstRowInViewPort - (int) (pageLength * cache_rate)));
+                int last = firstRowInViewPort + (int) (cache_rate * pageLength)
+                        + pageLength - 1;
+                if (last >= totalRows) {
+                    last = totalRows - 1;
+                }
+                setReqRows(last - getReqFirstRow() + 1);
+                updatedReqRows = true;
+                schedule(250);
+            } else {
+
+                int firstRendered = scrollBody.getFirstRendered();
+                int lastRendered = scrollBody.getLastRendered();
+                if (lastRendered > totalRows) {
+                    lastRendered = totalRows - 1;
+                }
+                boolean rendered = firstRendered >= 0 && lastRendered >= 0;
+
+                int firstToBeRendered = firstRendered;
+
+                if (reqFirstRow < firstToBeRendered) {
+                    firstToBeRendered = reqFirstRow;
+                } else if (firstRowInViewPort - (int) (cache_rate * pageLength) > firstToBeRendered) {
+                    firstToBeRendered = firstRowInViewPort
+                            - (int) (cache_rate * pageLength);
+                    if (firstToBeRendered < 0) {
+                        firstToBeRendered = 0;
+                    }
+                } else if (rendered && firstRendered + 1 < reqFirstRow
+                        && lastRendered + 1 < reqFirstRow) {
+                    // requested rows must fall within the requested rendering
+                    // area
+                    firstToBeRendered = reqFirstRow;
+                }
+                if (firstToBeRendered + reqRows < firstRendered) {
+                    // must increase the required row count accordingly,
+                    // otherwise may leave a gap and the rows beyond will get
+                    // removed
+                    setReqRows(firstRendered - firstToBeRendered);
+                }
+
+                int lastToBeRendered = lastRendered;
+                int lastReqRow = reqFirstRow + reqRows - 1;
+
+                if (lastReqRow > lastToBeRendered) {
+                    lastToBeRendered = lastReqRow;
+                } else if (firstRowInViewPort + pageLength + pageLength
+                        * cache_rate < lastToBeRendered) {
+                    lastToBeRendered = (firstRowInViewPort + pageLength + (int) (pageLength * cache_rate));
+                    if (lastToBeRendered >= totalRows) {
+                        lastToBeRendered = totalRows - 1;
+                    }
+                    // due Safari 3.1 bug (see #2607), verify reqrows, original
+                    // problem unknown, but this should catch the issue
+                    if (lastReqRow > lastToBeRendered) {
+                        setReqRows(lastToBeRendered - reqFirstRow);
+                    }
+                } else if (rendered && lastRendered - 1 > lastReqRow
+                        && firstRendered - 1 > lastReqRow) {
+                    // requested rows must fall within the requested rendering
+                    // area
+                    lastToBeRendered = lastReqRow;
+                }
+
+                if (lastToBeRendered > totalRows) {
+                    lastToBeRendered = totalRows - 1;
+                }
+                if (reqFirstRow < firstToBeRendered
+                        || (reqFirstRow > firstToBeRendered && (reqFirstRow < firstRendered || reqFirstRow > lastRendered + 1))) {
+                    setReqFirstRow(firstToBeRendered);
+                }
+                if (lastRendered < lastToBeRendered
+                        && lastRendered + reqRows < lastToBeRendered) {
+                    // must increase the required row count accordingly,
+                    // otherwise may leave a gap and the rows after will get
+                    // removed
+                    setReqRows(lastToBeRendered - lastRendered);
+                } else if (lastToBeRendered >= firstRendered
+                        && reqFirstRow + reqRows < firstRendered) {
+                    setReqRows(lastToBeRendered - lastRendered);
+                }
+
+                client.updateVariable(paintableId, "firstToBeRendered",
+                        firstToBeRendered, false);
+                client.updateVariable(paintableId, "lastToBeRendered",
+                        lastToBeRendered, false);
+
+                // don't request server to update page first index in case it
+                // has not been changed
+                if (firstRowInViewPort != firstvisible) {
+                    // remember which firstvisible we requested, in case the
+                    // server has a differing opinion
+                    lastRequestedFirstvisible = firstRowInViewPort;
+                    client.updateVariable(paintableId, "firstvisible",
+                            firstRowInViewPort, false);
+                }
+                client.updateVariable(paintableId, "reqfirstrow", reqFirstRow,
+                        false);
+                client.updateVariable(paintableId, "reqrows", reqRows, true);
+
+                if (selectionChanged) {
+                    unSyncedselectionsBeforeRowFetch = new HashSet<Object>(
+                            selectedRowKeys);
+                }
+                isRequestHandlerRunning = false;
+            }
+        }
+
+        /**
+         * Sends request to refresh content at this position.
+         */
+        public void refreshContent() {
+            isRequestHandlerRunning = true;
+            int first = (int) (firstRowInViewPort - pageLength * cache_rate);
+            int reqRows = (int) (2 * pageLength * cache_rate + pageLength);
+            if (first < 0) {
+                reqRows = reqRows + first;
+                first = 0;
+            }
+            setReqFirstRow(first);
+            setReqRows(reqRows);
+            run();
+        }
+    }
+
+    /** The Class HeaderCell.
+	 */
+    public class HeaderCell extends Widget {
+
+        /** The td. */
+        Element td = DOM.createTD();
+
+        /** The caption container. */
+        Element captionContainer = DOM.createDiv();
+
+        /** The sort indicator. */
+        Element sortIndicator = DOM.createDiv();
+
+        /** The col resize widget. */
+        Element colResizeWidget = DOM.createDiv();
+
+        /** The floating copy of header cell. */
+        Element floatingCopyOfHeaderCell;
+
+        /** The sortable. */
+        private boolean sortable = false;
+        
+        /** The cid. */
+        private final String cid;
+        
+        /** The dragging. */
+        private boolean dragging;
+
+        /** The drag start x. */
+        private int dragStartX;
+        
+        /** The col index. */
+        private int colIndex;
+        
+        /** The original width. */
+        private int originalWidth;
+
+        /** The is resizing. */
+        private boolean isResizing;
+
+        /** The header x. */
+        private int headerX;
+
+        /** The moved. */
+        private boolean moved;
+
+        /** The closest slot. */
+        private int closestSlot;
+
+        /** The width. */
+        private int width = -1;
+
+        /** The natural width. */
+        private int naturalWidth = -1;
+
+        /** The align. */
+        private char align = ALIGN_LEFT;
+
+        /** The defined width. */
+        boolean definedWidth = false;
+
+        /** The expand ratio. */
+        private float expandRatio = 0;
+
+        /** The sorted. */
+        private boolean sorted;
+
+        /** Sets the sortable.
+		 *
+		 * @param b
+		 *            the new sortable
+		 */
+        public void setSortable(boolean b) {
+            sortable = b;
+        }
+
+        /** Makes room for the sorting indicator in case the column that the
+		 * header cell belongs to is sorted. This is done by resizing the width
+		 * of the caption container element by the correct amount
+		 *
+		 * @param rightSpacing
+		 *            the right spacing
+		 */
+        public void resizeCaptionContainer(int rightSpacing) {
+            int captionContainerWidth = width
+                    - colResizeWidget.getOffsetWidth() - rightSpacing;
+
+            if (td.getClassName().contains("-asc")
+                    || td.getClassName().contains("-desc")) {
+                // Leave room for the sort indicator
+                captionContainerWidth -= sortIndicator.getOffsetWidth();
+            }
+
+            if (captionContainerWidth < 0) {
+                rightSpacing += captionContainerWidth;
+                captionContainerWidth = 0;
+            }
+
+            captionContainer.getStyle().setPropertyPx("width",
+                    captionContainerWidth);
+
+            // Apply/Remove spacing if defined
+            if (rightSpacing > 0) {
+                colResizeWidget.getStyle().setMarginLeft(rightSpacing, Unit.PX);
+            } else {
+                colResizeWidget.getStyle().clearMarginLeft();
+            }
+        }
+
+        /** Sets the natural minimum column width.
+		 *
+		 * @param w
+		 *            the new natural minimum column width
+		 */
+        public void setNaturalMinimumColumnWidth(int w) {
+            naturalWidth = w;
+        }
+
+        /** Instantiates a new header cell.
+		 *
+		 * @param colId
+		 *            the col id
+		 * @param headerText
+		 *            the header text
+		 */
+        public HeaderCell(String colId, String headerText) {
+            cid = colId;
+
+            setText(headerText);
+
+            td.appendChild(colResizeWidget);
+
+            // ensure no clipping initially (problem on column additions)
+            captionContainer.getStyle().setOverflow(Overflow.VISIBLE);
+
+            td.appendChild(sortIndicator);
+            td.appendChild(captionContainer);
+
+            DOM.sinkEvents(td, Event.MOUSEEVENTS | Event.ONDBLCLICK
+                    | Event.ONCONTEXTMENU | Event.TOUCHEVENTS);
+
+            setElement(td);
+
+            setAlign(ALIGN_LEFT);
+        }
+
+        /** Update style names.
+		 *
+		 * @param primaryStyleName
+		 *            the primary style name
+		 */
+        protected void updateStyleNames(String primaryStyleName) {
+            colResizeWidget.setClassName(primaryStyleName + "-resizer");
+            sortIndicator.setClassName(primaryStyleName + "-sort-indicator");
+            captionContainer.setClassName(primaryStyleName
+                    + "-caption-container");
+            if (sorted) {
+                if (sortAscending) {
+                    setStyleName(primaryStyleName + "-header-cell-asc");
+                } else {
+                    setStyleName(primaryStyleName + "-header-cell-desc");
+                }
+            } else {
+                setStyleName(primaryStyleName + "-header-cell");
+            }
+
+            final String ALIGN_PREFIX = primaryStyleName
+                    + "-caption-container-align-";
+
+            switch (align) {
+            case ALIGN_CENTER:
+                captionContainer.addClassName(ALIGN_PREFIX + "center");
+                break;
+            case ALIGN_RIGHT:
+                captionContainer.addClassName(ALIGN_PREFIX + "right");
+                break;
+            default:
+                captionContainer.addClassName(ALIGN_PREFIX + "left");
+                break;
+            }
+
+        }
+
+        /** Disable auto width calculation.
+		 */
+        public void disableAutoWidthCalculation() {
+            definedWidth = true;
+            expandRatio = 0;
+        }
+
+        /**
+         * Sets width to the header cell. This width should not include any
+         * possible indent modifications that are present in
+         * {@link VScrollTableBody#getMaxIndent()}.
+         * 
+         * @param w
+         *            required width of the cell sans indentations
+         * @param ensureDefinedWidth
+         *            disables expand ratio if required
+         */
+        public void setWidth(int w, boolean ensureDefinedWidth) {
+            if (ensureDefinedWidth) {
+                definedWidth = true;
+                // on column resize expand ratio becomes zero
+                expandRatio = 0;
+            }
+            if (width == -1) {
+                // go to default mode, clip content if necessary
+                captionContainer.getStyle().clearOverflow();
+            }
+            width = w;
+            if (w == -1) {
+                captionContainer.getStyle().clearWidth();
+                setWidth("");
+            } else {
+                tHead.resizeCaptionContainer(this);
+
+                /*
+                 * if we already have tBody, set the header width properly, if
+                 * not defer it. IE will fail with complex float in table header
+                 * unless TD width is not explicitly set.
+                 */
+                if (scrollBody != null) {
+                    int maxIndent = scrollBody.getMaxIndent();
+                    if (w < maxIndent && isHierarchyColumn()) {
+                        w = maxIndent;
+                    }
+                    int tdWidth = w + scrollBody.getCellExtraWidth();
+                    setWidth(tdWidth + "px");
+                } else {
+                    Scheduler.get().scheduleDeferred(new Command() {
+
+                        @Override
+                        public void execute() {
+                            int maxIndent = scrollBody.getMaxIndent();
+                            int tdWidth = width;
+                            if (tdWidth < maxIndent && isHierarchyColumn()) {
+                                tdWidth = maxIndent;
+                            }
+                            tdWidth += scrollBody.getCellExtraWidth();
+                            setWidth(tdWidth + "px");
+                        }
+                    });
+                }
+            }
+        }
+
+        /** Sets the undefined width.
+		 */
+        public void setUndefinedWidth() {
+            definedWidth = false;
+            if (!isResizing) {
+                setWidth(-1, false);
+            }
+        }
+
+        /**
+         * Detects if width is fixed by developer on server side or resized to
+         * current width by user.
+         * 
+         * @return true if defined, false if "natural" width
+         */
+        public boolean isDefinedWidth() {
+            return definedWidth && width >= 0;
+        }
+
+        /**
+         * This method exists for the needs of {@link VTreeTable} only.
+         * 
+         * Returns the pixels width of the header cell. This includes the
+         * indent, if applicable.
+         * 
+         * @return The width in pixels
+         */
+        public int getWidthWithIndent() {
+            if (scrollBody != null && isHierarchyColumn()) {
+                int maxIndent = scrollBody.getMaxIndent();
+                if (maxIndent > width) {
+                    return maxIndent;
+                }
+            }
+            return width;
+        }
+
+        /**
+         * Returns the pixels width of the header cell.
+         * 
+         * @return The width in pixels
+         */
+        public int getWidth() {
+            return width;
+        }
+
+        /**
+         * This method exists for the needs of {@link VTreeTable} only.
+         * 
+         * @return <code>true</code> if this is hierarcyColumn's header cell,
+         *         <code>false</code> otherwise
+         */
+        private boolean isHierarchyColumn() {
+            int hierarchyColumnIndex = getHierarchyColumnIndex();
+            return hierarchyColumnIndex >= 0
+                    && tHead.visibleCells.indexOf(this) == hierarchyColumnIndex;
+        }
+
+        /** Sets the text.
+		 *
+		 * @param headerText
+		 *            the new text
+		 */
+        public void setText(String headerText) {
+            DOM.setInnerHTML(captionContainer, headerText);
+        }
+
+        /** Gets the col key.
+		 *
+		 * @return the col key
+		 */
+        public String getColKey() {
+            return cid;
+        }
+
+        /** Sets the sorted.
+		 *
+		 * @param sorted
+		 *            the new sorted
+		 */
+        private void setSorted(boolean sorted) {
+            this.sorted = sorted;
+            updateStyleNames(VCustomScrollTable.this.getStylePrimaryName());
+        }
+
+        /** Handle column reordering.
+		 *
+		 * @param event
+		 *            the event
+		 */
+
+        @Override
+        public void onBrowserEvent(Event event) {
+            if (enabled && event != null) {
+                if (isResizing
+                        || event.getEventTarget().cast() == colResizeWidget) {
+                    if (dragging
+                            && (event.getTypeInt() == Event.ONMOUSEUP || event
+                                    .getTypeInt() == Event.ONTOUCHEND)) {
+                        // Handle releasing column header on spacer #5318
+                        handleCaptionEvent(event);
+                    } else {
+                        onResizeEvent(event);
+                    }
+                } else {
+                    /*
+                     * Ensure focus before handling caption event. Otherwise
+                     * variables changed from caption event may be before
+                     * variables from other components that fire variables when
+                     * they lose focus.
+                     */
+                    if (event.getTypeInt() == Event.ONMOUSEDOWN
+                            || event.getTypeInt() == Event.ONTOUCHSTART) {
+                        scrollBodyPanel.setFocus(true);
+                    }
+                    handleCaptionEvent(event);
+                    boolean stopPropagation = true;
+                    if (event.getTypeInt() == Event.ONCONTEXTMENU
+                            && !client.hasEventListeners(
+                                    VCustomScrollTable.this,
+                                    TableConstants.HEADER_CLICK_EVENT_ID)) {
+                        // Prevent showing the browser's context menu only when
+                        // there is a header click listener.
+                        stopPropagation = false;
+                    }
+                    if (stopPropagation) {
+                        event.stopPropagation();
+                        event.preventDefault();
+                    }
+                }
+            }
+        }
+
+        /** Creates the floating copy.
+		 */
+        private void createFloatingCopy() {
+            floatingCopyOfHeaderCell = DOM.createDiv();
+            DOM.setInnerHTML(floatingCopyOfHeaderCell, DOM.getInnerHTML(td));
+            floatingCopyOfHeaderCell = DOM
+                    .getChild(floatingCopyOfHeaderCell, 2);
+            // #12714 the shown "ghost element" should be inside
+            // v-overlay-container, and it should contain the same styles as the
+            // table to enable theming (except v-table & v-widget).
+            String stylePrimaryName = VCustomScrollTable.this
+                    .getStylePrimaryName();
+            StringBuilder sb = new StringBuilder();
+            for (String s : VCustomScrollTable.this.getStyleName().split(" ")) {
+                if (!s.equals(StyleConstants.UI_WIDGET)) {
+                    sb.append(s);
+                    if (s.equals(stylePrimaryName)) {
+                        sb.append("-header-drag ");
+                    } else {
+                        sb.append(" ");
+                    }
+                }
+            }
+            floatingCopyOfHeaderCell.setClassName(sb.toString().trim());
+            // otherwise might wrap or be cut if narrow column
+            floatingCopyOfHeaderCell.getStyle().setProperty("width", "auto");
+            updateFloatingCopysPosition(DOM.getAbsoluteLeft(td),
+                    DOM.getAbsoluteTop(td));
+            DOM.appendChild(VOverlay.getOverlayContainer(client),
+                    floatingCopyOfHeaderCell);
+        }
+
+        /** Update floating copys position.
+		 *
+		 * @param x
+		 *            the x
+		 * @param y
+		 *            the y
+		 */
+        private void updateFloatingCopysPosition(int x, int y) {
+            x -= DOM.getElementPropertyInt(floatingCopyOfHeaderCell,
+                    "offsetWidth") / 2;
+            floatingCopyOfHeaderCell.getStyle().setLeft(x, Unit.PX);
+            if (y > 0) {
+                floatingCopyOfHeaderCell.getStyle().setTop(y + 7, Unit.PX);
+            }
+        }
+
+        /** Hide floating copy.
+		 */
+        private void hideFloatingCopy() {
+            floatingCopyOfHeaderCell.removeFromParent();
+            floatingCopyOfHeaderCell = null;
+        }
+
+        /** Fires a header click event after the user has clicked a column
+		 * header cell.
+		 *
+		 * @param event
+		 *            The click event
+		 */
+        private void fireHeaderClickedEvent(Event event) {
+            if (client.hasEventListeners(VCustomScrollTable.this,
+                    TableConstants.HEADER_CLICK_EVENT_ID)) {
+                MouseEventDetails details = MouseEventDetailsBuilder
+                        .buildMouseEventDetails(event);
+                client.updateVariable(paintableId, "headerClickEvent",
+                        details.toString(), false);
+                client.updateVariable(paintableId, "headerClickCID", cid, true);
+            }
+        }
+
+        /** Handle caption event.
+		 *
+		 * @param event
+		 *            the event
+		 */
+        protected void handleCaptionEvent(Event event) {
+            switch (DOM.eventGetType(event)) {
+            case Event.ONTOUCHSTART:
+            case Event.ONMOUSEDOWN:
+                if (columnReordering
+                        && Util.isTouchEventOrLeftMouseButton(event)) {
+                    if (event.getTypeInt() == Event.ONTOUCHSTART) {
+                        /*
+                         * prevent using this event in e.g. scrolling
+                         */
+                        event.stopPropagation();
+                    }
+                    dragging = true;
+                    moved = false;
+                    colIndex = getColIndexByKey(cid);
+                    DOM.setCapture(getElement());
+                    headerX = tHead.getAbsoluteLeft();
+                    event.preventDefault(); // prevent selecting text &&
+                                            // generated touch events
+                }
+                break;
+            case Event.ONMOUSEUP:
+            case Event.ONTOUCHEND:
+            case Event.ONTOUCHCANCEL:
+                if (columnReordering
+                        && Util.isTouchEventOrLeftMouseButton(event)) {
+                    dragging = false;
+                    DOM.releaseCapture(getElement());
+                    if (moved) {
+                        hideFloatingCopy();
+                        tHead.removeSlotFocus();
+                        if (closestSlot != colIndex
+                                && closestSlot != (colIndex + 1)) {
+                            if (closestSlot > colIndex) {
+                                reOrderColumn(cid, closestSlot - 1);
+                            } else {
+                                reOrderColumn(cid, closestSlot);
+                            }
+                        }
+                    }
+                    if (Util.isTouchEvent(event)) {
+                        /*
+                         * Prevent using in e.g. scrolling and prevent generated
+                         * events.
+                         */
+                        event.preventDefault();
+                        event.stopPropagation();
+                    }
+                }
+
+                if (!moved) {
+                    // mouse event was a click to header -> sort column
+                    if (sortable && Util.isTouchEventOrLeftMouseButton(event)) {
+                        if (sortColumn.equals(cid)) {
+                            // just toggle order
+                            client.updateVariable(paintableId, "sortascending",
+                                    !sortAscending, false);
+                        } else {
+                            // set table sorted by this column
+                            client.updateVariable(paintableId, "sortcolumn",
+                                    cid, false);
+                        }
+                        // get also cache columns at the same request
+                        scrollBodyPanel.setScrollPosition(0);
+                        firstvisible = 0;
+                        rowRequestHandler.setReqFirstRow(0);
+                        rowRequestHandler.setReqRows((int) (2 * pageLength
+                                * cache_rate + pageLength));
+                        rowRequestHandler.deferRowFetch(); // some validation +
+                                                           // defer 250ms
+                        rowRequestHandler.cancel(); // instead of waiting
+                        rowRequestHandler.run(); // run immediately
+                    }
+                    fireHeaderClickedEvent(event);
+                    if (Util.isTouchEvent(event)) {
+                        /*
+                         * Prevent using in e.g. scrolling and prevent generated
+                         * events.
+                         */
+                        event.preventDefault();
+                        event.stopPropagation();
+                    }
+                    break;
+                }
+                break;
+            case Event.ONDBLCLICK:
+                fireHeaderClickedEvent(event);
+                break;
+            case Event.ONTOUCHMOVE:
+            case Event.ONMOUSEMOVE:
+                if (dragging && Util.isTouchEventOrLeftMouseButton(event)) {
+                    if (event.getTypeInt() == Event.ONTOUCHMOVE) {
+                        /*
+                         * prevent using this event in e.g. scrolling
+                         */
+                        event.stopPropagation();
+                    }
+                    if (!moved) {
+                        createFloatingCopy();
+                        moved = true;
+                    }
+
+                    final int clientX = Util.getTouchOrMouseClientX(event);
+                    final int x = clientX + tHead.hTableWrapper.getScrollLeft();
+                    int slotX = headerX;
+                    closestSlot = colIndex;
+                    int closestDistance = -1;
+                    int start = 0;
+                    if (showRowHeaders) {
+                        start++;
+                    }
+                    final int visibleCellCount = tHead.getVisibleCellCount();
+                    for (int i = start; i <= visibleCellCount; i++) {
+                        if (i > 0) {
+                            final String colKey = getColKeyByIndex(i - 1);
+                            // getColWidth only returns the internal width
+                            // without padding, not the offset width of the
+                            // whole td (#10890)
+                            slotX += getColWidth(colKey)
+                                    + scrollBody.getCellExtraWidth();
+                        }
+                        final int dist = Math.abs(x - slotX);
+                        if (closestDistance == -1 || dist < closestDistance) {
+                            closestDistance = dist;
+                            closestSlot = i;
+                        }
+                    }
+                    tHead.focusSlot(closestSlot);
+
+                    updateFloatingCopysPosition(clientX, -1);
+                }
+                break;
+            default:
+                break;
+            }
+        }
+
+        /** On resize event.
+		 *
+		 * @param event
+		 *            the event
+		 */
+        private void onResizeEvent(Event event) {
+            switch (DOM.eventGetType(event)) {
+            case Event.ONMOUSEDOWN:
+                if (!Util.isTouchEventOrLeftMouseButton(event)) {
+                    return;
+                }
+                isResizing = true;
+                DOM.setCapture(getElement());
+                dragStartX = DOM.eventGetClientX(event);
+                colIndex = getColIndexByKey(cid);
+                originalWidth = getWidthWithIndent();
+                DOM.eventPreventDefault(event);
+                break;
+            case Event.ONMOUSEUP:
+                if (!Util.isTouchEventOrLeftMouseButton(event)) {
+                    return;
+                }
+                isResizing = false;
+                DOM.releaseCapture(getElement());
+                tHead.disableAutoColumnWidthCalculation(this);
+
+                // Ensure last header cell is taking into account possible
+                // column selector
+                HeaderCell lastCell = tHead.getHeaderCell(tHead
+                        .getVisibleCellCount() - 1);
+                tHead.resizeCaptionContainer(lastCell);
+                triggerLazyColumnAdjustment(true);
+
+                fireColumnResizeEvent(cid, originalWidth, getColWidth(cid));
+                break;
+            case Event.ONMOUSEMOVE:
+                if (!Util.isTouchEventOrLeftMouseButton(event)) {
+                    return;
+                }
+                if (isResizing) {
+                    final int deltaX = DOM.eventGetClientX(event) - dragStartX;
+                    if (deltaX == 0) {
+                        return;
+                    }
+                    tHead.disableAutoColumnWidthCalculation(this);
+
+                    int newWidth = originalWidth + deltaX;
+                    // get min width with indent, no padding
+                    int minWidth = getMinWidth(true, false);
+                    if (newWidth < minWidth) {
+                        // already includes indent if any
+                        newWidth = minWidth;
+                    }
+                    setColWidth(colIndex, newWidth, true);
+                    triggerLazyColumnAdjustment(false);
+                    forceRealignColumnHeaders();
+                }
+                break;
+            default:
+                break;
+            }
+        }
+
+        /** Returns the smallest possible cell width in pixels.
+		 *
+		 * @param includeIndent
+		 *            - width should include hierarchy column indent if
+		 *            applicable (VTreeTable only)
+		 * @param includeCellExtraWidth
+		 *            - width should include paddings etc.
+		 * @return the min width
+		 */
+        private int getMinWidth(boolean includeIndent,
+                boolean includeCellExtraWidth) {
+            int minWidth = sortIndicator.getOffsetWidth();
+            if (scrollBody != null) {
+                // check the need for indent before adding paddings etc.
+                if (includeIndent && isHierarchyColumn()) {
+                    int maxIndent = scrollBody.getMaxIndent();
+                    if (minWidth < maxIndent) {
+                        minWidth = maxIndent;
+                    }
+                }
+                if (includeCellExtraWidth) {
+                    minWidth += scrollBody.getCellExtraWidth();
+                }
+            }
+            return minWidth;
+        }
+
+        /** Gets the min width.
+		 *
+		 * @return the min width
+		 */
+        public int getMinWidth() {
+            // get min width with padding, no indent
+            return getMinWidth(false, true);
+        }
+
+        /** Gets the caption.
+		 *
+		 * @return the caption
+		 */
+        public String getCaption() {
+            return DOM.getInnerText(captionContainer);
+        }
+
+        /** Checks if is enabled.
+		 *
+		 * @return true, if is enabled
+		 */
+        public boolean isEnabled() {
+            return getParent() != null;
+        }
+
+        /** Sets the align.
+		 *
+		 * @param c
+		 *            the new align
+		 */
+        public void setAlign(char c) {
+            align = c;
+            updateStyleNames(VCustomScrollTable.this.getStylePrimaryName());
+        }
+
+        /** Gets the align.
+		 *
+		 * @return the align
+		 */
+        public char getAlign() {
+            return align;
+        }
+
+        /** Detects the natural minimum width for the column of this header
+		 * cell. If column is resized by user or the width is defined by server
+		 * the actual width is returned. Else the natural min width is returned.
+		 *
+		 * @param columnIndex
+		 *            column index hint, if -1 (unknown) it will be detected
+		 * @return the natural column width
+		 */
+        public int getNaturalColumnWidth(int columnIndex) {
+            final int iw = columnIndex == getHierarchyColumnIndex() ? scrollBody
+                    .getMaxIndent() : 0;
+            if (isDefinedWidth()) {
+                if (iw > width) {
+                    return iw;
+                }
+                return width;
+            } else {
+                if (naturalWidth < 0) {
+                    // This is recently revealed column. Try to detect a proper
+                    // value (greater of header and data columns)
+
+                    int hw = captionContainer.getOffsetWidth()
+                            + getHeaderPadding();
+                    if (BrowserInfo.get().isGecko()) {
+                        hw += sortIndicator.getOffsetWidth();
+                    }
+                    if (columnIndex < 0) {
+                        columnIndex = 0;
+                        for (Iterator<Widget> it = tHead.iterator(); it
+                                .hasNext(); columnIndex++) {
+                            if (it.next() == this) {
+                                break;
+                            }
+                        }
+                    }
+                    final int cw = scrollBody.getColWidth(columnIndex);
+                    naturalWidth = (hw > cw ? hw : cw);
+                }
+                if (iw > naturalWidth) {
+                    // indent is temporary value, naturalWidth shouldn't be
+                    // updated
+                    return iw;
+                } else {
+                    return naturalWidth;
+                }
+            }
+        }
+
+        /** Sets the expand ratio.
+		 *
+		 * @param floatAttribute
+		 *            the new expand ratio
+		 */
+        public void setExpandRatio(float floatAttribute) {
+            if (floatAttribute != expandRatio) {
+                triggerLazyColumnAdjustment(false);
+            }
+            expandRatio = floatAttribute;
+        }
+
+        /** Gets the expand ratio.
+		 *
+		 * @return the expand ratio
+		 */
+        public float getExpandRatio() {
+            return expandRatio;
+        }
+
+        /** Checks if is sorted.
+		 *
+		 * @return true, if is sorted
+		 */
+        public boolean isSorted() {
+            return sorted;
+        }
+    }
+
+    /**
+     * HeaderCell that is header cell for row headers.
+     * 
+     * Reordering disabled and clicking on it resets sorting.
+     */
+    public class RowHeadersHeaderCell extends HeaderCell {
+
+        /** Instantiates a new row headers header cell.
+		 */
+        RowHeadersHeaderCell() {
+            super(ROW_HEADER_COLUMN_KEY, "");
+            updateStyleNames(VCustomScrollTable.this.getStylePrimaryName());
+        }
+
+        /* (non-Javadoc)
+         * @see com.vaadin.client.ui.VCustomScrollTable.HeaderCell#updateStyleNames(java.lang.String)
+         */
+        @Override
+        protected void updateStyleNames(String primaryStyleName) {
+            super.updateStyleNames(primaryStyleName);
+            setStyleName(primaryStyleName + "-header-cell-rowheader");
+        }
+
+        /* (non-Javadoc)
+         * @see com.vaadin.client.ui.VCustomScrollTable.HeaderCell#handleCaptionEvent(com.google.gwt.user.client.Event)
+         */
+        @Override
+        protected void handleCaptionEvent(Event event) {
+            // NOP: RowHeaders cannot be reordered
+            // TODO It'd be nice to reset sorting here
+        }
+    }
+
+    /** The Class TableHead.
+	 */
+    public class TableHead extends Panel implements ActionOwner {
+
+        /** The Constant WRAPPER_WIDTH. */
+        private static final int WRAPPER_WIDTH = 900000;
+
+        /** The visible cells. */
+        ArrayList<Widget> visibleCells = new ArrayList<Widget>();
+
+        /** The available cells. */
+        HashMap<String, HeaderCell> availableCells = new HashMap<String, HeaderCell>();
+
+        /** The div. */
+        Element div = DOM.createDiv();
+        
+        /** The h table wrapper. */
+        Element hTableWrapper = DOM.createDiv();
+        
+        /** The h table container. */
+        Element hTableContainer = DOM.createDiv();
+        
+        /** The table. */
+        Element table = DOM.createTable();
+        
+        /** The header table body. */
+        Element headerTableBody = DOM.createTBody();
+        
+        /** The tr. */
+        Element tr = DOM.createTR();
+
+        /** The column selector. */
+        private final Element columnSelector = DOM.createDiv();
+
+        /** The focused slot. */
+        private int focusedSlot = -1;
+
+        /** Instantiates a new table head.
+		 */
+        public TableHead() {
+            if (BrowserInfo.get().isIE()) {
+                table.setPropertyInt("cellSpacing", 0);
+            }
+
+            hTableWrapper.getStyle().setOverflow(Overflow.HIDDEN);
+            columnSelector.getStyle().setDisplay(Display.NONE);
+
+            DOM.appendChild(table, headerTableBody);
+            DOM.appendChild(headerTableBody, tr);
+            DOM.appendChild(hTableContainer, table);
+            DOM.appendChild(hTableWrapper, hTableContainer);
+            DOM.appendChild(div, hTableWrapper);
+            DOM.appendChild(div, columnSelector);
+            setElement(div);
+
+            DOM.sinkEvents(columnSelector, Event.ONCLICK);
+
+            availableCells.put(ROW_HEADER_COLUMN_KEY,
+                    new RowHeadersHeaderCell());
+        }
+
+        /** Update style names.
+		 *
+		 * @param primaryStyleName
+		 *            the primary style name
+		 */
+        protected void updateStyleNames(String primaryStyleName) {
+            hTableWrapper.setClassName(primaryStyleName + "-header");
+            columnSelector.setClassName(primaryStyleName + "-column-selector");
+            setStyleName(primaryStyleName + "-header-wrap");
+            for (HeaderCell c : availableCells.values()) {
+                c.updateStyleNames(primaryStyleName);
+            }
+        }
+
+        /** Resize caption container.
+		 *
+		 * @param cell
+		 *            the cell
+		 */
+        public void resizeCaptionContainer(HeaderCell cell) {
+            HeaderCell lastcell = getHeaderCell(visibleCells.size() - 1);
+            int columnSelectorOffset = columnSelector.getOffsetWidth();
+
+            if (cell == lastcell && columnSelectorOffset > 0
+                    && !hasVerticalScrollbar()) {
+
+                // Measure column widths
+                int columnTotalWidth = 0;
+                for (Widget w : visibleCells) {
+                    int cellExtraWidth = w.getOffsetWidth();
+                    if (scrollBody != null
+                            && visibleCells.indexOf(w) == getHierarchyColumnIndex()
+                            && cellExtraWidth < scrollBody.getMaxIndent()) {
+                        // indent must be taken into consideration even if it
+                        // hasn't been applied yet
+                        columnTotalWidth += scrollBody.getMaxIndent();
+                    } else {
+                        columnTotalWidth += cellExtraWidth;
+                    }
+                }
+
+                int divOffset = div.getOffsetWidth();
+                if (columnTotalWidth >= divOffset - columnSelectorOffset) {
+                    /*
+                     * Ensure column caption is visible when placed under the
+                     * column selector widget by shifting and resizing the
+                     * caption.
+                     */
+                    int offset = 0;
+                    int diff = divOffset - columnTotalWidth;
+                    if (diff < columnSelectorOffset && diff > 0) {
+                        /*
+                         * If the difference is less than the column selectors
+                         * width then just offset by the difference
+                         */
+                        offset = columnSelectorOffset - diff;
+                    } else {
+                        // Else offset by the whole column selector
+                        offset = columnSelectorOffset;
+                    }
+                    lastcell.resizeCaptionContainer(offset);
+                } else {
+                    cell.resizeCaptionContainer(0);
+                }
+            } else {
+                cell.resizeCaptionContainer(0);
+            }
+        }
+
+        /* (non-Javadoc)
+         * @see com.google.gwt.user.client.ui.Panel#clear()
+         */
+        @Override
+        public void clear() {
+            for (String cid : availableCells.keySet()) {
+                removeCell(cid);
+            }
+            availableCells.clear();
+            availableCells.put(ROW_HEADER_COLUMN_KEY,
+                    new RowHeadersHeaderCell());
+        }
+
+        /** Update cells from uidl.
+		 *
+		 * @param uidl
+		 *            the uidl
+		 */
+        public void updateCellsFromUIDL(UIDL uidl) {
+            Iterator<?> it = uidl.getChildIterator();
+            HashSet<String> updated = new HashSet<String>();
+            boolean refreshContentWidths = initializedAndAttached
+                    && hadScrollBars != willHaveScrollbars();
+            while (it.hasNext()) {
+                final UIDL col = (UIDL) it.next();
+                final String cid = col.getStringAttribute("cid");
+                updated.add(cid);
+
+                String caption = buildCaptionHtmlSnippet(col);
+                HeaderCell c = getHeaderCell(cid);
+                if (c == null) {
+                    c = new HeaderCell(cid, caption);
+                    availableCells.put(cid, c);
+                    if (initializedAndAttached) {
+                        // we will need a column width recalculation
+                        initializedAndAttached = false;
+                        initialContentReceived = false;
+                        isNewBody = true;
+                    }
+                } else {
+                    c.setText(caption);
+                }
+
+                if (col.hasAttribute("sortable")) {
+                    c.setSortable(true);
+                    c.setSorted(false);
+                } else {
+                    c.setSortable(false);
+                }
+
+                if (col.hasAttribute("align")) {
+                    c.setAlign(col.getStringAttribute("align").charAt(0));
+                } else {
+                    c.setAlign(ALIGN_LEFT);
+
+                }
+                if (col.hasAttribute("width") && !c.isResizing) {
+                    // Make sure to accomodate for the sort indicator if
+                    // necessary.
+                    int width = col.getIntAttribute("width");
+                    int widthWithoutAddedIndent = width;
+
+                    // get min width with indent, no padding
+                    int minWidth = c.getMinWidth(true, false);
+                    if (width < minWidth) {
+                        width = minWidth;
+                    }
+                    if (scrollBody != null && width != c.getWidthWithIndent()) {
+                        // Do a more thorough update if a column is resized from
+                        // the server *after* the header has been properly
+                        // initialized
+                        final int colIx = getColIndexByKey(c.cid);
+                        final int newWidth = width;
+                        Scheduler.get().scheduleDeferred(
+                                new ScheduledCommand() {
+
+                                    @Override
+                                    public void execute() {
+                                        setColWidth(colIx, newWidth, true);
+                                    }
+                                });
+                        refreshContentWidths = true;
+                    } else {
+                        // get min width with no indent or padding
+                        minWidth = c.getMinWidth(false, false);
+                        if (widthWithoutAddedIndent < minWidth) {
+                            widthWithoutAddedIndent = minWidth;
+                        }
+                        // save min width without indent
+                        c.setWidth(widthWithoutAddedIndent, true);
+                    }
+                } else if (col.hasAttribute("er")) {
+                    c.setExpandRatio(col.getFloatAttribute("er"));
+
+                } else if (recalcWidths) {
+                    c.setUndefinedWidth();
+
+                } else {
+                    boolean hadExpandRatio = c.getExpandRatio() > 0;
+                    boolean hadDefinedWidth = c.isDefinedWidth();
+                    if (hadExpandRatio || hadDefinedWidth) {
+                        // Someone has removed a expand width or the defined
+                        // width on the server side (setting it to -1), make the
+                        // column undefined again and measure columns again.
+                        c.setUndefinedWidth();
+                        c.setExpandRatio(0);
+                        refreshContentWidths = true;
+                    }
+                }
+
+                if (col.hasAttribute("collapsed")) {
+                    // ensure header is properly removed from parent (case when
+                    // collapsing happens via servers side api)
+                    if (c.isAttached()) {
+                        c.removeFromParent();
+                        headerChangedDuringUpdate = true;
+                    }
+                }
+            }
+
+            if (refreshContentWidths) {
+                // Recalculate the column sizings if any column has changed
+                Scheduler.get().scheduleDeferred(new ScheduledCommand() {
+
+                    @Override
+                    public void execute() {
+                        triggerLazyColumnAdjustment(true);
+                    }
+                });
+            }
+
+            // check for orphaned header cells
+            for (Iterator<String> cit = availableCells.keySet().iterator(); cit
+                    .hasNext();) {
+                String cid = cit.next();
+                if (!updated.contains(cid)) {
+                    removeCell(cid);
+                    cit.remove();
+                    // we will need a column width recalculation, since columns
+                    // with expand ratios should expand to fill the void.
+                    initializedAndAttached = false;
+                    initialContentReceived = false;
+                    isNewBody = true;
+                }
+            }
+        }
+
+        /** Enable column.
+		 *
+		 * @param cid
+		 *            the cid
+		 * @param index
+		 *            the index
+		 */
+        public void enableColumn(String cid, int index) {
+            final HeaderCell c = getHeaderCell(cid);
+            if (!c.isEnabled() || getHeaderCell(index) != c) {
+                setHeaderCell(index, c);
+                if (initializedAndAttached) {
+                    headerChangedDuringUpdate = true;
+                }
+            }
+        }
+
+        /** Gets the visible cell count.
+		 *
+		 * @return the visible cell count
+		 */
+        public int getVisibleCellCount() {
+            return visibleCells.size();
+        }
+
+        /** Sets the horizontal scroll position.
+		 *
+		 * @param scrollLeft
+		 *            the new horizontal scroll position
+		 */
+        public void setHorizontalScrollPosition(int scrollLeft) {
+            hTableWrapper.setScrollLeft(scrollLeft);
+        }
+
+        /** Sets the column collapsing allowed.
+		 *
+		 * @param cc
+		 *            the new column collapsing allowed
+		 */
+        public void setColumnCollapsingAllowed(boolean cc) {
+            if (cc) {
+                columnSelector.getStyle().setDisplay(Display.BLOCK);
+            } else {
+                columnSelector.getStyle().setDisplay(Display.NONE);
+            }
+        }
+
+        /** Disable browser intelligence.
+		 */
+        public void disableBrowserIntelligence() {
+            hTableContainer.getStyle().setWidth(WRAPPER_WIDTH, Unit.PX);
+        }
+
+        /** Enable browser intelligence.
+		 */
+        public void enableBrowserIntelligence() {
+            hTableContainer.getStyle().clearWidth();
+        }
+
+        /** Sets the header cell.
+		 *
+		 * @param index
+		 *            the index
+		 * @param cell
+		 *            the cell
+		 */
+        public void setHeaderCell(int index, HeaderCell cell) {
+            if (cell.isEnabled()) {
+                // we're moving the cell
+                DOM.removeChild(tr, cell.getElement());
+                orphan(cell);
+                visibleCells.remove(cell);
+            }
+            if (index < visibleCells.size()) {
+                // insert to right slot
+                DOM.insertChild(tr, cell.getElement(), index);
+                adopt(cell);
+                visibleCells.add(index, cell);
+            } else if (index == visibleCells.size()) {
+                // simply append
+                DOM.appendChild(tr, cell.getElement());
+                adopt(cell);
+                visibleCells.add(cell);
+            } else {
+                throw new RuntimeException(
+                        "Header cells must be appended in order");
+            }
+        }
+
+        /** Gets the header cell.
+		 *
+		 * @param index
+		 *            the index
+		 * @return the header cell
+		 */
+        public HeaderCell getHeaderCell(int index) {
+            if (index >= 0 && index < visibleCells.size()) {
+                return (HeaderCell) visibleCells.get(index);
+            } else {
+                return null;
+            }
+        }
+
+        /**
+         * Get's HeaderCell by it's column Key.
+         * 
+         * Note that this returns HeaderCell even if it is currently collapsed.
+         * 
+         * @param cid
+         *            Column key of accessed HeaderCell
+         * @return HeaderCell
+         */
+        public HeaderCell getHeaderCell(String cid) {
+            return availableCells.get(cid);
+        }
+
+        /** Move cell.
+		 *
+		 * @param oldIndex
+		 *            the old index
+		 * @param newIndex
+		 *            the new index
+		 */
+        public void moveCell(int oldIndex, int newIndex) {
+            final HeaderCell hCell = getHeaderCell(oldIndex);
+            final Element cell = hCell.getElement();
+
+            visibleCells.remove(oldIndex);
+            DOM.removeChild(tr, cell);
+
+            DOM.insertChild(tr, cell, newIndex);
+            visibleCells.add(newIndex, hCell);
+        }
+
+        /* (non-Javadoc)
+         * @see com.google.gwt.user.client.ui.HasWidgets#iterator()
+         */
+        @Override
+        public Iterator<Widget> iterator() {
+            return visibleCells.iterator();
+        }
+
+        /* (non-Javadoc)
+         * @see com.google.gwt.user.client.ui.Panel#remove(com.google.gwt.user.client.ui.Widget)
+         */
+        @Override
+        public boolean remove(Widget w) {
+            if (visibleCells.contains(w)) {
+                visibleCells.remove(w);
+                orphan(w);
+                DOM.removeChild(DOM.getParent(w.getElement()), w.getElement());
+                return true;
+            }
+            return false;
+        }
+
+        /** Removes the cell.
+		 *
+		 * @param colKey
+		 *            the col key
+		 */
+        public void removeCell(String colKey) {
+            final HeaderCell c = getHeaderCell(colKey);
+            remove(c);
+        }
+
+        /** Focus slot.
+		 *
+		 * @param index
+		 *            the index
+		 */
+        private void focusSlot(int index) {
+            removeSlotFocus();
+            if (index > 0) {
+                Element child = tr.getChild(index - 1).getFirstChild().cast();
+                child.setClassName(VCustomScrollTable.this
+                        .getStylePrimaryName() + "-resizer");
+                child.addClassName(VCustomScrollTable.this
+                        .getStylePrimaryName() + "-focus-slot-right");
+            } else {
+                Element child = tr.getChild(index).getFirstChild().cast();
+                child.setClassName(VCustomScrollTable.this
+                        .getStylePrimaryName() + "-resizer");
+                child.addClassName(VCustomScrollTable.this
+                        .getStylePrimaryName() + "-focus-slot-left");
+            }
+            focusedSlot = index;
+        }
+
+        /** Removes the slot focus.
+		 */
+        private void removeSlotFocus() {
+            if (focusedSlot < 0) {
+                return;
+            }
+            if (focusedSlot == 0) {
+                Element child = tr.getChild(focusedSlot).getFirstChild().cast();
+                child.setClassName(VCustomScrollTable.this
+                        .getStylePrimaryName() + "-resizer");
+            } else if (focusedSlot > 0) {
+                Element child = tr.getChild(focusedSlot - 1).getFirstChild()
+                        .cast();
+                child.setClassName(VCustomScrollTable.this
+                        .getStylePrimaryName() + "-resizer");
+            }
+            focusedSlot = -1;
+        }
+
+        /* (non-Javadoc)
+         * @see com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt.user.client.Event)
+         */
+        @Override
+        public void onBrowserEvent(Event event) {
+            if (enabled) {
+                if (event.getEventTarget().cast() == columnSelector) {
+                    final int left = DOM.getAbsoluteLeft(columnSelector);
+                    final int top = DOM.getAbsoluteTop(columnSelector)
+                            + DOM.getElementPropertyInt(columnSelector,
+                                    "offsetHeight");
+                    client.getContextMenu().showAt(this, left, top);
+                }
+            }
+        }
+
+        /* (non-Javadoc)
+         * @see com.google.gwt.user.client.ui.Widget#onDetach()
+         */
+        @Override
+        protected void onDetach() {
+            super.onDetach();
+            if (client != null) {
+                client.getContextMenu().ensureHidden(this);
+            }
+        }
+
+        /** The Class VisibleColumnAction.
+		 */
+        class VisibleColumnAction extends Action {
+
+            /** The col key. */
+            String colKey;
+            
+            /** The collapsed. */
+            private boolean collapsed;
+            
+            /** The noncollapsible. */
+            private boolean noncollapsible = false;
+            
+            /** The currently focused row. */
+            private VScrollTableRow currentlyFocusedRow;
+
+            /** Instantiates a new visible column action.
+			 *
+			 * @param colKey
+			 *            the col key
+			 */
+            public VisibleColumnAction(String colKey) {
+                super(VCustomScrollTable.TableHead.this);
+                this.colKey = colKey;
+                caption = tHead.getHeaderCell(colKey).getCaption();
+                currentlyFocusedRow = focusedRow;
+            }
+
+            /* (non-Javadoc)
+             * @see com.vaadin.client.ui.Action#execute()
+             */
+            @Override
+            public void execute() {
+                if (noncollapsible) {
+                    return;
+                }
+                client.getContextMenu().hide();
+                // toggle selected column
+                if (collapsedColumns.contains(colKey)) {
+                    collapsedColumns.remove(colKey);
+                } else {
+                    tHead.removeCell(colKey);
+                    collapsedColumns.add(colKey);
+                    triggerLazyColumnAdjustment(true);
+                }
+
+                // update variable to server
+                client.updateVariable(paintableId, "collapsedcolumns",
+                        collapsedColumns.toArray(new String[collapsedColumns
+                                .size()]), false);
+                // let rowRequestHandler determine proper rows
+                rowRequestHandler.refreshContent();
+                lazyRevertFocusToRow(currentlyFocusedRow);
+            }
+
+            /** Sets the collapsed.
+			 *
+			 * @param b
+			 *            the new collapsed
+			 */
+            public void setCollapsed(boolean b) {
+                collapsed = b;
+            }
+
+            /** Sets the noncollapsible.
+			 *
+			 * @param b
+			 *            the new noncollapsible
+			 */
+            public void setNoncollapsible(boolean b) {
+                noncollapsible = b;
+            }
+
+            /** Override default method to distinguish on/off columns.
+			 *
+			 * @return the html
+			 */
+
+            @Override
+            public String getHTML() {
+                final StringBuffer buf = new StringBuffer();
+                buf.append("<span class=\"");
+                if (collapsed) {
+                    buf.append("v-off");
+                } else {
+                    buf.append("v-on");
+                }
+                if (noncollapsible) {
+                    buf.append(" v-disabled");
+                }
+                buf.append("\">");
+
+                buf.append(super.getHTML());
+                buf.append("</span>");
+
+                return buf.toString();
+            }
+
+        }
+
+        /*
+         * Returns columns as Action array for column select popup
+         */
+
+        /* (non-Javadoc)
+         * @see com.vaadin.client.ui.ActionOwner#getActions()
+         */
+        @Override
+        public Action[] getActions() {
+            Object[] cols;
+            if (columnReordering && columnOrder != null) {
+                cols = columnOrder;
+            } else {
+                // if columnReordering is disabled, we need different way to get
+                // all available columns
+                cols = visibleColOrder;
+                cols = new Object[visibleColOrder.length
+                        + collapsedColumns.size()];
+                int i;
+                for (i = 0; i < visibleColOrder.length; i++) {
+                    cols[i] = visibleColOrder[i];
+                }
+                for (final Iterator<String> it = collapsedColumns.iterator(); it
+                        .hasNext();) {
+                    cols[i++] = it.next();
+                }
+            }
+            final Action[] actions = new Action[cols.length];
+
+            for (int i = 0; i < cols.length; i++) {
+                final String cid = (String) cols[i];
+                final HeaderCell c = getHeaderCell(cid);
+                final VisibleColumnAction a = new VisibleColumnAction(
+                        c.getColKey());
+                a.setCaption(c.getCaption());
+                if (!c.isEnabled()) {
+                    a.setCollapsed(true);
+                }
+                if (noncollapsibleColumns.contains(cid)) {
+                    a.setNoncollapsible(true);
+                }
+                actions[i] = a;
+            }
+            return actions;
+        }
+
+        /* (non-Javadoc)
+         * @see com.vaadin.client.ui.ActionOwner#getClient()
+         */
+        @Override
+        public ApplicationConnection getClient() {
+            return client;
+        }
+
+        /* (non-Javadoc)
+         * @see com.vaadin.client.ui.ActionOwner#getPaintableId()
+         */
+        @Override
+        public String getPaintableId() {
+            return paintableId;
+        }
+
+        /** Returns column alignments for visible columns.
+		 *
+		 * @return the column alignments
+		 */
+        public char[] getColumnAlignments() {
+            final Iterator<Widget> it = visibleCells.iterator();
+            final char[] aligns = new char[visibleCells.size()];
+            int colIndex = 0;
+            while (it.hasNext()) {
+                aligns[colIndex++] = ((HeaderCell) it.next()).getAlign();
+            }
+            return aligns;
+        }
+
+        /** Disables the automatic calculation of all column widths by
+		 * forcing the widths to be "defined" thus turning off expand ratios and
+		 * such.
+		 *
+		 * @param source
+		 *            the source
+		 */
+        public void disableAutoColumnWidthCalculation(HeaderCell source) {
+            for (HeaderCell cell : availableCells.values()) {
+                cell.disableAutoWidthCalculation();
+            }
+            // fire column resize events for all columns but the source of the
+            // resize action, since an event will fire separately for this.
+            ArrayList<HeaderCell> columns = new ArrayList<HeaderCell>(
+                    availableCells.values());
+            columns.remove(source);
+            sendColumnWidthUpdates(columns);
+            forceRealignColumnHeaders();
+        }
+    }
+
+    /** A cell in the footer.
+	 */
+    public class FooterCell extends Widget {
+        
+        /** The td. */
+        private final Element td = DOM.createTD();
+        
+        /** The caption container. */
+        private final Element captionContainer = DOM.createDiv();
+        
+        /** The align. */
+        private char align = ALIGN_LEFT;
+        
+        /** The width. */
+        private int width = -1;
+        
+        /** The expand ratio. */
+        private float expandRatio = 0;
+        
+        /** The cid. */
+        private final String cid;
+        
+        /** The defined width. */
+        boolean definedWidth = false;
+        
+        /** The natural width. */
+        private int naturalWidth = -1;
+
+        /** Instantiates a new footer cell.
+		 *
+		 * @param colId
+		 *            the col id
+		 * @param headerText
+		 *            the header text
+		 */
+        public FooterCell(String colId, String headerText) {
+            cid = colId;
+
+            setText(headerText);
+
+            // ensure no clipping initially (problem on column additions)
+            captionContainer.getStyle().setOverflow(Overflow.VISIBLE);
+
+            DOM.sinkEvents(captionContainer, Event.MOUSEEVENTS);
+
+            DOM.appendChild(td, captionContainer);
+
+            DOM.sinkEvents(td, Event.MOUSEEVENTS | Event.ONDBLCLICK
+                    | Event.ONCONTEXTMENU);
+
+            setElement(td);
+
+            updateStyleNames(VCustomScrollTable.this.getStylePrimaryName());
+        }
+
+        /** Update style names.
+		 *
+		 * @param primaryStyleName
+		 *            the primary style name
+		 */
+        protected void updateStyleNames(String primaryStyleName) {
+            captionContainer.setClassName(primaryStyleName
+                    + "-footer-container");
+        }
+
+        /** Sets the text of the footer.
+		 *
+		 * @param footerText
+		 *            The text in the footer
+		 */
+        public void setText(String footerText) {
+            if (footerText == null || footerText.equals("")) {
+                footerText = "&nbsp;";
+            }
+
+            DOM.setInnerHTML(captionContainer, footerText);
+        }
+
+        /** Set alignment of the text in the cell.
+		 *
+		 * @param c
+		 *            The alignment which can be ALIGN_CENTER, ALIGN_LEFT,
+		 *            ALIGN_RIGHT
+		 */
+        public void setAlign(char c) {
+            if (align != c) {
+                switch (c) {
+                case ALIGN_CENTER:
+                    captionContainer.getStyle().setTextAlign(TextAlign.CENTER);
+                    break;
+                case ALIGN_RIGHT:
+                    captionContainer.getStyle().setTextAlign(TextAlign.RIGHT);
+                    break;
+                default:
+                    captionContainer.getStyle().setTextAlign(TextAlign.LEFT);
+                    break;
+                }
+            }
+            align = c;
+        }
+
+        /** Get the alignment of the text int the cell.
+		 *
+		 * @return Returns either ALIGN_CENTER, ALIGN_LEFT or ALIGN_RIGHT
+		 */
+        public char getAlign() {
+            return align;
+        }
+
+        /**
+         * Sets the width of the cell. This width should not include any
+         * possible indent modifications that are present in
+         * {@link VScrollTableBody#getMaxIndent()}.
+         * 
+         * @param w
+         *            The width of the cell
+         * @param ensureDefinedWidth
+         *            Ensures that the given width is not recalculated
+         */
+        public void setWidth(int w, boolean ensureDefinedWidth) {
+
+            if (ensureDefinedWidth) {
+                definedWidth = true;
+                // on column resize expand ratio becomes zero
+                expandRatio = 0;
+            }
+            if (width == w) {
+                return;
+            }
+            if (width == -1) {
+                // go to default mode, clip content if necessary
+                captionContainer.getStyle().clearOverflow();
+            }
+            width = w;
+            if (w == -1) {
+                captionContainer.getStyle().clearWidth();
+                setWidth("");
+            } else {
+                /*
+                 * Reduce width with one pixel for the right border since the
+                 * footers does not have any spacers between them.
+                 */
+                final int borderWidths = 1;
+
+                // Set the container width (check for negative value)
+                captionContainer.getStyle().setPropertyPx("width",
+                        Math.max(w - borderWidths, 0));
+
+                /*
+                 * if we already have tBody, set the header width properly, if
+                 * not defer it. IE will fail with complex float in table header
+                 * unless TD width is not explicitly set.
+                 */
+                if (scrollBody != null) {
+                    int maxIndent = scrollBody.getMaxIndent();
+                    if (w < maxIndent
+                            && tFoot.visibleCells.indexOf(this) == getHierarchyColumnIndex()) {
+                        // ensure there's room for the indent
+                        w = maxIndent;
+                    }
+                    int tdWidth = w + scrollBody.getCellExtraWidth()
+                            - borderWidths;
+                    setWidth(Math.max(tdWidth, 0) + "px");
+                } else {
+                    Scheduler.get().scheduleDeferred(new Command() {
+
+                        @Override
+                        public void execute() {
+                            int tdWidth = width;
+                            int maxIndent = scrollBody.getMaxIndent();
+                            if (tdWidth < maxIndent
+                                    && tFoot.visibleCells.indexOf(this) == getHierarchyColumnIndex()) {
+                                // ensure there's room for the indent
+                                tdWidth = maxIndent;
+                            }
+                            tdWidth += scrollBody.getCellExtraWidth()
+                                    - borderWidths;
+                            setWidth(Math.max(tdWidth, 0) + "px");
+                        }
+                    });
+                }
+            }
+        }
+
+        /** Sets the width to undefined.
+		 */
+        public void setUndefinedWidth() {
+            definedWidth = false;
+            setWidth(-1, false);
+        }
+
+        /**
+         * Detects if width is fixed by developer on server side or resized to
+         * current width by user.
+         * 
+         * @return true if defined, false if "natural" width
+         */
+        public boolean isDefinedWidth() {
+            return definedWidth && width >= 0;
+        }
+
+        /**
+         * Returns the pixels width of the footer cell.
+         * 
+         * @return The width in pixels
+         */
+        public int getWidth() {
+            return width;
+        }
+
+        /** Sets the expand ratio of the cell.
+		 *
+		 * @param floatAttribute
+		 *            The expand ratio
+		 */
+        public void setExpandRatio(float floatAttribute) {
+            expandRatio = floatAttribute;
+        }
+
+        /** Returns the expand ration of the cell.
+		 *
+		 * @return The expand ratio
+		 */
+        public float getExpandRatio() {
+            return expandRatio;
+        }
+
+        /** Is the cell enabled?.
+		 *
+		 * @return True if enabled else False
+		 */
+        public boolean isEnabled() {
+            return getParent() != null;
+        }
+
+        /** Handle column clicking.
+		 *
+		 * @param event
+		 *            the event
+		 */
+
+        @Override
+        public void onBrowserEvent(Event event) {
+            if (enabled && event != null) {
+                handleCaptionEvent(event);
+
+                if (DOM.eventGetType(event) == Event.ONMOUSEUP) {
+                    scrollBodyPanel.setFocus(true);
+                }
+                boolean stopPropagation = true;
+                if (event.getTypeInt() == Event.ONCONTEXTMENU
+                        && !client.hasEventListeners(VCustomScrollTable.this,
+                                TableConstants.FOOTER_CLICK_EVENT_ID)) {
+                    // Show browser context menu if a footer click listener is
+                    // not present
+                    stopPropagation = false;
+                }
+                if (stopPropagation) {
+                    event.stopPropagation();
+                    event.preventDefault();
+                }
+            }
+        }
+
+        /** Handles a event on the captions.
+		 *
+		 * @param event
+		 *            The event to handle
+		 */
+        protected void handleCaptionEvent(Event event) {
+            if (event.getTypeInt() == Event.ONMOUSEUP
+                    || event.getTypeInt() == Event.ONDBLCLICK) {
+                fireFooterClickedEvent(event);
+            }
+        }
+
+        /** Fires a footer click event after the user has clicked a column
+		 * footer cell.
+		 *
+		 * @param event
+		 *            The click event
+		 */
+        private void fireFooterClickedEvent(Event event) {
+            if (client.hasEventListeners(VCustomScrollTable.this,
+                    TableConstants.FOOTER_CLICK_EVENT_ID)) {
+                MouseEventDetails details = MouseEventDetailsBuilder
+                        .buildMouseEventDetails(event);
+                client.updateVariable(paintableId, "footerClickEvent",
+                        details.toString(), false);
+                client.updateVariable(paintableId, "footerClickCID", cid, true);
+            }
+        }
+
+        /** Returns the column key of the column.
+		 *
+		 * @return The column key
+		 */
+        public String getColKey() {
+            return cid;
+        }
+
+        /** Detects the natural minimum width for the column of this header
+		 * cell. If column is resized by user or the width is defined by server
+		 * the actual width is returned. Else the natural min width is returned.
+		 *
+		 * @param columnIndex
+		 *            column index hint, if -1 (unknown) it will be detected
+		 * @return the natural column width
+		 */
+        public int getNaturalColumnWidth(int columnIndex) {
+            final int iw = columnIndex == getHierarchyColumnIndex() ? scrollBody
+                    .getMaxIndent() : 0;
+            if (isDefinedWidth()) {
+                if (iw > width) {
+                    return iw;
+                }
+                return width;
+            } else {
+                if (naturalWidth < 0) {
+                    // This is recently revealed column. Try to detect a proper
+                    // value (greater of header and data
+                    // cols)
+
+                    final int hw = ((Element) getElement().getLastChild())
+                            .getOffsetWidth() + getHeaderPadding();
+                    if (columnIndex < 0) {
+                        columnIndex = 0;
+                        for (Iterator<Widget> it = tHead.iterator(); it
+                                .hasNext(); columnIndex++) {
+                            if (it.next() == this) {
+                                break;
+                            }
+                        }
+                    }
+                    final int cw = scrollBody.getColWidth(columnIndex);
+                    naturalWidth = (hw > cw ? hw : cw);
+                }
+                if (iw > naturalWidth) {
+                    return iw;
+                } else {
+                    return naturalWidth;
+                }
+            }
+        }
+
+        /** Sets the natural minimum column width.
+		 *
+		 * @param w
+		 *            the new natural minimum column width
+		 */
+        public void setNaturalMinimumColumnWidth(int w) {
+            naturalWidth = w;
+        }
+    }
+
+    /**
+     * HeaderCell that is header cell for row headers.
+     * 
+     * Reordering disabled and clicking on it resets sorting.
+     */
+    public class RowHeadersFooterCell extends FooterCell {
+
+        /** Instantiates a new row headers footer cell.
+		 */
+        RowHeadersFooterCell() {
+            super(ROW_HEADER_COLUMN_KEY, "");
+        }
+
+        /* (non-Javadoc)
+         * @see com.vaadin.client.ui.VCustomScrollTable.FooterCell#handleCaptionEvent(com.google.gwt.user.client.Event)
+         */
+        @Override
+        protected void handleCaptionEvent(Event event) {
+            // NOP: RowHeaders cannot be reordered
+            // TODO It'd be nice to reset sorting here
+        }
+    }
+
+    /**
+     * The footer of the table which can be seen in the bottom of the Table.
+     */
+    public class TableFooter extends Panel {
+
+        /** The Constant WRAPPER_WIDTH. */
+        private static final int WRAPPER_WIDTH = 900000;
+
+        /** The visible cells. */
+        ArrayList<Widget> visibleCells = new ArrayList<Widget>();
+        
+        /** The available cells. */
+        HashMap<String, FooterCell> availableCells = new HashMap<String, FooterCell>();
+
+        /** The div. */
+        Element div = DOM.createDiv();
+        
+        /** The h table wrapper. */
+        Element hTableWrapper = DOM.createDiv();
+        
+        /** The h table container. */
+        Element hTableContainer = DOM.createDiv();
+        
+        /** The table. */
+        Element table = DOM.createTable();
+        
+        /** The header table body. */
+        Element headerTableBody = DOM.createTBody();
+        
+        /** The tr. */
+        Element tr = DOM.createTR();
+
+        /** Instantiates a new table footer.
+		 */
+        public TableFooter() {
+
+            hTableWrapper.getStyle().setOverflow(Overflow.HIDDEN);
+
+            DOM.appendChild(table, headerTableBody);
+            DOM.appendChild(headerTableBody, tr);
+            DOM.appendChild(hTableContainer, table);
+            DOM.appendChild(hTableWrapper, hTableContainer);
+            DOM.appendChild(div, hTableWrapper);
+            setElement(div);
+
+            availableCells.put(ROW_HEADER_COLUMN_KEY,
+                    new RowHeadersFooterCell());
+
+            updateStyleNames(VCustomScrollTable.this.getStylePrimaryName());
+        }
+
+        /** Update style names.
+		 *
+		 * @param primaryStyleName
+		 *            the primary style name
+		 */
+        protected void updateStyleNames(String primaryStyleName) {
+            hTableWrapper.setClassName(primaryStyleName + "-footer");
+            setStyleName(primaryStyleName + "-footer-wrap");
+            for (FooterCell c : availableCells.values()) {
+                c.updateStyleNames(primaryStyleName);
+            }
+        }
+
+        /* (non-Javadoc)
+         * @see com.google.gwt.user.client.ui.Panel#clear()
+         */
+        @Override
+        public void clear() {
+            for (String cid : availableCells.keySet()) {
+                removeCell(cid);
+            }
+            availableCells.clear();
+            availableCells.put(ROW_HEADER_COLUMN_KEY,
+                    new RowHeadersFooterCell());
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see
+         * com.google.gwt.user.client.ui.Panel#remove(com.google.gwt.user.client
+         * .ui.Widget)
+         */
+
+        @Override
+        public boolean remove(Widget w) {
+            if (visibleCells.contains(w)) {
+                visibleCells.remove(w);
+                orphan(w);
+                DOM.removeChild(DOM.getParent(w.getElement()), w.getElement());
+                return true;
+            }
+            return false;
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see com.google.gwt.user.client.ui.HasWidgets#iterator()
+         */
+
+        @Override
+        public Iterator<Widget> iterator() {
+            return visibleCells.iterator();
+        }
+
+        /** Gets a footer cell which represents the given columnId.
+		 *
+		 * @param cid
+		 *            The columnId
+		 * @return The cell
+		 */
+        public FooterCell getFooterCell(String cid) {
+            return availableCells.get(cid);
+        }
+
+        /** Gets a footer cell by using a column index.
+		 *
+		 * @param index
+		 *            The index of the column
+		 * @return The Cell
+		 */
+        public FooterCell getFooterCell(int index) {
+            if (index < visibleCells.size()) {
+                return (FooterCell) visibleCells.get(index);
+            } else {
+                return null;
+            }
+        }
+
+        /** Updates the cells contents when updateUIDL request is received.
+		 *
+		 * @param uidl
+		 *            The UIDL
+		 */
+        public void updateCellsFromUIDL(UIDL uidl) {
+            Iterator<?> columnIterator = uidl.getChildIterator();
+            HashSet<String> updated = new HashSet<String>();
+            while (columnIterator.hasNext()) {
+                final UIDL col = (UIDL) columnIterator.next();
+                final String cid = col.getStringAttribute("cid");
+                updated.add(cid);
+
+                String caption = col.hasAttribute("fcaption") ? col
+                        .getStringAttribute("fcaption") : "";
+                FooterCell c = getFooterCell(cid);
+                if (c == null) {
+                    c = new FooterCell(cid, caption);
+                    availableCells.put(cid, c);
+                    if (initializedAndAttached) {
+                        // we will need a column width recalculation
+                        initializedAndAttached = false;
+                        initialContentReceived = false;
+                        isNewBody = true;
+                    }
+                } else {
+                    c.setText(caption);
+                }
+
+                if (col.hasAttribute("align")) {
+                    c.setAlign(col.getStringAttribute("align").charAt(0));
+                } else {
+                    c.setAlign(ALIGN_LEFT);
+
+                }
+                if (col.hasAttribute("width")) {
+                    if (scrollBody == null || isNewBody) {
+                        // Already updated by setColWidth called from
+                        // TableHeads.updateCellsFromUIDL in case of a server
+                        // side resize
+                        final int width = col.getIntAttribute("width");
+                        c.setWidth(width, true);
+                    }
+                } else if (recalcWidths) {
+                    c.setUndefinedWidth();
+                }
+                if (col.hasAttribute("er")) {
+                    c.setExpandRatio(col.getFloatAttribute("er"));
+                }
+                if (col.hasAttribute("collapsed")) {
+                    // ensure header is properly removed from parent (case when
+                    // collapsing happens via servers side api)
+                    if (c.isAttached()) {
+                        c.removeFromParent();
+                        headerChangedDuringUpdate = true;
+                    }
+                }
+            }
+
+            // check for orphaned header cells
+            for (Iterator<String> cit = availableCells.keySet().iterator(); cit
+                    .hasNext();) {
+                String cid = cit.next();
+                if (!updated.contains(cid)) {
+                    removeCell(cid);
+                    cit.remove();
+                }
+            }
+        }
+
+        /** Set a footer cell for a specified column index.
+		 *
+		 * @param index
+		 *            The index
+		 * @param cell
+		 *            The footer cell
+		 */
+        public void setFooterCell(int index, FooterCell cell) {
+            if (cell.isEnabled()) {
+                // we're moving the cell
+                DOM.removeChild(tr, cell.getElement());
+                orphan(cell);
+                visibleCells.remove(cell);
+            }
+            if (index < visibleCells.size()) {
+                // insert to right slot
+                DOM.insertChild(tr, cell.getElement(), index);
+                adopt(cell);
+                visibleCells.add(index, cell);
+            } else if (index == visibleCells.size()) {
+                // simply append
+                DOM.appendChild(tr, cell.getElement());
+                adopt(cell);
+                visibleCells.add(cell);
+            } else {
+                throw new RuntimeException(
+                        "Header cells must be appended in order");
+            }
+        }
+
+        /** Remove a cell by using the columnId.
+		 *
+		 * @param colKey
+		 *            The columnId to remove
+		 */
+        public void removeCell(String colKey) {
+            final FooterCell c = getFooterCell(colKey);
+            remove(c);
+        }
+
+        /** Enable a column (Sets the footer cell).
+		 *
+		 * @param cid
+		 *            The columnId
+		 * @param index
+		 *            The index of the column
+		 */
+        public void enableColumn(String cid, int index) {
+            final FooterCell c = getFooterCell(cid);
+            if (!c.isEnabled() || getFooterCell(index) != c) {
+                setFooterCell(index, c);
+                if (initializedAndAttached) {
+                    headerChangedDuringUpdate = true;
+                }
+            }
+        }
+
+        /** Disable browser measurement of the table width.
+		 */
+        public void disableBrowserIntelligence() {
+            hTableContainer.getStyle().setWidth(WRAPPER_WIDTH, Unit.PX);
+        }
+
+        /** Enable browser measurement of the table width.
+		 */
+        public void enableBrowserIntelligence() {
+            hTableContainer.getStyle().clearWidth();
+        }
+
+        /**
+         * Set the horizontal position in the cell in the footer. This is done
+         * when a horizontal scrollbar is present.
+         * 
+         * @param scrollLeft
+         *            The value of the leftScroll
+         */
+        public void setHorizontalScrollPosition(int scrollLeft) {
+            hTableWrapper.setScrollLeft(scrollLeft);
+        }
+
+        /** Swap cells when the column are dragged.
+		 *
+		 * @param oldIndex
+		 *            The old index of the cell
+		 * @param newIndex
+		 *            The new index of the cell
+		 */
+        public void moveCell(int oldIndex, int newIndex) {
+            final FooterCell hCell = getFooterCell(oldIndex);
+            final Element cell = hCell.getElement();
+
+            visibleCells.remove(oldIndex);
+            DOM.removeChild(tr, cell);
+
+            DOM.insertChild(tr, cell, newIndex);
+            visibleCells.add(newIndex, hCell);
+        }
+    }
+
+    /**
+     * This Panel can only contain VScrollTableRow type of widgets. This
+     * "simulates" very large table, keeping spacers which take room of
+     * unrendered rows.
+     * 
+     */
+    public class VScrollTableBody extends Panel {
+
+        /** The Constant DEFAULT_ROW_HEIGHT. */
+        public static final int DEFAULT_ROW_HEIGHT = 24;
+
+        /** The row height. */
+        private double rowHeight = -1;
+
+        /** The rendered rows. */
+        private final LinkedList<Widget> renderedRows = new LinkedList<Widget>();
+
+        /**
+         * Due some optimizations row height measuring is deferred and initial
+         * set of rows is rendered detached. Flag set on when table body has
+         * been attached in dom and rowheight has been measured.
+         */
+        private boolean tBodyMeasurementsDone = false;
+
+        /** The pre spacer. */
+        Element preSpacer = DOM.createDiv();
+        
+        /** The post spacer. */
+        Element postSpacer = DOM.createDiv();
+
+        /** The container. */
+        Element container = DOM.createDiv();
+
+        /** The t body element. */
+        TableSectionElement tBodyElement = Document.get().createTBodyElement();
+        
+        /** The table. */
+        Element table = DOM.createTable();
+
+        /** The first rendered. */
+        private int firstRendered;
+        
+        /** The last rendered. */
+        private int lastRendered;
+
+        /** The aligns. */
+        private char[] aligns;
+
+        /** Instantiates a new v scroll table body.
+		 */
+        protected VScrollTableBody() {
+            constructDOM();
+            setElement(container);
+        }
+
+        /** Sets the last rendered.
+		 *
+		 * @param lastRendered
+		 *            the new last rendered
+		 */
+        public void setLastRendered(int lastRendered) {
+            if (totalRows >= 0 && lastRendered > totalRows) {
+                VConsole.log("setLastRendered: " + this.lastRendered + " -> "
+                        + lastRendered);
+                this.lastRendered = totalRows - 1;
+            } else {
+                this.lastRendered = lastRendered;
+            }
+        }
+
+        /** Gets the last rendered.
+		 *
+		 * @return the last rendered
+		 */
+        public int getLastRendered() {
+            return lastRendered;
+        }
+
+        /** Gets the first rendered.
+		 *
+		 * @return the first rendered
+		 */
+        public int getFirstRendered() {
+            return firstRendered;
+        }
+
+        /** Gets the row by row index.
+		 *
+		 * @param indexInTable
+		 *            the index in table
+		 * @return the row by row index
+		 */
+        public VScrollTableRow getRowByRowIndex(int indexInTable) {
+            int internalIndex = indexInTable - firstRendered;
+            if (internalIndex >= 0 && internalIndex < renderedRows.size()) {
+                return (VScrollTableRow) renderedRows.get(internalIndex);
+            } else {
+                return null;
+            }
+        }
+
+        /** Gets the required height.
+		 *
+		 * @return the height of scrollable body, subpixels ceiled.
+		 */
+        public int getRequiredHeight() {
+            return preSpacer.getOffsetHeight() + postSpacer.getOffsetHeight()
+                    + Util.getRequiredHeight(table);
+        }
+
+        /** Construct dom.
+		 */
+        private void constructDOM() {
+            if (BrowserInfo.get().isIE()) {
+                table.setPropertyInt("cellSpacing", 0);
+            }
+
+            table.appendChild(tBodyElement);
+            DOM.appendChild(container, preSpacer);
+            DOM.appendChild(container, table);
+            DOM.appendChild(container, postSpacer);
+            if (BrowserInfo.get().requiresTouchScrollDelegate()) {
+                NodeList<Node> childNodes = container.getChildNodes();
+                for (int i = 0; i < childNodes.getLength(); i++) {
+                    Element item = (Element) childNodes.getItem(i);
+                    item.getStyle().setProperty("webkitTransform",
+                            "translate3d(0,0,0)");
+                }
+            }
+            updateStyleNames(VCustomScrollTable.this.getStylePrimaryName());
+        }
+
+        /** Update style names.
+		 *
+		 * @param primaryStyleName
+		 *            the primary style name
+		 */
+        protected void updateStyleNames(String primaryStyleName) {
+            table.setClassName(primaryStyleName + "-table");
+            preSpacer.setClassName(primaryStyleName + "-row-spacer");
+            postSpacer.setClassName(primaryStyleName + "-row-spacer");
+            for (Widget w : renderedRows) {
+                VScrollTableRow row = (VScrollTableRow) w;
+                row.updateStyleNames(primaryStyleName);
+            }
+        }
+
+        /** Gets the available width.
+		 *
+		 * @return the available width
+		 */
+        public int getAvailableWidth() {
+            int availW = scrollBodyPanel.getOffsetWidth() - getBorderWidth();
+            return availW;
+        }
+
+        /** Render initial rows.
+		 *
+		 * @param rowData
+		 *            the row data
+		 * @param firstIndex
+		 *            the first index
+		 * @param rows
+		 *            the rows
+		 */
+        public void renderInitialRows(UIDL rowData, int firstIndex, int rows) {
+            firstRendered = firstIndex;
+            setLastRendered(firstIndex + rows - 1);
+            final Iterator<?> it = rowData.getChildIterator();
+            aligns = tHead.getColumnAlignments();
+            while (it.hasNext()) {
+                final VScrollTableRow row = createRow((UIDL) it.next(), aligns);
+                addRow(row);
+            }
+            if (isAttached()) {
+                fixSpacers();
+            }
+        }
+
+        /** Render rows.
+		 *
+		 * @param rowData
+		 *            the row data
+		 * @param firstIndex
+		 *            the first index
+		 * @param rows
+		 *            the rows
+		 */
+        public void renderRows(UIDL rowData, int firstIndex, int rows) {
+            // FIXME REVIEW
+            aligns = tHead.getColumnAlignments();
+            final Iterator<?> it = rowData.getChildIterator();
+            if (firstIndex == lastRendered + 1) {
+                while (it.hasNext()) {
+                    final VScrollTableRow row = prepareRow((UIDL) it.next());
+                    addRow(row);
+                    setLastRendered(lastRendered + 1);
+                }
+                fixSpacers();
+            } else if (firstIndex + rows == firstRendered) {
+                final VScrollTableRow[] rowArray = new VScrollTableRow[rows];
+                int i = rows;
+                while (it.hasNext()) {
+                    i--;
+                    rowArray[i] = prepareRow((UIDL) it.next());
+                }
+                for (i = 0; i < rows; i++) {
+                    addRowBeforeFirstRendered(rowArray[i]);
+                    firstRendered--;
+                }
+            } else {
+                // completely new set of rows
+
+                // there can't be sanity checks for last rendered within this
+                // while loop regardless of what has been set previously, so
+                // change it temporarily to true and then return the original
+                // value
+                boolean temp = postponeSanityCheckForLastRendered;
+                postponeSanityCheckForLastRendered = true;
+                while (lastRendered + 1 > firstRendered) {
+                    unlinkRow(false);
+                }
+                postponeSanityCheckForLastRendered = temp;
+                VScrollTableRow row = prepareRow((UIDL) it.next());
+                firstRendered = firstIndex;
+                setLastRendered(firstIndex - 1);
+                addRow(row);
+                setLastRendered(lastRendered + 1);
+                setContainerHeight();
+                fixSpacers();
+                while (it.hasNext()) {
+                    addRow(prepareRow((UIDL) it.next()));
+                    setLastRendered(lastRendered + 1);
+                }
+                fixSpacers();
+            }
+
+            // this may be a new set of rows due content change,
+            // ensure we have proper cache rows
+            ensureCacheFilled();
+        }
+
+        /**
+         * Ensure we have the correct set of rows on client side, e.g. if the
+         * content on the server side has changed, or the client scroll position
+         * has changed since the last request.
+         */
+        protected void ensureCacheFilled() {
+            int reactFirstRow = (int) (firstRowInViewPort - pageLength
+                    * cache_react_rate);
+            int reactLastRow = (int) (firstRowInViewPort + pageLength + pageLength
+                    * cache_react_rate);
+            if (reactFirstRow < 0) {
+                reactFirstRow = 0;
+            }
+            if (reactLastRow >= totalRows) {
+                reactLastRow = totalRows - 1;
+            }
+            if (lastRendered < reactFirstRow || firstRendered > reactLastRow) {
+                /*
+                 * #8040 - scroll position is completely changed since the
+                 * latest request, so request a new set of rows.
+                 * 
+                 * TODO: We should probably check whether the fetched rows match
+                 * the current scroll position right when they arrive, so as to
+                 * not waste time rendering a set of rows that will never be
+                 * visible...
+                 */
+                rowRequestHandler.triggerRowFetch(reactFirstRow, reactLastRow
+                        - reactFirstRow + 1, 1);
+            } else if (lastRendered < reactLastRow) {
+                // get some cache rows below visible area
+                rowRequestHandler.triggerRowFetch(lastRendered + 1,
+                        reactLastRow - lastRendered, 1);
+            } else if (firstRendered > reactFirstRow) {
+                /*
+                 * Branch for fetching cache above visible area.
+                 * 
+                 * If cache needed for both before and after visible area, this
+                 * will be rendered after-cache is received and rendered. So in
+                 * some rare situations the table may make two cache visits to
+                 * server.
+                 */
+                rowRequestHandler.triggerRowFetch(reactFirstRow, firstRendered
+                        - reactFirstRow, 1);
+            }
+        }
+
+        /** Inserts rows as provided in the rowData starting at firstIndex.
+		 *
+		 * @param rowData
+		 *            the row data
+		 * @param firstIndex
+		 *            the first index
+		 * @param rows
+		 *            the number of rows
+		 * @return a list of the rows added.
+		 */
+        protected List<VScrollTableRow> insertRows(UIDL rowData,
+                int firstIndex, int rows) {
+            aligns = tHead.getColumnAlignments();
+            final Iterator<?> it = rowData.getChildIterator();
+            List<VScrollTableRow> insertedRows = new ArrayList<VScrollTableRow>();
+
+            if (firstIndex == lastRendered + 1) {
+                while (it.hasNext()) {
+                    final VScrollTableRow row = prepareRow((UIDL) it.next());
+                    addRow(row);
+                    insertedRows.add(row);
+                    if (postponeSanityCheckForLastRendered) {
+                        lastRendered++;
+                    } else {
+                        setLastRendered(lastRendered + 1);
+                    }
+                }
+                fixSpacers();
+            } else if (firstIndex + rows == firstRendered) {
+                final VScrollTableRow[] rowArray = new VScrollTableRow[rows];
+                int i = rows;
+                while (it.hasNext()) {
+                    i--;
+                    rowArray[i] = prepareRow((UIDL) it.next());
+                }
+                for (i = 0; i < rows; i++) {
+                    addRowBeforeFirstRendered(rowArray[i]);
+                    insertedRows.add(rowArray[i]);
+                    firstRendered--;
+                }
+            } else {
+                // insert in the middle
+                int ix = firstIndex;
+                while (it.hasNext()) {
+                    VScrollTableRow row = prepareRow((UIDL) it.next());
+                    insertRowAt(row, ix);
+                    insertedRows.add(row);
+                    if (postponeSanityCheckForLastRendered) {
+                        lastRendered++;
+                    } else {
+                        setLastRendered(lastRendered + 1);
+                    }
+                    ix++;
+                }
+                fixSpacers();
+            }
+            return insertedRows;
+        }
+
+        /** Insert and reindex rows.
+		 *
+		 * @param rowData
+		 *            the row data
+		 * @param firstIndex
+		 *            the first index
+		 * @param rows
+		 *            the rows
+		 * @return the list
+		 */
+        protected List<VScrollTableRow> insertAndReindexRows(UIDL rowData,
+                int firstIndex, int rows) {
+            List<VScrollTableRow> inserted = insertRows(rowData, firstIndex,
+                    rows);
+            int actualIxOfFirstRowAfterInserted = firstIndex + rows
+                    - firstRendered;
+            for (int ix = actualIxOfFirstRowAfterInserted; ix < renderedRows
+                    .size(); ix++) {
+                VScrollTableRow r = (VScrollTableRow) renderedRows.get(ix);
+                r.setIndex(r.getIndex() + rows);
+            }
+            setContainerHeight();
+            return inserted;
+        }
+
+        /** Insert rows delete below.
+		 *
+		 * @param rowData
+		 *            the row data
+		 * @param firstIndex
+		 *            the first index
+		 * @param rows
+		 *            the rows
+		 */
+        protected void insertRowsDeleteBelow(UIDL rowData, int firstIndex,
+                int rows) {
+            unlinkAllRowsStartingAt(firstIndex);
+            insertRows(rowData, firstIndex, rows);
+            setContainerHeight();
+        }
+
+        /** This method is used to instantiate new rows for this table. It
+		 * automatically sets correct widths to rows cells and assigns correct
+		 * client reference for child widgets.
+		 * 
+		 * This method can be called only after table has been initialized
+		 *
+		 * @param uidl
+		 *            the uidl
+		 * @return the v scroll table row
+		 */
+        private VScrollTableRow prepareRow(UIDL uidl) {
+            final VScrollTableRow row = createRow(uidl, aligns);
+            row.initCellWidths();
+            return row;
+        }
+
+        /** Creates the row.
+		 *
+		 * @param uidl
+		 *            the uidl
+		 * @param aligns2
+		 *            the aligns2
+		 * @return the v scroll table row
+		 */
+        protected VScrollTableRow createRow(UIDL uidl, char[] aligns2) {
+            if (uidl.hasAttribute("gen_html")) {
+                // This is a generated row.
+                return new VScrollTableGeneratedRow(uidl, aligns2);
+            }
+            return new VScrollTableRow(uidl, aligns2);
+        }
+
+        /** Adds the row before first rendered.
+		 *
+		 * @param row
+		 *            the row
+		 */
+        private void addRowBeforeFirstRendered(VScrollTableRow row) {
+            row.setIndex(firstRendered - 1);
+            if (row.isSelected()) {
+                row.addStyleName("v-selected");
+            }
+            tBodyElement.insertBefore(row.getElement(),
+                    tBodyElement.getFirstChild());
+            adopt(row);
+            renderedRows.add(0, row);
+        }
+
+        /** Adds the row.
+		 *
+		 * @param row
+		 *            the row
+		 */
+        private void addRow(VScrollTableRow row) {
+            row.setIndex(firstRendered + renderedRows.size());
+            if (row.isSelected()) {
+                row.addStyleName("v-selected");
+            }
+            tBodyElement.appendChild(row.getElement());
+            // Add to renderedRows before adopt so iterator() will return also
+            // this row if called in an attach handler (#9264)
+            renderedRows.add(row);
+            adopt(row);
+        }
+
+        /** Insert row at.
+		 *
+		 * @param row
+		 *            the row
+		 * @param index
+		 *            the index
+		 */
+        private void insertRowAt(VScrollTableRow row, int index) {
+            row.setIndex(index);
+            if (row.isSelected()) {
+                row.addStyleName("v-selected");
+            }
+            if (index > 0) {
+                VScrollTableRow sibling = getRowByRowIndex(index - 1);
+                tBodyElement
+                        .insertAfter(row.getElement(), sibling.getElement());
+            } else {
+                VScrollTableRow sibling = getRowByRowIndex(index);
+                tBodyElement.insertBefore(row.getElement(),
+                        sibling.getElement());
+            }
+            adopt(row);
+            int actualIx = index - firstRendered;
+            renderedRows.add(actualIx, row);
+        }
+
+        /* (non-Javadoc)
+         * @see com.google.gwt.user.client.ui.HasWidgets#iterator()
+         */
+        @Override
+        public Iterator<Widget> iterator() {
+            return renderedRows.iterator();
+        }
+
+        /** Unlink row.
+		 *
+		 * @param fromBeginning
+		 *            the from beginning
+		 * @return false if couldn't remove row
+		 */
+        protected boolean unlinkRow(boolean fromBeginning) {
+            if (lastRendered - firstRendered < 0) {
+                return false;
+            }
+            int actualIx;
+            if (fromBeginning) {
+                actualIx = 0;
+                firstRendered++;
+            } else {
+                actualIx = renderedRows.size() - 1;
+                if (postponeSanityCheckForLastRendered) {
+                    --lastRendered;
+                } else {
+                    setLastRendered(lastRendered - 1);
+                }
+            }
+            if (actualIx >= 0) {
+                unlinkRowAtActualIndex(actualIx);
+                fixSpacers();
+                return true;
+            }
+            return false;
+        }
+
+        /** Unlink rows.
+		 *
+		 * @param firstIndex
+		 *            the first index
+		 * @param count
+		 *            the count
+		 */
+        protected void unlinkRows(int firstIndex, int count) {
+            if (count < 1) {
+                return;
+            }
+            if (firstRendered > firstIndex
+                    && firstRendered < firstIndex + count) {
+                count = count - (firstRendered - firstIndex);
+                firstIndex = firstRendered;
+            }
+            int lastIndex = firstIndex + count - 1;
+            if (lastRendered < lastIndex) {
+                lastIndex = lastRendered;
+            }
+            for (int ix = lastIndex; ix >= firstIndex; ix--) {
+                unlinkRowAtActualIndex(actualIndex(ix));
+                if (postponeSanityCheckForLastRendered) {
+                    // partialUpdate handles sanity check later
+                    lastRendered--;
+                } else {
+                    setLastRendered(lastRendered - 1);
+                }
+            }
+            fixSpacers();
+        }
+
+        /** Unlink and reindex rows.
+		 *
+		 * @param firstIndex
+		 *            the first index
+		 * @param count
+		 *            the count
+		 */
+        protected void unlinkAndReindexRows(int firstIndex, int count) {
+            unlinkRows(firstIndex, count);
+            int actualFirstIx = firstIndex - firstRendered;
+            for (int ix = actualFirstIx; ix < renderedRows.size(); ix++) {
+                VScrollTableRow r = (VScrollTableRow) renderedRows.get(ix);
+                r.setIndex(r.getIndex() - count);
+            }
+            setContainerHeight();
+        }
+
+        /** Unlink all rows starting at.
+		 *
+		 * @param index
+		 *            the index
+		 */
+        protected void unlinkAllRowsStartingAt(int index) {
+            if (firstRendered > index) {
+                index = firstRendered;
+            }
+            for (int ix = renderedRows.size() - 1; ix >= index; ix--) {
+                unlinkRowAtActualIndex(actualIndex(ix));
+                setLastRendered(lastRendered - 1);
+            }
+            fixSpacers();
+        }
+
+        /** Actual index.
+		 *
+		 * @param index
+		 *            the index
+		 * @return the int
+		 */
+        private int actualIndex(int index) {
+            return index - firstRendered;
+        }
+
+        /** Unlink row at actual index.
+		 *
+		 * @param index
+		 *            the index
+		 */
+        private void unlinkRowAtActualIndex(int index) {
+            final VScrollTableRow toBeRemoved = (VScrollTableRow) renderedRows
+                    .get(index);
+            tBodyElement.removeChild(toBeRemoved.getElement());
+            orphan(toBeRemoved);
+            renderedRows.remove(index);
+        }
+
+        /* (non-Javadoc)
+         * @see com.google.gwt.user.client.ui.Panel#remove(com.google.gwt.user.client.ui.Widget)
+         */
+        @Override
+        public boolean remove(Widget w) {
+            throw new UnsupportedOperationException();
+        }
+
+        /** Fix container blocks height according to totalRows to avoid
+		 * "bouncing" when scrolling.
+		 */
+        private void setContainerHeight() {
+            fixSpacers();
+            container.getStyle().setHeight(measureRowHeightOffset(totalRows),
+                    Unit.PX);
+        }
+
+        /** Fix spacers.
+		 */
+        private void fixSpacers() {
+            int prepx = measureRowHeightOffset(firstRendered);
+            if (prepx < 0) {
+                prepx = 0;
+            }
+            preSpacer.getStyle().setPropertyPx("height", prepx);
+            int postpx;
+            if (pageLength == 0 && totalRows == pageLength) {
+                /*
+                 * TreeTable depends on having lastRendered out of sync in some
+                 * situations, which makes this method miss the special
+                 * situation in which one row worth of post spacer to be added
+                 * if there are no rows in the table. #9203
+                 */
+                postpx = measureRowHeightOffset(1);
+            } else {
+                postpx = measureRowHeightOffset(totalRows - 1)
+                        - measureRowHeightOffset(lastRendered);
+            }
+
+            if (postpx < 0) {
+                postpx = 0;
+            }
+            postSpacer.getStyle().setPropertyPx("height", postpx);
+        }
+
+        /** Gets the row height.
+		 *
+		 * @return the row height
+		 */
+        public double getRowHeight() {
+            return getRowHeight(false);
+        }
+
+        /** Gets the row height.
+		 *
+		 * @param forceUpdate
+		 *            the force update
+		 * @return the row height
+		 */
+        public double getRowHeight(boolean forceUpdate) {
+            if (tBodyMeasurementsDone && !forceUpdate) {
+                return rowHeight;
+            } else {
+                if (tBodyElement.getRows().getLength() > 0) {
+                    int tableHeight = getTableHeight();
+                    int rowCount = tBodyElement.getRows().getLength();
+                    rowHeight = tableHeight / (double) rowCount;
+                } else {
+                    // Special cases if we can't just measure the current rows
+                    if (!Double.isNaN(lastKnownRowHeight)) {
+                        // Use previous value if available
+                        if (BrowserInfo.get().isIE()) {
+                            /*
+                             * IE needs to reflow the table element at this
+                             * point to work correctly (e.g.
+                             * com.vaadin.tests.components.table.
+                             * ContainerSizeChange) - the other code paths
+                             * already trigger reflows, but here it must be done
+                             * explicitly.
+                             */
+                            getTableHeight();
+                        }
+                        rowHeight = lastKnownRowHeight;
+                    } else if (isAttached()) {
+                        // measure row height by adding a dummy row
+                        VScrollTableRow scrollTableRow = new VScrollTableRow();
+                        tBodyElement.appendChild(scrollTableRow.getElement());
+                        getRowHeight(forceUpdate);
+                        tBodyElement.removeChild(scrollTableRow.getElement());
+                    } else {
+                        // TODO investigate if this can never happen anymore
+                        return DEFAULT_ROW_HEIGHT;
+                    }
+                }
+                lastKnownRowHeight = rowHeight;
+                tBodyMeasurementsDone = true;
+                return rowHeight;
+            }
+        }
+
+        /** Gets the table height.
+		 *
+		 * @return the table height
+		 */
+        public int getTableHeight() {
+            return table.getOffsetHeight();
+        }
+
+        /** Returns the width available for column content.
+		 *
+		 * @param columnIndex
+		 *            the column index
+		 * @return the col width
+		 */
+        public int getColWidth(int columnIndex) {
+            if (tBodyMeasurementsDone) {
+                if (renderedRows.isEmpty()) {
+                    // no rows yet rendered
+                    return 0;
+                }
+                for (Widget row : renderedRows) {
+                    if (!(row instanceof VScrollTableGeneratedRow)) {
+                        TableRowElement tr = row.getElement().cast();
+                        Element wrapperdiv = tr.getCells().getItem(columnIndex)
+                                .getFirstChildElement().cast();
+                        return wrapperdiv.getOffsetWidth();
+                    }
+                }
+                return 0;
+            } else {
+                return 0;
+            }
+        }
+
+        /** Sets the content width of a column.
+		 * 
+		 * Due IE limitation, we must set the width to a wrapper elements inside
+		 * table cells (with overflow hidden, which does not work on td
+		 * elements).
+		 * 
+		 * To get this work properly crossplatform, we will also set the width
+		 * of td.
+		 *
+		 * @param colIndex
+		 *            the col index
+		 * @param w
+		 *            the w
+		 */
+        public void setColWidth(int colIndex, int w) {
+            for (Widget row : renderedRows) {
+                ((VScrollTableRow) row).setCellWidth(colIndex, w);
+            }
+        }
+
+        /** The cell extra width. */
+        private int cellExtraWidth = -1;
+
+        /** Method to return the space used for cell paddings + border.
+		 *
+		 * @return the cell extra width
+		 */
+        private int getCellExtraWidth() {
+            if (cellExtraWidth < 0) {
+                detectExtrawidth();
+            }
+            return cellExtraWidth;
+        }
+
+        /** This method exists for the needs of {@link VTreeTable} only. May
+		 * be removed or replaced in the future.<br> <br> Returns the maximum
+		 * indent of the hierarcyColumn, if applicable.
+		 *
+		 * @return maximum indent in pixels
+		 * @see #getHierarchyColumnIndex()
+		 */
+        protected int getMaxIndent() {
+            return 0;
+        }
+
+        /**
+         * This method exists for the needs of {@link VTreeTable} only. May be
+         * removed or replaced in the future.<br> <br> Calculates the maximum
+         * indent of the hierarcyColumn, if applicable.
+         */
+        protected void calculateMaxIndent() {
+            // NOP
+        }
+
+        /** Detect extrawidth.
+		 */
+        private void detectExtrawidth() {
+            NodeList<TableRowElement> rows = tBodyElement.getRows();
+            if (rows.getLength() == 0) {
+                /* need to temporary add empty row and detect */
+                VScrollTableRow scrollTableRow = new VScrollTableRow();
+                scrollTableRow.updateStyleNames(VCustomScrollTable.this
+                        .getStylePrimaryName());
+                tBodyElement.appendChild(scrollTableRow.getElement());
+                detectExtrawidth();
+                tBodyElement.removeChild(scrollTableRow.getElement());
+            } else {
+                boolean noCells = false;
+                TableRowElement item = rows.getItem(0);
+                TableCellElement firstTD = item.getCells().getItem(0);
+                if (firstTD == null) {
+                    // content is currently empty, we need to add a fake cell
+                    // for measuring
+                    noCells = true;
+                    VScrollTableRow next = (VScrollTableRow) iterator().next();
+                    boolean sorted = tHead.getHeaderCell(0) != null ? tHead
+                            .getHeaderCell(0).isSorted() : false;
+                    next.addCell(null, "", ALIGN_LEFT, "", true, sorted);
+                    firstTD = item.getCells().getItem(0);
+                }
+                com.google.gwt.dom.client.Element wrapper = firstTD
+                        .getFirstChildElement();
+                cellExtraWidth = firstTD.getOffsetWidth()
+                        - wrapper.getOffsetWidth();
+                if (noCells) {
+                    firstTD.getParentElement().removeChild(firstTD);
+                }
+            }
+        }
+
+        /** Move col.
+		 *
+		 * @param oldIndex
+		 *            the old index
+		 * @param newIndex
+		 *            the new index
+		 */
+        public void moveCol(int oldIndex, int newIndex) {
+
+            // loop all rows and move given index to its new place
+            final Iterator<?> rows = iterator();
+            while (rows.hasNext()) {
+                final VScrollTableRow row = (VScrollTableRow) rows.next();
+
+                final Element td = DOM.getChild(row.getElement(), oldIndex);
+                if (td != null) {
+                    DOM.removeChild(row.getElement(), td);
+
+                    DOM.insertChild(row.getElement(), td, newIndex);
+                }
+            }
+
+        }
+
+        /**
+         * Restore row visibility which is set to "none" when the row is
+         * rendered (due a performance optimization).
+         */
+        private void restoreRowVisibility() {
+            for (Widget row : renderedRows) {
+                row.getElement().getStyle().setProperty("visibility", "");
+            }
+        }
+
+        /** Index of.
+		 *
+		 * @param row
+		 *            the row
+		 * @return the int
+		 */
+        public int indexOf(Widget row) {
+            int relIx = -1;
+            for (int ix = 0; ix < renderedRows.size(); ix++) {
+                if (renderedRows.get(ix) == row) {
+                    relIx = ix;
+                    break;
+                }
+            }
+            if (relIx >= 0) {
+                return firstRendered + relIx;
+            }
+            return -1;
+        }
+
+        /** The Class VScrollTableRow.
+		 */
+        public class VScrollTableRow extends Panel implements ActionOwner,
+                ContextMenuOwner {
+
+            /** The Constant TOUCHSCROLL_TIMEOUT. */
+            private static final int TOUCHSCROLL_TIMEOUT = 100;
+            
+            /** The Constant DRAGMODE_MULTIROW. */
+            private static final int DRAGMODE_MULTIROW = 2;
+            
+            /** The child widgets. */
+            protected ArrayList<Widget> childWidgets = new ArrayList<Widget>();
+            
+            /** The selected. */
+            private boolean selected = false;
+            
+            /** The row key. */
+            protected final int rowKey;
+
+            /** The action keys. */
+            private String[] actionKeys = null;
+            
+            /** The row element. */
+            private final TableRowElement rowElement;
+            
+            /** The index. */
+            private int index;
+            
+            /** The touch start. */
+            private Event touchStart;
+
+            /** The Constant TOUCH_CONTEXT_MENU_TIMEOUT. */
+            private static final int TOUCH_CONTEXT_MENU_TIMEOUT = 500;
+            
+            /** The context touch timeout. */
+            private Timer contextTouchTimeout;
+            
+            /** The drag touch timeout. */
+            private Timer dragTouchTimeout;
+            
+            /** The touch start y. */
+            private int touchStartY;
+            
+            /** The touch start x. */
+            private int touchStartX;
+
+            /** The touch context provider. */
+            private TouchContextProvider touchContextProvider = new TouchContextProvider(
+                    this);
+
+            /** The tooltip info. */
+            private TooltipInfo tooltipInfo = null;
+            
+            /** The cell tool tips. */
+            private Map<TableCellElement, TooltipInfo> cellToolTips = new HashMap<TableCellElement, TooltipInfo>();
+            
+            /** The is dragging. */
+            private boolean isDragging = false;
+            
+            /** The row style. */
+            private String rowStyle = null;
+
+            /** Instantiates a new v scroll table row.
+			 *
+			 * @param rowKey
+			 *            the row key
+			 */
+            private VScrollTableRow(int rowKey) {
+                this.rowKey = rowKey;
+                rowElement = Document.get().createTRElement();
+                setElement(rowElement);
+                DOM.sinkEvents(getElement(), Event.MOUSEEVENTS
+                        | Event.TOUCHEVENTS | Event.ONDBLCLICK
+                        | Event.ONCONTEXTMENU | VTooltip.TOOLTIP_EVENTS);
+            }
+
+            /** Instantiates a new v scroll table row.
+			 *
+			 * @param uidl
+			 *            the uidl
+			 * @param aligns
+			 *            the aligns
+			 */
+            public VScrollTableRow(UIDL uidl, char[] aligns) {
+                this(uidl.getIntAttribute("key"));
+
+                /*
+                 * Rendering the rows as hidden improves Firefox and Safari
+                 * performance drastically.
+                 */
+                getElement().getStyle().setProperty("visibility", "hidden");
+
+                rowStyle = uidl.getStringAttribute("rowstyle");
+                updateStyleNames(VCustomScrollTable.this.getStylePrimaryName());
+
+                String rowDescription = uidl.getStringAttribute("rowdescr");
+                if (rowDescription != null && !rowDescription.equals("")) {
+                    tooltipInfo = new TooltipInfo(rowDescription, null, this);
+                } else {
+                    tooltipInfo = null;
+                }
+
+                tHead.getColumnAlignments();
+                int col = 0;
+                int visibleColumnIndex = -1;
+
+                // row header
+                if (showRowHeaders) {
+                    boolean sorted = tHead.getHeaderCell(col).isSorted();
+                    addCell(uidl, buildCaptionHtmlSnippet(uidl), aligns[col++],
+                            "rowheader", true, sorted);
+                    visibleColumnIndex++;
+                }
+
+                if (uidl.hasAttribute("al")) {
+                    actionKeys = uidl.getStringArrayAttribute("al");
+                }
+
+                addCellsFromUIDL(uidl, aligns, col, visibleColumnIndex);
+
+                if (uidl.hasAttribute("selected") && !isSelected()) {
+                    toggleSelection();
+                }
+            }
+
+            /** Update style names.
+			 *
+			 * @param primaryStyleName
+			 *            the primary style name
+			 */
+            protected void updateStyleNames(String primaryStyleName) {
+
+                if (getStylePrimaryName().contains("odd")) {
+                    setStyleName(primaryStyleName + "-row-odd");
+                } else {
+                    setStyleName(primaryStyleName + "-row");
+                }
+
+                if (rowStyle != null) {
+                    addStyleName(primaryStyleName + "-row-" + rowStyle);
+                }
+
+                for (int i = 0; i < rowElement.getChildCount(); i++) {
+                    TableCellElement cell = (TableCellElement) rowElement
+                            .getChild(i);
+                    updateCellStyleNames(cell, primaryStyleName);
+                }
+            }
+
+            /** Gets the tooltip info.
+			 *
+			 * @return the tooltip info
+			 */
+            public TooltipInfo getTooltipInfo() {
+                return tooltipInfo;
+            }
+
+            /**
+             * Add a dummy row, used for measurements if Table is empty.
+             */
+            public VScrollTableRow() {
+                this(0);
+                addCell(null, "_", 'b', "", true, false);
+            }
+
+            /** Inits the cell widths.
+			 */
+            protected void initCellWidths() {
+                final int cells = tHead.getVisibleCellCount();
+                for (int i = 0; i < cells; i++) {
+                    int w = VCustomScrollTable.this
+                            .getColWidth(getColKeyByIndex(i));
+                    if (w < 0) {
+                        w = 0;
+                    }
+                    setCellWidth(i, w);
+                }
+            }
+
+            /** Sets the cell width.
+			 *
+			 * @param cellIx
+			 *            the cell ix
+			 * @param width
+			 *            the width
+			 */
+            protected void setCellWidth(int cellIx, int width) {
+                final Element cell = DOM.getChild(getElement(), cellIx);
+                Style wrapperStyle = cell.getFirstChildElement().getStyle();
+                int wrapperWidth = width;
+                if (BrowserInfo.get().isWebkit()
+                        || BrowserInfo.get().isOpera10()) {
+                    /*
+                     * Some versions of Webkit and Opera ignore the width
+                     * definition of zero width table cells. Instead, use 1px
+                     * and compensate with a negative margin.
+                     */
+                    if (width == 0) {
+                        wrapperWidth = 1;
+                        wrapperStyle.setMarginRight(-1, Unit.PX);
+                    } else {
+                        wrapperStyle.clearMarginRight();
+                    }
+                }
+                wrapperStyle.setPropertyPx("width", wrapperWidth);
+                cell.getStyle().setPropertyPx("width", width);
+            }
+
+            /** Adds the cells from uidl.
+			 *
+			 * @param uidl
+			 *            the uidl
+			 * @param aligns
+			 *            the aligns
+			 * @param col
+			 *            the col
+			 * @param visibleColumnIndex
+			 *            the visible column index
+			 */
+            protected void addCellsFromUIDL(UIDL uidl, char[] aligns, int col,
+                    int visibleColumnIndex) {
+                final Iterator<?> cells = uidl.getChildIterator();
+                while (cells.hasNext()) {
+                    final Object cell = cells.next();
+                    visibleColumnIndex++;
+
+                    String columnId = visibleColOrder[visibleColumnIndex];
+
+                    String style = "";
+                    if (uidl.hasAttribute("style-" + columnId)) {
+                        style = uidl.getStringAttribute("style-" + columnId);
+                    }
+
+                    String description = null;
+                    if (uidl.hasAttribute("descr-" + columnId)) {
+                        description = uidl.getStringAttribute("descr-"
+                                + columnId);
+                    }
+
+                    boolean sorted = tHead.getHeaderCell(col).isSorted();
+                    if (cell instanceof String) {
+                        addCell(uidl, cell.toString(), aligns[col++], style,
+                                isRenderHtmlInCells(), sorted, description);
+                    } else {
+                        final ComponentConnector cellContent = client
+                                .getPaintable((UIDL) cell);
+
+                        addCell(uidl, cellContent.getWidget(), aligns[col++],
+                                style, sorted, description);
+                    }
+                }
+            }
+
+            /**
+             * Overriding this and returning true causes all text cells to be
+             * rendered as HTML.
+             * 
+             * @return always returns false in the default implementation
+             */
+            protected boolean isRenderHtmlInCells() {
+                return false;
+            }
+
+            /** Detects whether row is visible in tables viewport.
+			 *
+			 * @return true, if is in view port
+			 */
+            public boolean isInViewPort() {
+                int absoluteTop = getAbsoluteTop();
+                int absoluteBottom = absoluteTop + getOffsetHeight();
+                int viewPortTop = scrollBodyPanel.getAbsoluteTop();
+                int viewPortBottom = viewPortTop
+                        + scrollBodyPanel.getOffsetHeight();
+                return absoluteBottom > viewPortTop
+                        && absoluteTop < viewPortBottom;
+            }
+
+            /** Makes a check based on indexes whether the row is before the
+			 * compared row.
+			 *
+			 * @param row1
+			 *            the row1
+			 * @return true if this rows index is smaller than in the row1
+			 */
+            public boolean isBefore(VScrollTableRow row1) {
+                return getIndex() < row1.getIndex();
+            }
+
+            /** Sets the index of the row in the whole table. Currently used
+			 * just to set even/odd classname
+			 *
+			 * @param indexInWholeTable
+			 *            the new index
+			 */
+            private void setIndex(int indexInWholeTable) {
+                index = indexInWholeTable;
+                boolean isOdd = indexInWholeTable % 2 == 0;
+                // Inverted logic to be backwards compatible with earlier 6.4.
+                // It is very strange because rows 1,3,5 are considered "even"
+                // and 2,4,6 "odd".
+                //
+                // First remove any old styles so that both styles aren't
+                // applied when indexes are updated.
+                String primaryStyleName = getStylePrimaryName();
+                if (primaryStyleName != null && !primaryStyleName.equals("")) {
+                    removeStyleName(getStylePrimaryName());
+                }
+                if (!isOdd) {
+                    addStyleName(VCustomScrollTable.this.getStylePrimaryName()
+                            + "-row-odd");
+                } else {
+                    addStyleName(VCustomScrollTable.this.getStylePrimaryName()
+                            + "-row");
+                }
+            }
+
+            /** Gets the index.
+			 *
+			 * @return the index
+			 */
+            public int getIndex() {
+                return index;
+            }
+
+            /* (non-Javadoc)
+             * @see com.google.gwt.user.client.ui.Widget#onDetach()
+             */
+            @Override
+            protected void onDetach() {
+                super.onDetach();
+                client.getContextMenu().ensureHidden(this);
+            }
+
+            /** Gets the key.
+			 *
+			 * @return the key
+			 */
+            public String getKey() {
+                return String.valueOf(rowKey);
+            }
+
+            /** Adds the cell.
+			 *
+			 * @param rowUidl
+			 *            the row uidl
+			 * @param text
+			 *            the text
+			 * @param align
+			 *            the align
+			 * @param style
+			 *            the style
+			 * @param textIsHTML
+			 *            the text is html
+			 * @param sorted
+			 *            the sorted
+			 */
+            public void addCell(UIDL rowUidl, String text, char align,
+                    String style, boolean textIsHTML, boolean sorted) {
+                addCell(rowUidl, text, align, style, textIsHTML, sorted, null);
+            }
+
+            /** Adds the cell.
+			 *
+			 * @param rowUidl
+			 *            the row uidl
+			 * @param text
+			 *            the text
+			 * @param align
+			 *            the align
+			 * @param style
+			 *            the style
+			 * @param textIsHTML
+			 *            the text is html
+			 * @param sorted
+			 *            the sorted
+			 * @param description
+			 *            the description
+			 */
+            public void addCell(UIDL rowUidl, String text, char align,
+                    String style, boolean textIsHTML, boolean sorted,
+                    String description) {
+                // String only content is optimized by not using Label widget
+                final TableCellElement td = DOM.createTD().cast();
+                initCellWithText(text, align, style, textIsHTML, sorted,
+                        description, td);
+            }
+
+            /** Inits the cell with text.
+			 *
+			 * @param text
+			 *            the text
+			 * @param align
+			 *            the align
+			 * @param style
+			 *            the style
+			 * @param textIsHTML
+			 *            the text is html
+			 * @param sorted
+			 *            the sorted
+			 * @param description
+			 *            the description
+			 * @param td
+			 *            the td
+			 */
+            protected void initCellWithText(String text, char align,
+                    String style, boolean textIsHTML, boolean sorted,
+                    String description, final TableCellElement td) {
+                final Element container = DOM.createDiv();
+                container.setClassName(VCustomScrollTable.this
+                        .getStylePrimaryName() + "-cell-wrapper");
+
+                td.setClassName(VCustomScrollTable.this.getStylePrimaryName()
+                        + "-cell-content");
+
+                if (style != null && !style.equals("")) {
+                    td.addClassName(VCustomScrollTable.this
+                            .getStylePrimaryName() + "-cell-content-" + style);
+                }
+
+                if (sorted) {
+                    td.addClassName(VCustomScrollTable.this
+                            .getStylePrimaryName() + "-cell-content-sorted");
+                }
+
+                if (textIsHTML) {
+                    container.setInnerHTML(text);
+                } else {
+                    container.setInnerText(text);
+                }
+                setAlign(align, container);
+                setTooltip(td, description);
+
+                td.appendChild(container);
+                getElement().appendChild(td);
+            }
+
+            /** Update cell style names.
+			 *
+			 * @param td
+			 *            the td
+			 * @param primaryStyleName
+			 *            the primary style name
+			 */
+            protected void updateCellStyleNames(TableCellElement td,
+                    String primaryStyleName) {
+                Element container = td.getFirstChild().cast();
+                container.setClassName(primaryStyleName + "-cell-wrapper");
+
+                /*
+                 * Replace old primary style name with new one
+                 */
+                String className = td.getClassName();
+                String oldPrimaryName = className.split("-cell-content")[0];
+                td.setClassName(className.replaceAll(oldPrimaryName,
+                        primaryStyleName));
+            }
+
+            /** Adds the cell.
+			 *
+			 * @param rowUidl
+			 *            the row uidl
+			 * @param w
+			 *            the w
+			 * @param align
+			 *            the align
+			 * @param style
+			 *            the style
+			 * @param sorted
+			 *            the sorted
+			 * @param description
+			 *            the description
+			 */
+            public void addCell(UIDL rowUidl, Widget w, char align,
+                    String style, boolean sorted, String description) {
+                final TableCellElement td = DOM.createTD().cast();
+                initCellWithWidget(w, align, style, sorted, td);
+                setTooltip(td, description);
+            }
+
+            /** Sets the tooltip.
+			 *
+			 * @param td
+			 *            the td
+			 * @param description
+			 *            the description
+			 */
+            private void setTooltip(TableCellElement td, String description) {
+                if (description != null && !description.equals("")) {
+                    TooltipInfo info = new TooltipInfo(description, null, this);
+                    cellToolTips.put(td, info);
+                } else {
+                    cellToolTips.remove(td);
+                }
+
+            }
+
+            /** Sets the align.
+			 *
+			 * @param align
+			 *            the align
+			 * @param container
+			 *            the container
+			 */
+            private void setAlign(char align, final Element container) {
+                switch (align) {
+                case ALIGN_CENTER:
+                    container.getStyle().setProperty("textAlign", "center");
+                    break;
+                case ALIGN_LEFT:
+                    container.getStyle().setProperty("textAlign", "left");
+                    break;
+                case ALIGN_RIGHT:
+                default:
+                    container.getStyle().setProperty("textAlign", "right");
+                    break;
+                }
+            }
+
+            /** Inits the cell with widget.
+			 *
+			 * @param w
+			 *            the w
+			 * @param align
+			 *            the align
+			 * @param style
+			 *            the style
+			 * @param sorted
+			 *            the sorted
+			 * @param td
+			 *            the td
+			 */
+            protected void initCellWithWidget(Widget w, char align,
+                    String style, boolean sorted, final TableCellElement td) {
+                final Element container = DOM.createDiv();
+                String className = VCustomScrollTable.this
+                        .getStylePrimaryName() + "-cell-content";
+                if (style != null && !style.equals("")) {
+                    className += " "
+                            + VCustomScrollTable.this.getStylePrimaryName()
+                            + "-cell-content-" + style;
+                }
+                if (sorted) {
+                    className += " "
+                            + VCustomScrollTable.this.getStylePrimaryName()
+                            + "-cell-content-sorted";
+                }
+                td.setClassName(className);
+                container.setClassName(VCustomScrollTable.this
+                        .getStylePrimaryName() + "-cell-wrapper");
+                setAlign(align, container);
+                td.appendChild(container);
+                getElement().appendChild(td);
+                // ensure widget not attached to another element (possible tBody
+                // change)
+                w.removeFromParent();
+                container.appendChild(w.getElement());
+                adopt(w);
+                childWidgets.add(w);
+            }
+
+            /* (non-Javadoc)
+             * @see com.google.gwt.user.client.ui.HasWidgets#iterator()
+             */
+            @Override
+            public Iterator<Widget> iterator() {
+                return childWidgets.iterator();
+            }
+
+            /* (non-Javadoc)
+             * @see com.google.gwt.user.client.ui.Panel#remove(com.google.gwt.user.client.ui.Widget)
+             */
+            @Override
+            public boolean remove(Widget w) {
+                if (childWidgets.contains(w)) {
+                    orphan(w);
+                    DOM.removeChild(DOM.getParent(w.getElement()),
+                            w.getElement());
+                    childWidgets.remove(w);
+                    return true;
+                } else {
+                    return false;
+                }
+            }
+
+            /** If there are registered click listeners, sends a click event
+			 * and returns true. Otherwise, does nothing and returns false.
+			 *
+			 * @param event
+			 *            the event
+			 * @param targetTdOrTr
+			 *            the target td or tr
+			 * @param immediate
+			 *            Whether the event is sent immediately
+			 * @return Whether a click event was sent
+			 */
+            private boolean handleClickEvent(Event event, Element targetTdOrTr,
+                    boolean immediate) {
+                if (!client.hasEventListeners(VCustomScrollTable.this,
+                        TableConstants.ITEM_CLICK_EVENT_ID)) {
+                    // Don't send an event if nobody is listening
+                    return false;
+                }
+
+                // This row was clicked
+                client.updateVariable(paintableId, "clickedKey", "" + rowKey,
+                        false);
+
+                if (getElement() == targetTdOrTr.getParentElement()) {
+                    // A specific column was clicked
+                    int childIndex = DOM.getChildIndex(getElement(),
+                            targetTdOrTr);
+                    String colKey = null;
+                    colKey = tHead.getHeaderCell(childIndex).getColKey();
+                    client.updateVariable(paintableId, "clickedColKey", colKey,
+                            false);
+                }
+
+                MouseEventDetails details = MouseEventDetailsBuilder
+                        .buildMouseEventDetails(event);
+
+                client.updateVariable(paintableId, "clickEvent",
+                        details.toString(), immediate);
+
+                return true;
+            }
+
+            /** Gets the tooltip.
+			 *
+			 * @param target
+			 *            the target
+			 * @return the tooltip
+			 */
+            public TooltipInfo getTooltip(
+                    com.google.gwt.dom.client.Element target) {
+
+                TooltipInfo info = null;
+                final Element targetTdOrTr = getTdOrTr(target);
+                if (targetTdOrTr != null
+                        && "td".equals(targetTdOrTr.getTagName().toLowerCase())) {
+                    TableCellElement td = (TableCellElement) targetTdOrTr
+                            .cast();
+                    info = cellToolTips.get(td);
+                }
+
+                if (info == null) {
+                    info = tooltipInfo;
+                }
+
+                return info;
+            }
+
+            /** Gets the td or tr.
+			 *
+			 * @param target
+			 *            the target
+			 * @return the td or tr
+			 */
+            private Element getTdOrTr(Element target) {
+                Element thisTrElement = getElement();
+                if (target == thisTrElement) {
+                    // This was a on the TR element
+                    return target;
+                }
+
+                // Iterate upwards until we find the TR element
+                Element element = target;
+                while (element != null
+                        && element.getParentElement() != thisTrElement) {
+                    element = element.getParentElement();
+                }
+                return element;
+            }
+
+            /** Special handler for touch devices that support native
+			 * scrolling.
+			 *
+			 * @param event
+			 *            the event
+			 * @return Whether the event was handled by this method.
+			 */
+            private boolean handleTouchEvent(final Event event) {
+
+                boolean touchEventHandled = false;
+
+                if (enabled && hasNativeTouchScrolling) {
+                    touchContextProvider.handleTouchEvent(event);
+
+                    final Element targetTdOrTr = getEventTargetTdOrTr(event);
+                    final int type = event.getTypeInt();
+
+                    switch (type) {
+                    case Event.ONTOUCHSTART:
+                        touchEventHandled = true;
+                        touchStart = event;
+                        isDragging = false;
+                        Touch touch = event.getChangedTouches().get(0);
+                        // save position to fields, touches in events are same
+                        // instance during the operation.
+                        touchStartX = touch.getClientX();
+                        touchStartY = touch.getClientY();
+
+                        if (dragmode != 0) {
+                            if (dragTouchTimeout == null) {
+                                dragTouchTimeout = new Timer() {
+
+                                    @Override
+                                    public void run() {
+                                        if (touchStart != null) {
+                                            // Start a drag if a finger is held
+                                            // in place long enough, then moved
+                                            isDragging = true;
+                                        }
+                                    }
+                                };
+                            }
+                            dragTouchTimeout.schedule(TOUCHSCROLL_TIMEOUT);
+                        }
+
+                        if (actionKeys != null) {
+                            if (contextTouchTimeout == null) {
+                                contextTouchTimeout = new Timer() {
+
+                                    @Override
+                                    public void run() {
+                                        if (touchStart != null) {
+                                            // Open the context menu if finger
+                                            // is held in place long enough.
+                                            showContextMenu(touchStart);
+                                            event.preventDefault();
+                                            touchStart = null;
+                                        }
+                                    }
+                                };
+                            }
+                            contextTouchTimeout
+                                    .schedule(TOUCH_CONTEXT_MENU_TIMEOUT);
+                        }
+                        break;
+                    case Event.ONTOUCHMOVE:
+                        touchEventHandled = true;
+                        if (isSignificantMove(event)) {
+                            if (contextTouchTimeout != null) {
+                                // Moved finger before the context menu timer
+                                // expired, so let the browser handle this as a
+                                // scroll.
+                                contextTouchTimeout.cancel();
+                                contextTouchTimeout = null;
+                            }
+                            if (!isDragging && dragTouchTimeout != null) {
+                                // Moved finger before the drag timer expired,
+                                // so let the browser handle this as a scroll.
+                                dragTouchTimeout.cancel();
+                                dragTouchTimeout = null;
+                            }
+
+                            if (dragmode != 0 && touchStart != null
+                                    && isDragging) {
+                                event.preventDefault();
+                                event.stopPropagation();
+                                startRowDrag(touchStart, type, targetTdOrTr);
+                            }
+                            touchStart = null;
+                        }
+                        break;
+                    case Event.ONTOUCHEND:
+                    case Event.ONTOUCHCANCEL:
+                        touchEventHandled = true;
+                        if (contextTouchTimeout != null) {
+                            contextTouchTimeout.cancel();
+                        }
+                        if (dragTouchTimeout != null) {
+                            dragTouchTimeout.cancel();
+                        }
+                        if (touchStart != null) {
+                            if (!BrowserInfo.get().isAndroid()) {
+                                event.preventDefault();
+                                event.stopPropagation();
+                                Util.simulateClickFromTouchEvent(touchStart,
+                                        this);
+                            }
+                            touchStart = null;
+                        }
+                        isDragging = false;
+                        break;
+                    }
+                }
+                return touchEventHandled;
+            }
+
+            /*
+             * React on click that occur on content cells only
+             */
+
+            /* (non-Javadoc)
+             * @see com.google.gwt.user.client.ui.Widget#onBrowserEvent(com.google.gwt.user.client.Event)
+             */
+            @Override
+            public void onBrowserEvent(final Event event) {
+
+                final boolean touchEventHandled = handleTouchEvent(event);
+
+                if (enabled && !touchEventHandled) {
+                    final int type = event.getTypeInt();
+                    final Element targetTdOrTr = getEventTargetTdOrTr(event);
+                    if (type == Event.ONCONTEXTMENU) {
+                        showContextMenu(event);
+                        if (enabled
+                                && (actionKeys != null || client
+                                        .hasEventListeners(
+                                                VCustomScrollTable.this,
+                                                TableConstants.ITEM_CLICK_EVENT_ID))) {
+                            /*
+                             * Prevent browser context menu only if there are
+                             * action handlers or item click listeners
+                             * registered
+                             */
+                            event.stopPropagation();
+                            event.preventDefault();
+                        }
+                        return;
+                    }
+
+                    boolean targetCellOrRowFound = targetTdOrTr != null;
+
+                    switch (type) {
+                    case Event.ONDBLCLICK:
+                        if (targetCellOrRowFound) {
+                            handleClickEvent(event, targetTdOrTr, true);
+                        }
+                        break;
+                    case Event.ONMOUSEUP:
+                        /*
+                         * Only fire a click if the mouseup hits the same
+                         * element as the corresponding mousedown. This is first
+                         * checked in the event preview but we can't fire the
+                         * event there as the event might get canceled before it
+                         * gets here.
+                         */
+                        if (mouseUpPreviewMatched
+                                && lastMouseDownTarget != null
+                                && lastMouseDownTarget == getElementTdOrTr(Util
+                                        .getElementUnderMouse(event))) {
+                            // "Click" with left, right or middle button
+
+                            if (targetCellOrRowFound) {
+                                /*
+                                 * Queue here, send at the same time as the
+                                 * corresponding value change event - see #7127
+                                 */
+                                boolean clickEventSent = handleClickEvent(
+                                        event, targetTdOrTr, false);
+
+                                if (event.getButton() == Event.BUTTON_LEFT
+                                        && isSelectable()) {
+
+                                    // Ctrl+Shift click
+                                    if ((event.getCtrlKey() || event
+                                            .getMetaKey())
+                                            && event.getShiftKey()
+                                            && isMultiSelectModeDefault()) {
+                                        toggleShiftSelection(false);
+                                        setRowFocus(this);
+
+                                        // Ctrl click
+                                    } else if ((event.getCtrlKey() || event
+                                            .getMetaKey())
+                                            && isMultiSelectModeDefault()) {
+                                        boolean wasSelected = isSelected();
+                                        toggleSelection();
+                                        setRowFocus(this);
+                                        /*
+                                         * next possible range select must start
+                                         * on this row
+                                         */
+                                        selectionRangeStart = this;
+                                        if (wasSelected) {
+                                            removeRowFromUnsentSelectionRanges(this);
+                                        }
+
+                                    } else if ((event.getCtrlKey() || event
+                                            .getMetaKey())
+                                            && isSingleSelectMode()) {
+                                        // Ctrl (or meta) click (Single
+                                        // selection)
+                                        if (!isSelected()
+                                                || (isSelected() && nullSelectionAllowed)) {
+
+                                            if (!isSelected()) {
+                                                deselectAll();
+                                            }
+
+                                            toggleSelection();
+                                            setRowFocus(this);
+                                        }
+
+                                    } else if (event.getShiftKey()
+                                            && isMultiSelectModeDefault()) {
+                                        // Shift click
+                                        toggleShiftSelection(true);
+
+                                    } else {
+                                        // click
+                                        boolean currentlyJustThisRowSelected = selectedRowKeys
+                                                .size() == 1
+                                                && selectedRowKeys
+                                                        .contains(getKey());
+
+                                        if (!currentlyJustThisRowSelected) {
+                                            if (isSingleSelectMode()
+                                                    || isMultiSelectModeDefault()) {
+                                                /*
+                                                 * For default multi select mode
+                                                 * (ctrl/shift) and for single
+                                                 * select mode we need to clear
+                                                 * the previous selection before
+                                                 * selecting a new one when the
+                                                 * user clicks on a row. Only in
+                                                 * multiselect/simple mode the
+                                                 * old selection should remain
+                                                 * after a normal click.
+                                                 */
+                                                deselectAll();
+                                            }
+                                            toggleSelection();
+                                        } else if ((isSingleSelectMode() || isMultiSelectModeSimple())
+                                                && nullSelectionAllowed) {
+                                            toggleSelection();
+                                        }/*
+                                          * else NOP to avoid excessive server
+                                          * visits (selection is removed with
+                                          * CTRL/META click)
+                                          */
+
+                                        selectionRangeStart = this;
+                                        setRowFocus(this);
+                                    }
+
+                                    // Remove IE text selection hack
+                                    if (BrowserInfo.get().isIE()) {
+                                        ((Element) event.getEventTarget()
+                                                .cast()).setPropertyJSO(
+                                                "onselectstart", null);
+                                    }
+                                    // Queue value change
+                                    sendSelectedRows(false);
+                                }
+                                /*
+                                 * Send queued click and value change events if
+                                 * any If a click event is sent, send value
+                                 * change with it regardless of the immediate
+                                 * flag, see #7127
+                                 */
+                                if (immediate || clickEventSent) {
+                                    client.sendPendingVariableChanges();
+                                }
+                            }
+                        }
+                        mouseUpPreviewMatched = false;
+                        lastMouseDownTarget = null;
+                        break;
+                    case Event.ONTOUCHEND:
+                    case Event.ONTOUCHCANCEL:
+                        if (touchStart != null) {
+                            /*
+                             * Touch has not been handled as neither context or
+                             * drag start, handle it as a click.
+                             */
+                            Util.simulateClickFromTouchEvent(touchStart, this);
+                            touchStart = null;
+                        }
+                        touchContextProvider.cancel();
+                        break;
+                    case Event.ONTOUCHMOVE:
+                        if (isSignificantMove(event)) {
+                            /*
+                             * TODO figure out scroll delegate don't eat events
+                             * if row is selected. Null check for active
+                             * delegate is as a workaround.
+                             */
+                            if (dragmode != 0
+                                    && touchStart != null
+                                    && (TouchScrollDelegate
+                                            .getActiveScrollDelegate() == null)) {
+                                startRowDrag(touchStart, type, targetTdOrTr);
+                            }
+                            touchContextProvider.cancel();
+                            /*
+                             * Avoid clicks and drags by clearing touch start
+                             * flag.
+                             */
+                            touchStart = null;
+                        }
+
+                        break;
+                    case Event.ONTOUCHSTART:
+                        touchStart = event;
+                        Touch touch = event.getChangedTouches().get(0);
+                        // save position to fields, touches in events are same
+                        // isntance during the operation.
+                        touchStartX = touch.getClientX();
+                        touchStartY = touch.getClientY();
+                        /*
+                         * Prevent simulated mouse events.
+                         */
+                        touchStart.preventDefault();
+                        if (dragmode != 0 || actionKeys != null) {
+                            new Timer() {
+
+                                @Override
+                                public void run() {
+                                    TouchScrollDelegate activeScrollDelegate = TouchScrollDelegate
+                                            .getActiveScrollDelegate();
+                                    /*
+                                     * If there's a scroll delegate, check if
+                                     * we're actually scrolling and handle it.
+                                     * If no delegate, do nothing here and let
+                                     * the row handle potential drag'n'drop or
+                                     * context menu.
+                                     */
+                                    if (activeScrollDelegate != null) {
+                                        if (activeScrollDelegate.isMoved()) {
+                                            /*
+                                             * Prevent the row from handling
+                                             * touch move/end events (the
+                                             * delegate handles those) and from
+                                             * doing drag'n'drop or opening a
+                                             * context menu.
+                                             */
+                                            touchStart = null;
+                                        } else {
+                                            /*
+                                             * Scrolling hasn't started, so
+                                             * cancel delegate and let the row
+                                             * handle potential drag'n'drop or
+                                             * context menu.
+                                             */
+                                            activeScrollDelegate
+                                                    .stopScrolling();
+                                        }
+                                    }
+                                }
+                            }.schedule(TOUCHSCROLL_TIMEOUT);
+
+                            if (contextTouchTimeout == null
+                                    && actionKeys != null) {
+                                contextTouchTimeout = new Timer() {
+
+                                    @Override
+                                    public void run() {
+                                        if (touchStart != null) {
+                                            showContextMenu(touchStart);
+                                            touchStart = null;
+                                        }
+                                    }
+                                };
+                            }
+                            if (contextTouchTimeout != null) {
+                                contextTouchTimeout.cancel();
+                                contextTouchTimeout
+                                        .schedule(TOUCH_CONTEXT_MENU_TIMEOUT);
+                            }
+                        }
+                        break;
+                    case Event.ONMOUSEDOWN:
+                        /*
+                         * When getting a mousedown event, we must detect where
+                         * the corresponding mouseup event if it's on a
+                         * different part of the page.
+                         */
+                        lastMouseDownTarget = getElementTdOrTr(Util
+                                .getElementUnderMouse(event));
+                        mouseUpPreviewMatched = false;
+                        mouseUpEventPreviewRegistration = Event
+                                .addNativePreviewHandler(mouseUpPreviewHandler);
+
+                        if (targetCellOrRowFound) {
+                            setRowFocus(this);
+                            ensureFocus();
+                            if (dragmode != 0
+                                    && (event.getButton() == NativeEvent.BUTTON_LEFT)) {
+                                startRowDrag(event, type, targetTdOrTr);
+
+                            } else if (event.getCtrlKey()
+                                    || event.getShiftKey()
+                                    || event.getMetaKey()
+                                    && isMultiSelectModeDefault()) {
+
+                                // Prevent default text selection in Firefox
+                                event.preventDefault();
+
+                                // Prevent default text selection in IE
+                                if (BrowserInfo.get().isIE()) {
+                                    ((Element) event.getEventTarget().cast())
+                                            .setPropertyJSO(
+                                                    "onselectstart",
+                                                    getPreventTextSelectionIEHack());
+                                }
+
+                                event.stopPropagation();
+                            }
+                        }
+                        break;
+                    case Event.ONMOUSEOUT:
+                        break;
+                    default:
+                        break;
+                    }
+                }
+                super.onBrowserEvent(event);
+            }
+
+            /** Checks if is significant move.
+			 *
+			 * @param event
+			 *            the event
+			 * @return true, if is significant move
+			 */
+            private boolean isSignificantMove(Event event) {
+                if (touchStart == null) {
+                    // no touch start
+                    return false;
+                }
+                /*
+                 * TODO calculate based on real distance instead of separate
+                 * axis checks
+                 */
+                Touch touch = event.getChangedTouches().get(0);
+                if (Math.abs(touch.getClientX() - touchStartX) > TouchScrollDelegate.SIGNIFICANT_MOVE_THRESHOLD) {
+                    return true;
+                }
+                if (Math.abs(touch.getClientY() - touchStartY) > TouchScrollDelegate.SIGNIFICANT_MOVE_THRESHOLD) {
+                    return true;
+                }
+                return false;
+            }
+
+            /** Checks if the row represented by the row key has been
+			 * selected.
+			 *
+			 * @param rowKey
+			 *            the row key
+			 * @return true, if successful
+			 */
+            private boolean rowKeyIsSelected(int rowKey) {
+                // Check single selections
+                if (selectedRowKeys.contains("" + rowKey)) {
+                    return true;
+                }
+
+                // Check range selections
+                for (SelectionRange r : selectedRowRanges) {
+                    if (r.inRange(getRenderedRowByKey("" + rowKey))) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+
+            /** Start row drag.
+			 *
+			 * @param event
+			 *            the event
+			 * @param type
+			 *            the type
+			 * @param targetTdOrTr
+			 *            the target td or tr
+			 */
+            protected void startRowDrag(Event event, final int type,
+                    Element targetTdOrTr) {
+                VTransferable transferable = new VTransferable();
+                transferable.setDragSource(ConnectorMap.get(client)
+                        .getConnector(VCustomScrollTable.this));
+                transferable.setData("itemId", "" + rowKey);
+                NodeList<TableCellElement> cells = rowElement.getCells();
+                for (int i = 0; i < cells.getLength(); i++) {
+                    if (cells.getItem(i).isOrHasChild(targetTdOrTr)) {
+                        HeaderCell headerCell = tHead.getHeaderCell(i);
+                        transferable.setData("propertyId", headerCell.cid);
+                        break;
+                    }
+                }
+
+                VDragEvent ev = VDragAndDropManager.get().startDrag(
+                        transferable, event, true);
+                if (dragmode == DRAGMODE_MULTIROW && isMultiSelectModeAny()
+                        && rowKeyIsSelected(rowKey)) {
+
+                    // Create a drag image of ALL rows
+                    ev.createDragImage(scrollBody.tBodyElement, true);
+
+                    // Hide rows which are not selected
+                    Element dragImage = ev.getDragImage();
+                    int i = 0;
+                    for (Iterator<Widget> iterator = scrollBody.iterator(); iterator
+                            .hasNext();) {
+                        VScrollTableRow next = (VScrollTableRow) iterator
+                                .next();
+
+                        Element child = (Element) dragImage.getChild(i++);
+
+                        if (!rowKeyIsSelected(next.rowKey)) {
+                            child.getStyle().setVisibility(Visibility.HIDDEN);
+                        }
+                    }
+                } else {
+                    ev.createDragImage(getElement(), true);
+                }
+                if (type == Event.ONMOUSEDOWN) {
+                    event.preventDefault();
+                }
+                event.stopPropagation();
+            }
+
+            /** Finds the TD that the event interacts with. Returns null if
+			 * the target of the event should not be handled. If the event
+			 * target is the row directly this method returns the TR element
+			 * instead of the TD.
+			 *
+			 * @param event
+			 *            the event
+			 * @return TD or TR element that the event targets (the actual event
+			 *         target is this element or a child of it)
+			 */
+            private Element getEventTargetTdOrTr(Event event) {
+                final Element eventTarget = event.getEventTarget().cast();
+                return getElementTdOrTr(eventTarget);
+            }
+
+            /** Gets the element td or tr.
+			 *
+			 * @param element
+			 *            the element
+			 * @return the element td or tr
+			 */
+            private Element getElementTdOrTr(Element element) {
+
+                Widget widget = Util.findWidget(element, null);
+
+                if (widget != this) {
+                    /*
+                     * This is a workaround to make Labels, read only TextFields
+                     * and Embedded in a Table clickable (see #2688). It is
+                     * really not a fix as it does not work with a custom read
+                     * only components (not extending VLabel/VEmbedded).
+                     */
+                    while (widget != null && widget.getParent() != this) {
+                        widget = widget.getParent();
+                    }
+
+                    if (!(widget instanceof VLabel)
+                            && !(widget instanceof VEmbedded)
+                            && !(widget instanceof VTextField && ((VTextField) widget)
+                                    .isReadOnly())) {
+                        return null;
+                    }
+                }
+                return getTdOrTr(element);
+            }
+
+            /* (non-Javadoc)
+             * @see com.vaadin.client.ui.VCustomScrollTable.ContextMenuOwner#showContextMenu(com.google.gwt.user.client.Event)
+             */
+            @Override
+            public void showContextMenu(Event event) {
+                if (enabled && actionKeys != null) {
+                    // Show context menu if there are registered action handlers
+                    int left = Util.getTouchOrMouseClientX(event)
+                            + Window.getScrollLeft();
+                    int top = Util.getTouchOrMouseClientY(event)
+                            + Window.getScrollTop();
+                    showContextMenu(left, top);
+                }
+            }
+
+            /** Show context menu.
+			 *
+			 * @param left
+			 *            the left
+			 * @param top
+			 *            the top
+			 */
+            public void showContextMenu(int left, int top) {
+                VContextMenu menu = client.getContextMenu();
+                contextMenu = new ContextMenuDetails(menu, getKey(), left, top);
+                menu.showAt(this, left, top);
+            }
+
+            /** Has the row been selected?.
+			 *
+			 * @return Returns true if selected, else false
+			 */
+            public boolean isSelected() {
+                return selected;
+            }
+
+            /** Toggle the selection of the row.
+			 */
+            public void toggleSelection() {
+                selected = !selected;
+                selectionChanged = true;
+                if (selected) {
+                    selectedRowKeys.add(String.valueOf(rowKey));
+                    addStyleName("v-selected");
+                } else {
+                    removeStyleName("v-selected");
+                    selectedRowKeys.remove(String.valueOf(rowKey));
+                }
+            }
+
+            /**
+             * Is called when a user clicks an item when holding SHIFT key down.
+             * This will select a new range from the last focused row
+             * 
+             * @param deselectPrevious
+             *            Should the previous selected range be deselected
+             */
+            private void toggleShiftSelection(boolean deselectPrevious) {
+
+                /*
+                 * Ensures that we are in multiselect mode and that we have a
+                 * previous selection which was not a deselection
+                 */
+                if (isSingleSelectMode()) {
+                    // No previous selection found
+                    deselectAll();
+                    toggleSelection();
+                    return;
+                }
+
+                // Set the selectable range
+                VScrollTableRow endRow = this;
+                VScrollTableRow startRow = selectionRangeStart;
+                if (startRow == null) {
+                    startRow = focusedRow;
+                    selectionRangeStart = focusedRow;
+                    // If start row is null then we have a multipage selection
+                    // from
+                    // above
+                    if (startRow == null) {
+                        startRow = (VScrollTableRow) scrollBody.iterator()
+                                .next();
+                        setRowFocus(endRow);
+                    }
+                } else if (!startRow.isSelected()) {
+                    // The start row is no longer selected (probably removed)
+                    // and so we select from above
+                    startRow = (VScrollTableRow) scrollBody.iterator().next();
+                    setRowFocus(endRow);
+                }
+
+                // Deselect previous items if so desired
+                if (deselectPrevious) {
+                    deselectAll();
+                }
+
+                // we'll ensure GUI state from top down even though selection
+                // was the opposite way
+                if (!startRow.isBefore(endRow)) {
+                    VScrollTableRow tmp = startRow;
+                    startRow = endRow;
+                    endRow = tmp;
+                }
+                SelectionRange range = new SelectionRange(startRow, endRow);
+
+                for (Widget w : scrollBody) {
+                    VScrollTableRow row = (VScrollTableRow) w;
+                    if (range.inRange(row)) {
+                        if (!row.isSelected()) {
+                            row.toggleSelection();
+                        }
+                        selectedRowKeys.add(row.getKey());
+                    }
+                }
+
+                // Add range
+                if (startRow != endRow) {
+                    selectedRowRanges.add(range);
+                }
+            }
+
+            /*
+             * (non-Javadoc)
+             * 
+             * @see com.vaadin.client.ui.IActionOwner#getActions ()
+             */
+
+            @Override
+            public Action[] getActions() {
+                if (actionKeys == null) {
+                    return new Action[] {};
+                }
+                final Action[] actions = new Action[actionKeys.length];
+                for (int i = 0; i < actions.length; i++) {
+                    final String actionKey = actionKeys[i];
+                    final TreeAction a = new TreeAction(this,
+                            String.valueOf(rowKey), actionKey) {
+
+                        @Override
+                        public void execute() {
+                            super.execute();
+                            lazyRevertFocusToRow(VScrollTableRow.this);
+                        }
+                    };
+                    a.setCaption(getActionCaption(actionKey));
+                    a.setIconUrl(getActionIcon(actionKey));
+                    actions[i] = a;
+                }
+                return actions;
+            }
+
+            /* (non-Javadoc)
+             * @see com.vaadin.client.ui.ActionOwner#getClient()
+             */
+            @Override
+            public ApplicationConnection getClient() {
+                return client;
+            }
+
+            /* (non-Javadoc)
+             * @see com.vaadin.client.ui.ActionOwner#getPaintableId()
+             */
+            @Override
+            public String getPaintableId() {
+                return paintableId;
+            }
+
+            /** Gets the col index of.
+			 *
+			 * @param child
+			 *            the child
+			 * @return the col index of
+			 */
+            private int getColIndexOf(Widget child) {
+                com.google.gwt.dom.client.Element widgetCell = child
+                        .getElement().getParentElement().getParentElement();
+                NodeList<TableCellElement> cells = rowElement.getCells();
+                for (int i = 0; i < cells.getLength(); i++) {
+                    if (cells.getItem(i) == widgetCell) {
+                        return i;
+                    }
+                }
+                return -1;
+            }
+
+            /** Gets the widget for paintable.
+			 *
+			 * @return the widget for paintable
+			 */
+            public Widget getWidgetForPaintable() {
+                return this;
+            }
+        }
+
+        /** The Class VScrollTableGeneratedRow.
+		 */
+        protected class VScrollTableGeneratedRow extends VScrollTableRow {
+
+            /** The span columns. */
+            private boolean spanColumns;
+            
+            /** The html content allowed. */
+            private boolean htmlContentAllowed;
+
+            /** Instantiates a new v scroll table generated row.
+			 *
+			 * @param uidl
+			 *            the uidl
+			 * @param aligns
+			 *            the aligns
+			 */
+            public VScrollTableGeneratedRow(UIDL uidl, char[] aligns) {
+                super(uidl, aligns);
+                addStyleName("v-table-generated-row");
+            }
+
+            /** Checks if is span columns.
+			 *
+			 * @return true, if is span columns
+			 */
+            public boolean isSpanColumns() {
+                return spanColumns;
+            }
+
+            /* (non-Javadoc)
+             * @see com.vaadin.client.ui.VCustomScrollTable.VScrollTableBody.VScrollTableRow#initCellWidths()
+             */
+            @Override
+            protected void initCellWidths() {
+                if (spanColumns) {
+                    setSpannedColumnWidthAfterDOMFullyInited();
+                } else {
+                    super.initCellWidths();
+                }
+            }
+
+            /** Sets the spanned column width after dom fully inited.
+			 */
+            private void setSpannedColumnWidthAfterDOMFullyInited() {
+                // Defer setting width on spanned columns to make sure that
+                // they are added to the DOM before trying to calculate
+                // widths.
+                Scheduler.get().scheduleDeferred(new ScheduledCommand() {
+
+                    @Override
+                    public void execute() {
+                        if (showRowHeaders) {
+                            setCellWidth(0, tHead.getHeaderCell(0)
+                                    .getWidthWithIndent());
+                            calcAndSetSpanWidthOnCell(1);
+                        } else {
+                            calcAndSetSpanWidthOnCell(0);
+                        }
+                    }
+                });
+            }
+
+            /* (non-Javadoc)
+             * @see com.vaadin.client.ui.VCustomScrollTable.VScrollTableBody.VScrollTableRow#isRenderHtmlInCells()
+             */
+            @Override
+            protected boolean isRenderHtmlInCells() {
+                return htmlContentAllowed;
+            }
+
+            /* (non-Javadoc)
+             * @see com.vaadin.client.ui.VCustomScrollTable.VScrollTableBody.VScrollTableRow#addCellsFromUIDL(com.vaadin.client.UIDL, char[], int, int)
+             */
+            @Override
+            protected void addCellsFromUIDL(UIDL uidl, char[] aligns, int col,
+                    int visibleColumnIndex) {
+                htmlContentAllowed = uidl.getBooleanAttribute("gen_html");
+                spanColumns = uidl.getBooleanAttribute("gen_span");
+
+                final Iterator<?> cells = uidl.getChildIterator();
+                if (spanColumns) {
+                    int colCount = uidl.getChildCount();
+                    if (cells.hasNext()) {
+                        final Object cell = cells.next();
+                        if (cell instanceof String) {
+                            addSpannedCell(uidl, cell.toString(), aligns[0],
+                                    "", htmlContentAllowed, false, null,
+                                    colCount);
+                        } else {
+                            addSpannedCell(uidl, (Widget) cell, aligns[0], "",
+                                    false, colCount);
+                        }
+                    }
+                } else {
+                    super.addCellsFromUIDL(uidl, aligns, col,
+                            visibleColumnIndex);
+                }
+            }
+
+            /** Adds the spanned cell.
+			 *
+			 * @param rowUidl
+			 *            the row uidl
+			 * @param w
+			 *            the w
+			 * @param align
+			 *            the align
+			 * @param style
+			 *            the style
+			 * @param sorted
+			 *            the sorted
+			 * @param colCount
+			 *            the col count
+			 */
+            private void addSpannedCell(UIDL rowUidl, Widget w, char align,
+                    String style, boolean sorted, int colCount) {
+                TableCellElement td = DOM.createTD().cast();
+                td.setColSpan(colCount);
+                initCellWithWidget(w, align, style, sorted, td);
+            }
+
+            /** Adds the spanned cell.
+			 *
+			 * @param rowUidl
+			 *            the row uidl
+			 * @param text
+			 *            the text
+			 * @param align
+			 *            the align
+			 * @param style
+			 *            the style
+			 * @param textIsHTML
+			 *            the text is html
+			 * @param sorted
+			 *            the sorted
+			 * @param description
+			 *            the description
+			 * @param colCount
+			 *            the col count
+			 */
+            private void addSpannedCell(UIDL rowUidl, String text, char align,
+                    String style, boolean textIsHTML, boolean sorted,
+                    String description, int colCount) {
+                // String only content is optimized by not using Label widget
+                final TableCellElement td = DOM.createTD().cast();
+                td.setColSpan(colCount);
+                initCellWithText(text, align, style, textIsHTML, sorted,
+                        description, td);
+            }
+
+            /* (non-Javadoc)
+             * @see com.vaadin.client.ui.VCustomScrollTable.VScrollTableBody.VScrollTableRow#setCellWidth(int, int)
+             */
+            @Override
+            protected void setCellWidth(int cellIx, int width) {
+                if (isSpanColumns()) {
+                    if (showRowHeaders) {
+                        if (cellIx == 0) {
+                            super.setCellWidth(0, width);
+                        } else {
+                            // We need to recalculate the spanning TDs width for
+                            // every cellIx in order to support column resizing.
+                            calcAndSetSpanWidthOnCell(1);
+                        }
+                    } else {
+                        // Same as above.
+                        calcAndSetSpanWidthOnCell(0);
+                    }
+                } else {
+                    super.setCellWidth(cellIx, width);
+                }
+            }
+
+            /** Calc and set span width on cell.
+			 *
+			 * @param cellIx
+			 *            the cell ix
+			 */
+            private void calcAndSetSpanWidthOnCell(final int cellIx) {
+                int spanWidth = 0;
+                for (int ix = (showRowHeaders ? 1 : 0); ix < tHead
+                        .getVisibleCellCount(); ix++) {
+                    spanWidth += tHead.getHeaderCell(ix).getOffsetWidth();
+                }
+                Util.setWidthExcludingPaddingAndBorder((Element) getElement()
+                        .getChild(cellIx), spanWidth, 13, false);
+            }
+        }
+
+        /**
+         * Ensure the component has a focus.
+         * 
+         * TODO the current implementation simply always calls focus for the
+         * component. In case the Table at some point implements focus/blur
+         * listeners, this method needs to be evolved to conditionally call
+         * focus only if not currently focused.
+         */
+        protected void ensureFocus() {
+            if (!hasFocus) {
+                scrollBodyPanel.setFocus(true);
+            }
+
+        }
+
+    }
+
+    /** Deselects all items.
+	 */
+    public void deselectAll() {
+        for (Widget w : scrollBody) {
+            VScrollTableRow row = (VScrollTableRow) w;
+            if (row.isSelected()) {
+                row.toggleSelection();
+            }
+        }
+        // still ensure all selects are removed from (not necessary rendered)
+        selectedRowKeys.clear();
+        selectedRowRanges.clear();
+        // also notify server that it clears all previous selections (the client
+        // side does not know about the invisible ones)
+        instructServerToForgetPreviousSelections();
+    }
+
+    /**
+     * Used in multiselect mode when the client side knows that all selections
+     * are in the next request.
+     */
+    private void instructServerToForgetPreviousSelections() {
+        client.updateVariable(paintableId, "clearSelections", true, false);
+    }
+
+    /**
+     * Determines the pagelength when the table height is fixed.
+     */
+    public void updatePageLength() {
+        // Only update if visible and enabled
+        if (!isVisible() || !enabled) {
+            return;
+        }
+
+        if (scrollBody == null) {
+            return;
+        }
+
+        if (isDynamicHeight()) {
+            return;
+        }
+
+        int rowHeight = (int) Math.round(scrollBody.getRowHeight());
+        int bodyH = scrollBodyPanel.getOffsetHeight();
+        int rowsAtOnce = bodyH / rowHeight;
+        boolean anotherPartlyVisible = ((bodyH % rowHeight) != 0);
+        if (anotherPartlyVisible) {
+            rowsAtOnce++;
+        }
+        if (pageLength != rowsAtOnce) {
+            pageLength = rowsAtOnce;
+            client.updateVariable(paintableId, "pagelength", pageLength, false);
+
+            if (!rendering) {
+                int currentlyVisible = scrollBody.getLastRendered()
+                        - scrollBody.getFirstRendered();
+                if (currentlyVisible < pageLength
+                        && currentlyVisible < totalRows) {
+                    // shake scrollpanel to fill empty space
+                    scrollBodyPanel.setScrollPosition(scrollTop + 1);
+                    scrollBodyPanel.setScrollPosition(scrollTop - 1);
+                }
+
+                sizeNeedsInit = true;
+            }
+        }
+
+    }
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public void updateWidth() {
+        if (!isVisible()) {
+            /*
+             * Do not update size when the table is hidden as all column widths
+             * will be set to zero and they won't be recalculated when the table
+             * is set visible again (until the size changes again)
+             */
+            return;
+        }
+
+        if (!isDynamicWidth()) {
+            int innerPixels = getOffsetWidth() - getBorderWidth();
+            if (innerPixels < 0) {
+                innerPixels = 0;
+            }
+            setContentWidth(innerPixels);
+
+            // readjust undefined width columns
+            triggerLazyColumnAdjustment(false);
+
+        } else {
+
+            sizeNeedsInit = true;
+
+            // readjust undefined width columns
+            triggerLazyColumnAdjustment(false);
+        }
+
+        /*
+         * setting width may affect wheter the component has scrollbars -> needs
+         * scrolling or not
+         */
+        setProperTabIndex();
+    }
+
+    /** The Constant LAZY_COLUMN_ADJUST_TIMEOUT. */
+    private static final int LAZY_COLUMN_ADJUST_TIMEOUT = 300;
+
+    /** The lazy adjust column widths. */
+    private final Timer lazyAdjustColumnWidths = new Timer() {
+        /**
+         * Check for column widths, and available width, to see if we can fix
+         * column widths "optimally". Doing this lazily to avoid expensive
+         * calculation when resizing is not yet finished.
+         */
+
+        @Override
+        public void run() {
+            if (scrollBody == null) {
+                // Try again later if we get here before scrollBody has been
+                // initalized
+                triggerLazyColumnAdjustment(false);
+                return;
+            }
+
+            Iterator<Widget> headCells = tHead.iterator();
+            int usedMinimumWidth = 0;
+            int totalExplicitColumnsWidths = 0;
+            float expandRatioDivider = 0;
+            int colIndex = 0;
+
+            int hierarchyColumnIndent = scrollBody.getMaxIndent();
+            int hierarchyColumnIndex = getHierarchyColumnIndex();
+            HeaderCell hierarchyHeaderInNeedOfFurtherHandling = null;
+
+            while (headCells.hasNext()) {
+                final HeaderCell hCell = (HeaderCell) headCells.next();
+                boolean hasIndent = hierarchyColumnIndent > 0
+                        && hCell.isHierarchyColumn();
+                if (hCell.isDefinedWidth()) {
+                    // get width without indent to find out whether adjustments
+                    // are needed (requires special handling further ahead)
+                    int w = hCell.getWidth();
+                    if (hasIndent && w < hierarchyColumnIndent) {
+                        // enforce indent if necessary
+                        w = hierarchyColumnIndent;
+                        hierarchyHeaderInNeedOfFurtherHandling = hCell;
+                    }
+                    totalExplicitColumnsWidths += w;
+                    usedMinimumWidth += w;
+                } else {
+                    // natural width already includes indent if any
+                    int naturalColumnWidth = hCell
+                            .getNaturalColumnWidth(colIndex);
+                    usedMinimumWidth += naturalColumnWidth;
+                    expandRatioDivider += hCell.getExpandRatio();
+                    if (hasIndent) {
+                        hierarchyHeaderInNeedOfFurtherHandling = hCell;
+                    }
+                }
+                colIndex++;
+            }
+
+            int availW = scrollBody.getAvailableWidth();
+            // Hey IE, are you really sure about this?
+            availW = scrollBody.getAvailableWidth();
+            int visibleCellCount = tHead.getVisibleCellCount();
+            int totalExtraWidth = scrollBody.getCellExtraWidth()
+                    * visibleCellCount;
+            if (willHaveScrollbars()) {
+                totalExtraWidth += Util.getNativeScrollbarSize();
+            }
+            availW -= totalExtraWidth;
+            int forceScrollBodyWidth = -1;
+
+            int extraSpace = availW - usedMinimumWidth;
+            if (extraSpace < 0) {
+                if (getTotalRows() == 0) {
+                    /*
+                     * Too wide header combined with no rows in the table.
+                     * 
+                     * No horizontal scrollbars would be displayed because
+                     * there's no rows that grows too wide causing the
+                     * scrollBody container div to overflow. Must explicitely
+                     * force a width to a scrollbar. (see #9187)
+                     */
+                    forceScrollBodyWidth = usedMinimumWidth + totalExtraWidth;
+                }
+                extraSpace = 0;
+            }
+
+            if (forceScrollBodyWidth > 0) {
+                scrollBody.container.getStyle().setWidth(forceScrollBodyWidth,
+                        Unit.PX);
+            } else {
+                // Clear width that might have been set to force horizontal
+                // scrolling if there are no rows
+                scrollBody.container.getStyle().clearWidth();
+            }
+
+            int totalUndefinedNaturalWidths = usedMinimumWidth
+                    - totalExplicitColumnsWidths;
+
+            if (hierarchyHeaderInNeedOfFurtherHandling != null
+                    && !hierarchyHeaderInNeedOfFurtherHandling.isDefinedWidth()) {
+                // ensure the cell gets enough space for the indent
+                int w = hierarchyHeaderInNeedOfFurtherHandling
+                        .getNaturalColumnWidth(hierarchyColumnIndex);
+                int newSpace = Math.round(w + (float) extraSpace * (float) w
+                        / totalUndefinedNaturalWidths);
+                if (newSpace >= hierarchyColumnIndent) {
+                    // no special handling required
+                    hierarchyHeaderInNeedOfFurtherHandling = null;
+                } else {
+                    // treat as a defined width column of indent's width
+                    totalExplicitColumnsWidths += hierarchyColumnIndent;
+                    usedMinimumWidth -= w - hierarchyColumnIndent;
+                    totalUndefinedNaturalWidths = usedMinimumWidth
+                            - totalExplicitColumnsWidths;
+                    expandRatioDivider += hierarchyHeaderInNeedOfFurtherHandling
+                            .getExpandRatio();
+                    extraSpace = Math.max(availW - usedMinimumWidth, 0);
+                }
+            }
+
+            // we have some space that can be divided optimally
+            HeaderCell hCell;
+            colIndex = 0;
+            headCells = tHead.iterator();
+            int checksum = 0;
+            while (headCells.hasNext()) {
+                hCell = (HeaderCell) headCells.next();
+                if (hCell.isResizing) {
+                    continue;
+                }
+                if (!hCell.isDefinedWidth()) {
+                    int w = hCell.getNaturalColumnWidth(colIndex);
+                    int newSpace;
+                    if (expandRatioDivider > 0) {
+                        // divide excess space by expand ratios
+                        newSpace = Math.round((w + extraSpace
+                                * hCell.getExpandRatio() / expandRatioDivider));
+                    } else {
+                        if (hierarchyHeaderInNeedOfFurtherHandling == hCell) {
+                            // still exists, so needs exactly the indent's width
+                            newSpace = hierarchyColumnIndent;
+                        } else if (totalUndefinedNaturalWidths != 0) {
+                            // divide relatively to natural column widths
+                            newSpace = Math.round(w + (float) extraSpace
+                                    * (float) w / totalUndefinedNaturalWidths);
+                        } else {
+                            newSpace = w;
+                        }
+                    }
+                    checksum += newSpace;
+                    setColWidth(colIndex, newSpace, false);
+
+                } else {
+                    if (hierarchyHeaderInNeedOfFurtherHandling == hCell) {
+                        // defined with enforced into indent width
+                        checksum += hierarchyColumnIndent;
+                        setColWidth(colIndex, hierarchyColumnIndent, false);
+                    } else {
+                        int cellWidth = hCell.getWidthWithIndent();
+                        checksum += cellWidth;
+                        if (hCell.isHierarchyColumn()) {
+                            // update in case the indent has changed
+                            // (not detectable earlier)
+                            setColWidth(colIndex, cellWidth, true);
+                        }
+                    }
+                }
+                colIndex++;
+            }
+
+            if (extraSpace > 0 && checksum != availW) {
+                /*
+                 * There might be in some cases a rounding error of 1px when
+                 * extra space is divided so if there is one then we give the
+                 * first undefined column 1 more pixel
+                 */
+                headCells = tHead.iterator();
+                colIndex = 0;
+                while (headCells.hasNext()) {
+                    HeaderCell hc = (HeaderCell) headCells.next();
+                    if (!hc.isResizing && !hc.isDefinedWidth()) {
+                        setColWidth(colIndex, hc.getWidthWithIndent() + availW
+                                - checksum, false);
+                        break;
+                    }
+                    colIndex++;
+                }
+            }
+
+            if (isDynamicHeight() && totalRows == pageLength) {
+                // fix body height (may vary if lazy loading is offhorizontal
+                // scrollbar appears/disappears)
+                int bodyHeight = scrollBody.getRequiredHeight();
+                boolean needsSpaceForHorizontalScrollbar = (availW < usedMinimumWidth);
+                if (needsSpaceForHorizontalScrollbar) {
+                    bodyHeight += Util.getNativeScrollbarSize();
+                }
+                int heightBefore = getOffsetHeight();
+                scrollBodyPanel.setHeight(bodyHeight + "px");
+
+                if (heightBefore != getOffsetHeight()) {
+                    Util.notifyParentOfSizeChange(VCustomScrollTable.this,
+                            rendering);
+                }
+            }
+
+            Util.runWebkitOverflowAutoFixDeferred(scrollBodyPanel.getElement());
+
+            forceRealignColumnHeaders();
+        }
+
+    };
+
+    /** Force realign column headers.
+	 */
+    private void forceRealignColumnHeaders() {
+        if (BrowserInfo.get().isIE()) {
+            /*
+             * IE does not fire onscroll event if scroll position is reverted to
+             * 0 due to the content element size growth. Ensure headers are in
+             * sync with content manually. Safe to use null event as we don't
+             * actually use the event object in listener.
+             */
+            onScroll(null);
+        }
+    }
+
+    /** helper to set pixel size of head and body part.
+	 *
+	 * @param pixels
+	 *            the new content width
+	 */
+    protected void setContentWidth(int pixels) {
+        tHead.setWidth(pixels + "px");
+        scrollBodyPanel.setWidth(pixels + "px");
+        tFoot.setWidth(pixels + "px");
+    }
+
+    /** The border width. */
+    private int borderWidth = -1;
+
+    /** Gets the border width.
+	 *
+	 * @return border left + border right
+	 */
+    private int getBorderWidth() {
+        if (borderWidth < 0) {
+            borderWidth = Util.measureHorizontalPaddingAndBorder(
+                    scrollBodyPanel.getElement(), 2);
+            if (borderWidth < 0) {
+                borderWidth = 0;
+            }
+        }
+        return borderWidth;
+    }
+
+    /**
+     * Ensures scrollable area is properly sized. This method is used when fixed
+     * size is used.
+     */
+    protected int containerHeight;
+
+    /** Sets the container height.
+	 */
+    protected void setContainerHeight() {
+        if (!isDynamicHeight()) {
+
+            /*
+             * Android 2.3 cannot measure the height of the inline-block
+             * properly, and will return the wrong offset height. So for android
+             * 2.3 we set the element to a block element while measuring and
+             * then restore it which yields the correct result. #11331
+             */
+            if (BrowserInfo.get().isAndroid23()) {
+                getElement().getStyle().setDisplay(Display.BLOCK);
+            }
+
+            containerHeight = getOffsetHeight();
+            containerHeight -= showColHeaders ? tHead.getOffsetHeight() : 0;
+            containerHeight -= tFoot.getOffsetHeight();
+            containerHeight -= getContentAreaBorderHeight();
+            if (containerHeight < 0) {
+                containerHeight = 0;
+            }
+
+            scrollBodyPanel.setHeight(containerHeight + "px");
+
+            if (BrowserInfo.get().isAndroid23()) {
+                getElement().getStyle().clearDisplay();
+            }
+        }
+    }
+
+    /** The content area border height. */
+    private int contentAreaBorderHeight = -1;
+    
+    /** The scroll left. */
+    protected int scrollLeft;
+    
+    /** The scroll top. */
+    private int scrollTop;
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public VScrollTableDropHandler dropHandler;
+
+    /** The nav key down. */
+    private boolean navKeyDown;
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public boolean multiselectPending;
+
+    /** Gets the content area border height.
+	 *
+	 * @return border top + border bottom of the scrollable area of table
+	 */
+    protected int getContentAreaBorderHeight() {
+        if (contentAreaBorderHeight < 0) {
+
+            scrollBodyPanel.getElement().getStyle()
+                    .setOverflow(Overflow.HIDDEN);
+            int oh = scrollBodyPanel.getOffsetHeight();
+            int ch = scrollBodyPanel.getElement()
+                    .getPropertyInt("clientHeight");
+            contentAreaBorderHeight = oh - ch;
+            scrollBodyPanel.getElement().getStyle().setOverflow(Overflow.AUTO);
+        }
+        return contentAreaBorderHeight;
+    }
+
+    /* (non-Javadoc)
+     * @see com.google.gwt.user.client.ui.UIObject#setHeight(java.lang.String)
+     */
+    @Override
+    public void setHeight(String height) {
+        if (height.length() == 0
+                && getElement().getStyle().getHeight().length() != 0) {
+            /*
+             * Changing from defined to undefined size -> should do a size init
+             * to take page length into account again
+             */
+            sizeNeedsInit = true;
+        }
+        super.setHeight(height);
+    }
+
+    /** For internal use only. May be removed or replaced in the future. */
+    public void updateHeight() {
+        setContainerHeight();
+
+        if (initializedAndAttached) {
+            updatePageLength();
+        }
+        if (!rendering) {
+            // Webkit may sometimes get an odd rendering bug (white space
+            // between header and body), see bug #3875. Running
+            // overflow hack here to shake body element a bit.
+            // We must run the fix as a deferred command to prevent it from
+            // overwriting the scroll position with an outdated value, see
+            // #7607.
+            Util.runWebkitOverflowAutoFixDeferred(scrollBodyPanel.getElement());
+        }
+
+        triggerLazyColumnAdjustment(false);
+
+        /*
+         * setting height may affect wheter the component has scrollbars ->
+         * needs scrolling or not
+         */
+        setProperTabIndex();
+
+    }
+
+    /*
+     * Overridden due Table might not survive of visibility change (scroll pos
+     * lost). Example ITabPanel just set contained components invisible and back
+     * when changing tabs.
+     */
+
+    /* (non-Javadoc)
+     * @see com.google.gwt.user.client.ui.UIObject#setVisible(boolean)
+     */
+    @Override
+    public void setVisible(boolean visible) {
+        if (isVisible() != visible) {
+            super.setVisible(visible);
+            if (initializedAndAttached) {
+                if (visible) {
+                    Scheduler.get().scheduleDeferred(new Command() {
+
+                        @Override
+                        public void execute() {
+                            scrollBodyPanel
+                                    .setScrollPosition(measureRowHeightOffset(firstRowInViewPort));
+                        }
+                    });
+                }
+            }
+        }
+    }
+
+    /** Helper function to build html snippet for column or row headers.
+	 *
+	 * @param uidl
+	 *            possibly with values caption and icon
+	 * @return html snippet containing possibly an icon + caption text
+	 */
+    protected String buildCaptionHtmlSnippet(UIDL uidl) {
+        String s = uidl.hasAttribute("caption") ? uidl
+                .getStringAttribute("caption") : "";
+        if (uidl.hasAttribute("icon")) {
+            Icon icon = client.getIcon(uidl.getStringAttribute("icon"));
+            icon.setAlternateText("icon");
+            s = icon.getElement().getString() + s;
+        }
+        return s;
+    }
+
+    /** This method has logic which rows needs to be requested from server
+	 * when user scrolls.
+	 *
+	 * @param event
+	 *            the event
+	 */
+
+    @Override
+    public void onScroll(ScrollEvent event) {
+        // Do not handle scroll events while there is scroll initiated from
+        // server side which is not yet executed (#11454)
+        if (isLazyScrollerActive()) {
+            return;
+        }
+
+        scrollLeft = scrollBodyPanel.getElement().getScrollLeft();
+        scrollTop = scrollBodyPanel.getScrollPosition();
+        /*
+         * #6970 - IE sometimes fires scroll events for a detached table.
+         * 
+         * FIXME initializedAndAttached should probably be renamed - its name
+         * doesn't seem to reflect its semantics. onDetach() doesn't set it to
+         * false, and changing that might break something else, so we need to
+         * check isAttached() separately.
+         */
+        if (!initializedAndAttached || !isAttached()) {
+            return;
+        }
+        if (!enabled) {
+            scrollBodyPanel
+                    .setScrollPosition(measureRowHeightOffset(firstRowInViewPort));
+            return;
+        }
+
+        rowRequestHandler.cancel();
+
+        if (BrowserInfo.get().isSafari() && event != null && scrollTop == 0) {
+            // due to the webkitoverflowworkaround, top may sometimes report 0
+            // for webkit, although it really is not. Expecting to have the
+            // correct
+            // value available soon.
+            Scheduler.get().scheduleDeferred(new Command() {
+
+                @Override
+                public void execute() {
+                    onScroll(null);
+                }
+            });
+            return;
+        }
+
+        // fix headers horizontal scrolling
+        tHead.setHorizontalScrollPosition(scrollLeft);
+
+        // fix footers horizontal scrolling
+        tFoot.setHorizontalScrollPosition(scrollLeft);
+
+        if (totalRows == 0) {
+            // No rows, no need to fetch new rows
+            return;
+        }
+
+        firstRowInViewPort = calcFirstRowInViewPort();
+        int maxFirstRow = totalRows - pageLength;
+        if (firstRowInViewPort > maxFirstRow && maxFirstRow >= 0) {
+            firstRowInViewPort = maxFirstRow;
+        }
+
+        int postLimit = (int) (firstRowInViewPort + (pageLength - 1) + pageLength
+                * cache_react_rate);
+        if (postLimit > totalRows - 1) {
+            postLimit = totalRows - 1;
+        }
+        int preLimit = (int) (firstRowInViewPort - pageLength
+                * cache_react_rate);
+        if (preLimit < 0) {
+            preLimit = 0;
+        }
+        final int lastRendered = scrollBody.getLastRendered();
+        final int firstRendered = scrollBody.getFirstRendered();
+
+        if (postLimit <= lastRendered && preLimit >= firstRendered) {
+            // we're within no-react area, no need to request more rows
+            // remember which firstvisible we requested, in case the server has
+            // a differing opinion
+            lastRequestedFirstvisible = firstRowInViewPort;
+            client.updateVariable(paintableId, "firstvisible",
+                    firstRowInViewPort, false);
+            return;
+        }
+
+        if (allRenderedRowsAreNew()) {
+            // need a totally new set of rows
+            rowRequestHandler
+                    .setReqFirstRow((firstRowInViewPort - (int) (pageLength * cache_rate)));
+            int last = firstRowInViewPort + (int) (cache_rate * pageLength)
+                    + pageLength - 1;
+            if (last >= totalRows) {
+                last = totalRows - 1;
+            }
+            rowRequestHandler.setReqRows(last
+                    - rowRequestHandler.getReqFirstRow() + 1);
+            updatedReqRows = false;
+            rowRequestHandler.deferRowFetch();
+            return;
+        }
+        if (preLimit < firstRendered) {
+            // need some rows to the beginning of the rendered area
+            rowRequestHandler
+                    .setReqFirstRow((int) (firstRowInViewPort - pageLength
+                            * cache_rate));
+            rowRequestHandler.setReqRows(firstRendered
+                    - rowRequestHandler.getReqFirstRow());
+            rowRequestHandler.deferRowFetch();
+
+            return;
+        }
+        if (postLimit > lastRendered) {
+            // need some rows to the end of the rendered area
+            int reqRows = (int) ((firstRowInViewPort + pageLength + pageLength
+                    * cache_rate) - lastRendered);
+            rowRequestHandler.triggerRowFetch(lastRendered + 1, reqRows);
+        }
+    }
+
+    /** All rendered rows are new.
+	 *
+	 * @return true, if successful
+	 */
+    private boolean allRenderedRowsAreNew() {
+        int firstRowInViewPort = calcFirstRowInViewPort();
+        int firstRendered = scrollBody.getFirstRendered();
+        int lastRendered = scrollBody.getLastRendered();
+        return (firstRowInViewPort - pageLength * cache_rate > lastRendered || firstRowInViewPort
+                + pageLength + pageLength * cache_rate < firstRendered);
+    }
+
+    /** Calc first row in view port.
+	 *
+	 * @return the int
+	 */
+    protected int calcFirstRowInViewPort() {
+        return (int) Math.ceil(scrollTop / scrollBody.getRowHeight());
+    }
+
+    /* (non-Javadoc)
+     * @see com.vaadin.client.ui.dd.VHasDropHandler#getDropHandler()
+     */
+    @Override
+    public VScrollTableDropHandler getDropHandler() {
+        return dropHandler;
+    }
+
+    /** The Class TableDDDetails.
+	 */
+    private static class TableDDDetails {
+        
+        /** The overkey. */
+        int overkey = -1;
+        
+        /** The drop location. */
+        VerticalDropLocation dropLocation;
+        
+        /** The colkey. */
+        String colkey;
+
+        /* (non-Javadoc)
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if (obj instanceof TableDDDetails) {
+                TableDDDetails other = (TableDDDetails) obj;
+                return dropLocation == other.dropLocation
+                        && overkey == other.overkey
+                        && ((colkey != null && colkey.equals(other.colkey)) || (colkey == null && other.colkey == null));
+            }
+            return false;
+        }
+
+        //
+        // public int hashCode() {
+        // return overkey;
+        // }
+    }
+
+    /** The Class VScrollTableDropHandler.
+	 */
+    public class VScrollTableDropHandler extends VAbstractDropHandler {
+
+        /** The Constant ROWSTYLEBASE. */
+        private static final String ROWSTYLEBASE = "v-table-row-drag-";
+        
+        /** The drop details. */
+        private TableDDDetails dropDetails;
+        
+        /** The last emphasized. */
+        private TableDDDetails lastEmphasized;
+
+        /* (non-Javadoc)
+         * @see com.vaadin.client.ui.dd.VAbstractDropHandler#dragEnter(com.vaadin.client.ui.dd.VDragEvent)
+         */
+        @Override
+        public void dragEnter(VDragEvent drag) {
+            updateDropDetails(drag);
+            super.dragEnter(drag);
+        }
+
+        /** Update drop details.
+		 *
+		 * @param drag
+		 *            the drag
+		 */
+        private void updateDropDetails(VDragEvent drag) {
+            dropDetails = new TableDDDetails();
+            Element elementOver = drag.getElementOver();
+
+            Class<? extends Widget> clazz = getRowClass();
+            VScrollTableRow row = null;
+            if (clazz != null) {
+                row = Util.findWidget(elementOver, clazz);
+            }
+            if (row != null) {
+                dropDetails.overkey = row.rowKey;
+                Element tr = row.getElement();
+                Element element = elementOver;
+                while (element != null && element.getParentElement() != tr) {
+                    element = element.getParentElement();
+                }
+                int childIndex = DOM.getChildIndex(tr, element);
+                dropDetails.colkey = tHead.getHeaderCell(childIndex)
+                        .getColKey();
+                dropDetails.dropLocation = DDUtil.getVerticalDropLocation(
+                        row.getElement(), drag.getCurrentGwtEvent(), 0.2);
+            }
+
+            drag.getDropDetails().put("itemIdOver", dropDetails.overkey + "");
+            drag.getDropDetails().put(
+                    "detail",
+                    dropDetails.dropLocation != null ? dropDetails.dropLocation
+                            .toString() : null);
+
+        }
+
+        /** Gets the row class.
+		 *
+		 * @return the row class
+		 */
+        private Class<? extends Widget> getRowClass() {
+            // get the row type this way to make dd work in derived
+            // implementations
+            Iterator<Widget> iterator = scrollBody.iterator();
+            if (iterator.hasNext()) {
+                return iterator.next().getClass();
+            } else {
+                return null;
+            }
+        }
+
+        /* (non-Javadoc)
+         * @see com.vaadin.client.ui.dd.VAbstractDropHandler#dragOver(com.vaadin.client.ui.dd.VDragEvent)
+         */
+        @Override
+        public void dragOver(VDragEvent drag) {
+            TableDDDetails oldDetails = dropDetails;
+            updateDropDetails(drag);
+            if (!oldDetails.equals(dropDetails)) {
+                deEmphasis();
+                final TableDDDetails newDetails = dropDetails;
+                VAcceptCallback cb = new VAcceptCallback() {
+
+                    @Override
+                    public void accepted(VDragEvent event) {
+                        if (newDetails.equals(dropDetails)) {
+                            dragAccepted(event);
+                        }
+                        /*
+                         * Else new target slot already defined, ignore
+                         */
+                    }
+                };
+                validate(cb, drag);
+            }
+        }
+
+        /* (non-Javadoc)
+         * @see com.vaadin.client.ui.dd.VAbstractDropHandler#dragLeave(com.vaadin.client.ui.dd.VDragEvent)
+         */
+        @Override
+        public void dragLeave(VDragEvent drag) {
+            deEmphasis();
+            super.dragLeave(drag);
+        }
+
+        /* (non-Javadoc)
+         * @see com.vaadin.client.ui.dd.VAbstractDropHandler#drop(com.vaadin.client.ui.dd.VDragEvent)
+         */
+        @Override
+        public boolean drop(VDragEvent drag) {
+            deEmphasis();
+            return super.drop(drag);
+        }
+
+        /** De emphasis.
+		 */
+        private void deEmphasis() {
+            UIObject.setStyleName(getElement(),
+                    getStylePrimaryName() + "-drag", false);
+            if (lastEmphasized == null) {
+                return;
+            }
+            for (Widget w : scrollBody.renderedRows) {
+                VScrollTableRow row = (VScrollTableRow) w;
+                if (lastEmphasized != null
+                        && row.rowKey == lastEmphasized.overkey) {
+                    String stylename = ROWSTYLEBASE
+                            + lastEmphasized.dropLocation.toString()
+                                    .toLowerCase();
+                    VScrollTableRow.setStyleName(row.getElement(), stylename,
+                            false);
+                    lastEmphasized = null;
+                    return;
+                }
+            }
+        }
+
+        /** TODO needs different drop modes ?? (on cells, on rows), now only
+		 * supports rows.
+		 *
+		 * @param details
+		 *            the details
+		 */
+        private void emphasis(TableDDDetails details) {
+            deEmphasis();
+            UIObject.setStyleName(getElement(),
+                    getStylePrimaryName() + "-drag", true);
+            // iterate old and new emphasized row
+            for (Widget w : scrollBody.renderedRows) {
+                VScrollTableRow row = (VScrollTableRow) w;
+                if (details != null && details.overkey == row.rowKey) {
+                    String stylename = ROWSTYLEBASE
+                            + details.dropLocation.toString().toLowerCase();
+                    VScrollTableRow.setStyleName(row.getElement(), stylename,
+                            true);
+                    lastEmphasized = details;
+                    return;
+                }
+            }
+        }
+
+        /* (non-Javadoc)
+         * @see com.vaadin.client.ui.dd.VAbstractDropHandler#dragAccepted(com.vaadin.client.ui.dd.VDragEvent)
+         */
+        @Override
+        protected void dragAccepted(VDragEvent drag) {
+            emphasis(dropDetails);
+        }
+
+        /* (non-Javadoc)
+         * @see com.vaadin.client.ui.dd.VAbstractDropHandler#getConnector()
+         */
+        @Override
+        public ComponentConnector getConnector() {
+            return ConnectorMap.get(client).getConnector(
+                    VCustomScrollTable.this);
+        }
+
+        /* (non-Javadoc)
+         * @see com.vaadin.client.ui.dd.VDropHandler#getApplicationConnection()
+         */
+        @Override
+        public ApplicationConnection getApplicationConnection() {
+            return client;
+        }
+
+    }
+
+    /** Gets the currently focused row.
+	 *
+	 * @return the currently focused row
+	 */
+    protected VScrollTableRow getFocusedRow() {
+        return focusedRow;
+    }
+
+    /** Moves the selection head to a specific row.
+	 *
+	 * @param row
+	 *            The row to where the selection head should move
+	 * @return Returns true if focus was moved successfully, else false
+	 */
+    public boolean setRowFocus(VScrollTableRow row) {
+
+        if (!isSelectable()) {
+            return false;
+        }
+
+        // Remove previous selection
+        if (focusedRow != null && focusedRow != row) {
+            focusedRow.removeStyleName(getStylePrimaryName() + "-focus");
+        }
+
+        if (row != null) {
+            // Apply focus style to new selection
+            row.addStyleName(getStylePrimaryName() + "-focus");
+
+            /*
+             * Trying to set focus on already focused row
+             */
+            if (row == focusedRow) {
+                return false;
+            }
+
+            // Set new focused row
+            focusedRow = row;
+
+            ensureRowIsVisible(row);
+
+            return true;
+        }
+
+        return false;
+    }
+
+    /** Ensures that the row is visible.
+	 *
+	 * @param row
+	 *            The row to ensure is visible
+	 */
+    private void ensureRowIsVisible(VScrollTableRow row) {
+        if (BrowserInfo.get().isTouchDevice()) {
+            // Skip due to android devices that have broken scrolltop will may
+            // get odd scrolling here.
+            return;
+        }
+        /*
+         * FIXME The next line doesn't always do what expected, because if the
+         * row is not in the DOM it won't scroll to it.
+         */
+        Util.scrollIntoViewVertically(row.getElement());
+    }
+
+    /** Handles the keyboard events handled by the table.
+	 *
+	 * @param keycode
+	 *            the keycode
+	 * @param ctrl
+	 *            the ctrl
+	 * @param shift
+	 *            the shift
+	 * @return true iff the navigation event was handled
+	 */
+    protected boolean handleNavigation(int keycode, boolean ctrl, boolean shift) {
+        if (keycode == KeyCodes.KEY_TAB || keycode == KeyCodes.KEY_SHIFT) {
+            // Do not handle tab key
+            return false;
+        }
+
+        // Down navigation
+        if (!isSelectable() && keycode == getNavigationDownKey()) {
+            scrollBodyPanel.setScrollPosition(scrollBodyPanel
+                    .getScrollPosition() + scrollingVelocity);
+            return true;
+        } else if (keycode == getNavigationDownKey()) {
+            if (isMultiSelectModeAny() && moveFocusDown()) {
+                selectFocusedRow(ctrl, shift);
+
+            } else if (isSingleSelectMode() && !shift && moveFocusDown()) {
+                selectFocusedRow(ctrl, shift);
+            }
+            return true;
+        }
+
+        // Up navigation
+        if (!isSelectable() && keycode == getNavigationUpKey()) {
+            scrollBodyPanel.setScrollPosition(scrollBodyPanel
+                    .getScrollPosition() - scrollingVelocity);
+            return true;
+        } else if (keycode == getNavigationUpKey()) {
+            if (isMultiSelectModeAny() && moveFocusUp()) {
+                selectFocusedRow(ctrl, shift);
+            } else if (isSingleSelectMode() && !shift && moveFocusUp()) {
+                selectFocusedRow(ctrl, shift);
+            }
+            return true;
+        }
+
+        if (keycode == getNavigationLeftKey()) {
+            // Left navigation
+            scrollBodyPanel.setHorizontalScrollPosition(scrollBodyPanel
+                    .getHorizontalScrollPosition() - scrollingVelocity);
+            return true;
+
+        } else if (keycode == getNavigationRightKey()) {
+            // Right navigation
+            scrollBodyPanel.setHorizontalScrollPosition(scrollBodyPanel
+                    .getHorizontalScrollPosition() + scrollingVelocity);
+            return true;
+        }
+
+        // Select navigation
+        if (isSelectable() && keycode == getNavigationSelectKey()) {
+            if (isSingleSelectMode()) {
+                boolean wasSelected = focusedRow.isSelected();
+                deselectAll();
+                if (!wasSelected || !nullSelectionAllowed) {
+                    focusedRow.toggleSelection();
+                }
+            } else {
+                focusedRow.toggleSelection();
+                removeRowFromUnsentSelectionRanges(focusedRow);
+            }
+
+            sendSelectedRows();
+            return true;
+        }
+
+        // Page Down navigation
+        if (keycode == getNavigationPageDownKey()) {
+            if (isSelectable()) {
+                /*
+                 * If selectable we plagiate MSW behaviour: first scroll to the
+                 * end of current view. If at the end, scroll down one page
+                 * length and keep the selected row in the bottom part of
+                 * visible area.
+                 */
+                if (!isFocusAtTheEndOfTable()) {
+                    VScrollTableRow lastVisibleRowInViewPort = scrollBody
+                            .getRowByRowIndex(firstRowInViewPort
+                                    + getFullyVisibleRowCount() - 1);
+                    if (lastVisibleRowInViewPort != null
+                            && lastVisibleRowInViewPort != focusedRow) {
+                        // focused row is not at the end of the table, move
+                        // focus and select the last visible row
+                        setRowFocus(lastVisibleRowInViewPort);
+                        selectFocusedRow(ctrl, shift);
+                        sendSelectedRows();
+                    } else {
+                        int indexOfToBeFocused = focusedRow.getIndex()
+                                + getFullyVisibleRowCount();
+                        if (indexOfToBeFocused >= totalRows) {
+                            indexOfToBeFocused = totalRows - 1;
+                        }
+                        VScrollTableRow toBeFocusedRow = scrollBody
+                                .getRowByRowIndex(indexOfToBeFocused);
+
+                        if (toBeFocusedRow != null) {
+                            /*
+                             * if the next focused row is rendered
+                             */
+                            setRowFocus(toBeFocusedRow);
+                            selectFocusedRow(ctrl, shift);
+                            // TODO needs scrollintoview ?
+                            sendSelectedRows();
+                        } else {
+                            // scroll down by pixels and return, to wait for
+                            // new rows, then select the last item in the
+                            // viewport
+                            selectLastItemInNextRender = true;
+                            multiselectPending = shift;
+                            scrollByPagelenght(1);
+                        }
+                    }
+                }
+            } else {
+                /* No selections, go page down by scrolling */
+                scrollByPagelenght(1);
+            }
+            return true;
+        }
+
+        // Page Up navigation
+        if (keycode == getNavigationPageUpKey()) {
+            if (isSelectable()) {
+                /*
+                 * If selectable we plagiate MSW behaviour: first scroll to the
+                 * end of current view. If at the end, scroll down one page
+                 * length and keep the selected row in the bottom part of
+                 * visible area.
+                 */
+                if (!isFocusAtTheBeginningOfTable()) {
+                    VScrollTableRow firstVisibleRowInViewPort = scrollBody
+                            .getRowByRowIndex(firstRowInViewPort);
+                    if (firstVisibleRowInViewPort != null
+                            && firstVisibleRowInViewPort != focusedRow) {
+                        // focus is not at the beginning of the table, move
+                        // focus and select the first visible row
+                        setRowFocus(firstVisibleRowInViewPort);
+                        selectFocusedRow(ctrl, shift);
+                        sendSelectedRows();
+                    } else {
+                        int indexOfToBeFocused = focusedRow.getIndex()
+                                - getFullyVisibleRowCount();
+                        if (indexOfToBeFocused < 0) {
+                            indexOfToBeFocused = 0;
+                        }
+                        VScrollTableRow toBeFocusedRow = scrollBody
+                                .getRowByRowIndex(indexOfToBeFocused);
+
+                        if (toBeFocusedRow != null) { // if the next focused row
+                                                      // is rendered
+                            setRowFocus(toBeFocusedRow);
+                            selectFocusedRow(ctrl, shift);
+                            // TODO needs scrollintoview ?
+                            sendSelectedRows();
+                        } else {
+                            // unless waiting for the next rowset already
+                            // scroll down by pixels and return, to wait for
+                            // new rows, then select the last item in the
+                            // viewport
+                            selectFirstItemInNextRender = true;
+                            multiselectPending = shift;
+                            scrollByPagelenght(-1);
+                        }
+                    }
+                }
+            } else {
+                /* No selections, go page up by scrolling */
+                scrollByPagelenght(-1);
+            }
+
+            return true;
+        }
+
+        // Goto start navigation
+        if (keycode == getNavigationStartKey()) {
+            scrollBodyPanel.setScrollPosition(0);
+            if (isSelectable()) {
+                if (focusedRow != null && focusedRow.getIndex() == 0) {
+                    return false;
+                } else {
+                    VScrollTableRow rowByRowIndex = (VScrollTableRow) scrollBody
+                            .iterator().next();
+                    if (rowByRowIndex.getIndex() == 0) {
+                        setRowFocus(rowByRowIndex);
+                        selectFocusedRow(ctrl, shift);
+                        sendSelectedRows();
+                    } else {
+                        // first row of table will come in next row fetch
+                        if (ctrl) {
+                            focusFirstItemInNextRender = true;
+                        } else {
+                            selectFirstItemInNextRender = true;
+                            multiselectPending = shift;
+                        }
+                    }
+                }
+            }
+            return true;
+        }
+
+        // Goto end navigation
+        if (keycode == getNavigationEndKey()) {
+            scrollBodyPanel.setScrollPosition(scrollBody.getOffsetHeight());
+            if (isSelectable()) {
+                final int lastRendered = scrollBody.getLastRendered();
+                if (lastRendered + 1 == totalRows) {
+                    VScrollTableRow rowByRowIndex = scrollBody
+                            .getRowByRowIndex(lastRendered);
+                    if (focusedRow != rowByRowIndex) {
+                        setRowFocus(rowByRowIndex);
+                        selectFocusedRow(ctrl, shift);
+                        sendSelectedRows();
+                    }
+                } else {
+                    if (ctrl) {
+                        focusLastItemInNextRender = true;
+                    } else {
+                        selectLastItemInNextRender = true;
+                        multiselectPending = shift;
+                    }
+                }
+            }
+            return true;
+        }
+
+        return false;
+    }
+
+    /** Checks if is focus at the beginning of table.
+	 *
+	 * @return true, if is focus at the beginning of table
+	 */
+    private boolean isFocusAtTheBeginningOfTable() {
+        return focusedRow.getIndex() == 0;
+    }
+
+    /** Checks if is focus at the end of table.
+	 *
+	 * @return true, if is focus at the end of table
+	 */
+    private boolean isFocusAtTheEndOfTable() {
+        return focusedRow.getIndex() + 1 >= totalRows;
+    }
+
+    /** Gets the fully visible row count.
+	 *
+	 * @return the fully visible row count
+	 */
+    private int getFullyVisibleRowCount() {
+        return (int) (scrollBodyPanel.getOffsetHeight() / scrollBody
+                .getRowHeight());
+    }
+
+    /** Scroll by pagelenght.
+	 *
+	 * @param i
+	 *            the i
+	 */
+    private void scrollByPagelenght(int i) {
+        int pixels = i * scrollBodyPanel.getOffsetHeight();
+        int newPixels = scrollBodyPanel.getScrollPosition() + pixels;
+        if (newPixels < 0) {
+            newPixels = 0;
+        } // else if too high, NOP (all know browsers accept illegally big
+          // values here)
+        scrollBodyPanel.setScrollPosition(newPixels);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * com.google.gwt.event.dom.client.FocusHandler#onFocus(com.google.gwt.event
+     * .dom.client.FocusEvent)
+     */
+
+    @Override
+    public void onFocus(FocusEvent event) {
+        if (isFocusable()) {
+            hasFocus = true;
+
+            // Focus a row if no row is in focus
+            if (focusedRow == null) {
+                focusRowFromBody();
+            } else {
+                setRowFocus(focusedRow);
+            }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see
+     * com.google.gwt.event.dom.client.BlurHandler#onBlur(com.google.gwt.event
+     * .dom.client.BlurEvent)
+     */
+
+    @Override
+    public void onBlur(BlurEvent event) {
+        hasFocus = false;
+        navKeyDown = false;
+
+        if (BrowserInfo.get().isIE()) {
+            /*
+             * IE sometimes moves focus to a clicked table cell... (#7965)
+             * ...and sometimes it sends blur events even though the focus
+             * handler is still active. (#10464)
+             */
+            Element focusedElement = Util.getIEFocusedElement();
+            if (Util.getConnectorForElement(client, getParent(), focusedElement) == this
+                    && focusedElement != null
+                    && focusedElement != scrollBodyPanel.getFocusElement()) {
+                /*
+                 * Steal focus back to the focus handler if it was moved to some
+                 * other part of the table. Avoid stealing focus in other cases.
+                 */
+                focus();
+                return;
+            }
+        }
+
+        if (isFocusable()) {
+            // Unfocus any row
+            setRowFocus(null);
+        }
+    }
+
+    /** Removes a key from a range if the key is found in a selected range.
+	 *
+	 * @param row
+	 *            the row
+	 */
+    private void removeRowFromUnsentSelectionRanges(VScrollTableRow row) {
+        Collection<SelectionRange> newRanges = null;
+        for (Iterator<SelectionRange> iterator = selectedRowRanges.iterator(); iterator
+                .hasNext();) {
+            SelectionRange range = iterator.next();
+            if (range.inRange(row)) {
+                // Split the range if given row is in range
+                Collection<SelectionRange> splitranges = range.split(row);
+                if (newRanges == null) {
+                    newRanges = new ArrayList<SelectionRange>();
+                }
+                newRanges.addAll(splitranges);
+                iterator.remove();
+            }
+        }
+        if (newRanges != null) {
+            selectedRowRanges.addAll(newRanges);
+        }
+    }
+
+    /** Can the Table be focused?.
+	 *
+	 * @return True if the table can be focused, else false
+	 */
+    public boolean isFocusable() {
+        if (scrollBody != null && enabled) {
+            return !(!hasHorizontalScrollbar() && !hasVerticalScrollbar() && !isSelectable());
+        }
+        return false;
+    }
+
+    /** Checks for horizontal scrollbar.
+	 *
+	 * @return true, if successful
+	 */
+    private boolean hasHorizontalScrollbar() {
+        return scrollBody.getOffsetWidth() > scrollBodyPanel.getOffsetWidth();
+    }
+
+    /** Checks for vertical scrollbar.
+	 *
+	 * @return true, if successful
+	 */
+    private boolean hasVerticalScrollbar() {
+        return scrollBody.getOffsetHeight() > scrollBodyPanel.getOffsetHeight();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.vaadin.client.Focusable#focus()
+     */
+
+    @Override
+    public void focus() {
+        if (isFocusable()) {
+            scrollBodyPanel.focus();
+        }
+    }
+
+    /**
+     * Sets the proper tabIndex for scrollBodyPanel (the focusable elemen in the
+     * component).
+     * <p>
+     * If the component has no explicit tabIndex a zero is given (default
+     * tabbing order based on dom hierarchy) or -1 if the component does not
+     * need to gain focus. The component needs no focus if it has no scrollabars
+     * (not scrollable) and not selectable. Note that in the future shortcut
+     * actions may need focus.
+     * <p>
+     * For internal use only. May be removed or replaced in the future.
+     */
+    public void setProperTabIndex() {
+        int storedScrollTop = 0;
+        int storedScrollLeft = 0;
+
+        if (BrowserInfo.get().getOperaVersion() >= 11) {
+            // Workaround for Opera scroll bug when changing tabIndex (#6222)
+            storedScrollTop = scrollBodyPanel.getScrollPosition();
+            storedScrollLeft = scrollBodyPanel.getHorizontalScrollPosition();
+        }
+
+        if (tabIndex == 0 && !isFocusable()) {
+            scrollBodyPanel.setTabIndex(-1);
+        } else {
+            scrollBodyPanel.setTabIndex(tabIndex);
+        }
+
+        if (BrowserInfo.get().getOperaVersion() >= 11) {
+            // Workaround for Opera scroll bug when changing tabIndex (#6222)
+            scrollBodyPanel.setScrollPosition(storedScrollTop);
+            scrollBodyPanel.setHorizontalScrollPosition(storedScrollLeft);
+        }
+    }
+
+    /** Start scrolling velocity timer.
+	 */
+    public void startScrollingVelocityTimer() {
+        if (scrollingVelocityTimer == null) {
+            scrollingVelocityTimer = new Timer() {
+
+                @Override
+                public void run() {
+                    scrollingVelocity++;
+                }
+            };
+            scrollingVelocityTimer.scheduleRepeating(100);
+        }
+    }
+
+    /** Cancel scrolling velocity timer.
+	 */
+    public void cancelScrollingVelocityTimer() {
+        if (scrollingVelocityTimer != null) {
+            // Remove velocityTimer if it exists and the Table is disabled
+            scrollingVelocityTimer.cancel();
+            scrollingVelocityTimer = null;
+            scrollingVelocity = 10;
+        }
+    }
+
+    /** Checks if is navigation key.
+	 *
+	 * @param keyCode
+	 *            the key code
+	 * @return true if the given keyCode is used by the table for navigation
+	 */
+    private boolean isNavigationKey(int keyCode) {
+        return keyCode == getNavigationUpKey()
+                || keyCode == getNavigationLeftKey()
+                || keyCode == getNavigationRightKey()
+                || keyCode == getNavigationDownKey()
+                || keyCode == getNavigationPageUpKey()
+                || keyCode == getNavigationPageDownKey()
+                || keyCode == getNavigationEndKey()
+                || keyCode == getNavigationStartKey();
+    }
+
+    /** Lazy revert focus to row.
+	 *
+	 * @param currentlyFocusedRow
+	 *            the currently focused row
+	 */
+    public void lazyRevertFocusToRow(final VScrollTableRow currentlyFocusedRow) {
+        Scheduler.get().scheduleFinally(new ScheduledCommand() {
+            @Override
+            public void execute() {
+                if (currentlyFocusedRow != null) {
+                    setRowFocus(currentlyFocusedRow);
+                } else {
+                    VConsole.log("no row?");
+                    focusRowFromBody();
+                }
+                scrollBody.ensureFocus();
+            }
+        });
+    }
+
+    /* (non-Javadoc)
+     * @see com.vaadin.client.ui.ActionOwner#getActions()
+     */
+    @Override
+    public Action[] getActions() {
+        if (bodyActionKeys == null) {
+            return new Action[] {};
+        }
+        final Action[] actions = new Action[bodyActionKeys.length];
+        for (int i = 0; i < actions.length; i++) {
+            final String actionKey = bodyActionKeys[i];
+            Action bodyAction = new TreeAction(this, null, actionKey);
+            bodyAction.setCaption(getActionCaption(actionKey));
+            bodyAction.setIconUrl(getActionIcon(actionKey));
+            actions[i] = bodyAction;
+        }
+        return actions;
+    }
+
+    /* (non-Javadoc)
+     * @see com.vaadin.client.ui.ActionOwner#getClient()
+     */
+    @Override
+    public ApplicationConnection getClient() {
+        return client;
+    }
+
+    /* (non-Javadoc)
+     * @see com.vaadin.client.ui.ActionOwner#getPaintableId()
+     */
+    @Override
+    public String getPaintableId() {
+        return paintableId;
+    }
+
+    /**
+     * Add this to the element mouse down event by using element.setPropertyJSO
+     * ("onselectstart",applyDisableTextSelectionIEHack()); Remove it then again
+     * when the mouse is depressed in the mouse up event.
+     * 
+     * @return Returns the JSO preventing text selection
+     */
+    private static native JavaScriptObject getPreventTextSelectionIEHack()
+    /*-{
+            return function(){ return false; };
+    }-*/;
+
+    /** Trigger lazy column adjustment.
+	 *
+	 * @param now
+	 *            the now
+	 */
+    public void triggerLazyColumnAdjustment(boolean now) {
+        lazyAdjustColumnWidths.cancel();
+        if (now) {
+            lazyAdjustColumnWidths.run();
+        } else {
+            lazyAdjustColumnWidths.schedule(LAZY_COLUMN_ADJUST_TIMEOUT);
+        }
+    }
+
+    /** Checks if is dynamic width.
+	 *
+	 * @return true, if is dynamic width
+	 */
+    private boolean isDynamicWidth() {
+        ComponentConnector paintable = ConnectorMap.get(client).getConnector(
+                this);
+        return paintable.isUndefinedWidth();
+    }
+
+    /** Checks if is dynamic height.
+	 *
+	 * @return true, if is dynamic height
+	 */
+    protected boolean isDynamicHeight() {
+        ComponentConnector paintable = ConnectorMap.get(client).getConnector(
+                this);
+        if (paintable == null) {
+            // This should be refactored. As isDynamicHeight can be called from
+            // a timer it is possible that the connector has been unregistered
+            // when this method is called, causing getConnector to return null.
+            return false;
+        }
+        return paintable.isUndefinedHeight();
+    }
+
+    /** Debug.
+	 *
+	 * @param msg
+	 *            the msg
+	 */
+    private void debug(String msg) {
+        if (enableDebug) {
+            VConsole.error(msg);
+        }
+    }
+
+    /** Gets the widget for paintable.
+	 *
+	 * @return the widget for paintable
+	 */
+    public Widget getWidgetForPaintable() {
+        return this;
+    }
+
+    /** The Constant SUBPART_HEADER. */
+    private static final String SUBPART_HEADER = "header";
+    
+    /** The Constant SUBPART_FOOTER. */
+    private static final String SUBPART_FOOTER = "footer";
+    
+    /** The Constant SUBPART_ROW. */
+    private static final String SUBPART_ROW = "row";
+    
+    /** The Constant SUBPART_COL. */
+    private static final String SUBPART_COL = "col";
+    
+    /** Matches header[ix] - used for extracting the index of the targeted
+	 * header cell.
+	 */
+    private static final RegExp SUBPART_HEADER_REGEXP = RegExp
+            .compile(SUBPART_HEADER + "\\[(\\d+)\\]");
+    
+    /** Matches footer[ix] - used for extracting the index of the targeted
+	 * footer cell.
+	 */
+    private static final RegExp SUBPART_FOOTER_REGEXP = RegExp
+            .compile(SUBPART_FOOTER + "\\[(\\d+)\\]");
+    
+    /** Matches row[ix] - used for extracting the index of the targeted row. */
+    private static final RegExp SUBPART_ROW_REGEXP = RegExp.compile(SUBPART_ROW
+            + "\\[(\\d+)]");
+    
+    /** Matches col[ix] - used for extracting the index of the targeted
+	 * column.
+	 */
+    private static final RegExp SUBPART_ROW_COL_REGEXP = RegExp
+            .compile(SUBPART_ROW + "\\[(\\d+)\\]/" + SUBPART_COL
+                    + "\\[(\\d+)\\]");
+
+    /* (non-Javadoc)
+     * @see com.vaadin.client.ui.SubPartAware#getSubPartElement(java.lang.String)
+     */
+    @Override
+    public com.google.gwt.user.client.Element getSubPartElement(String subPart) {
+        if (SUBPART_ROW_COL_REGEXP.test(subPart)) {
+            MatchResult result = SUBPART_ROW_COL_REGEXP.exec(subPart);
+            int rowIx = Integer.valueOf(result.getGroup(1));
+            int colIx = Integer.valueOf(result.getGroup(2));
+            VScrollTableRow row = scrollBody.getRowByRowIndex(rowIx);
+            if (row != null) {
+                Element rowElement = row.getElement();
+                if (colIx < rowElement.getChildCount()) {
+                    return rowElement.getChild(colIx).getFirstChild().cast();
+                }
+            }
+
+        } else if (SUBPART_ROW_REGEXP.test(subPart)) {
+            MatchResult result = SUBPART_ROW_REGEXP.exec(subPart);
+            int rowIx = Integer.valueOf(result.getGroup(1));
+            VScrollTableRow row = scrollBody.getRowByRowIndex(rowIx);
+            if (row != null) {
+                return row.getElement();
+            }
+
+        } else if (SUBPART_HEADER_REGEXP.test(subPart)) {
+            MatchResult result = SUBPART_HEADER_REGEXP.exec(subPart);
+            int headerIx = Integer.valueOf(result.getGroup(1));
+            HeaderCell headerCell = tHead.getHeaderCell(headerIx);
+            if (headerCell != null) {
+                return headerCell.getElement();
+            }
+
+        } else if (SUBPART_FOOTER_REGEXP.test(subPart)) {
+            MatchResult result = SUBPART_FOOTER_REGEXP.exec(subPart);
+            int footerIx = Integer.valueOf(result.getGroup(1));
+            FooterCell footerCell = tFoot.getFooterCell(footerIx);
+            if (footerCell != null) {
+                return footerCell.getElement();
+            }
+        }
+        // Nothing found.
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see com.vaadin.client.ui.SubPartAware#getSubPartName(com.google.gwt.user.client.Element)
+     */
+    @Override
+    public String getSubPartName(com.google.gwt.user.client.Element subElement) {
+        Widget widget = Util.findWidget(subElement, null);
+        if (widget instanceof HeaderCell) {
+            return SUBPART_HEADER + "[" + tHead.visibleCells.indexOf(widget)
+                    + "]";
+        } else if (widget instanceof FooterCell) {
+            return SUBPART_FOOTER + "[" + tFoot.visibleCells.indexOf(widget)
+                    + "]";
+        } else if (widget instanceof VScrollTableRow) {
+            // a cell in a row
+            VScrollTableRow row = (VScrollTableRow) widget;
+            int rowIx = scrollBody.indexOf(row);
+            if (rowIx >= 0) {
+                int colIx = -1;
+                for (int ix = 0; ix < row.getElement().getChildCount(); ix++) {
+                    if (row.getElement().getChild(ix).isOrHasChild(subElement)) {
+                        colIx = ix;
+                        break;
+                    }
+                }
+                if (colIx >= 0) {
+                    return SUBPART_ROW + "[" + rowIx + "]/" + SUBPART_COL + "["
+                            + colIx + "]";
+                }
+                return SUBPART_ROW + "[" + rowIx + "]";
+            }
+        }
+        // Nothing found.
+        return null;
+    }
+
+    /** On unregister.
+	 *
+	 * @since 7.2.6
+	 */
+    public void onUnregister() {
+        if (addCloseHandler != null) {
+            addCloseHandler.removeHandler();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see com.vaadin.client.DeferredWorker#isWorkPending()
+     */
+    /*
+     * Return true if component need to perform some work and false otherwise.
+     */
+    @Override
+    public boolean isWorkPending() {
+        return lazyAdjustColumnWidths.isRunning();
+    }
+
+    /** Gets the logger.
+	 *
+	 * @return the logger
+	 */
+    private static Logger getLogger() {
+        return Logger.getLogger(VCustomScrollTable.class.getName());
+    }
+}
diff --git a/org.eclipse.osbp.fork.vaadin.addon.filteringtable/src/com/vaadin/ui/CustomTable.java b/org.eclipse.osbp.fork.vaadin.addon.filteringtable/src/com/vaadin/ui/CustomTable.java
new file mode 100644
index 0000000..5456948
--- /dev/null
+++ b/org.eclipse.osbp.fork.vaadin.addon.filteringtable/src/com/vaadin/ui/CustomTable.java
@@ -0,0 +1,6638 @@
+/*
+ * Copyright 2000-2014 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.ui;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.vaadin.data.Container;
+import com.vaadin.data.Item;
+import com.vaadin.data.Property;
+import com.vaadin.data.util.ContainerOrderedWrapper;
+import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.data.util.converter.Converter;
+import com.vaadin.data.util.converter.ConverterUtil;
+import com.vaadin.event.Action;
+import com.vaadin.event.Action.Handler;
+import com.vaadin.event.DataBoundTransferable;
+import com.vaadin.event.ItemClickEvent;
+import com.vaadin.event.ItemClickEvent.ItemClickListener;
+import com.vaadin.event.ItemClickEvent.ItemClickNotifier;
+import com.vaadin.event.MouseEvents.ClickEvent;
+import com.vaadin.event.dd.DragAndDropEvent;
+import com.vaadin.event.dd.DragSource;
+import com.vaadin.event.dd.DropHandler;
+import com.vaadin.event.dd.DropTarget;
+import com.vaadin.event.dd.acceptcriteria.ServerSideCriterion;
+import com.vaadin.server.KeyMapper;
+import com.vaadin.server.LegacyCommunicationManager;
+import com.vaadin.server.LegacyPaint;
+import com.vaadin.server.PaintException;
+import com.vaadin.server.PaintTarget;
+import com.vaadin.server.Resource;
+import com.vaadin.shared.MouseEventDetails;
+import com.vaadin.shared.ui.MultiSelectMode;
+import com.vaadin.shared.ui.table.TableConstants;
+
+// TODO: Auto-generated Javadoc
+/**
+ * <p>
+ * <code>CustomTable</code> is used for representing data or components in a
+ * pageable and selectable CustomTable.
+ * 
+ * 
+ * <p>
+ * Scalability of the CustomTable is largely dictated by the container. A table
+ * does not have a limit for the number of items and is just as fast with
+ * hundreds of thousands of items as with just a few. The current GWT
+ * implementation with scrolling however limits the number of rows to around
+ * 500000, depending on the browser and the pixel height of rows.
+ * 
+ * 
+ * <p>
+ * Components in a CustomTable will not have their caption nor icon rendered.
+ * 
+ * 
+ * @author Vaadin Ltd.
+ * @since 3.0
+ */
+@SuppressWarnings({ "deprecation" })
+public class CustomTable extends AbstractSelect implements Action.Container,
+        Container.Ordered, Container.Sortable, ItemClickNotifier, DragSource,
+        DropTarget, HasComponents {
+
+    /** The logger. */
+    private transient Logger logger = null;
+
+    /**
+     * Modes that CustomTable support as drag sourse.
+     */
+    public enum TableDragMode {
+        /**
+         * CustomTable does not start drag and drop events. HTM5 style events
+         * started by browser may still happen.
+         */
+        NONE,
+        /**
+         * CustomTable starts drag with a one row only.
+         */
+        ROW,
+        /**
+         * CustomTable drags selected rows, if drag starts on a selected rows.
+         * Else it starts like in ROW mode. Note, that in Transferable there
+         * will still be only the row on which the drag started, other dragged
+         * rows need to be checked from the source CustomTable.
+         */
+        MULTIROW
+    }
+
+    /** The Constant CELL_KEY. */
+    protected static final int CELL_KEY = 0;
+
+    /** The Constant CELL_HEADER. */
+    protected static final int CELL_HEADER = 1;
+
+    /** The Constant CELL_ICON. */
+    protected static final int CELL_ICON = 2;
+
+    /** The Constant CELL_ITEMID. */
+    protected static final int CELL_ITEMID = 3;
+
+    /** The Constant CELL_GENERATED_ROW. */
+    protected static final int CELL_GENERATED_ROW = 4;
+
+    /** The Constant CELL_FIRSTCOL. */
+    protected static final int CELL_FIRSTCOL = 5;
+
+    /** The Enum Align.
+	 */
+    public enum Align {
+        /**
+         * Left column alignment. <b>This is the default behaviour. </b>
+         */
+        LEFT("b"),
+
+        /**
+         * Center column alignment.
+         */
+        CENTER("c"),
+
+        /**
+         * Right column alignment.
+         */
+        RIGHT("e");
+
+        /** The alignment. */
+        private String alignment;
+
+        /** Instantiates a new align.
+		 *
+		 * @param alignment
+		 *            the alignment
+		 */
+        private Align(String alignment) {
+            this.alignment = alignment;
+        }
+
+        /* (non-Javadoc)
+         * @see java.lang.Enum#toString()
+         */
+        @Override
+        public String toString() {
+            return alignment;
+        }
+
+        /** Convert string to align.
+		 *
+		 * @param string
+		 *            the string
+		 * @return the align
+		 */
+        public Align convertStringToAlign(String string) {
+            if (string == null) {
+                return null;
+            }
+            if (string.equals("b")) {
+                return Align.LEFT;
+            } else if (string.equals("c")) {
+                return Align.CENTER;
+            } else if (string.equals("e")) {
+                return Align.RIGHT;
+            } else {
+                return null;
+            }
+        }
+    }
+
+    /** The Constant ALIGN_LEFT.
+	 *
+	 * @deprecated As of 7.0, use {@link Align#LEFT} instead
+	 */
+    @Deprecated
+    public static final Align ALIGN_LEFT = Align.LEFT;
+
+    /** The Constant ALIGN_CENTER.
+	 *
+	 * @deprecated As of 7.0, use {@link Align#CENTER} instead
+	 */
+    @Deprecated
+    public static final Align ALIGN_CENTER = Align.CENTER;
+
+    /** The Constant ALIGN_RIGHT.
+	 *
+	 * @deprecated As of 7.0, use {@link Align#RIGHT} instead
+	 */
+    @Deprecated
+    public static final Align ALIGN_RIGHT = Align.RIGHT;
+
+    /** The Enum ColumnHeaderMode.
+	 */
+    public enum ColumnHeaderMode {
+        /**
+         * Column headers are hidden.
+         */
+        HIDDEN,
+        /**
+         * Property ID:s are used as column headers.
+         */
+        ID,
+        /**
+         * Column headers are explicitly specified with
+         * {@link #setColumnHeaders(String[])}.
+         */
+        EXPLICIT,
+        /**
+         * Column headers are explicitly specified with
+         * {@link #setColumnHeaders(String[])}. If a header is not specified for
+         * a given property, its property id is used instead.
+         * <p>
+         * <b>This is the default behavior. </b>
+         */
+        EXPLICIT_DEFAULTS_ID
+    }
+
+    /** The Constant COLUMN_HEADER_MODE_HIDDEN.
+	 *
+	 * @deprecated As of 7.0, use {@link ColumnHeaderMode#HIDDEN} instead
+	 */
+    @Deprecated
+    public static final ColumnHeaderMode COLUMN_HEADER_MODE_HIDDEN = ColumnHeaderMode.HIDDEN;
+
+    /** The Constant COLUMN_HEADER_MODE_ID.
+	 *
+	 * @deprecated As of 7.0, use {@link ColumnHeaderMode#ID} instead
+	 */
+    @Deprecated
+    public static final ColumnHeaderMode COLUMN_HEADER_MODE_ID = ColumnHeaderMode.ID;
+
+    /** The Constant COLUMN_HEADER_MODE_EXPLICIT.
+	 *
+	 * @deprecated As of 7.0, use {@link ColumnHeaderMode#EXPLICIT} instead
+	 */
+    @Deprecated
+    public static final ColumnHeaderMode COLUMN_HEADER_MODE_EXPLICIT = ColumnHeaderMode.EXPLICIT;
+
+    /** The Constant COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID.
+	 *
+	 * @deprecated As of 7.0, use {@link ColumnHeaderMode#EXPLICIT_DEFAULTS_ID}
+	 *             instead
+	 */
+    @Deprecated
+    public static final ColumnHeaderMode COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID = ColumnHeaderMode.EXPLICIT_DEFAULTS_ID;
+
+    /** The Enum RowHeaderMode.
+	 */
+    public enum RowHeaderMode {
+        /**
+         * Row caption mode: The row headers are hidden. <b>This is the default
+         * mode. </b>
+         */
+        HIDDEN(null),
+        /**
+         * Row caption mode: Items Id-objects toString is used as row caption.
+         */
+        ID(ItemCaptionMode.ID),
+        /**
+         * Row caption mode: Item-objects toString is used as row caption.
+         */
+        ITEM(ItemCaptionMode.ITEM),
+        /**
+         * Row caption mode: Index of the item is used as item caption. The
+         * index mode can only be used with the containers implementing the
+         * {@link com.vaadin.data.Container.Indexed} interface.
+         */
+        INDEX(ItemCaptionMode.INDEX),
+        /**
+         * Row caption mode: Item captions are explicitly specified, but if the
+         * caption is missing, the item id objects <code>toString()</code> is
+         * used instead.
+         */
+        EXPLICIT_DEFAULTS_ID(ItemCaptionMode.EXPLICIT_DEFAULTS_ID),
+        /**
+         * Row caption mode: Item captions are explicitly specified.
+         */
+        EXPLICIT(ItemCaptionMode.EXPLICIT),
+        /**
+         * Row caption mode: Only icons are shown, the captions are hidden.
+         */
+        ICON_ONLY(ItemCaptionMode.ICON_ONLY),
+        /**
+         * Row caption mode: Item captions are read from property specified with
+         * {@link #setItemCaptionPropertyId(Object)}.
+         */
+        PROPERTY(ItemCaptionMode.PROPERTY);
+
+        /** The mode. */
+        ItemCaptionMode mode;
+
+        /** Instantiates a new row header mode.
+		 *
+		 * @param mode
+		 *            the mode
+		 */
+        private RowHeaderMode(ItemCaptionMode mode) {
+            this.mode = mode;
+        }
+
+        /** Gets the item caption mode.
+		 *
+		 * @return the item caption mode
+		 */
+        public ItemCaptionMode getItemCaptionMode() {
+            return mode;
+        }
+    }
+
+    /** The Constant ROW_HEADER_MODE_HIDDEN.
+	 *
+	 * @deprecated As of 7.0, use {@link RowHeaderMode#HIDDEN} instead
+	 */
+    @Deprecated
+    public static final RowHeaderMode ROW_HEADER_MODE_HIDDEN = RowHeaderMode.HIDDEN;
+
+    /** The Constant ROW_HEADER_MODE_ID.
+	 *
+	 * @deprecated As of 7.0, use {@link RowHeaderMode#ID} instead
+	 */
+    @Deprecated
+    public static final RowHeaderMode ROW_HEADER_MODE_ID = RowHeaderMode.ID;
+
+    /** The Constant ROW_HEADER_MODE_ITEM.
+	 *
+	 * @deprecated As of 7.0, use {@link RowHeaderMode#ITEM} instead
+	 */
+    @Deprecated
+    public static final RowHeaderMode ROW_HEADER_MODE_ITEM = RowHeaderMode.ITEM;
+
+    /** The Constant ROW_HEADER_MODE_INDEX.
+	 *
+	 * @deprecated As of 7.0, use {@link RowHeaderMode#INDEX} instead
+	 */
+    @Deprecated
+    public static final RowHeaderMode ROW_HEADER_MODE_INDEX = RowHeaderMode.INDEX;
+
+    /** The Constant ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID.
+	 *
+	 * @deprecated As of 7.0, use {@link RowHeaderMode#EXPLICIT_DEFAULTS_ID}
+	 *             instead
+	 */
+    @Deprecated
+    public static final RowHeaderMode ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID = RowHeaderMode.EXPLICIT_DEFAULTS_ID;
+
+    /** The Constant ROW_HEADER_MODE_EXPLICIT.
+	 *
+	 * @deprecated As of 7.0, use {@link RowHeaderMode#EXPLICIT} instead
+	 */
+    @Deprecated
+    public static final RowHeaderMode ROW_HEADER_MODE_EXPLICIT = RowHeaderMode.EXPLICIT;
+
+    /** The Constant ROW_HEADER_MODE_ICON_ONLY.
+	 *
+	 * @deprecated As of 7.0, use {@link RowHeaderMode#ICON_ONLY} instead
+	 */
+    @Deprecated
+    public static final RowHeaderMode ROW_HEADER_MODE_ICON_ONLY = RowHeaderMode.ICON_ONLY;
+
+    /** The Constant ROW_HEADER_MODE_PROPERTY.
+	 *
+	 * @deprecated As of 7.0, use {@link RowHeaderMode#PROPERTY} instead
+	 */
+    @Deprecated
+    public static final RowHeaderMode ROW_HEADER_MODE_PROPERTY = RowHeaderMode.PROPERTY;
+
+    /**
+     * The default rate that table caches rows for smooth scrolling.
+     */
+    private static final double CACHE_RATE_DEFAULT = 2;
+
+    /** The Constant ROW_HEADER_COLUMN_KEY. */
+    private static final String ROW_HEADER_COLUMN_KEY = "0";
+    
+    /** The Constant ROW_HEADER_FAKE_PROPERTY_ID. */
+    private static final Object ROW_HEADER_FAKE_PROPERTY_ID = new UniqueSerializable() {
+    };
+
+    /* Private table extensions to Select */
+
+    /**
+     * True if column collapsing is allowed.
+     */
+    private boolean columnCollapsingAllowed = false;
+
+    /**
+     * True if reordering of columns is allowed on the client side.
+     */
+    private boolean columnReorderingAllowed = false;
+
+    /**
+     * Keymapper for column ids.
+     */
+    protected final KeyMapper<Object> columnIdMap = new KeyMapper<Object>();
+
+    /**
+     * Holds visible column propertyIds - in order.
+     */
+    private LinkedList<Object> visibleColumns = new LinkedList<Object>();
+
+    /**
+     * Holds noncollapsible columns.
+     */
+    private HashSet<Object> noncollapsibleColumns = new HashSet<Object>();
+
+    /**
+     * Holds propertyIds of currently collapsed columns.
+     */
+    private final HashSet<Object> collapsedColumns = new HashSet<Object>();
+
+    /**
+     * Holds headers for visible columns (by propertyId).
+     */
+    private final HashMap<Object, String> columnHeaders = new HashMap<Object, String>();
+
+    /**
+     * Holds footers for visible columns (by propertyId).
+     */
+    private final HashMap<Object, String> columnFooters = new HashMap<Object, String>();
+
+    /**
+     * Holds icons for visible columns (by propertyId).
+     */
+    private final HashMap<Object, Resource> columnIcons = new HashMap<Object, Resource>();
+
+    /**
+     * Holds alignments for visible columns (by propertyId).
+     */
+    private HashMap<Object, Align> columnAlignments = new HashMap<Object, Align>();
+
+    /**
+     * Holds column widths in pixels for visible columns (by propertyId).
+     */
+    private final HashMap<Object, Integer> columnWidths = new HashMap<Object, Integer>();
+
+    /**
+     * Holds column expand rations for visible columns (by propertyId).
+     */
+    private final HashMap<Object, Float> columnExpandRatios = new HashMap<Object, Float>();
+
+    /** Holds column generators. */
+    private final HashMap<Object, ColumnGenerator> columnGenerators = new LinkedHashMap<Object, ColumnGenerator>();
+
+    /**
+     * Holds value of property pageLength. 0 disables paging.
+     */
+    private int pageLength = 15;
+
+    /**
+     * Id the first item on the current page.
+     */
+    private Object currentPageFirstItemId = null;
+
+    /**
+     * Index of the first item on the current page.
+     */
+    private int currentPageFirstItemIndex = 0;
+
+    /**
+     * Index of the "first" item on the last page if a user has used
+     * setCurrentPageFirstItemIndex to scroll down. -1 if not set.
+     */
+    private int currentPageFirstItemIndexOnLastPage = -1;
+
+    /**
+     * Holds value of property selectable.
+     */
+    private boolean selectable = false;
+
+    /**
+     * Holds value of property columnHeaderMode.
+     */
+    private ColumnHeaderMode columnHeaderMode = ColumnHeaderMode.EXPLICIT_DEFAULTS_ID;
+
+    /**
+     * Holds value of property rowHeaderMode.
+     */
+    private RowHeaderMode rowHeaderMode = RowHeaderMode.EXPLICIT_DEFAULTS_ID;
+
+    /** Should the CustomTable footer be visible?. */
+    private boolean columnFootersVisible = false;
+
+    /**
+     * Page contents buffer used in buffered mode.
+     */
+    private Object[][] pageBuffer = null;
+
+    /**
+     * Set of properties listened - the list is kept to release the listeners
+     * later.
+     */
+    private HashSet<Property<?>> listenedProperties = null;
+
+    /**
+     * Set of visible components - the is used for needsRepaint calculation.
+     */
+    protected HashSet<Component> visibleComponents = null;
+
+    /**
+     * List of action handlers.
+     */
+    private LinkedList<Handler> actionHandlers = null;
+
+    /**
+     * Action mapper.
+     */
+    private KeyMapper<Action> actionMapper = null;
+
+    /**
+     * CustomTable cell editor factory.
+     */
+    private TableFieldFactory fieldFactory = DefaultFieldFactory.get();
+
+    /**
+     * Is table editable.
+     */
+    private boolean editable = false;
+
+    /**
+     * Current sorting direction.
+     */
+    private boolean sortAscending = true;
+
+    /**
+     * Currently table is sorted on this propertyId.
+     */
+    private Object sortContainerPropertyId = null;
+
+    /**
+     * Is table sorting by the user enabled.
+     */
+    private boolean sortEnabled = true;
+
+    /**
+     * Number of rows explicitly requested by the client to be painted on next
+     * paint. This is -1 if no request by the client is made. Painting the
+     * component will automatically reset this to -1.
+     */
+    private int reqRowsToPaint = -1;
+
+    /**
+     * Index of the first rows explicitly requested by the client to be painted.
+     * This is -1 if no request by the client is made. Painting the component
+     * will automatically reset this to -1.
+     */
+    private int reqFirstRowToPaint = -1;
+
+    /** The first to be rendered in client. */
+    private int firstToBeRenderedInClient = -1;
+
+    /** The last to be rendered in client. */
+    private int lastToBeRenderedInClient = -1;
+
+    /** The is content refreshes enabled. */
+    private boolean isContentRefreshesEnabled = true;
+
+    /** The page buffer first index. */
+    private int pageBufferFirstIndex;
+
+    /** The container change to be rendered. */
+    private boolean containerChangeToBeRendered = false;
+
+    /** CustomTable cell specific style generator. */
+    private CellStyleGenerator cellStyleGenerator = null;
+
+    /** CustomTable cell specific tooltip generator. */
+    private ItemDescriptionGenerator itemDescriptionGenerator;
+
+    /** The always recalculate column widths. */
+    /*
+     * EXPERIMENTAL feature: will tell the client to re-calculate column widths
+     * if set to true. Currently no setter: extend to enable.
+     */
+    protected boolean alwaysRecalculateColumnWidths = false;
+
+    /** The cache rate. */
+    private double cacheRate = CACHE_RATE_DEFAULT;
+
+    /** The drag mode. */
+    private TableDragMode dragMode = TableDragMode.NONE;
+
+    /** The drop handler. */
+    private DropHandler dropHandler;
+
+    /** The multi select mode. */
+    private MultiSelectMode multiSelectMode = MultiSelectMode.DEFAULT;
+
+    /** The row cache invalidated. */
+    private boolean rowCacheInvalidated;
+
+    /** The row generator. */
+    private RowGenerator rowGenerator = null;
+
+    /** The associated properties. */
+    private final Map<Field<?>, Property<?>> associatedProperties = new HashMap<Field<?>, Property<?>>();
+
+    /** The painted. */
+    private boolean painted = false;
+
+    /** The property value converters. */
+    private HashMap<Object, Converter<String, Object>> propertyValueConverters = new HashMap<Object, Converter<String, Object>>();
+
+    /**
+     * Set to true if the client-side should be informed that the key mapper has
+     * been reset so it can avoid sending back references to keys that are no
+     * longer present.
+     */
+    private boolean keyMapperReset;
+
+    /** The exceptions during cache population. */
+    private List<Throwable> exceptionsDuringCachePopulation = new ArrayList<Throwable>();
+
+    /** The is being painted. */
+    private boolean isBeingPainted;
+
+    /* CustomTable constructors */
+
+    /**
+     * Creates a new empty table.
+     */
+    public CustomTable() {
+        setRowHeaderMode(ROW_HEADER_MODE_HIDDEN);
+    }
+
+    /** Creates a new empty table with caption.
+	 *
+	 * @param caption
+	 *            the caption
+	 */
+    public CustomTable(String caption) {
+        this();
+        setCaption(caption);
+    }
+
+    /** Creates a new table with caption and connect it to a Container.
+	 *
+	 * @param caption
+	 *            the caption
+	 * @param dataSource
+	 *            the data source
+	 */
+    public CustomTable(String caption, Container dataSource) {
+        this();
+        setCaption(caption);
+        setContainerDataSource(dataSource);
+    }
+
+    /* CustomTable functionality */
+
+    /**
+     * Gets the array of visible column id:s, including generated columns.
+     * 
+     * <p>
+     * The columns are show in the order of their appearance in this array.
+     * 
+     * 
+     * @return an array of currently visible propertyIds and generated column
+     *         ids.
+     */
+    public Object[] getVisibleColumns() {
+        if (visibleColumns == null) {
+            return null;
+        }
+        return visibleColumns.toArray();
+    }
+
+    /**
+     * Sets the array of visible column property id:s.
+     * 
+     * <p>
+     * The columns are show in the order of their appearance in this array.
+     * 
+     * 
+     * @param visibleColumns
+     *            the Array of shown property id:s.
+     */
+    public void setVisibleColumns(Object... visibleColumns) {
+
+        // Visible columns must exist
+        if (visibleColumns == null) {
+            throw new NullPointerException(
+                    "Can not set visible columns to null value");
+        }
+
+        final LinkedList<Object> newVC = new LinkedList<Object>();
+
+        // Checks that the new visible columns contains no nulls, properties
+        // exist and that there are no duplicates before adding them to newVC.
+        final Collection<?> properties = getContainerPropertyIds();
+        for (int i = 0; i < visibleColumns.length; i++) {
+            if (visibleColumns[i] == null) {
+                throw new NullPointerException("Ids must be non-nulls");
+            } else if (!properties.contains(visibleColumns[i])
+                    && !columnGenerators.containsKey(visibleColumns[i])) {
+                throw new IllegalArgumentException(
+                        "Ids must exist in the Container or as a generated column, missing id: "
+                                + visibleColumns[i]);
+            } else if (newVC.contains(visibleColumns[i])) {
+                throw new IllegalArgumentException(
+                        "Ids must be unique, duplicate id: "
+                                + visibleColumns[i]);
+            } else {
+                newVC.add(visibleColumns[i]);
+            }
+        }
+
+        // Removes alignments, icons and headers from hidden columns
+        if (this.visibleColumns != null) {
+            boolean disabledHere = disableContentRefreshing();
+            try {
+                for (final Iterator<Object> i = this.visibleColumns.iterator(); i
+                        .hasNext();) {
+                    final Object col = i.next();
+                    if (!newVC.contains(col)) {
+                        setColumnHeader(col, null);
+                        setColumnAlignment(col, (Align) null);
+                        setColumnIcon(col, null);
+                    }
+                }
+            } finally {
+                if (disabledHere) {
+                    enableContentRefreshing(false);
+                }
+            }
+        }
+
+        this.visibleColumns = newVC;
+
+        // Assures visual refresh
+        refreshRowCache();
+    }
+
+    /**
+     * Gets the headers of the columns.
+     * 
+     * <p>
+     * The headers match the property id:s given my the set visible column
+     * headers. The table must be set in either
+     * {@link #COLUMN_HEADER_MODE_EXPLICIT} or
+     * {@link #COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID} mode to show the
+     * headers. In the defaults mode any nulls in the headers array are replaced
+     * with id.toString().
+     * 
+     * 
+     * @return the Array of column headers.
+     */
+    public String[] getColumnHeaders() {
+        if (columnHeaders == null) {
+            return null;
+        }
+        final String[] headers = new String[visibleColumns.size()];
+        int i = 0;
+        for (final Iterator<Object> it = visibleColumns.iterator(); it
+                .hasNext(); i++) {
+            headers[i] = getColumnHeader(it.next());
+        }
+        return headers;
+    }
+
+    /**
+     * Sets the headers of the columns.
+     * 
+     * <p>
+     * The headers match the property id:s given my the set visible column
+     * headers. The table must be set in either
+     * {@link #COLUMN_HEADER_MODE_EXPLICIT} or
+     * {@link #COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID} mode to show the
+     * headers. In the defaults mode any nulls in the headers array are replaced
+     * with id.toString() outputs when rendering.
+     * 
+     * 
+     * @param columnHeaders
+     *            the Array of column headers that match the
+     *            {@link #getVisibleColumns()} method.
+     */
+    public void setColumnHeaders(String... columnHeaders) {
+
+        if (columnHeaders.length != visibleColumns.size()) {
+            throw new IllegalArgumentException(
+                    "The length of the headers array must match the number of visible columns");
+        }
+
+        this.columnHeaders.clear();
+        int i = 0;
+        for (final Iterator<Object> it = visibleColumns.iterator(); it
+                .hasNext() && i < columnHeaders.length; i++) {
+            this.columnHeaders.put(it.next(), columnHeaders[i]);
+        }
+
+        markAsDirty();
+    }
+
+    /**
+     * Gets the icons of the columns.
+     * 
+     * <p>
+     * The icons in headers match the property id:s given my the set visible
+     * column headers. The table must be set in either
+     * {@link #COLUMN_HEADER_MODE_EXPLICIT} or
+     * {@link #COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID} mode to show the headers
+     * with icons.
+     * 
+     * 
+     * @return the Array of icons that match the {@link #getVisibleColumns()}.
+     */
+    public Resource[] getColumnIcons() {
+        if (columnIcons == null) {
+            return null;
+        }
+        final Resource[] icons = new Resource[visibleColumns.size()];
+        int i = 0;
+        for (final Iterator<Object> it = visibleColumns.iterator(); it
+                .hasNext(); i++) {
+            icons[i] = columnIcons.get(it.next());
+        }
+
+        return icons;
+    }
+
+    /**
+     * Sets the icons of the columns.
+     * 
+     * <p>
+     * The icons in headers match the property id:s given my the set visible
+     * column headers. The table must be set in either
+     * {@link #COLUMN_HEADER_MODE_EXPLICIT} or
+     * {@link #COLUMN_HEADER_MODE_EXPLICIT_DEFAULTS_ID} mode to show the headers
+     * with icons.
+     * 
+     * 
+     * @param columnIcons
+     *            the Array of icons that match the {@link #getVisibleColumns()}
+     *            .
+     */
+    public void setColumnIcons(Resource... columnIcons) {
+
+        if (columnIcons.length != visibleColumns.size()) {
+            throw new IllegalArgumentException(
+                    "The length of the icons array must match the number of visible columns");
+        }
+
+        this.columnIcons.clear();
+        int i = 0;
+        for (final Iterator<Object> it = visibleColumns.iterator(); it
+                .hasNext() && i < columnIcons.length; i++) {
+            this.columnIcons.put(it.next(), columnIcons[i]);
+        }
+
+        markAsDirty();
+    }
+
+    /**
+     * Gets the array of column alignments.
+     * 
+     * <p>
+     * The items in the array must match the properties identified by
+     * {@link #getVisibleColumns()}. The possible values for the alignments
+     * include:
+     * <ul>
+     * <li>{@link Align#LEFT}: Left alignment</li>
+     * <li>{@link Align#CENTER}: Centered</li>
+     * <li>{@link Align#RIGHT}: Right alignment</li>
+     * </ul>
+     * The alignments default to {@link Align#LEFT}: any null values are
+     * rendered as align lefts.
+     * 
+     * 
+     * @return the Column alignments array.
+     */
+    public Align[] getColumnAlignments() {
+        if (columnAlignments == null) {
+            return null;
+        }
+        final Align[] alignments = new Align[visibleColumns.size()];
+        int i = 0;
+        for (final Iterator<Object> it = visibleColumns.iterator(); it
+                .hasNext(); i++) {
+            alignments[i] = getColumnAlignment(it.next());
+        }
+
+        return alignments;
+    }
+
+    /**
+     * Sets the column alignments.
+     * 
+     * <p>
+     * The amount of items in the array must match the amount of properties
+     * identified by {@link #getVisibleColumns()}. The possible values for the
+     * alignments include:
+     * <ul>
+     * <li>{@link Align#LEFT}: Left alignment</li>
+     * <li>{@link Align#CENTER}: Centered</li>
+     * <li>{@link Align#RIGHT}: Right alignment</li>
+     * </ul>
+     * The alignments default to {@link Align#LEFT}
+     * 
+     * 
+     * @param columnAlignments
+     *            the Column alignments array.
+     */
+    public void setColumnAlignments(Align... columnAlignments) {
+
+        if (columnAlignments.length != visibleColumns.size()) {
+            throw new IllegalArgumentException(
+                    "The length of the alignments array must match the number of visible columns");
+        }
+
+        // Resets the alignments
+        final HashMap<Object, Align> newCA = new HashMap<Object, Align>();
+        int i = 0;
+        for (final Iterator<Object> it = visibleColumns.iterator(); it
+                .hasNext() && i < columnAlignments.length; i++) {
+            newCA.put(it.next(), columnAlignments[i]);
+        }
+        this.columnAlignments = newCA;
+
+        // Assures the visual refresh. No need to reset the page buffer before
+        // as the content has not changed, only the alignments.
+        refreshRenderedCells();
+    }
+
+    /**
+     * Sets columns width (in pixels). Theme may not necessary respect very
+     * small or very big values. Setting width to -1 (default) means that theme
+     * will make decision of width.
+     * 
+     * <p>
+     * Column can either have a fixed width or expand ratio. The latter one set
+     * is used. See @link {@link #setColumnExpandRatio(Object, float)}.
+     * 
+     * @param propertyId
+     *            colunmns property id
+     * @param width
+     *            width to be reserved for colunmns content
+     * @since 4.0.3
+     */
+    public void setColumnWidth(Object propertyId, int width) {
+        if (propertyId == null) {
+            // Since propertyId is null, this is the row header. Use the magic
+            // id to store the width of the row header.
+            propertyId = ROW_HEADER_FAKE_PROPERTY_ID;
+        }
+
+        // Setting column width should remove any expand ratios as well
+        columnExpandRatios.remove(propertyId);
+
+        if (width < 0) {
+            columnWidths.remove(propertyId);
+        } else {
+            columnWidths.put(propertyId, width);
+        }
+        markAsDirty();
+    }
+
+    /**
+     * Sets the column expand ratio for given column.
+     * <p>
+     * Expand ratios can be defined to customize the way how excess space is
+     * divided among columns. CustomTable can have excess space if it has its
+     * width defined and there is horizontally more space than columns consume
+     * naturally. Excess space is the space that is not used by columns with
+     * explicit width (see {@link #setColumnWidth(Object, int)}) or with natural
+     * width (no width nor expand ratio).
+     * 
+     * <p>
+     * By default (without expand ratios) the excess space is divided
+     * proportionally to columns natural widths.
+     * 
+     * <p>
+     * Only expand ratios of visible columns are used in final calculations.
+     * 
+     * <p>
+     * Column can either have a fixed width or expand ratio. The latter one set
+     * is used.
+     * 
+     * <p>
+     * A column with expand ratio is considered to be minimum width by default
+     * (if no excess space exists). The minimum width is defined by terminal
+     * implementation.
+     * 
+     * <p>
+     * If terminal implementation supports re-sizable columns the column becomes
+     * fixed width column if users resizes the column.
+     * 
+     * @param propertyId
+     *            columns property id
+     * @param expandRatio
+     *            the expandRatio used to divide excess space for this column
+     */
+    public void setColumnExpandRatio(Object propertyId, float expandRatio) {
+        if (propertyId == null) {
+            // Since propertyId is null, this is the row header. Use the magic
+            // id to store the width of the row header.
+            propertyId = ROW_HEADER_FAKE_PROPERTY_ID;
+        }
+
+        // Setting the column expand ratio should remove and defined column
+        // width
+        columnWidths.remove(propertyId);
+
+        if (expandRatio < 0) {
+            columnExpandRatios.remove(propertyId);
+        } else {
+            columnExpandRatios.put(propertyId, expandRatio);
+        }
+
+        requestRepaint();
+    }
+
+    /**
+     * Gets the column expand ratio for a columnd. See
+     * {@link #setColumnExpandRatio(Object, float)}
+     * 
+     * @param propertyId
+     *            columns property id
+     * @return the expandRatio used to divide excess space for this column
+     */
+    public float getColumnExpandRatio(Object propertyId) {
+        final Float width = columnExpandRatios.get(propertyId);
+        if (width == null) {
+            return -1;
+        }
+        return width.floatValue();
+    }
+
+    /** Gets the pixel width of column.
+	 *
+	 * @param propertyId
+	 *            the property id
+	 * @return width of column or -1 when value not set
+	 */
+    public int getColumnWidth(Object propertyId) {
+        if (propertyId == null) {
+            // Since propertyId is null, this is the row header. Use the magic
+            // id to retrieve the width of the row header.
+            propertyId = ROW_HEADER_FAKE_PROPERTY_ID;
+        }
+        final Integer width = columnWidths.get(propertyId);
+        if (width == null) {
+            return -1;
+        }
+        return width.intValue();
+    }
+
+    /**
+     * Gets the page length.
+     * 
+     * <p>
+     * Setting page length 0 disables paging.
+     * 
+     * 
+     * @return the Length of one page.
+     */
+    public int getPageLength() {
+        return pageLength;
+    }
+
+    /**
+     * Sets the page length.
+     * 
+     * <p>
+     * Setting page length 0 disables paging. The page length defaults to 15.
+     * 
+     * 
+     * <p>
+     * If CustomTable has width set ({@link #setColumnWidth(Object, int)} ) the client
+     * side may update the page length automatically the correct value.
+     * 
+     * 
+     * @param pageLength
+     *            the length of one page.
+     */
+    public void setPageLength(int pageLength) {
+        if (pageLength >= 0 && this.pageLength != pageLength) {
+            this.pageLength = pageLength;
+            // Assures the visual refresh
+            refreshRowCache();
+        }
+    }
+
+    /**
+     * This method adjusts a possible caching mechanism of table implementation.
+     * 
+     * <p>
+     * CustomTable component may fetch and render some rows outside visible
+     * area. With complex tables (for example containing layouts and
+     * components), the client side may become unresponsive. Setting the value
+     * lower, UI will become more responsive. With higher values scrolling in
+     * client will hit server less frequently.
+     * 
+     * <p>
+     * The amount of cached rows will be cacheRate multiplied with pageLength (
+     * {@link #setPageLength(int)} both below and above visible area..
+     * 
+     * @param cacheRate
+     *            a value over 0 (fastest rendering time). Higher value will
+     *            cache more rows on server (smoother scrolling). Default value
+     *            is 2.
+     */
+    public void setCacheRate(double cacheRate) {
+        if (cacheRate < 0) {
+            throw new IllegalArgumentException(
+                    "cacheRate cannot be less than zero");
+        }
+        if (this.cacheRate != cacheRate) {
+            this.cacheRate = cacheRate;
+            markAsDirty();
+        }
+    }
+
+    /** Gets the cache rate.
+	 *
+	 * @return the current cache rate value
+	 * @see #setCacheRate(double)
+	 */
+    public double getCacheRate() {
+        return cacheRate;
+    }
+
+    /**
+     * Getter for property currentPageFirstItem.
+     * 
+     * @return the Value of property currentPageFirstItem.
+     */
+    public Object getCurrentPageFirstItemId() {
+
+        // Priorise index over id if indexes are supported
+        if (items instanceof Container.Indexed) {
+            final int index = getCurrentPageFirstItemIndex();
+            Object id = null;
+            if (index >= 0 && index < size()) {
+                id = getIdByIndex(index);
+            }
+            if (id != null && !id.equals(currentPageFirstItemId)) {
+                currentPageFirstItemId = id;
+            }
+        }
+
+        // If there is no item id at all, use the first one
+        if (currentPageFirstItemId == null) {
+            currentPageFirstItemId = firstItemId();
+        }
+
+        return currentPageFirstItemId;
+    }
+
+    /**
+     * Returns the item ID for the item represented by the index given. Assumes
+     * that the current container implements {@link Container.Indexed}.
+     * 
+     * See {@link Container.Indexed#getIdByIndex(int)} for more information
+     * about the exceptions that can be thrown.
+     * 
+     * @param index
+     *            the index for which the item ID should be fetched
+     * @return the item ID for the given index
+     * 
+     * @throws ClassCastException
+     *             if container does not implement {@link Container.Indexed}
+     * @throws IndexOutOfBoundsException
+     *             thrown by {@link Container.Indexed#getIdByIndex(int)} if the
+     *             index is invalid
+     */
+    protected Object getIdByIndex(int index) {
+        return ((Container.Indexed) items).getIdByIndex(index);
+    }
+
+    /**
+     * Setter for property currentPageFirstItemId.
+     * 
+     * @param currentPageFirstItemId
+     *            the New value of property currentPageFirstItemId.
+     */
+    public void setCurrentPageFirstItemId(Object currentPageFirstItemId) {
+
+        // Gets the corresponding index
+        int index = -1;
+        if (items instanceof Container.Indexed) {
+            index = indexOfId(currentPageFirstItemId);
+        } else {
+            // If the table item container does not have index, we have to
+            // calculates the index by hand
+            Object id = firstItemId();
+            while (id != null && !id.equals(currentPageFirstItemId)) {
+                index++;
+                id = nextItemId(id);
+            }
+            if (id == null) {
+                index = -1;
+            }
+        }
+
+        // If the search for item index was successful
+        if (index >= 0) {
+            /*
+             * The table is not capable of displaying an item in the container
+             * as the first if there are not enough items following the selected
+             * item so the whole table (pagelength) is filled.
+             */
+            int maxIndex = size() - pageLength;
+            if (maxIndex < 0) {
+                maxIndex = 0;
+            }
+
+            if (index > maxIndex) {
+                // Note that we pass index, not maxIndex, letting
+                // setCurrentPageFirstItemIndex handle the situation.
+                setCurrentPageFirstItemIndex(index);
+                return;
+            }
+
+            this.currentPageFirstItemId = currentPageFirstItemId;
+            currentPageFirstItemIndex = index;
+        }
+
+        // Assures the visual refresh
+        refreshRowCache();
+
+    }
+
+    /** Index of id.
+	 *
+	 * @param itemId
+	 *            the item id
+	 * @return the int
+	 */
+    protected int indexOfId(Object itemId) {
+        return ((Container.Indexed) items).indexOfId(itemId);
+    }
+
+    /**
+     * Gets the icon Resource for the specified column.
+     * 
+     * @param propertyId
+     *            the propertyId indentifying the column.
+     * @return the icon for the specified column; null if the column has no icon
+     *         set, or if the column is not visible.
+     */
+    public Resource getColumnIcon(Object propertyId) {
+        return columnIcons.get(propertyId);
+    }
+
+    /**
+     * Sets the icon Resource for the specified column.
+     * <p>
+     * Throws IllegalArgumentException if the specified column is not visible.
+     * 
+     * 
+     * @param propertyId
+     *            the propertyId identifying the column.
+     * @param icon
+     *            the icon Resource to set.
+     */
+    public void setColumnIcon(Object propertyId, Resource icon) {
+
+        if (icon == null) {
+            columnIcons.remove(propertyId);
+        } else {
+            columnIcons.put(propertyId, icon);
+        }
+
+        markAsDirty();
+    }
+
+    /**
+     * Gets the header for the specified column.
+     * 
+     * @param propertyId
+     *            the propertyId identifying the column.
+     * @return the header for the specified column if it has one.
+     */
+    public String getColumnHeader(Object propertyId) {
+        if (getColumnHeaderMode() == ColumnHeaderMode.HIDDEN) {
+            return null;
+        }
+
+        String header = columnHeaders.get(propertyId);
+        if ((header == null && getColumnHeaderMode() == ColumnHeaderMode.EXPLICIT_DEFAULTS_ID)
+                || getColumnHeaderMode() == ColumnHeaderMode.ID) {
+            header = propertyId.toString();
+        }
+
+        return header;
+    }
+
+    /** Sets the column header for the specified column;.
+	 *
+	 * @param propertyId
+	 *            the propertyId identifying the column.
+	 * @param header
+	 *            the header to set.
+	 */
+    public void setColumnHeader(Object propertyId, String header) {
+
+        if (header == null) {
+            columnHeaders.remove(propertyId);
+        } else {
+            columnHeaders.put(propertyId, header);
+        }
+
+        markAsDirty();
+    }
+
+    /**
+     * Gets the specified column's alignment.
+     * 
+     * @param propertyId
+     *            the propertyID identifying the column.
+     * @return the specified column's alignment if it as one; {@link Align#LEFT}
+     *         otherwise.
+     */
+    public Align getColumnAlignment(Object propertyId) {
+        final Align a = columnAlignments.get(propertyId);
+        return a == null ? Align.LEFT : a;
+    }
+
+    /**
+     * Sets the specified column's alignment.
+     * 
+     * <p>
+     * Throws IllegalArgumentException if the alignment is not one of the
+     * following: {@link Align#LEFT}, {@link Align#CENTER} or
+     * {@link Align#RIGHT}
+     * 
+     * 
+     * @param propertyId
+     *            the propertyID identifying the column.
+     * @param alignment
+     *            the desired alignment.
+     */
+    public void setColumnAlignment(Object propertyId, Align alignment) {
+        if (alignment == null || alignment == Align.LEFT) {
+            columnAlignments.remove(propertyId);
+        } else {
+            columnAlignments.put(propertyId, alignment);
+        }
+
+        // Assures the visual refresh. No need to reset the page buffer before
+        // as the content has not changed, only the alignments.
+        refreshRenderedCells();
+    }
+
+    /**
+     * Checks if the specified column is collapsed.
+     * 
+     * @param propertyId
+     *            the propertyID identifying the column.
+     * @return true if the column is collapsed; false otherwise;
+     */
+    public boolean isColumnCollapsed(Object propertyId) {
+        return collapsedColumns != null
+                && collapsedColumns.contains(propertyId);
+    }
+
+    /**
+     * Sets whether the specified column is collapsed or not.
+     * 
+     * 
+     * @param propertyId
+     *            the propertyID identifying the column.
+     * @param collapsed
+     *            the desired collapsedness.
+     * @throws IllegalStateException
+     *             if column collapsing is not allowed
+     */
+    public void setColumnCollapsed(Object propertyId, boolean collapsed)
+            throws IllegalStateException {
+        if (!isColumnCollapsingAllowed()) {
+            throw new IllegalStateException("Column collapsing not allowed!");
+        }
+        if (collapsed && noncollapsibleColumns.contains(propertyId)) {
+            throw new IllegalStateException("The column is noncollapsible!");
+        }
+
+        if (collapsed) {
+            collapsedColumns.add(propertyId);
+        } else {
+            collapsedColumns.remove(propertyId);
+        }
+
+        // Assures the visual refresh
+        refreshRowCache();
+    }
+
+    /**
+     * Checks if column collapsing is allowed.
+     * 
+     * @return true if columns can be collapsed; false otherwise.
+     */
+    public boolean isColumnCollapsingAllowed() {
+        return columnCollapsingAllowed;
+    }
+
+    /**
+     * Sets whether column collapsing is allowed or not.
+     * 
+     * @param collapsingAllowed
+     *            specifies whether column collapsing is allowed.
+     */
+    public void setColumnCollapsingAllowed(boolean collapsingAllowed) {
+        columnCollapsingAllowed = collapsingAllowed;
+
+        if (!collapsingAllowed) {
+            collapsedColumns.clear();
+        }
+
+        // Assures the visual refresh. No need to reset the page buffer before
+        // as the content has not changed, only the alignments.
+        refreshRenderedCells();
+    }
+
+    /**
+     * Sets whether the given column is collapsible. Note that collapsible
+     * columns can only be actually collapsed (via UI or with
+     * {@link #setColumnCollapsed(Object, boolean) setColumnCollapsed()}) if
+     * {@link #isColumnCollapsingAllowed()} is true. By default all columns are
+     * collapsible.
+     * 
+     * @param propertyId
+     *            the propertyID identifying the column.
+     * @param collapsible
+     *            true if the column should be collapsible, false otherwise.
+     */
+    public void setColumnCollapsible(Object propertyId, boolean collapsible) {
+        if (collapsible) {
+            noncollapsibleColumns.remove(propertyId);
+        } else {
+            noncollapsibleColumns.add(propertyId);
+            collapsedColumns.remove(propertyId);
+        }
+        refreshRowCache();
+    }
+
+    /** Checks if the given column is collapsible. Note that even if this
+	 * method returns <code>true</code>, the column can only be actually
+	 * collapsed (via UI or with {@link #setColumnCollapsed(Object, boolean)
+	 * setColumnCollapsed()}) if {@link #isColumnCollapsingAllowed()} is also
+	 * true.
+	 *
+	 * @param propertyId
+	 *            the property id
+	 * @return true if the column can be collapsed; false otherwise.
+	 */
+    public boolean isColumnCollapsible(Object propertyId) {
+        return !noncollapsibleColumns.contains(propertyId);
+    }
+
+    /**
+     * Checks if column reordering is allowed.
+     * 
+     * @return true if columns can be reordered; false otherwise.
+     */
+    public boolean isColumnReorderingAllowed() {
+        return columnReorderingAllowed;
+    }
+
+    /**
+     * Sets whether column reordering is allowed or not.
+     * 
+     * @param columnReorderingAllowed
+     *            specifies whether column reordering is allowed.
+     */
+    public void setColumnReorderingAllowed(boolean columnReorderingAllowed) {
+        if (columnReorderingAllowed != this.columnReorderingAllowed) {
+            this.columnReorderingAllowed = columnReorderingAllowed;
+            markAsDirty();
+        }
+    }
+
+    /** Sets the column order.
+	 *
+	 * @param columnOrder
+	 *            the new column order
+	 */
+    /*
+     * Arranges visible columns according to given columnOrder. Silently ignores
+     * colimnId:s that are not visible columns, and keeps the internal order of
+     * visible columns left out of the ordering (trailing). Silently does
+     * nothing if columnReordering is not allowed.
+     */
+    private void setColumnOrder(Object[] columnOrder) {
+        if (columnOrder == null || !isColumnReorderingAllowed()) {
+            return;
+        }
+        final LinkedList<Object> newOrder = new LinkedList<Object>();
+        for (int i = 0; i < columnOrder.length; i++) {
+            if (columnOrder[i] != null
+                    && visibleColumns.contains(columnOrder[i])) {
+                visibleColumns.remove(columnOrder[i]);
+                newOrder.add(columnOrder[i]);
+            }
+        }
+        for (final Iterator<Object> it = visibleColumns.iterator(); it
+                .hasNext();) {
+            final Object columnId = it.next();
+            if (!newOrder.contains(columnId)) {
+                newOrder.add(columnId);
+            }
+        }
+        visibleColumns = newOrder;
+
+        // Assure visual refresh
+        refreshRowCache();
+    }
+
+    /**
+     * Getter for property currentPageFirstItem.
+     * 
+     * @return the Value of property currentPageFirstItem.
+     */
+    public int getCurrentPageFirstItemIndex() {
+        return currentPageFirstItemIndex;
+    }
+
+    /** Sets the current page first item index.
+	 *
+	 * @param newIndex
+	 *            the new index
+	 * @param needsPageBufferReset
+	 *            the needs page buffer reset
+	 */
+    void setCurrentPageFirstItemIndex(int newIndex, boolean needsPageBufferReset) {
+
+        if (newIndex < 0) {
+            newIndex = 0;
+        }
+
+        /*
+         * minimize Container.size() calls which may be expensive. For example
+         * it may cause sql query.
+         */
+        final int size = size();
+
+        /*
+         * The table is not capable of displaying an item in the container as
+         * the first if there are not enough items following the selected item
+         * so the whole table (pagelength) is filled.
+         */
+        int maxIndex = size - pageLength;
+        if (maxIndex < 0) {
+            maxIndex = 0;
+        }
+
+        /*
+         * If the new index is on the last page we set the index to be the first
+         * item on that last page and make a note of the real index for the
+         * client side to be able to move the scroll position to the correct
+         * position.
+         */
+        int indexOnLastPage = -1;
+        if (newIndex > maxIndex) {
+            indexOnLastPage = newIndex;
+            newIndex = maxIndex;
+        }
+
+        // Refresh first item id
+        if (items instanceof Container.Indexed) {
+            try {
+                currentPageFirstItemId = getIdByIndex(newIndex);
+            } catch (final IndexOutOfBoundsException e) {
+                currentPageFirstItemId = null;
+            }
+            currentPageFirstItemIndex = newIndex;
+
+            if (needsPageBufferReset) {
+                /*
+                 * The flag currentPageFirstItemIndexOnLastPage denotes a user
+                 * set scrolling position on the last page via
+                 * setCurrentPageFirstItemIndex() and shouldn't be changed by
+                 * the table component internally changing the firstvisible item
+                 * on lazy row fetching. Doing so would make the scrolling
+                 * position not be updated correctly when the lazy rows are
+                 * finally rendered.
+                 */
+
+                boolean isLastRowPossiblyPartiallyVisible = true;
+                if (indexOnLastPage != -1) {
+                    /*
+                     * If the requested row was greater than maxIndex, the last
+                     * row should be fully visible (See
+                     * TestCurrentPageFirstItem).
+                     */
+                    isLastRowPossiblyPartiallyVisible = false;
+                }
+
+                int extraRows = isLastRowPossiblyPartiallyVisible ? 0 : 1;
+                currentPageFirstItemIndexOnLastPage = currentPageFirstItemIndex
+                        + extraRows;
+            } else {
+                currentPageFirstItemIndexOnLastPage = -1;
+            }
+
+        } else {
+
+            // For containers not supporting indexes, we must iterate the
+            // container forwards / backwards
+            // next available item forward or backward
+
+            currentPageFirstItemId = firstItemId();
+
+            // Go forwards in the middle of the list (respect borders)
+            while (currentPageFirstItemIndex < newIndex
+                    && !isLastId(currentPageFirstItemId)) {
+                currentPageFirstItemIndex++;
+                currentPageFirstItemId = nextItemId(currentPageFirstItemId);
+            }
+
+            // If we did hit the border
+            if (isLastId(currentPageFirstItemId)) {
+                currentPageFirstItemIndex = size - 1;
+            }
+
+            // Go backwards in the middle of the list (respect borders)
+            while (currentPageFirstItemIndex > newIndex
+                    && !isFirstId(currentPageFirstItemId)) {
+                currentPageFirstItemIndex--;
+                currentPageFirstItemId = prevItemId(currentPageFirstItemId);
+            }
+
+            // If we did hit the border
+            if (isFirstId(currentPageFirstItemId)) {
+                currentPageFirstItemIndex = 0;
+            }
+
+            // Go forwards once more
+            while (currentPageFirstItemIndex < newIndex
+                    && !isLastId(currentPageFirstItemId)) {
+                currentPageFirstItemIndex++;
+                currentPageFirstItemId = nextItemId(currentPageFirstItemId);
+            }
+
+            // If for some reason we do hit border again, override
+            // the user index request
+            if (isLastId(currentPageFirstItemId)) {
+                newIndex = currentPageFirstItemIndex = size - 1;
+            }
+        }
+        if (needsPageBufferReset) {
+            // Assures the visual refresh
+            refreshRowCache();
+        }
+    }
+
+    /**
+     * Setter for property currentPageFirstItem.
+     * 
+     * @param newIndex
+     *            the New value of property currentPageFirstItem.
+     */
+    public void setCurrentPageFirstItemIndex(int newIndex) {
+        setCurrentPageFirstItemIndex(newIndex, true);
+    }
+
+    /**
+     * Getter for property selectable.
+     * 
+     * <p>
+     * The table is not selectable by default.
+     * 
+     * 
+     * @return the Value of property selectable.
+     */
+    public boolean isSelectable() {
+        return selectable;
+    }
+
+    /**
+     * Setter for property selectable.
+     * 
+     * <p>
+     * The table is not selectable by default.
+     * 
+     * 
+     * @param selectable
+     *            the New value of property selectable.
+     */
+    public void setSelectable(boolean selectable) {
+        if (this.selectable != selectable) {
+            this.selectable = selectable;
+            markAsDirty();
+        }
+    }
+
+    /**
+     * Getter for property columnHeaderMode.
+     * 
+     * @return the Value of property columnHeaderMode.
+     */
+    public ColumnHeaderMode getColumnHeaderMode() {
+        return columnHeaderMode;
+    }
+
+    /**
+     * Setter for property columnHeaderMode.
+     * 
+     * @param columnHeaderMode
+     *            the New value of property columnHeaderMode.
+     */
+    public void setColumnHeaderMode(ColumnHeaderMode columnHeaderMode) {
+        if (columnHeaderMode == null) {
+            throw new IllegalArgumentException(
+                    "Column header mode can not be null");
+        }
+        if (columnHeaderMode != this.columnHeaderMode) {
+            this.columnHeaderMode = columnHeaderMode;
+            markAsDirty();
+        }
+
+    }
+
+    /**
+     * Refreshes the rows in the internal cache. Only if
+     * {@link #resetPageBuffer()} is called before this then all values are
+     * guaranteed to be recreated.
+     */
+    protected void refreshRenderedCells() {
+        if (!isAttached()) {
+            return;
+        }
+
+        if (!isContentRefreshesEnabled) {
+            return;
+        }
+
+        // Collects the basic facts about the table page
+        final int pagelen = getPageLength();
+        int rows, totalRows;
+        rows = totalRows = size();
+        int firstIndex = Math
+                .min(getCurrentPageFirstItemIndex(), totalRows - 1);
+        if (rows > 0 && firstIndex >= 0) {
+            rows -= firstIndex;
+        }
+        if (pagelen > 0 && pagelen < rows) {
+            rows = pagelen;
+        }
+
+        // If "to be painted next" variables are set, use them
+        if (lastToBeRenderedInClient - firstToBeRenderedInClient > 0) {
+            rows = lastToBeRenderedInClient - firstToBeRenderedInClient + 1;
+        }
+        if (firstToBeRenderedInClient >= 0) {
+            if (firstToBeRenderedInClient < totalRows) {
+                firstIndex = firstToBeRenderedInClient;
+            } else {
+                firstIndex = totalRows - 1;
+            }
+        } else {
+            // initial load
+
+            // #8805 send one extra row in the beginning in case a partial
+            // row is shown on the UI
+            if (firstIndex > 0) {
+                firstIndex = firstIndex - 1;
+                rows = rows + 1;
+            }
+            firstToBeRenderedInClient = firstIndex;
+        }
+        if (totalRows > 0) {
+            if (rows + firstIndex > totalRows) {
+                rows = totalRows - firstIndex;
+            }
+        } else {
+            rows = 0;
+        }
+
+        // Saves the results to internal buffer
+        pageBuffer = getVisibleCellsNoCache(firstIndex, rows, true);
+
+        if (rows > 0) {
+            pageBufferFirstIndex = firstIndex;
+        }
+        if (getPageLength() != 0) {
+            removeUnnecessaryRows();
+        }
+
+        setRowCacheInvalidated(true);
+        markAsDirty();
+        maybeThrowCacheUpdateExceptions();
+
+    }
+
+    /** Maybe throw cache update exceptions.
+	 */
+    private void maybeThrowCacheUpdateExceptions() {
+        if (!exceptionsDuringCachePopulation.isEmpty()) {
+            Throwable[] causes = new Throwable[exceptionsDuringCachePopulation
+                    .size()];
+            exceptionsDuringCachePopulation.toArray(causes);
+
+            exceptionsDuringCachePopulation.clear();
+            throw new CacheUpdateException(this,
+                    "Error during CustomTable cache update.", causes);
+        }
+
+    }
+
+    /**
+     * Exception thrown when one or more exceptions occurred during updating of
+     * the CustomTable cache.
+     * <p>
+     * Contains all exceptions which occurred during the cache update. The first
+     * occurred exception is set as the cause of this exception. All occurred
+     * exceptions can be accessed using {@link #getCauses()}.
+     * 
+     * 
+     */
+    public static class CacheUpdateException extends RuntimeException {
+        
+        /** The causes. */
+        private Throwable[] causes;
+        
+        /** The table. */
+        private CustomTable table;
+
+        /** Instantiates a new cache update exception.
+		 *
+		 * @param table
+		 *            the table
+		 * @param message
+		 *            the message
+		 * @param causes
+		 *            the causes
+		 */
+        public CacheUpdateException(CustomTable table, String message,
+                Throwable[] causes) {
+            super(maybeSupplementMessage(message, causes.length), causes[0]);
+            this.table = table;
+            this.causes = causes;
+        }
+
+        /** Maybe supplement message.
+		 *
+		 * @param message
+		 *            the message
+		 * @param causeCount
+		 *            the cause count
+		 * @return the string
+		 */
+        private static String maybeSupplementMessage(String message,
+                int causeCount) {
+            if (causeCount > 1) {
+                return message + " Additional causes not shown.";
+            } else {
+                return message;
+            }
+        }
+
+        /** Returns the cause(s) for this exception.
+		 *
+		 * @return the exception(s) which caused this exception
+		 */
+        public Throwable[] getCauses() {
+            return causes;
+        }
+
+        /** Gets the table.
+		 *
+		 * @return the table
+		 */
+        public CustomTable getTable() {
+            return table;
+        }
+
+    }
+
+    /**
+     * Removes rows that fall outside the required cache.
+     */
+    private void removeUnnecessaryRows() {
+        int minPageBufferIndex = getMinPageBufferIndex();
+        int maxPageBufferIndex = getMaxPageBufferIndex();
+
+        int maxBufferSize = maxPageBufferIndex - minPageBufferIndex + 1;
+
+        /*
+         * Number of rows that were previously cached. This is not necessarily
+         * the same as pageLength if we do not have enough rows in the
+         * container.
+         */
+        int currentlyCachedRowCount = pageBuffer[CELL_ITEMID].length;
+
+        if (currentlyCachedRowCount <= maxBufferSize) {
+            // removal unnecessary
+            return;
+        }
+
+        /* Figure out which rows to get rid of. */
+        int firstCacheRowToRemoveInPageBuffer = -1;
+        if (minPageBufferIndex > pageBufferFirstIndex) {
+            firstCacheRowToRemoveInPageBuffer = pageBufferFirstIndex;
+        } else if (maxPageBufferIndex < pageBufferFirstIndex
+                + currentlyCachedRowCount) {
+            firstCacheRowToRemoveInPageBuffer = maxPageBufferIndex + 1;
+        }
+
+        if (firstCacheRowToRemoveInPageBuffer - pageBufferFirstIndex < currentlyCachedRowCount) {
+            /*
+             * Unregister all components that fall beyond the cache limits after
+             * inserting the new rows.
+             */
+            unregisterComponentsAndPropertiesInRows(
+                    firstCacheRowToRemoveInPageBuffer, currentlyCachedRowCount
+                            - firstCacheRowToRemoveInPageBuffer);
+        }
+    }
+
+    /**
+     * Requests that the CustomTable should be repainted as soon as possible.
+     * 
+     * Note that a {@code CustomTable} does not necessarily repaint its contents
+     * when this method has been called. See {@link #refreshRowCache()} for
+     * forcing an update of the contents.
+     * 
+     * @deprecated As of 7.0, use {@link #markAsDirty()} instead
+     */
+
+    @Deprecated
+    @Override
+    public void requestRepaint() {
+        markAsDirty();
+    }
+
+    /**
+     * Requests that the CustomTable should be repainted as soon as possible.
+     * 
+     * Note that a {@code CustomTable} does not necessarily repaint its contents
+     * when this method has been called. See {@link #refreshRowCache()} for
+     * forcing an update of the contents.
+     */
+
+    @Override
+    public void markAsDirty() {
+        // Overridden only for javadoc
+        super.markAsDirty();
+    }
+
+    /* (non-Javadoc)
+     * @see com.vaadin.server.AbstractClientConnector#markAsDirtyRecursive()
+     */
+    @Override
+    public void markAsDirtyRecursive() {
+        super.markAsDirtyRecursive();
+
+        // Avoid sending a partial repaint (#8714)
+        refreshRowCache();
+    }
+
+    /** Removes the rows from cache and fill bottom.
+	 *
+	 * @param firstIndex
+	 *            the first index
+	 * @param rows
+	 *            the rows
+	 */
+    private void removeRowsFromCacheAndFillBottom(int firstIndex, int rows) {
+        int totalCachedRows = pageBuffer[CELL_ITEMID].length;
+        int totalRows = size();
+        int firstIndexInPageBuffer = firstIndex - pageBufferFirstIndex;
+
+        /*
+         * firstIndexInPageBuffer is the first row to be removed. "rows" rows
+         * after that should be removed. If the page buffer does not contain
+         * that many rows, we only remove the rows that actually are in the page
+         * buffer.
+         */
+        if (firstIndexInPageBuffer + rows > totalCachedRows) {
+            rows = totalCachedRows - firstIndexInPageBuffer;
+        }
+
+        /*
+         * Unregister components that will no longer be in the page buffer to
+         * make sure that no components leak.
+         */
+        unregisterComponentsAndPropertiesInRows(firstIndex, rows);
+
+        /*
+         * The number of rows that should be in the cache after this operation
+         * is done (pageBuffer currently contains the expanded items).
+         */
+        int newCachedRowCount = totalCachedRows;
+        if (newCachedRowCount + pageBufferFirstIndex > totalRows) {
+            newCachedRowCount = totalRows - pageBufferFirstIndex;
+        }
+
+        /*
+         * The index at which we should render the first row that does not come
+         * from the previous page buffer.
+         */
+        int firstAppendedRowInPageBuffer = totalCachedRows - rows;
+        int firstAppendedRow = firstAppendedRowInPageBuffer
+                + pageBufferFirstIndex;
+
+        /*
+         * Calculate the maximum number of new rows that we can add to the page
+         * buffer. Less than the rows we removed if the container does not
+         * contain that many items afterwards.
+         */
+        int maxRowsToRender = (totalRows - firstAppendedRow);
+        int rowsToAdd = rows;
+        if (rowsToAdd > maxRowsToRender) {
+            rowsToAdd = maxRowsToRender;
+        }
+
+        Object[][] cells = null;
+        if (rowsToAdd > 0) {
+            cells = getVisibleCellsNoCache(firstAppendedRow, rowsToAdd, false);
+        }
+        /*
+         * Create the new cache buffer by copying the first rows from the old
+         * buffer, moving the following rows upwards and appending more rows if
+         * applicable.
+         */
+        Object[][] newPageBuffer = new Object[pageBuffer.length][newCachedRowCount];
+
+        for (int i = 0; i < pageBuffer.length; i++) {
+            for (int row = 0; row < firstIndexInPageBuffer; row++) {
+                // Copy the first rows
+                newPageBuffer[i][row] = pageBuffer[i][row];
+            }
+            for (int row = firstIndexInPageBuffer; row < firstAppendedRowInPageBuffer; row++) {
+                // Move the rows that were after the expanded rows
+                newPageBuffer[i][row] = pageBuffer[i][row + rows];
+            }
+            for (int row = firstAppendedRowInPageBuffer; row < newCachedRowCount; row++) {
+                // Add the newly rendered rows. Only used if rowsToAdd > 0
+                // (cells != null)
+                newPageBuffer[i][row] = cells[i][row
+                        - firstAppendedRowInPageBuffer];
+            }
+        }
+        pageBuffer = newPageBuffer;
+    }
+
+    /** Gets the visible cells update cache rows.
+	 *
+	 * @param firstIndex
+	 *            the first index
+	 * @param rows
+	 *            the rows
+	 * @return the visible cells update cache rows
+	 */
+    private Object[][] getVisibleCellsUpdateCacheRows(int firstIndex, int rows) {
+        Object[][] cells = getVisibleCellsNoCache(firstIndex, rows, false);
+        int cacheIx = firstIndex - pageBufferFirstIndex;
+        // update the new rows in the cache.
+        int totalCachedRows = pageBuffer[CELL_ITEMID].length;
+        int end = Math.min(cacheIx + rows, totalCachedRows);
+        for (int ix = cacheIx; ix < end; ix++) {
+            for (int i = 0; i < pageBuffer.length; i++) {
+                pageBuffer[i][ix] = cells[i][ix - cacheIx];
+            }
+        }
+        return cells;
+    }
+
+    /** Gets the visible cells insert into cache.
+	 *
+	 * @param firstIndex
+	 *            The position where new rows should be inserted
+	 * @param rows
+	 *            The maximum number of rows that should be inserted at position
+	 *            firstIndex. Less rows will be inserted if the page buffer is
+	 *            too small.
+	 * @return the visible cells insert into cache
+	 */
+    private Object[][] getVisibleCellsInsertIntoCache(int firstIndex, int rows) {
+        getLogger()
+                .log(Level.FINEST,
+                        "Insert {0} rows at index {1} to existing page buffer requested",
+                        new Object[] { rows, firstIndex });
+
+        int minPageBufferIndex = getMinPageBufferIndex();
+        int maxPageBufferIndex = getMaxPageBufferIndex();
+
+        int maxBufferSize = maxPageBufferIndex - minPageBufferIndex + 1;
+
+        if (getPageLength() == 0) {
+            // If pageLength == 0 then all rows should be rendered
+            maxBufferSize = pageBuffer[CELL_ITEMID].length + rows;
+        }
+        /*
+         * Number of rows that were previously cached. This is not necessarily
+         * the same as maxBufferSize.
+         */
+        int currentlyCachedRowCount = pageBuffer[CELL_ITEMID].length;
+
+        /* If rows > size available in page buffer */
+        if (firstIndex + rows - 1 > maxPageBufferIndex) {
+            rows = maxPageBufferIndex - firstIndex + 1;
+        }
+
+        /*
+         * "rows" rows will be inserted at firstIndex. Find out how many old
+         * rows fall outside the new buffer so we can unregister components in
+         * the cache.
+         */
+
+        /*
+         * if there are rows before the new pageBuffer limits they must be
+         * removed
+         */
+        int lastCacheRowToRemove = minPageBufferIndex - 1;
+        int rowsFromBeginning = lastCacheRowToRemove - pageBufferFirstIndex + 1;
+        if (lastCacheRowToRemove >= pageBufferFirstIndex) {
+            unregisterComponentsAndPropertiesInRows(pageBufferFirstIndex,
+                    rowsFromBeginning);
+        } else {
+            rowsFromBeginning = 0;
+        }
+
+        /*
+         * the rows that fall outside of the new pageBuffer limits after the new
+         * rows are inserted must also be removed
+         */
+        int firstCacheRowToRemove = firstIndex;
+        /*
+         * IF there is space remaining in the buffer after the rows have been
+         * inserted, we can keep more rows.
+         */
+        int numberOfOldRowsAfterInsertedRows = Math.min(pageBufferFirstIndex
+                + currentlyCachedRowCount + rows, maxPageBufferIndex + 1)
+                - (firstIndex + rows - 1);
+        if (numberOfOldRowsAfterInsertedRows > 0) {
+            firstCacheRowToRemove += numberOfOldRowsAfterInsertedRows;
+        }
+        int rowsFromAfter = currentlyCachedRowCount
+                - (firstCacheRowToRemove - pageBufferFirstIndex);
+
+        if (rowsFromAfter > 0) {
+            /*
+             * Unregister all components that fall beyond the cache limits after
+             * inserting the new rows.
+             */
+            unregisterComponentsAndPropertiesInRows(firstCacheRowToRemove,
+                    rowsFromAfter);
+        }
+
+        // Calculate the new cache size
+        int newCachedRowCount = maxBufferSize;
+        if (pageBufferFirstIndex + currentlyCachedRowCount + rows - 1 < maxPageBufferIndex) {
+            // there aren't enough rows to fill the whole potential -> use what
+            // there is
+            newCachedRowCount -= maxPageBufferIndex
+                    - (pageBufferFirstIndex + currentlyCachedRowCount + rows - 1);
+        } else if (minPageBufferIndex < pageBufferFirstIndex) {
+            newCachedRowCount -= pageBufferFirstIndex - minPageBufferIndex;
+        }
+        /* calculate the internal location of the new rows within the new cache */
+        int firstIndexInNewPageBuffer = firstIndex - pageBufferFirstIndex
+                - rowsFromBeginning;
+
+        /* Paint the new rows into a separate buffer */
+        Object[][] cells = getVisibleCellsNoCache(firstIndex, rows, false);
+
+        /*
+         * Create the new cache buffer and fill it with the data from the old
+         * buffer as well as the inserted rows.
+         */
+        Object[][] newPageBuffer = new Object[pageBuffer.length][newCachedRowCount];
+
+        for (int i = 0; i < pageBuffer.length; i++) {
+            for (int row = 0; row < firstIndexInNewPageBuffer; row++) {
+                // Copy the first rows
+                newPageBuffer[i][row] = pageBuffer[i][rowsFromBeginning + row];
+            }
+            for (int row = firstIndexInNewPageBuffer; row < firstIndexInNewPageBuffer
+                    + rows; row++) {
+                // Copy the newly created rows
+                newPageBuffer[i][row] = cells[i][row
+                        - firstIndexInNewPageBuffer];
+            }
+            for (int row = firstIndexInNewPageBuffer + rows; row < newCachedRowCount; row++) {
+                // Move the old rows down below the newly inserted rows
+                newPageBuffer[i][row] = pageBuffer[i][rowsFromBeginning + row
+                        - rows];
+            }
+        }
+        pageBuffer = newPageBuffer;
+        pageBufferFirstIndex = Math.max(pageBufferFirstIndex
+                + rowsFromBeginning, minPageBufferIndex);
+        if (getLogger().isLoggable(Level.FINEST)) {
+            getLogger().log(
+                    Level.FINEST,
+                    "Page Buffer now contains {0} rows ({1}-{2})",
+                    new Object[] {
+                            pageBuffer[CELL_ITEMID].length,
+                            pageBufferFirstIndex,
+                            (pageBufferFirstIndex
+                                    + pageBuffer[CELL_ITEMID].length - 1) });
+        }
+        return cells;
+    }
+
+    /** Gets the max page buffer index.
+	 *
+	 * @return the max page buffer index
+	 */
+    private int getMaxPageBufferIndex() {
+        int total = size();
+        if (getPageLength() == 0) {
+            // everything is shown at once, no caching
+            return total - 1;
+        }
+        // Page buffer must not become larger than pageLength*cacheRate after
+        // the current page
+        int maxPageBufferIndex = getCurrentPageFirstItemIndex()
+                + (int) (getPageLength() * (1 + getCacheRate()));
+        if (shouldHideNullSelectionItem()) {
+            --total;
+        }
+        if (maxPageBufferIndex >= total) {
+            maxPageBufferIndex = total - 1;
+        }
+        return maxPageBufferIndex;
+    }
+
+    /** Gets the min page buffer index.
+	 *
+	 * @return the min page buffer index
+	 */
+    private int getMinPageBufferIndex() {
+        if (getPageLength() == 0) {
+            // everything is shown at once, no caching
+            return 0;
+        }
+        // Page buffer must not become larger than pageLength*cacheRate before
+        // the current page
+        int minPageBufferIndex = getCurrentPageFirstItemIndex()
+                - (int) (getPageLength() * getCacheRate());
+        if (minPageBufferIndex < 0) {
+            minPageBufferIndex = 0;
+        }
+        return minPageBufferIndex;
+    }
+
+    /** Render rows with index "firstIndex" to "firstIndex+rows-1" to a new
+	 * buffer.
+	 * 
+	 * Reuses values from the current page buffer if the rows are found there.
+	 *
+	 * @param firstIndex
+	 *            the first index
+	 * @param rows
+	 *            the rows
+	 * @param replaceListeners
+	 *            the replace listeners
+	 * @return the visible cells no cache
+	 */
+    private Object[][] getVisibleCellsNoCache(int firstIndex, int rows,
+            boolean replaceListeners) {
+        if (getLogger().isLoggable(Level.FINEST)) {
+            getLogger().log(Level.FINEST,
+                    "Render visible cells for rows {0}-{1}",
+                    new Object[] { firstIndex, (firstIndex + rows - 1) });
+        }
+        final Object[] colids = getVisibleColumns();
+        final int cols = colids.length;
+
+        HashSet<Property<?>> oldListenedProperties = listenedProperties;
+        HashSet<Component> oldVisibleComponents = visibleComponents;
+
+        if (replaceListeners) {
+            // initialize the listener collections, this should only be done if
+            // the entire cache is refreshed (through refreshRenderedCells)
+            listenedProperties = new HashSet<Property<?>>();
+            visibleComponents = new HashSet<Component>();
+        }
+
+        Object[][] cells = new Object[cols + CELL_FIRSTCOL][rows];
+        if (rows == 0) {
+            unregisterPropertiesAndComponents(oldListenedProperties,
+                    oldVisibleComponents);
+            return cells;
+        }
+
+        final RowHeaderMode headmode = getRowHeaderMode();
+        final boolean[] iscomponent = new boolean[cols];
+        for (int i = 0; i < cols; i++) {
+            iscomponent[i] = columnGenerators.containsKey(colids[i])
+                    || Component.class.isAssignableFrom(getType(colids[i]));
+        }
+        int firstIndexNotInCache;
+        if (pageBuffer != null && pageBuffer[CELL_ITEMID].length > 0) {
+            firstIndexNotInCache = pageBufferFirstIndex
+                    + pageBuffer[CELL_ITEMID].length;
+        } else {
+            firstIndexNotInCache = -1;
+        }
+
+        // Creates the page contents
+        int filledRows = 0;
+        if (items instanceof Container.Indexed) {
+            // more efficient implementation for containers supporting access by
+            // index
+
+            List<?> itemIds = getItemIds(firstIndex, rows);
+            for (int i = 0; i < rows && i < itemIds.size(); i++) {
+                Object id = itemIds.get(i);
+                // Start by parsing the values, id should already be set
+                parseItemIdToCells(cells, id, i, firstIndex, headmode, cols,
+                        colids, firstIndexNotInCache, iscomponent,
+                        oldListenedProperties);
+
+                filledRows++;
+            }
+        } else {
+            // slow back-up implementation for cases where the container does
+            // not support access by index
+
+            // Gets the first item id
+            Object id = firstItemId();
+            for (int i = 0; i < firstIndex; i++) {
+                id = nextItemId(id);
+            }
+            for (int i = 0; i < rows && id != null; i++) {
+                // Start by parsing the values, id should already be set
+                parseItemIdToCells(cells, id, i, firstIndex, headmode, cols,
+                        colids, firstIndexNotInCache, iscomponent,
+                        oldListenedProperties);
+
+                // Gets the next item id for non indexed container
+                id = nextItemId(id);
+
+                filledRows++;
+            }
+        }
+
+        // Assures that all the rows of the cell-buffer are valid
+        if (filledRows != cells[0].length) {
+            final Object[][] temp = new Object[cells.length][filledRows];
+            for (int i = 0; i < cells.length; i++) {
+                for (int j = 0; j < filledRows; j++) {
+                    temp[i][j] = cells[i][j];
+                }
+            }
+            cells = temp;
+        }
+
+        unregisterPropertiesAndComponents(oldListenedProperties,
+                oldVisibleComponents);
+
+        return cells;
+    }
+
+    /** Gets the item ids.
+	 *
+	 * @param firstIndex
+	 *            the first index
+	 * @param rows
+	 *            the rows
+	 * @return the item ids
+	 */
+    protected List<Object> getItemIds(int firstIndex, int rows) {
+        return (List<Object>) ((Container.Indexed) items).getItemIds(
+                firstIndex, rows);
+    }
+
+    /** Update a cache array for a row, register any relevant listeners etc.
+	 * 
+	 * This is an internal method extracted from
+	 * {@link #getVisibleCellsNoCache(int, int, boolean)} and should be removed
+	 * when the CustomTable is rewritten.
+	 *
+	 * @param cells
+	 *            the cells
+	 * @param id
+	 *            the id
+	 * @param i
+	 *            the i
+	 * @param firstIndex
+	 *            the first index
+	 * @param headmode
+	 *            the headmode
+	 * @param cols
+	 *            the cols
+	 * @param colids
+	 *            the colids
+	 * @param firstIndexNotInCache
+	 *            the first index not in cache
+	 * @param iscomponent
+	 *            the iscomponent
+	 * @param oldListenedProperties
+	 *            the old listened properties
+	 */
+    private void parseItemIdToCells(Object[][] cells, Object id, int i,
+            int firstIndex, RowHeaderMode headmode, int cols, Object[] colids,
+            int firstIndexNotInCache, boolean[] iscomponent,
+            HashSet<Property<?>> oldListenedProperties) {
+
+        cells[CELL_ITEMID][i] = id;
+        cells[CELL_KEY][i] = itemIdMapper.key(id);
+        if (headmode != ROW_HEADER_MODE_HIDDEN) {
+            switch (headmode) {
+            case INDEX:
+                cells[CELL_HEADER][i] = String.valueOf(i + firstIndex + 1);
+                break;
+            default:
+                try {
+                    cells[CELL_HEADER][i] = getItemCaption(id);
+                } catch (Exception e) {
+                    exceptionsDuringCachePopulation.add(e);
+                    cells[CELL_HEADER][i] = "";
+                }
+            }
+            try {
+                cells[CELL_ICON][i] = getItemIcon(id);
+            } catch (Exception e) {
+                exceptionsDuringCachePopulation.add(e);
+                cells[CELL_ICON][i] = null;
+            }
+        }
+
+        GeneratedRow generatedRow = rowGenerator != null ? rowGenerator
+                .generateRow(this, id) : null;
+        cells[CELL_GENERATED_ROW][i] = generatedRow;
+
+        for (int j = 0; j < cols; j++) {
+            if (isColumnCollapsed(colids[j])) {
+                continue;
+            }
+            Property<?> p = null;
+            Object value = "";
+            boolean isGeneratedRow = generatedRow != null;
+            boolean isGeneratedColumn = columnGenerators.containsKey(colids[j]);
+            boolean isGenerated = isGeneratedRow || isGeneratedColumn;
+
+            if (!isGenerated) {
+                try {
+                    p = getContainerProperty(id, colids[j]);
+                } catch (Exception e) {
+                    exceptionsDuringCachePopulation.add(e);
+                    value = null;
+                }
+            }
+
+            if (isGeneratedRow) {
+                if (generatedRow.isSpanColumns() && j > 0) {
+                    value = null;
+                } else if (generatedRow.isSpanColumns() && j == 0
+                        && generatedRow.getValue() instanceof Component) {
+                    value = generatedRow.getValue();
+                } else if (generatedRow.getText().length > j) {
+                    value = generatedRow.getText()[j];
+                }
+            } else {
+                // check if current pageBuffer already has row
+                int index = firstIndex + i;
+                if (p != null || isGenerated) {
+                    int indexInOldBuffer = index - pageBufferFirstIndex;
+                    if (index < firstIndexNotInCache
+                            && index >= pageBufferFirstIndex
+                            && pageBuffer[CELL_GENERATED_ROW][indexInOldBuffer] == null
+                            && id.equals(pageBuffer[CELL_ITEMID][indexInOldBuffer])) {
+                        // we already have data in our cache,
+                        // recycle it instead of fetching it via
+                        // getValue/getPropertyValue
+                        value = pageBuffer[CELL_FIRSTCOL + j][indexInOldBuffer];
+                        if (!isGeneratedColumn && iscomponent[j]
+                                || !(value instanceof Component)) {
+                            listenProperty(p, oldListenedProperties);
+                        }
+                    } else {
+                        if (isGeneratedColumn) {
+                            ColumnGenerator cg = columnGenerators
+                                    .get(colids[j]);
+                            try {
+                                value = cg.generateCell(this, id, colids[j]);
+                            } catch (Exception e) {
+                                exceptionsDuringCachePopulation.add(e);
+                                value = null;
+                            }
+                            if (value != null && !(value instanceof Component)
+                                    && !(value instanceof String)) {
+                                // Avoid errors if a generator returns
+                                // something
+                                // other than a Component or a String
+                                value = value.toString();
+                            }
+                        } else if (iscomponent[j]) {
+                            try {
+                                value = p.getValue();
+                            } catch (Exception e) {
+                                exceptionsDuringCachePopulation.add(e);
+                                value = null;
+                            }
+                            listenProperty(p, oldListenedProperties);
+                        } else if (p != null) {
+                            try {
+                                value = getPropertyValue(id, colids[j], p);
+                            } catch (Exception e) {
+                                exceptionsDuringCachePopulation.add(e);
+                                value = null;
+                            }
+                            /*
+                             * If returned value is Component (via fieldfactory
+                             * or overridden getPropertyValue) we expect it to
+                             * listen property value changes. Otherwise if
+                             * property emits value change events, table will
+                             * start to listen them and refresh content when
+                             * needed.
+                             */
+                            if (!(value instanceof Component)) {
+                                listenProperty(p, oldListenedProperties);
+                            }
+                        } else {
+                            try {
+                                value = getPropertyValue(id, colids[j], null);
+                            } catch (Exception e) {
+                                exceptionsDuringCachePopulation.add(e);
+                                value = null;
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (value instanceof Component) {
+                registerComponent((Component) value);
+            }
+            cells[CELL_FIRSTCOL + j][i] = value;
+        }
+    }
+
+    /** Register component.
+	 *
+	 * @param component
+	 *            the component
+	 */
+    protected void registerComponent(Component component) {
+        getLogger().log(
+                Level.FINEST,
+                "Registered {0}: {1}",
+                new Object[] { component.getClass().getSimpleName(),
+                        component.getCaption() });
+        if (!equals(component.getParent())) {
+            component.setParent(this);
+        }
+        visibleComponents.add(component);
+    }
+
+    /** Listen property.
+	 *
+	 * @param p
+	 *            the p
+	 * @param oldListenedProperties
+	 *            the old listened properties
+	 */
+    private void listenProperty(Property<?> p,
+            HashSet<Property<?>> oldListenedProperties) {
+        if (p instanceof Property.ValueChangeNotifier) {
+            if (oldListenedProperties == null
+                    || !oldListenedProperties.contains(p)) {
+                ((Property.ValueChangeNotifier) p).addListener(this);
+            }
+            /*
+             * register listened properties, so we can do proper cleanup to free
+             * memory. Essential if table has loads of data and it is used for a
+             * long time.
+             */
+            listenedProperties.add(p);
+
+        }
+    }
+
+    /** Unregister components and properties in rows.
+	 *
+	 * @param firstIx
+	 *            Index of the first row to process. Global index, not relative
+	 *            to page buffer.
+	 * @param count
+	 *            the count
+	 */
+    private void unregisterComponentsAndPropertiesInRows(int firstIx, int count) {
+        if (getLogger().isLoggable(Level.FINEST)) {
+            getLogger().log(Level.FINEST,
+                    "Unregistering components in rows {0}-{1}",
+                    new Object[] { firstIx, (firstIx + count - 1) });
+        }
+        Object[] colids = getVisibleColumns();
+        if (pageBuffer != null && pageBuffer[CELL_ITEMID].length > 0) {
+            int bufSize = pageBuffer[CELL_ITEMID].length;
+            int ix = firstIx - pageBufferFirstIndex;
+            ix = ix < 0 ? 0 : ix;
+            if (ix < bufSize) {
+                count = count > bufSize - ix ? bufSize - ix : count;
+                for (int i = 0; i < count; i++) {
+                    for (int c = 0; c < colids.length; c++) {
+                        Object cellVal = pageBuffer[CELL_FIRSTCOL + c][i + ix];
+                        if (cellVal instanceof Component
+                                && visibleComponents.contains(cellVal)) {
+                            visibleComponents.remove(cellVal);
+                            unregisterComponent((Component) cellVal);
+                        } else {
+                            Property<?> p = getContainerProperty(
+                                    pageBuffer[CELL_ITEMID][i + ix], colids[c]);
+                            if (p instanceof ValueChangeNotifier
+                                    && listenedProperties.contains(p)) {
+                                listenedProperties.remove(p);
+                                ((ValueChangeNotifier) p).removeListener(this);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Helper method to remove listeners and maintain correct component
+     * hierarchy. Detaches properties and components if those are no more
+     * rendered in client.
+     * 
+     * @param oldListenedProperties
+     *            set of properties that where listened in last render
+     * @param oldVisibleComponents
+     *            set of components that where attached in last render
+     */
+    private void unregisterPropertiesAndComponents(
+            HashSet<Property<?>> oldListenedProperties,
+            HashSet<Component> oldVisibleComponents) {
+        if (oldVisibleComponents != null) {
+            for (final Iterator<Component> i = oldVisibleComponents.iterator(); i
+                    .hasNext();) {
+                Component c = i.next();
+                if (!visibleComponents.contains(c)) {
+                    unregisterComponent(c);
+                }
+            }
+        }
+
+        if (oldListenedProperties != null) {
+            for (final Iterator<Property<?>> i = oldListenedProperties
+                    .iterator(); i.hasNext();) {
+                Property.ValueChangeNotifier o = (ValueChangeNotifier) i.next();
+                if (!listenedProperties.contains(o)) {
+                    o.removeListener(this);
+                }
+            }
+        }
+    }
+
+    /** This method cleans up a Component that has been generated when
+	 * CustomTable is in editable mode. The component needs to be detached from
+	 * its parent and if it is a field, it needs to be detached from its
+	 * property data source in order to allow garbage collection to take care of
+	 * removing the unused component from memory.
+	 * 
+	 * Override this method and getPropertyValue(Object, Object, Property) with
+	 * custom logic if you need to deal with buffered fields.
+	 *
+	 * @param component
+	 *            the component
+	 * @see #getPropertyValue(Object, Object, Property)
+	 */
+    protected void unregisterComponent(Component component) {
+        getLogger().log(
+                Level.FINEST,
+                "Unregistered {0}: {1}",
+                new Object[] { component.getClass().getSimpleName(),
+                        component.getCaption() });
+        component.setParent(null);
+        /*
+         * Also remove property data sources to unregister listeners keeping the
+         * fields in memory.
+         */
+        if (component instanceof Field) {
+            Field<?> field = (Field<?>) component;
+            Property<?> associatedProperty = associatedProperties
+                    .remove(component);
+            if (associatedProperty != null
+                    && field.getPropertyDataSource() == associatedProperty) {
+                // Remove the property data source only if it's the one we
+                // added in getPropertyValue
+                field.setPropertyDataSource(null);
+            }
+        }
+    }
+
+    /**
+     * Sets the row header mode.
+     * <p>
+     * The mode can be one of the following ones:
+     * <ul>
+     * <li>{@link #ROW_HEADER_MODE_HIDDEN}: The row captions are hidden.</li>
+     * <li>{@link #ROW_HEADER_MODE_ID}: Items Id-objects <code>toString()</code>
+     * is used as row caption.
+     * <li>{@link #ROW_HEADER_MODE_ITEM}: Item-objects <code>toString()</code>
+     * is used as row caption.
+     * <li>{@link #ROW_HEADER_MODE_PROPERTY}: Property set with
+     * {@link #setItemCaptionPropertyId(Object)} is used as row header.
+     * <li>{@link #ROW_HEADER_MODE_EXPLICIT_DEFAULTS_ID}: Items Id-objects
+     * <code>toString()</code> is used as row header. If caption is explicitly
+     * specified, it overrides the id-caption.
+     * <li>{@link #ROW_HEADER_MODE_EXPLICIT}: The row headers must be explicitly
+     * specified.</li>
+     * <li>{@link #ROW_HEADER_MODE_INDEX}: The index of the item is used as row
+     * caption. The index mode can only be used with the containers implementing
+     * <code>Container.Indexed</code> interface.</li>
+     * </ul>
+     * The default value is {@link #ROW_HEADER_MODE_HIDDEN}
+     * 
+     * 
+     * @param mode
+     *            the One of the modes listed above.
+     */
+    public void setRowHeaderMode(RowHeaderMode mode) {
+        if (mode != null) {
+            rowHeaderMode = mode;
+            if (mode != RowHeaderMode.HIDDEN) {
+                setItemCaptionMode(mode.getItemCaptionMode());
+            }
+            // Assures the visual refresh. No need to reset the page buffer
+            // before
+            // as the content has not changed, only the alignments.
+            refreshRenderedCells();
+        }
+    }
+
+    /**
+     * Gets the row header mode.
+     * 
+     * @return the Row header mode.
+     * @see #setRowHeaderMode
+     */
+    public RowHeaderMode getRowHeaderMode() {
+        return rowHeaderMode;
+    }
+
+    /** Adds the new row to table and fill the visible cells (except
+	 * generated columns) with given values.
+	 *
+	 * @param cells
+	 *            the Object array that is used for filling the visible cells
+	 *            new row. The types must be settable to visible column property
+	 *            types.
+	 * @param itemId
+	 *            the Id the new row. If null, a new id is automatically
+	 *            assigned. If given, the table cant already have a item with
+	 *            given id.
+	 * @return Returns item id for the new row. Returns null if operation fails.
+	 * @throws UnsupportedOperationException
+	 *             the unsupported operation exception
+	 */
+    public Object addItem(Object[] cells, Object itemId)
+            throws UnsupportedOperationException {
+
+        // remove generated columns from the list of columns being assigned
+        final LinkedList<Object> availableCols = new LinkedList<Object>();
+        for (Iterator<Object> it = visibleColumns.iterator(); it.hasNext();) {
+            Object id = it.next();
+            if (!columnGenerators.containsKey(id)) {
+                availableCols.add(id);
+            }
+        }
+        // Checks that a correct number of cells are given
+        if (cells.length != availableCols.size()) {
+            return null;
+        }
+
+        // Creates new item
+        Item item;
+        if (itemId == null) {
+            itemId = items.addItem();
+            if (itemId == null) {
+                return null;
+            }
+            item = items.getItem(itemId);
+        } else {
+            item = items.addItem(itemId);
+        }
+        if (item == null) {
+            return null;
+        }
+
+        // Fills the item properties
+        for (int i = 0; i < availableCols.size(); i++) {
+            item.getItemProperty(availableCols.get(i)).setValue(cells[i]);
+        }
+
+        if (!(items instanceof Container.ItemSetChangeNotifier)) {
+            refreshRowCache();
+        }
+
+        return itemId;
+    }
+
+    /**
+     * Discards and recreates the internal row cache. Call this if you make
+     * changes that affect the rows but the information about the changes are
+     * not automatically propagated to the CustomTable.
+     * <p>
+     * Do not call this e.g. if you have updated the data model through a
+     * Property. These types of changes are automatically propagated to the
+     * CustomTable.
+     * <p>
+     * A typical case when this is needed is if you update a generator (e.g.
+     * CellStyleGenerator) and want to ensure that the rows are redrawn with new
+     * styles.
+     * <p>
+     * <i>Note that calling this method is not cheap so avoid calling it
+     * unnecessarily.</i>
+     * 
+     * @since 6.7.2
+     */
+    public void refreshRowCache() {
+        resetPageBuffer();
+        refreshRenderedCells();
+    }
+
+    /**
+     * Sets the Container that serves as the data source of the viewer. As a
+     * side-effect the table's selection value is set to null as the old
+     * selection might not exist in new Container.<br>
+     * <br>
+     * All rows and columns are generated as visible using this method. If the
+     * new container contains properties that are not meant to be shown you
+     * should use
+     * {@link CustomTable#setContainerDataSource(Container, Collection)}
+     * instead, especially if the table is editable.
+     * <p>
+     * Keeps propertyValueConverters if the corresponding id exists in the new
+     * data source and is of a compatible type.
+     * 
+     * 
+     * @param newDataSource
+     *            the new data source.
+     */
+    @Override
+    public void setContainerDataSource(Container newDataSource) {
+        if (newDataSource == null) {
+            newDataSource = new IndexedContainer();
+        }
+        Collection<Object> generated;
+        if (columnGenerators != null) {
+            generated = columnGenerators.keySet();
+        } else {
+            generated = Collections.emptyList();
+        }
+        List<Object> visibleIds = new ArrayList<Object>();
+        if (generated.isEmpty()) {
+            visibleIds.addAll(newDataSource.getContainerPropertyIds());
+        } else {
+            for (Object id : newDataSource.getContainerPropertyIds()) {
+                // don't add duplicates
+                if (!generated.contains(id)) {
+                    visibleIds.add(id);
+                }
+            }
+            // generated columns to the end
+            visibleIds.addAll(generated);
+        }
+        setContainerDataSource(newDataSource, visibleIds);
+    }
+
+    /** Sets the container data source and the columns that will be visible.
+	 * Columns are shown in the collection's iteration order.
+	 * <p>
+	 * Keeps propertyValueConverters if the corresponding id exists in the new
+	 * data source and is of a compatible type.
+	 *
+	 * @param newDataSource
+	 *            the new data source.
+	 * @param visibleIds
+	 *            IDs of the visible columns
+	 * @see CustomTable#setContainerDataSource(Container)
+	 * @see CustomTable#setVisibleColumns(Object[])
+	 * @see CustomTable#setConverter(Object, Converter)
+	 */
+    public void setContainerDataSource(Container newDataSource,
+            Collection<?> visibleIds) {
+
+        disableContentRefreshing();
+
+        if (newDataSource == null) {
+            newDataSource = new IndexedContainer();
+        }
+        if (visibleIds == null) {
+            visibleIds = new ArrayList<Object>();
+        }
+
+        // Retain propertyValueConverters if their corresponding ids are
+        // properties of the new
+        // data source and are of a compatible type
+        if (propertyValueConverters != null) {
+            Collection<?> newPropertyIds = newDataSource
+                    .getContainerPropertyIds();
+            LinkedList<Object> retainableValueConverters = new LinkedList<Object>();
+            for (Object propertyId : newPropertyIds) {
+                Converter<String, ?> converter = getConverter(propertyId);
+                if (converter != null) {
+                    if (typeIsCompatible(converter.getModelType(),
+                            newDataSource.getType(propertyId))) {
+                        retainableValueConverters.add(propertyId);
+                    }
+                }
+            }
+            propertyValueConverters.keySet().retainAll(
+                    retainableValueConverters);
+        }
+
+        // Assures that the data source is ordered by making unordered
+        // containers ordered by wrapping them
+        if (newDataSource instanceof Container.Ordered) {
+            super.setContainerDataSource(newDataSource);
+        } else {
+            super.setContainerDataSource(new ContainerOrderedWrapper(
+                    newDataSource));
+        }
+
+        // Resets page position
+        currentPageFirstItemId = null;
+        currentPageFirstItemIndex = 0;
+
+        // Resets column properties
+        if (collapsedColumns != null) {
+            collapsedColumns.clear();
+        }
+
+        // don't add the same id twice
+        Collection<Object> col = new LinkedList<Object>();
+        for (Iterator<?> it = visibleIds.iterator(); it.hasNext();) {
+            Object id = it.next();
+            if (!col.contains(id)) {
+                col.add(id);
+            }
+        }
+
+        setVisibleColumns(col.toArray());
+
+        // Assure visual refresh
+        resetPageBuffer();
+
+        enableContentRefreshing(true);
+    }
+
+    /** Checks if class b can be safely assigned to class a.
+	 *
+	 * @param a
+	 *            the a
+	 * @param b
+	 *            the b
+	 * @return true, if successful
+	 */
+    private boolean typeIsCompatible(Class<?> a, Class<?> b) {
+        // TODO Implement this check properly
+        // Basically we need to do a a.isAssignableFrom(b)
+        // with special considerations for primitive types.
+        return true;
+    }
+
+    /** Gets items ids from a range of key values.
+	 *
+	 * @param itemId
+	 *            the item id
+	 * @param length
+	 *            the length
+	 * @return the item ids in range
+	 */
+    private LinkedHashSet<Object> getItemIdsInRange(Object itemId,
+            final int length) {
+        LinkedHashSet<Object> ids = new LinkedHashSet<Object>();
+        for (int i = 0; i < length; i++) {
+            assert itemId != null; // should not be null unless client-server
+                                   // are out of sync
+            ids.add(itemId);
+            itemId = nextItemId(itemId);
+        }
+        return ids;
+    }
+
+    /** Handles selection if selection is a multiselection.
+	 *
+	 * @param variables
+	 *            The variables
+	 */
+    private void handleSelectedItems(Map<String, Object> variables) {
+        final String[] ka = (String[]) variables.get("selected");
+        final String[] ranges = (String[]) variables.get("selectedRanges");
+
+        Set<Object> renderedButNotSelectedItemIds = getCurrentlyRenderedItemIds();
+
+        @SuppressWarnings("unchecked")
+        HashSet<Object> newValue = new LinkedHashSet<Object>(
+                (Collection<Object>) getValue());
+
+        if (variables.containsKey("clearSelections")) {
+            // the client side has instructed to swipe all previous selections
+            newValue.clear();
+        }
+
+        /*
+         * Then add (possibly some of them back) rows that are currently
+         * selected on the client side (the ones that the client side is aware
+         * of).
+         */
+        for (int i = 0; i < ka.length; i++) {
+            // key to id
+            final Object id = itemIdMapper.get(ka[i]);
+            if (!isNullSelectionAllowed()
+                    && (id == null || id == getNullSelectionItemId())) {
+                // skip empty selection if nullselection is not allowed
+                markAsDirty();
+            } else if (id != null && containsId(id)) {
+                newValue.add(id);
+                renderedButNotSelectedItemIds.remove(id);
+            }
+        }
+
+        /* Add range items aka shift clicked multiselection areas */
+        if (ranges != null) {
+            for (String range : ranges) {
+                String[] split = range.split("-");
+                Object startItemId = itemIdMapper.get(split[0]);
+                int length = Integer.valueOf(split[1]);
+                LinkedHashSet<Object> itemIdsInRange = getItemIdsInRange(
+                        startItemId, length);
+                newValue.addAll(itemIdsInRange);
+                renderedButNotSelectedItemIds.removeAll(itemIdsInRange);
+            }
+        }
+        /*
+         * finally clear all currently rendered rows (the ones that the client
+         * side counterpart is aware of) that the client didn't send as selected
+         */
+        newValue.removeAll(renderedButNotSelectedItemIds);
+
+        if (!isNullSelectionAllowed() && newValue.isEmpty()) {
+            // empty selection not allowed, keep old value
+            markAsDirty();
+            return;
+        }
+
+        setValue(newValue, true);
+
+    }
+
+    /** Gets the currently rendered item ids.
+	 *
+	 * @return the currently rendered item ids
+	 */
+    private Set<Object> getCurrentlyRenderedItemIds() {
+        HashSet<Object> ids = new HashSet<Object>();
+        if (pageBuffer != null) {
+            for (int i = 0; i < pageBuffer[CELL_ITEMID].length; i++) {
+                ids.add(pageBuffer[CELL_ITEMID][i]);
+            }
+        }
+        return ids;
+    }
+
+    /* Component basics */
+
+    /** Invoked when the value of a variable has changed.
+	 *
+	 * @param source
+	 *            the source
+	 * @param variables
+	 *            the variables
+	 * @see com.vaadin.ui.Select#changeVariables(java.lang.Object,
+	 *      java.util.Map)
+	 */
+
+    @Override
+    public void changeVariables(Object source, Map<String, Object> variables) {
+
+        boolean clientNeedsContentRefresh = false;
+
+        handleClickEvent(variables);
+
+        handleColumnResizeEvent(variables);
+
+        handleColumnWidthUpdates(variables);
+
+        disableContentRefreshing();
+
+        if (!isSelectable() && variables.containsKey("selected")) {
+            // Not-selectable is a special case, AbstractSelect does not support
+            // TODO could be optimized.
+            variables = new HashMap<String, Object>(variables);
+            variables.remove("selected");
+        }
+
+        /*
+         * The AbstractSelect cannot handle the multiselection properly, instead
+         * we handle it ourself
+         */
+        else if (isSelectable() && isMultiSelect()
+                && variables.containsKey("selected")
+                && multiSelectMode == MultiSelectMode.DEFAULT) {
+            handleSelectedItems(variables);
+            variables = new HashMap<String, Object>(variables);
+            variables.remove("selected");
+        }
+
+        super.changeVariables(source, variables);
+
+        // Client might update the pagelength if CustomTable height is fixed
+        if (variables.containsKey("pagelength")) {
+            // Sets pageLength directly to avoid repaint that setter causes
+            pageLength = (Integer) variables.get("pagelength");
+        }
+
+        // Page start index
+        if (variables.containsKey("firstvisible")) {
+            final Integer value = (Integer) variables.get("firstvisible");
+            if (value != null) {
+                setCurrentPageFirstItemIndex(value.intValue(), false);
+            }
+        }
+
+        // Sets requested firstrow and rows for the next paint
+        if (variables.containsKey("reqfirstrow")
+                || variables.containsKey("reqrows")) {
+
+            try {
+                firstToBeRenderedInClient = ((Integer) variables
+                        .get("firstToBeRendered")).intValue();
+                lastToBeRenderedInClient = ((Integer) variables
+                        .get("lastToBeRendered")).intValue();
+            } catch (Exception e) {
+                // FIXME: Handle exception
+                getLogger().log(Level.FINER,
+                        "Could not parse the first and/or last rows.", e);
+            }
+
+            // respect suggested rows only if table is not otherwise updated
+            // (row caches emptied by other event)
+            if (!containerChangeToBeRendered) {
+                Integer value = (Integer) variables.get("reqfirstrow");
+                if (value != null) {
+                    reqFirstRowToPaint = value.intValue();
+                }
+
+                value = (Integer) variables.get("reqrows");
+                if (value != null) {
+                    reqRowsToPaint = value.intValue();
+                    int size = size();
+                    // sanity check
+
+                    if (reqFirstRowToPaint >= size) {
+                        reqFirstRowToPaint = size;
+                    }
+
+                    if (reqFirstRowToPaint + reqRowsToPaint > size) {
+                        reqRowsToPaint = size - reqFirstRowToPaint;
+                    }
+                }
+            }
+            if (getLogger().isLoggable(Level.FINEST)) {
+                getLogger().log(
+                        Level.FINEST,
+                        "Client wants rows {0}-{1}",
+                        new Object[] { reqFirstRowToPaint,
+                                (reqFirstRowToPaint + reqRowsToPaint - 1) });
+            }
+            clientNeedsContentRefresh = true;
+        }
+
+        if (isSortEnabled()) {
+            // Sorting
+            boolean doSort = false;
+            if (variables.containsKey("sortcolumn")) {
+                final String colId = (String) variables.get("sortcolumn");
+                if (colId != null && !"".equals(colId) && !"null".equals(colId)) {
+                    final Object id = columnIdMap.get(colId);
+                    setSortContainerPropertyId(id, false);
+                    doSort = true;
+                }
+            }
+            if (variables.containsKey("sortascending")) {
+                final boolean state = ((Boolean) variables.get("sortascending"))
+                        .booleanValue();
+                if (state != sortAscending) {
+                    setSortAscending(state, false);
+                    doSort = true;
+                }
+            }
+            if (doSort) {
+                this.sort();
+                resetPageBuffer();
+            }
+        }
+
+        // Dynamic column hide/show and order
+        // Update visible columns
+        if (isColumnCollapsingAllowed()) {
+            if (variables.containsKey("collapsedcolumns")) {
+                try {
+                    final Object[] ids = (Object[]) variables
+                            .get("collapsedcolumns");
+                    Set<Object> idSet = new HashSet<Object>();
+                    for (Object id : ids) {
+                        idSet.add(columnIdMap.get(id.toString()));
+                    }
+                    for (final Iterator<Object> it = visibleColumns.iterator(); it
+                            .hasNext();) {
+                        Object propertyId = it.next();
+                        if (isColumnCollapsed(propertyId)) {
+                            if (!idSet.contains(propertyId)) {
+                                setColumnCollapsed(propertyId, false);
+                            }
+                        } else if (idSet.contains(propertyId)) {
+                            setColumnCollapsed(propertyId, true);
+                        }
+                    }
+                } catch (final Exception e) {
+                    // FIXME: Handle exception
+                    getLogger().log(Level.FINER,
+                            "Could not determine column collapsing state", e);
+                }
+                clientNeedsContentRefresh = true;
+            }
+        }
+        if (isColumnReorderingAllowed()) {
+            if (variables.containsKey("columnorder")) {
+                try {
+                    final Object[] ids = (Object[]) variables
+                            .get("columnorder");
+                    // need a real Object[], ids can be a String[]
+                    final Object[] idsTemp = new Object[ids.length];
+                    for (int i = 0; i < ids.length; i++) {
+                        idsTemp[i] = columnIdMap.get(ids[i].toString());
+                    }
+                    setColumnOrder(idsTemp);
+                    if (hasListeners(ColumnReorderEvent.class)) {
+                        fireEvent(new ColumnReorderEvent(this));
+                    }
+                } catch (final Exception e) {
+                    // FIXME: Handle exception
+                    getLogger().log(Level.FINER,
+                            "Could not determine column reordering state", e);
+                }
+                clientNeedsContentRefresh = true;
+            }
+        }
+
+        enableContentRefreshing(clientNeedsContentRefresh);
+
+        // Actions
+        if (variables.containsKey("action")) {
+            final StringTokenizer st = new StringTokenizer(
+                    (String) variables.get("action"), ",");
+            if (st.countTokens() == 2) {
+                final Object itemId = itemIdMapper.get(st.nextToken());
+                final Action action = actionMapper.get(st.nextToken());
+
+                if (action != null && (itemId == null || containsId(itemId))
+                        && actionHandlers != null) {
+                    for (Handler ah : actionHandlers) {
+                        ah.handleAction(action, this, itemId);
+                    }
+                }
+            }
+        }
+
+    }
+
+    /** Handles click event.
+	 *
+	 * @param variables
+	 *            the variables
+	 */
+    private void handleClickEvent(Map<String, Object> variables) {
+
+        // Item click event
+        if (variables.containsKey("clickEvent")) {
+            String key = (String) variables.get("clickedKey");
+            Object itemId = itemIdMapper.get(key);
+            Object propertyId = null;
+            String colkey = (String) variables.get("clickedColKey");
+            // click is not necessary on a property
+            if (colkey != null) {
+                propertyId = columnIdMap.get(colkey);
+            }
+            MouseEventDetails evt = MouseEventDetails
+                    .deSerialize((String) variables.get("clickEvent"));
+            Item item = getItem(itemId);
+            if (item != null) {
+                fireEvent(new ItemClickEvent(this, item, itemId, propertyId,
+                        evt));
+            }
+        }
+
+        // Header click event
+        else if (variables.containsKey("headerClickEvent")) {
+
+            MouseEventDetails details = MouseEventDetails
+                    .deSerialize((String) variables.get("headerClickEvent"));
+
+            Object cid = variables.get("headerClickCID");
+            Object propertyId = null;
+            if (cid != null) {
+                propertyId = columnIdMap.get(cid.toString());
+            }
+            fireEvent(new HeaderClickEvent(this, propertyId, details));
+        }
+
+        // Footer click event
+        else if (variables.containsKey("footerClickEvent")) {
+            MouseEventDetails details = MouseEventDetails
+                    .deSerialize((String) variables.get("footerClickEvent"));
+
+            Object cid = variables.get("footerClickCID");
+            Object propertyId = null;
+            if (cid != null) {
+                propertyId = columnIdMap.get(cid.toString());
+            }
+            fireEvent(new FooterClickEvent(this, propertyId, details));
+        }
+    }
+
+    /** Handles the column resize event sent by the client.
+	 *
+	 * @param variables
+	 *            the variables
+	 */
+    private void handleColumnResizeEvent(Map<String, Object> variables) {
+        if (variables.containsKey("columnResizeEventColumn")) {
+            Object cid = variables.get("columnResizeEventColumn");
+            Object propertyId = null;
+            if (cid != null) {
+                propertyId = columnIdMap.get(cid.toString());
+
+                Object prev = variables.get("columnResizeEventPrev");
+                int previousWidth = -1;
+                if (prev != null) {
+                    previousWidth = Integer.valueOf(prev.toString());
+                }
+
+                Object curr = variables.get("columnResizeEventCurr");
+                int currentWidth = -1;
+                if (curr != null) {
+                    currentWidth = Integer.valueOf(curr.toString());
+                }
+
+                fireColumnResizeEvent(propertyId, previousWidth, currentWidth);
+            }
+        }
+    }
+
+    /** Fire column resize event.
+	 *
+	 * @param propertyId
+	 *            the property id
+	 * @param previousWidth
+	 *            the previous width
+	 * @param currentWidth
+	 *            the current width
+	 */
+    private void fireColumnResizeEvent(Object propertyId, int previousWidth,
+            int currentWidth) {
+        /*
+         * Update the sizes on the server side. If a column previously had a
+         * expand ratio and the user resized the column then the expand ratio
+         * will be turned into a static pixel size.
+         */
+        setColumnWidth(propertyId, currentWidth);
+
+        fireEvent(new ColumnResizeEvent(this, propertyId, previousWidth,
+                currentWidth));
+    }
+
+    /** Handle column width updates.
+	 *
+	 * @param variables
+	 *            the variables
+	 */
+    private void handleColumnWidthUpdates(Map<String, Object> variables) {
+        if (variables.containsKey("columnWidthUpdates")) {
+            String[] events = (String[]) variables.get("columnWidthUpdates");
+            for (String str : events) {
+                String[] eventDetails = str.split(":");
+                Object propertyId = columnIdMap.get(eventDetails[0]);
+                if (propertyId == null) {
+                    propertyId = ROW_HEADER_FAKE_PROPERTY_ID;
+                }
+                int width = Integer.valueOf(eventDetails[1]);
+                setColumnWidth(propertyId, width);
+            }
+        }
+    }
+
+    /**
+     * Go to mode where content updates are not done. This is due we want to
+     * bypass expensive content for some reason (like when we know we may have
+     * other content changes on their way).
+     * 
+     * @return true if content refresh flag was enabled prior this call
+     */
+    protected boolean disableContentRefreshing() {
+        boolean wasDisabled = isContentRefreshesEnabled;
+        isContentRefreshesEnabled = false;
+        return wasDisabled;
+    }
+
+    /**
+     * Go to mode where content content refreshing has effect.
+     * 
+     * @param refreshContent
+     *            true if content refresh needs to be done
+     */
+    protected void enableContentRefreshing(boolean refreshContent) {
+        isContentRefreshesEnabled = true;
+        if (refreshContent) {
+            refreshRenderedCells();
+            // Ensure that client gets a response
+            markAsDirty();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see com.vaadin.ui.AbstractField#beforeClientResponse(boolean)
+     */
+    @Override
+    public void beforeClientResponse(boolean initial) {
+        super.beforeClientResponse(initial);
+
+        // Ensure pageBuffer is filled before sending the response to avoid
+        // calls to markAsDirty during paint
+        getVisibleCells();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see com.vaadin.ui.AbstractSelect#paintContent(com.vaadin.
+     * terminal.PaintTarget)
+     */
+
+    @Override
+    public void paintContent(PaintTarget target) throws PaintException {
+        isBeingPainted = true;
+        try {
+            doPaintContent(target);
+        } finally {
+            isBeingPainted = false;
+        }
+    }
+
+    /** Do paint content.
+	 *
+	 * @param target
+	 *            the target
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void doPaintContent(PaintTarget target) throws PaintException {
+        /*
+         * Body actions - Actions which has the target null and can be invoked
+         * by right clicking on the table body.
+         */
+        final Set<Action> actionSet = findAndPaintBodyActions(target);
+
+        final Object[][] cells = getVisibleCells();
+        int rows = findNumRowsToPaint(target, cells);
+
+        int total = size();
+        if (shouldHideNullSelectionItem()) {
+            total--;
+            rows--;
+        }
+
+        // CustomTable attributes
+        paintTableAttributes(target, rows, total);
+
+        paintVisibleColumnOrder(target);
+
+        // Rows
+        if (isPartialRowUpdate() && painted && !target.isFullRepaint()) {
+            paintPartialRowUpdate(target, actionSet);
+        } else if (target.isFullRepaint() || isRowCacheInvalidated()) {
+            paintRows(target, cells, actionSet);
+            setRowCacheInvalidated(false);
+        }
+
+        /*
+         * Send the page buffer indexes to ensure that the client side stays in
+         * sync. Otherwise we _might_ have the situation where the client side
+         * discards too few or too many rows, causing out of sync issues.
+         */
+        int pageBufferLastIndex = pageBufferFirstIndex
+                + pageBuffer[CELL_ITEMID].length - 1;
+        target.addAttribute(TableConstants.ATTRIBUTE_PAGEBUFFER_FIRST,
+                pageBufferFirstIndex);
+        target.addAttribute(TableConstants.ATTRIBUTE_PAGEBUFFER_LAST,
+                pageBufferLastIndex);
+
+        paintSorting(target);
+
+        resetVariablesAndPageBuffer(target);
+
+        // Actions
+        paintActions(target, actionSet);
+
+        paintColumnOrder(target);
+
+        // Available columns
+        paintAvailableColumns(target);
+
+        paintVisibleColumns(target);
+
+        if (keyMapperReset) {
+            keyMapperReset = false;
+            target.addAttribute(TableConstants.ATTRIBUTE_KEY_MAPPER_RESET, true);
+        }
+
+        if (dropHandler != null) {
+            dropHandler.getAcceptCriterion().paint(target);
+        }
+
+        painted = true;
+    }
+
+    /** Sets the row cache invalidated.
+	 *
+	 * @param invalidated
+	 *            the new row cache invalidated
+	 */
+    private void setRowCacheInvalidated(boolean invalidated) {
+        rowCacheInvalidated = invalidated;
+    }
+
+    /** Checks if is row cache invalidated.
+	 *
+	 * @return true, if is row cache invalidated
+	 */
+    protected boolean isRowCacheInvalidated() {
+        return rowCacheInvalidated;
+    }
+
+    /** Paint partial row update.
+	 *
+	 * @param target
+	 *            the target
+	 * @param actionSet
+	 *            the action set
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void paintPartialRowUpdate(PaintTarget target, Set<Action> actionSet)
+            throws PaintException {
+        paintPartialRowUpdates(target, actionSet);
+        paintPartialRowAdditions(target, actionSet);
+    }
+
+    /** Paint partial row updates.
+	 *
+	 * @param target
+	 *            the target
+	 * @param actionSet
+	 *            the action set
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void paintPartialRowUpdates(PaintTarget target,
+            Set<Action> actionSet) throws PaintException {
+        final boolean[] iscomponent = findCellsWithComponents();
+
+        int firstIx = getFirstUpdatedItemIndex();
+        int count = getUpdatedRowCount();
+
+        target.startTag("urows");
+        target.addAttribute("firsturowix", firstIx);
+        target.addAttribute("numurows", count);
+
+        // Partial row updates bypass the normal caching mechanism.
+        Object[][] cells = getVisibleCellsUpdateCacheRows(firstIx, count);
+        for (int indexInRowbuffer = 0; indexInRowbuffer < count; indexInRowbuffer++) {
+            final Object itemId = cells[CELL_ITEMID][indexInRowbuffer];
+
+            if (shouldHideNullSelectionItem()) {
+                // Remove null selection item if null selection is not allowed
+                continue;
+            }
+
+            paintRow(target, cells, isEditable(), actionSet, iscomponent,
+                    indexInRowbuffer, itemId);
+        }
+        target.endTag("urows");
+        maybeThrowCacheUpdateExceptions();
+    }
+
+    /** Paint partial row additions.
+	 *
+	 * @param target
+	 *            the target
+	 * @param actionSet
+	 *            the action set
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void paintPartialRowAdditions(PaintTarget target,
+            Set<Action> actionSet) throws PaintException {
+        final boolean[] iscomponent = findCellsWithComponents();
+
+        int firstIx = getFirstAddedItemIndex();
+        int count = getAddedRowCount();
+
+        target.startTag("prows");
+
+        if (!shouldHideAddedRows()) {
+            getLogger().log(Level.FINEST,
+                    "Paint rows for add. Index: {0}, count: {1}.",
+                    new Object[] { firstIx, count });
+
+            // Partial row additions bypass the normal caching mechanism.
+            Object[][] cells = getVisibleCellsInsertIntoCache(firstIx, count);
+            if (cells[0].length < count) {
+                // delete the rows below, since they will fall beyond the cache
+                // page.
+                target.addAttribute("delbelow", true);
+                count = cells[0].length;
+            }
+
+            for (int indexInRowbuffer = 0; indexInRowbuffer < count; indexInRowbuffer++) {
+                final Object itemId = cells[CELL_ITEMID][indexInRowbuffer];
+                if (shouldHideNullSelectionItem()) {
+                    // Remove null selection item if null selection is not
+                    // allowed
+                    continue;
+                }
+
+                paintRow(target, cells, isEditable(), actionSet, iscomponent,
+                        indexInRowbuffer, itemId);
+            }
+        } else {
+            getLogger().log(Level.FINEST,
+                    "Paint rows for remove. Index: {0}, count: {1}.",
+                    new Object[] { firstIx, count });
+            removeRowsFromCacheAndFillBottom(firstIx, count);
+            target.addAttribute("hide", true);
+        }
+
+        target.addAttribute("firstprowix", firstIx);
+        target.addAttribute("numprows", count);
+        target.endTag("prows");
+        maybeThrowCacheUpdateExceptions();
+    }
+
+    /**
+     * Subclass and override this to enable partial row updates and additions,
+     * which bypass the normal caching mechanism. This is useful for e.g.
+     * TreeTable.
+     * 
+     * @return true if this update is a partial row update, false if not. For
+     *         plain CustomTable it is always false.
+     */
+    protected boolean isPartialRowUpdate() {
+        return false;
+    }
+
+    /**
+     * Subclass and override this to enable partial row additions, bypassing the
+     * normal caching mechanism. This is useful for e.g. TreeTable, where
+     * expanding a node should only fetch and add the items inside of that node.
+     * 
+     * @return The index of the first added item. For plain CustomTable it is
+     *         always 0.
+     */
+    protected int getFirstAddedItemIndex() {
+        return 0;
+    }
+
+    /**
+     * Subclass and override this to enable partial row additions, bypassing the
+     * normal caching mechanism. This is useful for e.g. TreeTable, where
+     * expanding a node should only fetch and add the items inside of that node.
+     * 
+     * @return the number of rows to be added, starting at the index returned by
+     *         {@link #getFirstAddedItemIndex()}. For plain CustomTable it is
+     *         always 0.
+     */
+    protected int getAddedRowCount() {
+        return 0;
+    }
+
+    /**
+     * Subclass and override this to enable removing of rows, bypassing the
+     * normal caching and lazy loading mechanism. This is useful for e.g.
+     * TreeTable, when you need to hide certain rows as a node is collapsed.
+     * 
+     * This should return true if the rows pointed to by
+     * {@link #getFirstAddedItemIndex()} and {@link #getAddedRowCount()} should
+     * be hidden instead of added.
+     * 
+     * @return whether the rows to add (see {@link #getFirstAddedItemIndex()}
+     *         and {@link #getAddedRowCount()}) should be added or hidden. For
+     *         plain CustomTable it is always false.
+     */
+    protected boolean shouldHideAddedRows() {
+        return false;
+    }
+
+    /**
+     * Subclass and override this to enable partial row updates, bypassing the
+     * normal caching and lazy loading mechanism. This is useful for updating
+     * the state of certain rows, e.g. in the TreeTable the collapsed state of a
+     * single node is updated using this mechanism.
+     * 
+     * @return the index of the first item to be updated. For plain CustomTable
+     *         it is always 0.
+     */
+    protected int getFirstUpdatedItemIndex() {
+        return 0;
+    }
+
+    /**
+     * Subclass and override this to enable partial row updates, bypassing the
+     * normal caching and lazy loading mechanism. This is useful for updating
+     * the state of certain rows, e.g. in the TreeTable the collapsed state of a
+     * single node is updated using this mechanism.
+     * 
+     * @return the number of rows to update, starting at the index returned by
+     *         {@link #getFirstUpdatedItemIndex()}. For plain table it is always
+     *         0.
+     */
+    protected int getUpdatedRowCount() {
+        return 0;
+    }
+
+    /** Paint table attributes.
+	 *
+	 * @param target
+	 *            the target
+	 * @param rows
+	 *            the rows
+	 * @param total
+	 *            the total
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void paintTableAttributes(PaintTarget target, int rows, int total)
+            throws PaintException {
+        paintTabIndex(target);
+        paintDragMode(target);
+        paintSelectMode(target);
+
+        if (cacheRate != CACHE_RATE_DEFAULT) {
+            target.addAttribute("cr", cacheRate);
+        }
+
+        target.addAttribute("cols", getVisibleColumns().length);
+        target.addAttribute("rows", rows);
+
+        target.addAttribute("firstrow",
+                (reqFirstRowToPaint >= 0 ? reqFirstRowToPaint
+                        : firstToBeRenderedInClient));
+        target.addAttribute("totalrows", total);
+        if (getPageLength() != 0) {
+            target.addAttribute("pagelength", getPageLength());
+        }
+        if (areColumnHeadersEnabled()) {
+            target.addAttribute("colheaders", true);
+        }
+        if (rowHeadersAreEnabled()) {
+            target.addAttribute("rowheaders", true);
+        }
+
+        target.addAttribute("colfooters", columnFootersVisible);
+
+        // The cursors are only shown on pageable table
+        if (getCurrentPageFirstItemIndex() != 0 || getPageLength() > 0) {
+            target.addVariable(this, "firstvisible",
+                    getCurrentPageFirstItemIndex());
+            target.addVariable(this, "firstvisibleonlastpage",
+                    currentPageFirstItemIndexOnLastPage);
+        }
+    }
+
+    /** Resets and paints "to be painted next" variables. Also reset
+	 * pageBuffer
+	 *
+	 * @param target
+	 *            the target
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void resetVariablesAndPageBuffer(PaintTarget target)
+            throws PaintException {
+        reqFirstRowToPaint = -1;
+        reqRowsToPaint = -1;
+        containerChangeToBeRendered = false;
+        target.addVariable(this, "reqrows", reqRowsToPaint);
+        target.addVariable(this, "reqfirstrow", reqFirstRowToPaint);
+    }
+
+    /** Are column headers enabled.
+	 *
+	 * @return true, if successful
+	 */
+    private boolean areColumnHeadersEnabled() {
+        return getColumnHeaderMode() != ColumnHeaderMode.HIDDEN;
+    }
+
+    /** Paint visible columns.
+	 *
+	 * @param target
+	 *            the target
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void paintVisibleColumns(PaintTarget target) throws PaintException {
+        target.startTag("visiblecolumns");
+        if (rowHeadersAreEnabled()) {
+            target.startTag("column");
+            target.addAttribute("cid", ROW_HEADER_COLUMN_KEY);
+            paintColumnWidth(target, ROW_HEADER_FAKE_PROPERTY_ID);
+            paintColumnExpandRatio(target, ROW_HEADER_FAKE_PROPERTY_ID);
+            target.endTag("column");
+        }
+        final Collection<?> sortables = getSortableContainerPropertyIds();
+        for (Object colId : visibleColumns) {
+            if (colId != null) {
+                target.startTag("column");
+                target.addAttribute("cid", columnIdMap.key(colId));
+                final String head = getColumnHeader(colId);
+                target.addAttribute("caption", (head != null ? head : ""));
+                final String foot = getColumnFooter(colId);
+                target.addAttribute("fcaption", (foot != null ? foot : ""));
+                if (isColumnCollapsed(colId)) {
+                    target.addAttribute("collapsed", true);
+                }
+                if (areColumnHeadersEnabled()) {
+                    if (getColumnIcon(colId) != null) {
+                        target.addAttribute("icon", getColumnIcon(colId));
+                    }
+                    if (sortables.contains(colId)) {
+                        target.addAttribute("sortable", true);
+                    }
+                }
+                if (!Align.LEFT.equals(getColumnAlignment(colId))) {
+                    target.addAttribute("align", getColumnAlignment(colId)
+                            .toString());
+                }
+                paintColumnWidth(target, colId);
+                paintColumnExpandRatio(target, colId);
+                target.endTag("column");
+            }
+        }
+        target.endTag("visiblecolumns");
+    }
+
+    /** Paint available columns.
+	 *
+	 * @param target
+	 *            the target
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void paintAvailableColumns(PaintTarget target)
+            throws PaintException {
+        if (columnCollapsingAllowed) {
+            final HashSet<Object> collapsedCols = new HashSet<Object>();
+            for (Object colId : visibleColumns) {
+                if (isColumnCollapsed(colId)) {
+                    collapsedCols.add(colId);
+                }
+            }
+            final String[] collapsedKeys = new String[collapsedCols.size()];
+            int nextColumn = 0;
+            for (Object colId : visibleColumns) {
+                if (isColumnCollapsed(colId)) {
+                    collapsedKeys[nextColumn++] = columnIdMap.key(colId);
+                }
+            }
+            target.addVariable(this, "collapsedcolumns", collapsedKeys);
+
+            final String[] noncollapsibleKeys = new String[noncollapsibleColumns
+                    .size()];
+            nextColumn = 0;
+            for (Object colId : noncollapsibleColumns) {
+                noncollapsibleKeys[nextColumn++] = columnIdMap.key(colId);
+            }
+            target.addVariable(this, "noncollapsiblecolumns",
+                    noncollapsibleKeys);
+        }
+
+    }
+
+    /** Paint actions.
+	 *
+	 * @param target
+	 *            the target
+	 * @param actionSet
+	 *            the action set
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void paintActions(PaintTarget target, final Set<Action> actionSet)
+            throws PaintException {
+        if (!actionSet.isEmpty()) {
+            target.addVariable(this, "action", "");
+            target.startTag("actions");
+            for (Action a : actionSet) {
+                target.startTag("action");
+                if (a.getCaption() != null) {
+                    target.addAttribute("caption", a.getCaption());
+                }
+                if (a.getIcon() != null) {
+                    target.addAttribute("icon", a.getIcon());
+                }
+                target.addAttribute("key", actionMapper.key(a));
+                target.endTag("action");
+            }
+            target.endTag("actions");
+        }
+    }
+
+    /** Paint column order.
+	 *
+	 * @param target
+	 *            the target
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void paintColumnOrder(PaintTarget target) throws PaintException {
+        if (columnReorderingAllowed) {
+            final String[] colorder = new String[visibleColumns.size()];
+            int i = 0;
+            for (Object colId : visibleColumns) {
+                colorder[i++] = columnIdMap.key(colId);
+            }
+            target.addVariable(this, "columnorder", colorder);
+        }
+    }
+
+    /** Paint sorting.
+	 *
+	 * @param target
+	 *            the target
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void paintSorting(PaintTarget target) throws PaintException {
+        // Sorting
+        if (getContainerDataSource() instanceof Container.Sortable) {
+            target.addVariable(this, "sortcolumn",
+                    columnIdMap.key(sortContainerPropertyId));
+            target.addVariable(this, "sortascending", sortAscending);
+        }
+    }
+
+    /** Paint rows.
+	 *
+	 * @param target
+	 *            the target
+	 * @param cells
+	 *            the cells
+	 * @param actionSet
+	 *            the action set
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void paintRows(PaintTarget target, final Object[][] cells,
+            final Set<Action> actionSet) throws PaintException {
+        final boolean[] iscomponent = findCellsWithComponents();
+
+        target.startTag("rows");
+        // cells array contains all that are supposed to be visible on client,
+        // but we'll start from the one requested by client
+        int start = 0;
+        if (reqFirstRowToPaint != -1 && firstToBeRenderedInClient != -1) {
+            start = reqFirstRowToPaint - firstToBeRenderedInClient;
+        }
+        int end = cells[0].length;
+        if (reqRowsToPaint != -1) {
+            end = start + reqRowsToPaint;
+        }
+        // sanity check
+        if (lastToBeRenderedInClient != -1 && lastToBeRenderedInClient < end) {
+            end = lastToBeRenderedInClient + 1;
+        }
+        if (start > cells[CELL_ITEMID].length || start < 0) {
+            start = 0;
+        }
+        if (end > cells[CELL_ITEMID].length) {
+            end = cells[CELL_ITEMID].length;
+        }
+
+        for (int indexInRowbuffer = start; indexInRowbuffer < end; indexInRowbuffer++) {
+            final Object itemId = cells[CELL_ITEMID][indexInRowbuffer];
+
+            if (shouldHideNullSelectionItem()) {
+                // Remove null selection item if null selection is not allowed
+                continue;
+            }
+
+            paintRow(target, cells, isEditable(), actionSet, iscomponent,
+                    indexInRowbuffer, itemId);
+        }
+        target.endTag("rows");
+    }
+
+    /** Find cells with components.
+	 *
+	 * @return the boolean[]
+	 */
+    private boolean[] findCellsWithComponents() {
+        final boolean[] isComponent = new boolean[visibleColumns.size()];
+        int ix = 0;
+        for (Object columnId : visibleColumns) {
+            if (columnGenerators.containsKey(columnId)) {
+                isComponent[ix++] = true;
+            } else {
+                final Class<?> colType = getType(columnId);
+                isComponent[ix++] = colType != null
+                        && Component.class.isAssignableFrom(colType);
+            }
+        }
+        return isComponent;
+    }
+
+    /** Paint visible column order.
+	 *
+	 * @param target
+	 *            the target
+	 */
+    private void paintVisibleColumnOrder(PaintTarget target) {
+        // Visible column order
+        final ArrayList<String> visibleColOrder = new ArrayList<String>();
+        for (Object columnId : visibleColumns) {
+            if (!isColumnCollapsed(columnId)) {
+                visibleColOrder.add(columnIdMap.key(columnId));
+            }
+        }
+        target.addAttribute("vcolorder", visibleColOrder.toArray());
+    }
+
+    /** Find and paint body actions.
+	 *
+	 * @param target
+	 *            the target
+	 * @return the sets the
+	 */
+    private Set<Action> findAndPaintBodyActions(PaintTarget target) {
+        Set<Action> actionSet = new LinkedHashSet<Action>();
+        if (actionHandlers != null) {
+            final ArrayList<String> keys = new ArrayList<String>();
+            for (Handler ah : actionHandlers) {
+                // Getting actions for the null item, which in this case means
+                // the body item
+                final Action[] actions = ah.getActions(null, this);
+                if (actions != null) {
+                    for (Action action : actions) {
+                        actionSet.add(action);
+                        keys.add(actionMapper.key(action));
+                    }
+                }
+            }
+            target.addAttribute("alb", keys.toArray());
+        }
+        return actionSet;
+    }
+
+    /** Should hide null selection item.
+	 *
+	 * @return true, if successful
+	 */
+    private boolean shouldHideNullSelectionItem() {
+        return !isNullSelectionAllowed() && getNullSelectionItemId() != null
+                && containsId(getNullSelectionItemId());
+    }
+
+    /** Find num rows to paint.
+	 *
+	 * @param target
+	 *            the target
+	 * @param cells
+	 *            the cells
+	 * @return the int
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private int findNumRowsToPaint(PaintTarget target, final Object[][] cells)
+            throws PaintException {
+        int rows;
+        if (reqRowsToPaint >= 0) {
+            rows = reqRowsToPaint;
+        } else {
+            rows = cells[0].length;
+            if (alwaysRecalculateColumnWidths) {
+                // TODO experimental feature for now: tell the client to
+                // recalculate column widths.
+                // We'll only do this for paints that do not originate from
+                // table scroll/cache requests (i.e when reqRowsToPaint<0)
+                target.addAttribute("recalcWidths", true);
+            }
+        }
+        return rows;
+    }
+
+    /** Paint select mode.
+	 *
+	 * @param target
+	 *            the target
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void paintSelectMode(PaintTarget target) throws PaintException {
+        if (multiSelectMode != MultiSelectMode.DEFAULT) {
+            target.addAttribute("multiselectmode", multiSelectMode.ordinal());
+        }
+        if (isSelectable()) {
+            target.addAttribute("selectmode", (isMultiSelect() ? "multi"
+                    : "single"));
+        } else {
+            target.addAttribute("selectmode", "none");
+        }
+        if (!isNullSelectionAllowed()) {
+            target.addAttribute("nsa", false);
+        }
+
+        // selection support
+        // The select variable is only enabled if selectable
+        if (isSelectable()) {
+            target.addVariable(this, "selected", findSelectedKeys());
+        }
+    }
+
+    /** Find selected keys.
+	 *
+	 * @return the string[]
+	 */
+    private String[] findSelectedKeys() {
+        LinkedList<String> selectedKeys = new LinkedList<String>();
+        if (isMultiSelect()) {
+            HashSet<?> sel = new HashSet<Object>((Set<?>) getValue());
+            Collection<?> vids = getVisibleItemIds();
+            for (Iterator<?> it = vids.iterator(); it.hasNext();) {
+                Object id = it.next();
+                if (sel.contains(id)) {
+                    selectedKeys.add(itemIdMapper.key(id));
+                }
+            }
+        } else {
+            Object value = getValue();
+            if (value == null) {
+                value = getNullSelectionItemId();
+            }
+            if (value != null) {
+                selectedKeys.add(itemIdMapper.key(value));
+            }
+        }
+        return selectedKeys.toArray(new String[selectedKeys.size()]);
+    }
+
+    /** Paint drag mode.
+	 *
+	 * @param target
+	 *            the target
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void paintDragMode(PaintTarget target) throws PaintException {
+        if (dragMode != TableDragMode.NONE) {
+            target.addAttribute("dragmode", dragMode.ordinal());
+        }
+    }
+
+    /** Paint tab index.
+	 *
+	 * @param target
+	 *            the target
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void paintTabIndex(PaintTarget target) throws PaintException {
+        // The tab ordering number
+        if (getTabIndex() > 0) {
+            target.addAttribute("tabindex", getTabIndex());
+        }
+    }
+
+    /** Paint column width.
+	 *
+	 * @param target
+	 *            the target
+	 * @param columnId
+	 *            the column id
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void paintColumnWidth(PaintTarget target, final Object columnId)
+            throws PaintException {
+        if (columnWidths.containsKey(columnId)) {
+            target.addAttribute("width", getColumnWidth(columnId));
+        }
+    }
+
+    /** Paint column expand ratio.
+	 *
+	 * @param target
+	 *            the target
+	 * @param columnId
+	 *            the column id
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void paintColumnExpandRatio(PaintTarget target,
+            final Object columnId) throws PaintException {
+        if (columnExpandRatios.containsKey(columnId)) {
+            target.addAttribute("er", getColumnExpandRatio(columnId));
+        }
+    }
+
+    /** Row headers are enabled.
+	 *
+	 * @return true, if successful
+	 */
+    private boolean rowHeadersAreEnabled() {
+        return getRowHeaderMode() != ROW_HEADER_MODE_HIDDEN;
+    }
+
+    /** Paint row.
+	 *
+	 * @param target
+	 *            the target
+	 * @param cells
+	 *            the cells
+	 * @param iseditable
+	 *            the iseditable
+	 * @param actionSet
+	 *            the action set
+	 * @param iscomponent
+	 *            the iscomponent
+	 * @param indexInRowbuffer
+	 *            the index in rowbuffer
+	 * @param itemId
+	 *            the item id
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void paintRow(PaintTarget target, final Object[][] cells,
+            final boolean iseditable, final Set<Action> actionSet,
+            final boolean[] iscomponent, int indexInRowbuffer,
+            final Object itemId) throws PaintException {
+        target.startTag("tr");
+
+        paintRowAttributes(target, cells, actionSet, indexInRowbuffer, itemId);
+
+        // cells
+        int currentColumn = 0;
+        for (final Iterator<Object> it = visibleColumns.iterator(); it
+                .hasNext(); currentColumn++) {
+            final Object columnId = it.next();
+            if (columnId == null || isColumnCollapsed(columnId)) {
+                continue;
+            }
+            /*
+             * For each cell, if a cellStyleGenerator is specified, get the
+             * specific style for the cell. If there is any, add it to the
+             * target.
+             */
+            if (cellStyleGenerator != null) {
+                String cellStyle = cellStyleGenerator.getStyle(this, itemId,
+                        columnId);
+                if (cellStyle != null && !cellStyle.equals("")) {
+                    target.addAttribute("style-" + columnIdMap.key(columnId),
+                            cellStyle);
+                }
+            }
+
+            if ((iscomponent[currentColumn] || iseditable || cells[CELL_GENERATED_ROW][indexInRowbuffer] != null)
+                    && Component.class.isInstance(cells[CELL_FIRSTCOL
+                            + currentColumn][indexInRowbuffer])) {
+                final Component c = (Component) cells[CELL_FIRSTCOL
+                        + currentColumn][indexInRowbuffer];
+                if (c == null
+                        || !LegacyCommunicationManager
+                                .isComponentVisibleToClient(c)) {
+                    target.addText("");
+                } else {
+                    LegacyPaint.paint(c, target);
+                }
+            } else {
+                target.addText((String) cells[CELL_FIRSTCOL + currentColumn][indexInRowbuffer]);
+            }
+            paintCellTooltips(target, itemId, columnId);
+        }
+
+        target.endTag("tr");
+    }
+
+    /** Paint cell tooltips.
+	 *
+	 * @param target
+	 *            the target
+	 * @param itemId
+	 *            the item id
+	 * @param columnId
+	 *            the column id
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void paintCellTooltips(PaintTarget target, Object itemId,
+            Object columnId) throws PaintException {
+        if (itemDescriptionGenerator != null) {
+            String itemDescription = itemDescriptionGenerator
+                    .generateDescription(this, itemId, columnId);
+            if (itemDescription != null && !itemDescription.equals("")) {
+                target.addAttribute("descr-" + columnIdMap.key(columnId),
+                        itemDescription);
+            }
+        }
+    }
+
+    /** Paint row tooltips.
+	 *
+	 * @param target
+	 *            the target
+	 * @param itemId
+	 *            the item id
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void paintRowTooltips(PaintTarget target, Object itemId)
+            throws PaintException {
+        if (itemDescriptionGenerator != null) {
+            String rowDescription = itemDescriptionGenerator
+                    .generateDescription(this, itemId, null);
+            if (rowDescription != null && !rowDescription.equals("")) {
+                target.addAttribute("rowdescr", rowDescription);
+            }
+        }
+    }
+
+    /** Paint row attributes.
+	 *
+	 * @param target
+	 *            the target
+	 * @param cells
+	 *            the cells
+	 * @param actionSet
+	 *            the action set
+	 * @param indexInRowbuffer
+	 *            the index in rowbuffer
+	 * @param itemId
+	 *            the item id
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void paintRowAttributes(PaintTarget target, final Object[][] cells,
+            final Set<Action> actionSet, int indexInRowbuffer,
+            final Object itemId) throws PaintException {
+        // tr attributes
+
+        paintRowIcon(target, cells, indexInRowbuffer);
+        paintRowHeader(target, cells, indexInRowbuffer);
+        paintGeneratedRowInfo(target, cells, indexInRowbuffer);
+        target.addAttribute("key",
+                Integer.parseInt(cells[CELL_KEY][indexInRowbuffer].toString()));
+
+        if (isSelected(itemId)) {
+            target.addAttribute("selected", true);
+        }
+
+        // Actions
+        if (actionHandlers != null) {
+            final ArrayList<String> keys = new ArrayList<String>();
+            for (Handler ah : actionHandlers) {
+                final Action[] aa = ah.getActions(itemId, this);
+                if (aa != null) {
+                    for (int ai = 0; ai < aa.length; ai++) {
+                        final String key = actionMapper.key(aa[ai]);
+                        actionSet.add(aa[ai]);
+                        keys.add(key);
+                    }
+                }
+            }
+            target.addAttribute("al", keys.toArray());
+        }
+
+        /*
+         * For each row, if a cellStyleGenerator is specified, get the specific
+         * style for the cell, using null as propertyId. If there is any, add it
+         * to the target.
+         */
+        if (cellStyleGenerator != null) {
+            String rowStyle = cellStyleGenerator.getStyle(this, itemId, null);
+            if (rowStyle != null && !rowStyle.equals("")) {
+                target.addAttribute("rowstyle", rowStyle);
+            }
+        }
+
+        paintRowTooltips(target, itemId);
+
+        paintRowAttributes(target, itemId);
+    }
+
+    /** Paint generated row info.
+	 *
+	 * @param target
+	 *            the target
+	 * @param cells
+	 *            the cells
+	 * @param indexInRowBuffer
+	 *            the index in row buffer
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    private void paintGeneratedRowInfo(PaintTarget target, Object[][] cells,
+            int indexInRowBuffer) throws PaintException {
+        GeneratedRow generatedRow = (GeneratedRow) cells[CELL_GENERATED_ROW][indexInRowBuffer];
+        if (generatedRow != null) {
+            target.addAttribute("gen_html", generatedRow.isHtmlContentAllowed());
+            target.addAttribute("gen_span", generatedRow.isSpanColumns());
+            target.addAttribute("gen_widget",
+                    generatedRow.getValue() instanceof Component);
+        }
+    }
+
+    /** Paint row header.
+	 *
+	 * @param target
+	 *            the target
+	 * @param cells
+	 *            the cells
+	 * @param indexInRowbuffer
+	 *            the index in rowbuffer
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    protected void paintRowHeader(PaintTarget target, Object[][] cells,
+            int indexInRowbuffer) throws PaintException {
+        if (rowHeadersAreEnabled()) {
+            if (cells[CELL_HEADER][indexInRowbuffer] != null) {
+                target.addAttribute("caption",
+                        (String) cells[CELL_HEADER][indexInRowbuffer]);
+            }
+        }
+
+    }
+
+    /** Paint row icon.
+	 *
+	 * @param target
+	 *            the target
+	 * @param cells
+	 *            the cells
+	 * @param indexInRowbuffer
+	 *            the index in rowbuffer
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    protected void paintRowIcon(PaintTarget target, final Object[][] cells,
+            int indexInRowbuffer) throws PaintException {
+        if (rowHeadersAreEnabled()
+                && cells[CELL_ICON][indexInRowbuffer] != null) {
+            target.addAttribute("icon",
+                    (Resource) cells[CELL_ICON][indexInRowbuffer]);
+        }
+    }
+
+    /** A method where extended CustomTable implementations may add their
+	 * custom attributes for rows.
+	 *
+	 * @param target
+	 *            the target
+	 * @param itemId
+	 *            the item id
+	 * @throws PaintException
+	 *             the paint exception
+	 */
+    protected void paintRowAttributes(PaintTarget target, Object itemId)
+            throws PaintException {
+
+    }
+
+    /**
+     * Gets the cached visible table contents.
+     * 
+     * @return the cached visible table contents.
+     */
+    private Object[][] getVisibleCells() {
+        if (pageBuffer == null) {
+            refreshRenderedCells();
+        }
+        return pageBuffer;
+    }
+
+    /**
+     * Gets the value of property.
+     * 
+     * By default if the table is editable the fieldFactory is used to create
+     * editors for table cells. Otherwise formatPropertyValue is used to format
+     * the value representation.
+     * 
+     * @param rowId
+     *            the Id of the row (same as item Id).
+     * @param colId
+     *            the Id of the column.
+     * @param property
+     *            the Property to be presented.
+     * @return Object Either formatted value or Component for field.
+     * @see #setTableFieldFactory(TableFieldFactory)
+     */
+    protected Object getPropertyValue(Object rowId, Object colId,
+            Property property) {
+        if (isEditable() && fieldFactory != null) {
+            final Field<?> f = fieldFactory.createField(
+                    getContainerDataSource(), rowId, colId, this);
+            if (f != null) {
+                // Remember that we have made this association so we can remove
+                // it when the component is removed
+                associatedProperties.put(f, property);
+                bindPropertyToField(rowId, colId, property, f);
+                return f;
+            }
+        }
+
+        return formatPropertyValue(rowId, colId, property);
+    }
+
+    /** Binds an item property to a field generated by TableFieldFactory. The
+	 * default behavior is to bind property straight to Field. If
+	 * Property.Viewer type property (e.g. PropertyFormatter) is already set for
+	 * field, the property is bound to that Property.Viewer.
+	 *
+	 * @param rowId
+	 *            the row id
+	 * @param colId
+	 *            the col id
+	 * @param property
+	 *            the property
+	 * @param field
+	 *            the field
+	 * @since 6.7.3
+	 */
+    protected void bindPropertyToField(Object rowId, Object colId,
+            Property property, Field field) {
+        // check if field has a property that is Viewer set. In that case we
+        // expect developer has e.g. PropertyFormatter that he wishes to use and
+        // assign the property to the Viewer instead.
+        boolean hasFilterProperty = field.getPropertyDataSource() != null
+                && (field.getPropertyDataSource() instanceof Property.Viewer);
+        if (hasFilterProperty) {
+            ((Property.Viewer) field.getPropertyDataSource())
+                    .setPropertyDataSource(property);
+        } else {
+            field.setPropertyDataSource(property);
+        }
+    }
+
+    /**
+     * Formats table cell property values. By default the property.toString()
+     * and return a empty string for null properties.
+     * 
+     * @param rowId
+     *            the Id of the row (same as item Id).
+     * @param colId
+     *            the Id of the column.
+     * @param property
+     *            the Property to be formatted.
+     * @return the String representation of property and its value.
+     * @since 3.1
+     */
+    protected String formatPropertyValue(Object rowId, Object colId,
+            Property<?> property) {
+        if (property == null) {
+            return "";
+        }
+        Converter<String, Object> converter = null;
+
+        if (hasConverter(colId)) {
+            converter = getConverter(colId);
+        } else {
+            converter = (Converter) ConverterUtil.getConverter(String.class,
+                    property.getType(), getSession());
+        }
+        Object value = property.getValue();
+        if (converter != null) {
+            return converter.convertToPresentation(value, String.class,
+                    getLocale());
+        }
+        return (null != value) ? value.toString() : "";
+    }
+
+    /* Action container */
+
+    /** Registers a new action handler for this container.
+	 *
+	 * @param actionHandler
+	 *            the action handler
+	 * @see com.vaadin.event.Action.Container#addActionHandler(Action.Handler)
+	 */
+
+    @Override
+    public void addActionHandler(Action.Handler actionHandler) {
+
+        if (actionHandler != null) {
+
+            if (actionHandlers == null) {
+                actionHandlers = new LinkedList<Handler>();
+                actionMapper = new KeyMapper<Action>();
+            }
+
+            if (!actionHandlers.contains(actionHandler)) {
+                actionHandlers.add(actionHandler);
+                // Assures the visual refresh. No need to reset the page buffer
+                // before as the content has not changed, only the action
+                // handlers.
+                refreshRenderedCells();
+            }
+
+        }
+    }
+
+    /** Removes a previously registered action handler for the contents of
+	 * this container.
+	 *
+	 * @param actionHandler
+	 *            the action handler
+	 * @see com.vaadin.event.Action.Container#removeActionHandler(Action.Handler)
+	 */
+
+    @Override
+    public void removeActionHandler(Action.Handler actionHandler) {
+
+        if (actionHandlers != null && actionHandlers.contains(actionHandler)) {
+
+            actionHandlers.remove(actionHandler);
+
+            if (actionHandlers.isEmpty()) {
+                actionHandlers = null;
+                actionMapper = null;
+            }
+
+            // Assures the visual refresh. No need to reset the page buffer
+            // before as the content has not changed, only the action
+            // handlers.
+            refreshRenderedCells();
+        }
+    }
+
+    /** Removes all action handlers.
+	 */
+    public void removeAllActionHandlers() {
+        actionHandlers = null;
+        actionMapper = null;
+        // Assures the visual refresh. No need to reset the page buffer
+        // before as the content has not changed, only the action
+        // handlers.
+        refreshRenderedCells();
+    }
+
+    /* Property value change listening support */
+
+    /** Notifies this listener that the Property's value has changed.
+	 * 
+	 * Also listens changes in rendered items to refresh content area.
+	 *
+	 * @param event
+	 *            the event
+	 * @see com.vaadin.data.Property.ValueChangeListener#valueChange(Property.ValueChangeEvent)
+	 */
+
+    @Override
+    public void valueChange(Property.ValueChangeEvent event) {
+        if (equals(event.getProperty())
+                || event.getProperty() == getPropertyDataSource()) {
+            super.valueChange(event);
+        } else {
+            refreshRowCache();
+            containerChangeToBeRendered = true;
+        }
+        markAsDirty();
+    }
+
+    /**
+     * Clears the current page buffer. Call this before
+     * {@link #refreshRenderedCells()} to ensure that all content is updated
+     * from the properties.
+     */
+    protected void resetPageBuffer() {
+        firstToBeRenderedInClient = -1;
+        lastToBeRenderedInClient = -1;
+        reqFirstRowToPaint = -1;
+        reqRowsToPaint = -1;
+        pageBuffer = null;
+    }
+
+    /**
+     * Notifies the component that it is connected to an application.
+     * 
+     * @see com.vaadin.ui.Component#attach()
+     */
+
+    @Override
+    public void attach() {
+        super.attach();
+
+        refreshRenderedCells();
+    }
+
+    /** Notifies the component that it is detached from the application.
+	 *
+	 * @see com.vaadin.ui.Component#detach()
+	 */
+
+    @Override
+    public void detach() {
+        super.detach();
+    }
+
+    /** Removes all Items from the Container.
+	 *
+	 * @return true, if successful
+	 * @see com.vaadin.data.Container#removeAllItems()
+	 */
+
+    @Override
+    public boolean removeAllItems() {
+        currentPageFirstItemId = null;
+        currentPageFirstItemIndex = 0;
+        return super.removeAllItems();
+    }
+
+    /** Removes the Item identified by <code>ItemId</code> from the
+	 * Container.
+	 *
+	 * @param itemId
+	 *            the item id
+	 * @return true, if successful
+	 * @see com.vaadin.data.Container#removeItem(Object)
+	 */
+
+    @Override
+    public boolean removeItem(Object itemId) {
+        final Object nextItemId = nextItemId(itemId);
+        final boolean ret = super.removeItem(itemId);
+        if (ret && (itemId != null) && (itemId.equals(currentPageFirstItemId))) {
+            currentPageFirstItemId = nextItemId;
+        }
+        if (!(items instanceof Container.ItemSetChangeNotifier)) {
+            refreshRowCache();
+        }
+        return ret;
+    }
+
+    /** Removes a Property specified by the given Property ID from the
+	 * Container.
+	 *
+	 * @param propertyId
+	 *            the property id
+	 * @return true, if successful
+	 * @throws UnsupportedOperationException
+	 *             the unsupported operation exception
+	 * @see com.vaadin.data.Container#removeContainerProperty(Object)
+	 */
+
+    @Override
+    public boolean removeContainerProperty(Object propertyId)
+            throws UnsupportedOperationException {
+
+        // If a visible property is removed, remove the corresponding column
+        visibleColumns.remove(propertyId);
+        columnAlignments.remove(propertyId);
+        columnIcons.remove(propertyId);
+        columnHeaders.remove(propertyId);
+        columnFooters.remove(propertyId);
+        // If a propertyValueConverter was defined for the property, remove it.
+        propertyValueConverters.remove(propertyId);
+
+        return super.removeContainerProperty(propertyId);
+    }
+
+    /** Adds a new property to the table and show it as a visible column.
+	 *
+	 * @param propertyId
+	 *            the Id of the proprty.
+	 * @param type
+	 *            the class of the property.
+	 * @param defaultValue
+	 *            the default value given for all existing items.
+	 * @return true, if successful
+	 * @throws UnsupportedOperationException
+	 *             the unsupported operation exception
+	 * @see com.vaadin.data.Container#addContainerProperty(Object, Class,
+	 *      Object)
+	 */
+
+    @Override
+    public boolean addContainerProperty(Object propertyId, Class<?> type,
+            Object defaultValue) throws UnsupportedOperationException {
+
+        boolean visibleColAdded = false;
+        if (!visibleColumns.contains(propertyId)) {
+            visibleColumns.add(propertyId);
+            visibleColAdded = true;
+        }
+
+        if (!super.addContainerProperty(propertyId, type, defaultValue)) {
+            if (visibleColAdded) {
+                visibleColumns.remove(propertyId);
+            }
+            return false;
+        }
+        if (!(items instanceof Container.PropertySetChangeNotifier)) {
+            refreshRowCache();
+        }
+        return true;
+    }
+
+    /** Adds a new property to the table and show it as a visible column.
+	 *
+	 * @param propertyId
+	 *            the Id of the proprty
+	 * @param type
+	 *            the class of the property
+	 * @param defaultValue
+	 *            the default value given for all existing items
+	 * @param columnHeader
+	 *            the Explicit header of the column. If explicit header is not
+	 *            needed, this should be set null.
+	 * @param columnIcon
+	 *            the Icon of the column. If icon is not needed, this should be
+	 *            set null.
+	 * @param columnAlignment
+	 *            the Alignment of the column. Null implies align left.
+	 * @return true, if successful
+	 * @throws UnsupportedOperationException
+	 *             if the operation is not supported.
+	 * @see com.vaadin.data.Container#addContainerProperty(Object, Class,
+	 *      Object)
+	 */
+    public boolean addContainerProperty(Object propertyId, Class<?> type,
+            Object defaultValue, String columnHeader, Resource columnIcon,
+            Align columnAlignment) throws UnsupportedOperationException {
+        if (!this.addContainerProperty(propertyId, type, defaultValue)) {
+            return false;
+        }
+        setColumnAlignment(propertyId, columnAlignment);
+        setColumnHeader(propertyId, columnHeader);
+        setColumnIcon(propertyId, columnIcon);
+        return true;
+    }
+
+    /**
+     * Adds a generated column to the CustomTable.
+     * <p>
+     * A generated column is a column that exists only in the CustomTable, not
+     * as a property in the underlying Container. It shows up just as a regular
+     * column.
+     * 
+     * <p>
+     * A generated column will override a property with the same id, so that the
+     * generated column is shown instead of the column representing the
+     * property. Note that getContainerProperty() will still get the real
+     * property.
+     * 
+     * <p>
+     * CustomTable will not listen to value change events from properties
+     * overridden by generated columns. If the content of your generated column
+     * depends on properties that are not directly visible in the table, attach
+     * value change listener to update the content on all depended properties.
+     * Otherwise your UI might not get updated as expected.
+     * 
+     * <p>
+     * Also note that getVisibleColumns() will return the generated columns,
+     * while getContainerPropertyIds() will not.
+     * 
+     * 
+     * @param id
+     *            the id of the column to be added
+     * @param generatedColumn
+     *            the {@link ColumnGenerator} to use for this column
+     */
+    public void addGeneratedColumn(Object id, ColumnGenerator generatedColumn) {
+        if (generatedColumn == null) {
+            throw new IllegalArgumentException(
+                    "Can not add null as a GeneratedColumn");
+        }
+        if (columnGenerators.containsKey(id)) {
+            throw new IllegalArgumentException(
+                    "Can not add the same GeneratedColumn twice, id:" + id);
+        } else {
+            columnGenerators.put(id, generatedColumn);
+            /*
+             * add to visible column list unless already there (overriding
+             * column from DS)
+             */
+            if (!visibleColumns.contains(id)) {
+                visibleColumns.add(id);
+            }
+            refreshRowCache();
+        }
+    }
+
+    /** Returns the ColumnGenerator used to generate the given column.
+	 *
+	 * @param columnId
+	 *            The id of the generated column
+	 * @return The ColumnGenerator used for the given columnId or null.
+	 * @throws IllegalArgumentException
+	 *             the illegal argument exception
+	 */
+    public ColumnGenerator getColumnGenerator(Object columnId)
+            throws IllegalArgumentException {
+        return columnGenerators.get(columnId);
+    }
+
+    /**
+     * Removes a generated column previously added with addGeneratedColumn.
+     * 
+     * @param columnId
+     *            id of the generated column to remove
+     * @return true if the column could be removed (existed in the CustomTable)
+     */
+    public boolean removeGeneratedColumn(Object columnId) {
+        if (columnGenerators.containsKey(columnId)) {
+            columnGenerators.remove(columnId);
+            // remove column from visibleColumns list unless it exists in
+            // container (generator previously overrode this column)
+            if (!items.getContainerPropertyIds().contains(columnId)) {
+                visibleColumns.remove(columnId);
+            }
+            refreshRowCache();
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /** Returns item identifiers of the items which are currently rendered on
+	 * the client.
+	 * <p>
+	 * Note, that some due to historical reasons the name of the method is bit
+	 * misleading. Some items may be partly or totally out of the viewport of
+	 * the table's scrollable area. Actually detecting rows which can be
+	 * actually seen by the end user may be problematic due to the client server
+	 * architecture. Using {@link #getCurrentPageFirstItemId()} combined with
+	 * {@link #getPageLength()} may produce good enough estimates in some
+	 * situations.
+	 *
+	 * @return the visible item ids
+	 * @see com.vaadin.ui.Select#getVisibleItemIds()
+	 */
+
+    @Override
+    public Collection<?> getVisibleItemIds() {
+
+        final LinkedList<Object> visible = new LinkedList<Object>();
+
+        final Object[][] cells = getVisibleCells();
+        // may be null if the table has not been rendered yet (e.g. not attached
+        // to a layout)
+        if (null != cells) {
+            for (int i = 0; i < cells[CELL_ITEMID].length; i++) {
+                visible.add(cells[CELL_ITEMID][i]);
+            }
+        }
+
+        return visible;
+    }
+
+    /** Container datasource item set change. CustomTable must flush its
+	 * buffers on change.
+	 *
+	 * @param event
+	 *            the event
+	 * @see com.vaadin.data.Container.ItemSetChangeListener#containerItemSetChange(com.vaadin.data.Container.ItemSetChangeEvent)
+	 */
+
+    @Override
+    public void containerItemSetChange(Container.ItemSetChangeEvent event) {
+        if (isBeingPainted) {
+            return;
+        }
+
+        super.containerItemSetChange(event);
+
+        // super method clears the key map, must inform client about this to
+        // avoid getting invalid keys back (#8584)
+        keyMapperReset = true;
+
+        // ensure that page still has first item in page, ignore buffer refresh
+        // (forced in this method)
+        setCurrentPageFirstItemIndex(getCurrentPageFirstItemIndex(), false);
+        refreshRowCache();
+    }
+
+    /** Container datasource property set change. CustomTable must flush its
+	 * buffers on change.
+	 *
+	 * @param event
+	 *            the event
+	 * @see com.vaadin.data.Container.PropertySetChangeListener#containerPropertySetChange(com.vaadin.data.Container.PropertySetChangeEvent)
+	 */
+
+    @Override
+    public void containerPropertySetChange(
+            Container.PropertySetChangeEvent event) {
+        if (isBeingPainted) {
+            return;
+        }
+
+        disableContentRefreshing();
+        super.containerPropertySetChange(event);
+
+        // sanitetize visibleColumns. note that we are not adding previously
+        // non-existing properties as columns
+        Collection<?> containerPropertyIds = getContainerDataSource()
+                .getContainerPropertyIds();
+
+        LinkedList<Object> newVisibleColumns = new LinkedList<Object>(
+                visibleColumns);
+        for (Iterator<Object> iterator = newVisibleColumns.iterator(); iterator
+                .hasNext();) {
+            Object id = iterator.next();
+            if (!(containerPropertyIds.contains(id) || columnGenerators
+                    .containsKey(id))) {
+                iterator.remove();
+            }
+        }
+        setVisibleColumns(newVisibleColumns.toArray());
+        // same for collapsed columns
+        for (Iterator<Object> iterator = collapsedColumns.iterator(); iterator
+                .hasNext();) {
+            Object id = iterator.next();
+            if (!(containerPropertyIds.contains(id) || columnGenerators
+                    .containsKey(id))) {
+                iterator.remove();
+            }
+        }
+
+        resetPageBuffer();
+        enableContentRefreshing(true);
+    }
+
+    /** Adding new items is not supported.
+	 *
+	 * @param allowNewOptions
+	 *            the new new items allowed
+	 * @throws UnsupportedOperationException
+	 *             if set to true.
+	 * @see com.vaadin.ui.Select#setNewItemsAllowed(boolean)
+	 */
+
+    @Override
+    public void setNewItemsAllowed(boolean allowNewOptions)
+            throws UnsupportedOperationException {
+        if (allowNewOptions) {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    /** Gets the ID of the Item following the Item that corresponds to
+	 * itemId.
+	 *
+	 * @param itemId
+	 *            the item id
+	 * @return the object
+	 * @see com.vaadin.data.Container.Ordered#nextItemId(java.lang.Object)
+	 */
+
+    @Override
+    public Object nextItemId(Object itemId) {
+        return ((Container.Ordered) items).nextItemId(itemId);
+    }
+
+    /** Gets the ID of the Item preceding the Item that corresponds to the
+	 * itemId.
+	 *
+	 * @param itemId
+	 *            the item id
+	 * @return the object
+	 * @see com.vaadin.data.Container.Ordered#prevItemId(java.lang.Object)
+	 */
+
+    @Override
+    public Object prevItemId(Object itemId) {
+        return ((Container.Ordered) items).prevItemId(itemId);
+    }
+
+    /** Gets the ID of the first Item in the Container.
+	 *
+	 * @return the object
+	 * @see com.vaadin.data.Container.Ordered#firstItemId()
+	 */
+
+    @Override
+    public Object firstItemId() {
+        return ((Container.Ordered) items).firstItemId();
+    }
+
+    /** Gets the ID of the last Item in the Container.
+	 *
+	 * @return the object
+	 * @see com.vaadin.data.Container.Ordered#lastItemId()
+	 */
+
+    @Override
+    public Object lastItemId() {
+        return ((Container.Ordered) items).lastItemId();
+    }
+
+    /** Tests if the Item corresponding to the given Item ID is the first
+	 * Item in the Container.
+	 *
+	 * @param itemId
+	 *            the item id
+	 * @return true, if is first id
+	 * @see com.vaadin.data.Container.Ordered#isFirstId(java.lang.Object)
+	 */
+
+    @Override
+    public boolean isFirstId(Object itemId) {
+        return ((Container.Ordered) items).isFirstId(itemId);
+    }
+
+    /** Tests if the Item corresponding to the given Item ID is the last Item
+	 * in the Container.
+	 *
+	 * @param itemId
+	 *            the item id
+	 * @return true, if is last id
+	 * @see com.vaadin.data.Container.Ordered#isLastId(java.lang.Object)
+	 */
+
+    @Override
+    public boolean isLastId(Object itemId) {
+        return ((Container.Ordered) items).isLastId(itemId);
+    }
+
+    /** Adds new item after the given item.
+	 *
+	 * @param previousItemId
+	 *            the previous item id
+	 * @return the object
+	 * @throws UnsupportedOperationException
+	 *             the unsupported operation exception
+	 * @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object)
+	 */
+
+    @Override
+    public Object addItemAfter(Object previousItemId)
+            throws UnsupportedOperationException {
+        Object itemId = ((Container.Ordered) items)
+                .addItemAfter(previousItemId);
+        if (!(items instanceof Container.ItemSetChangeNotifier)) {
+            refreshRowCache();
+        }
+        return itemId;
+    }
+
+    /** Adds new item after the given item.
+	 *
+	 * @param previousItemId
+	 *            the previous item id
+	 * @param newItemId
+	 *            the new item id
+	 * @return the item
+	 * @throws UnsupportedOperationException
+	 *             the unsupported operation exception
+	 * @see com.vaadin.data.Container.Ordered#addItemAfter(java.lang.Object,
+	 *      java.lang.Object)
+	 */
+
+    @Override
+    public Item addItemAfter(Object previousItemId, Object newItemId)
+            throws UnsupportedOperationException {
+        Item item = ((Container.Ordered) items).addItemAfter(previousItemId,
+                newItemId);
+        if (!(items instanceof Container.ItemSetChangeNotifier)) {
+            refreshRowCache();
+        }
+        return item;
+    }
+
+    /**
+     * Sets the TableFieldFactory that is used to create editor for table cells.
+     * 
+     * The TableFieldFactory is only used if the CustomTable is editable. By
+     * default the DefaultFieldFactory is used.
+     * 
+     * @param fieldFactory
+     *            the field factory to set.
+     * @see #isEditable
+     * @see DefaultFieldFactory
+     */
+    public void setTableFieldFactory(TableFieldFactory fieldFactory) {
+        this.fieldFactory = fieldFactory;
+
+        // Assure visual refresh
+        refreshRowCache();
+    }
+
+    /**
+     * Gets the TableFieldFactory that is used to create editor for table cells.
+     * 
+     * The FieldFactory is only used if the CustomTable is editable.
+     * 
+     * @return TableFieldFactory used to create the Field instances.
+     * @see #isEditable
+     */
+    public TableFieldFactory getTableFieldFactory() {
+        return fieldFactory;
+    }
+
+    /**
+     * Is table editable.
+     * 
+     * If table is editable a editor of type Field is created for each table
+     * cell. The assigned FieldFactory is used to create the instances.
+     * 
+     * To provide custom editors for table cells create a class implementins the
+     * FieldFactory interface, and assign it to table, and set the editable
+     * property to true.
+     * 
+     * @return true if table is editable, false oterwise.
+     * @see Field
+     * @see fieldFactory
+     * 
+     */
+    public boolean isEditable() {
+        return editable;
+    }
+
+    /**
+     * Sets the editable property.
+     * 
+     * If table is editable a editor of type Field is created for each table
+     * cell. The assigned FieldFactory is used to create the instances.
+     * 
+     * To provide custom editors for table cells create a class implementins the
+     * FieldFactory interface, and assign it to table, and set the editable
+     * property to true.
+     * 
+     * @param editable
+     *            true if table should be editable by user.
+     * @see Field
+     * @see fieldFactory
+     * 
+     */
+    public void setEditable(boolean editable) {
+        this.editable = editable;
+
+        // Assure visual refresh
+        refreshRowCache();
+    }
+
+    /** Sorts the table.
+	 *
+	 * @param propertyId
+	 *            the property id
+	 * @param ascending
+	 *            the ascending
+	 * @throws UnsupportedOperationException
+	 *             if the container data source does not implement
+	 *             Container.Sortable
+	 * @see com.vaadin.data.Container.Sortable#sort(java.lang.Object[],
+	 *      boolean[])
+	 */
+
+    @Override
+    public void sort(Object[] propertyId, boolean[] ascending)
+            throws UnsupportedOperationException {
+        final Container c = getContainerDataSource();
+        if (c instanceof Container.Sortable) {
+            final int pageIndex = getCurrentPageFirstItemIndex();
+            boolean refreshingPreviouslyEnabled = disableContentRefreshing();
+            ((Container.Sortable) c).sort(propertyId, ascending);
+            setCurrentPageFirstItemIndex(pageIndex);
+            if (refreshingPreviouslyEnabled) {
+                enableContentRefreshing(true);
+            }
+            if (propertyId.length > 0 && ascending.length > 0) {
+                // The first propertyId is the primary sorting criterion,
+                // therefore the sort indicator should be there
+                sortAscending = ascending[0];
+                sortContainerPropertyId = propertyId[0];
+            } else {
+                sortAscending = true;
+                sortContainerPropertyId = null;
+            }
+        } else if (c != null) {
+            throw new UnsupportedOperationException(
+                    "Underlying Data does not allow sorting");
+        }
+    }
+
+    /**
+     * Sorts the table by currently selected sorting column.
+     * 
+     * @throws UnsupportedOperationException
+     *             if the container data source does not implement
+     *             Container.Sortable
+     */
+    public void sort() {
+        if (getSortContainerPropertyId() == null) {
+            return;
+        }
+        sort(new Object[] { sortContainerPropertyId },
+                new boolean[] { sortAscending });
+    }
+
+    /** Gets the container property IDs, which can be used to sort the item.
+	 * <p>
+	 * Note that the {@link #isSortEnabled()} state affects what this method
+	 * returns. Disabling sorting causes this method to always return an empty
+	 * collection.
+	 *
+	 * @return the sortable container property ids
+	 * @see com.vaadin.data.Container.Sortable#getSortableContainerPropertyIds()
+	 */
+
+    @Override
+    public Collection<?> getSortableContainerPropertyIds() {
+        final Container c = getContainerDataSource();
+        if (c instanceof Container.Sortable && isSortEnabled()) {
+            return ((Container.Sortable) c).getSortableContainerPropertyIds();
+        } else {
+            return Collections.EMPTY_LIST;
+        }
+    }
+
+    /**
+     * Gets the currently sorted column property ID.
+     * 
+     * @return the Container property id of the currently sorted column.
+     */
+    public Object getSortContainerPropertyId() {
+        return sortContainerPropertyId;
+    }
+
+    /**
+     * Sets the currently sorted column property id.
+     * 
+     * @param propertyId
+     *            the Container property id of the currently sorted column.
+     */
+    public void setSortContainerPropertyId(Object propertyId) {
+        setSortContainerPropertyId(propertyId, true);
+    }
+
+    /** Internal method to set currently sorted column property id. With
+	 * doSort flag actual sorting may be bypassed.
+	 *
+	 * @param propertyId
+	 *            the property id
+	 * @param doSort
+	 *            the do sort
+	 */
+    private void setSortContainerPropertyId(Object propertyId, boolean doSort) {
+        if ((sortContainerPropertyId != null && !sortContainerPropertyId
+                .equals(propertyId))
+                || (sortContainerPropertyId == null && propertyId != null)) {
+            sortContainerPropertyId = propertyId;
+
+            if (doSort) {
+                sort();
+                // Assures the visual refresh. This should not be necessary as
+                // sort() calls refreshRowCache
+                refreshRenderedCells();
+            }
+        }
+    }
+
+    /**
+     * Is the table currently sorted in ascending order.
+     * 
+     * @return <code>true</code> if ascending, <code>false</code> if descending.
+     */
+    public boolean isSortAscending() {
+        return sortAscending;
+    }
+
+    /**
+     * Sets the table in ascending order.
+     * 
+     * @param ascending
+     *            <code>true</code> if ascending, <code>false</code> if
+     *            descending.
+     */
+    public void setSortAscending(boolean ascending) {
+        setSortAscending(ascending, true);
+    }
+
+    /** Internal method to set sort ascending. With doSort flag actual sort
+	 * can be bypassed.
+	 *
+	 * @param ascending
+	 *            the ascending
+	 * @param doSort
+	 *            the do sort
+	 */
+    private void setSortAscending(boolean ascending, boolean doSort) {
+        if (sortAscending != ascending) {
+            sortAscending = ascending;
+            if (doSort) {
+                sort();
+                // Assures the visual refresh. This should not be necessary as
+                // sort() calls refreshRowCache
+                refreshRenderedCells();
+            }
+        }
+    }
+
+    /**
+     * Is sorting disabled altogether.
+     * 
+     * True iff no sortable columns are given even in the case where data source
+     * would support this.
+     * 
+     * @return True iff sorting is disabled.
+     * @deprecated As of 7.0, use {@link #isSortEnabled()} instead
+     */
+    @Deprecated
+    public boolean isSortDisabled() {
+        return !isSortEnabled();
+    }
+
+    /**
+     * Checks if sorting is enabled.
+     * 
+     * @return true if sorting by the user is allowed, false otherwise
+     */
+    public boolean isSortEnabled() {
+        return sortEnabled;
+    }
+
+    /**
+     * Disables the sorting by the user altogether.
+     * 
+     * @param sortDisabled
+     *            True iff sorting is disabled.
+     * @deprecated As of 7.0, use {@link #setSortEnabled(boolean)} instead
+     */
+    @Deprecated
+    public void setSortDisabled(boolean sortDisabled) {
+        setSortEnabled(!sortDisabled);
+    }
+
+    /**
+     * Enables or disables sorting.
+     * <p>
+     * Setting this to false disallows sorting by the user. It is still possible
+     * to call {@link #sort()}.
+     * 
+     * 
+     * @param sortEnabled
+     *            true to allow the user to sort the table, false to disallow it
+     */
+    public void setSortEnabled(boolean sortEnabled) {
+        if (this.sortEnabled != sortEnabled) {
+            this.sortEnabled = sortEnabled;
+            markAsDirty();
+        }
+    }
+
+    /**
+     * Used to create "generated columns"; columns that exist only in the
+     * CustomTable, not in the underlying Container. Implement this interface
+     * and pass it to CustomTable.addGeneratedColumn along with an id for the
+     * column to be generated.
+     * 
+     */
+    public interface ColumnGenerator extends Serializable {
+
+        /**
+         * Called by CustomTable when a cell in a generated column needs to be
+         * generated.
+         * 
+         * @param source
+         *            the source CustomTable
+         * @param itemId
+         *            the itemId (aka rowId) for the of the cell to be generated
+         * @param columnId
+         *            the id for the generated column (as specified in
+         *            addGeneratedColumn)
+         * @return A {@link Component} that should be rendered in the cell or a
+         *         {@link String} that should be displayed in the cell. Other
+         *         return values are not supported.
+         */
+        public abstract Object generateCell(CustomTable source, Object itemId,
+                Object columnId);
+    }
+
+    /**
+     * Set cell style generator for CustomTable.
+     * 
+     * @param cellStyleGenerator
+     *            New cell style generator or null to remove generator.
+     */
+    public void setCellStyleGenerator(CellStyleGenerator cellStyleGenerator) {
+        this.cellStyleGenerator = cellStyleGenerator;
+        // Assures the visual refresh. No need to reset the page buffer
+        // before as the content has not changed, only the style generators
+        refreshRenderedCells();
+
+    }
+
+    /** Get the current cell style generator.
+	 *
+	 * @return the customTable cell specific style generator
+	 */
+    public CellStyleGenerator getCellStyleGenerator() {
+        return cellStyleGenerator;
+    }
+
+    /**
+     * Allow to define specific style on cells (and rows) contents. Implements
+     * this interface and pass it to CustomTable.setCellStyleGenerator. Row
+     * styles are generated when porpertyId is null. The CSS class name that
+     * will be added to the cell content is
+     * <tt>v-table-cell-content-[style name]</tt>, and the row style will be
+     * <tt>v-table-row-[style name]</tt>.
+     */
+    public interface CellStyleGenerator extends Serializable {
+
+        /**
+         * Called by CustomTable when a cell (and row) is painted.
+         * 
+         * @param source
+         *            the source CustomTable
+         * @param itemId
+         *            The itemId of the painted cell
+         * @param propertyId
+         *            The propertyId of the cell, null when getting row style
+         * @return The style name to add to this cell or row. (the CSS class
+         *         name will be v-table-cell-content-[style name], or
+         *         v-table-row-[style name] for rows)
+         */
+        public abstract String getStyle(CustomTable source, Object itemId,
+                Object propertyId);
+    }
+
+    /* (non-Javadoc)
+     * @see com.vaadin.event.ItemClickEvent.ItemClickNotifier#addItemClickListener(com.vaadin.event.ItemClickEvent.ItemClickListener)
+     */
+    @Override
+    public void addItemClickListener(ItemClickListener listener) {
+        addListener(TableConstants.ITEM_CLICK_EVENT_ID, ItemClickEvent.class,
+                listener, ItemClickEvent.ITEM_CLICK_METHOD);
+    }
+
+    /** Adds the listener.
+	 *
+	 * @param listener
+	 *            the listener
+	 * @deprecated As of 7.0, replaced by
+	 *             {@link #addItemClickListener(ItemClickListener)}
+	 */
+    @Override
+    @Deprecated
+    public void addListener(ItemClickListener listener) {
+        addItemClickListener(listener);
+    }
+
+    /* (non-Javadoc)
+     * @see com.vaadin.event.ItemClickEvent.ItemClickNotifier#removeItemClickListener(com.vaadin.event.ItemClickEvent.ItemClickListener)
+     */
+    @Override
+    public void removeItemClickListener(ItemClickListener listener) {
+        removeListener(TableConstants.ITEM_CLICK_EVENT_ID,
+                ItemClickEvent.class, listener);
+    }
+
+    /** Removes the listener.
+	 *
+	 * @param listener
+	 *            the listener
+	 * @deprecated As of 7.0, replaced by
+	 *             {@link #removeItemClickListener(ItemClickListener)}
+	 */
+    @Override
+    @Deprecated
+    public void removeListener(ItemClickListener listener) {
+        removeItemClickListener(listener);
+    }
+
+    // Identical to AbstractCompoenentContainer.setEnabled();
+
+    /* (non-Javadoc)
+     * @see com.vaadin.ui.AbstractComponent#setEnabled(boolean)
+     */
+    @Override
+    public void setEnabled(boolean enabled) {
+        super.setEnabled(enabled);
+        if (getParent() != null && !getParent().isEnabled()) {
+            // some ancestor still disabled, don't update children
+            return;
+        } else {
+            markAsDirtyRecursive();
+        }
+    }
+
+    /** Sets the drag start mode of the CustomTable. Drag start mode controls
+	 * how CustomTable behaves as a drag source.
+	 *
+	 * @param newDragMode
+	 *            the new drag mode
+	 */
+    public void setDragMode(TableDragMode newDragMode) {
+        dragMode = newDragMode;
+        markAsDirty();
+    }
+
+    /** Gets the drag mode.
+	 *
+	 * @return the current start mode of the CustomTable. Drag start mode
+	 *         controls how CustomTable behaves as a drag source.
+	 */
+    public TableDragMode getDragMode() {
+        return dragMode;
+    }
+
+    /**
+     * Concrete implementation of {@link DataBoundTransferable} for data
+     * transferred from a table.
+     * 
+     * @see DataBoundTransferable
+     * 
+     * @since 6.3
+     */
+    public class TableTransferable extends DataBoundTransferable {
+
+        /** Instantiates a new table transferable.
+		 *
+		 * @param rawVariables
+		 *            the raw variables
+		 */
+        protected TableTransferable(Map<String, Object> rawVariables) {
+            super(CustomTable.this, rawVariables);
+            Object object = rawVariables.get("itemId");
+            if (object != null) {
+                setData("itemId", itemIdMapper.get((String) object));
+            }
+            object = rawVariables.get("propertyId");
+            if (object != null) {
+                setData("propertyId", columnIdMap.get((String) object));
+            }
+        }
+
+        /* (non-Javadoc)
+         * @see com.vaadin.event.DataBoundTransferable#getItemId()
+         */
+        @Override
+        public Object getItemId() {
+            return getData("itemId");
+        }
+
+        /* (non-Javadoc)
+         * @see com.vaadin.event.DataBoundTransferable#getPropertyId()
+         */
+        @Override
+        public Object getPropertyId() {
+            return getData("propertyId");
+        }
+
+        /* (non-Javadoc)
+         * @see com.vaadin.event.TransferableImpl#getSourceComponent()
+         */
+        @Override
+        public CustomTable getSourceComponent() {
+            return (CustomTable) super.getSourceComponent();
+        }
+
+    }
+
+    /* (non-Javadoc)
+     * @see com.vaadin.event.dd.DragSource#getTransferable(java.util.Map)
+     */
+    @Override
+    public TableTransferable getTransferable(Map<String, Object> rawVariables) {
+        TableTransferable transferable = new TableTransferable(rawVariables);
+        return transferable;
+    }
+
+    /* (non-Javadoc)
+     * @see com.vaadin.event.dd.DropTarget#getDropHandler()
+     */
+    @Override
+    public DropHandler getDropHandler() {
+        return dropHandler;
+    }
+
+    /** Sets the drop handler.
+	 *
+	 * @param dropHandler
+	 *            the new drop handler
+	 */
+    public void setDropHandler(DropHandler dropHandler) {
+        this.dropHandler = dropHandler;
+    }
+
+    /* (non-Javadoc)
+     * @see com.vaadin.event.dd.DropTarget#translateDropTargetDetails(java.util.Map)
+     */
+    @Override
+    public AbstractSelectTargetDetails translateDropTargetDetails(
+            Map<String, Object> clientVariables) {
+        return new AbstractSelectTargetDetails(clientVariables);
+    }
+
+    /**
+     * Sets the behavior of how the multi-select mode should behave when the
+     * table is both selectable and in multi-select mode.
+     * <p>
+     * Note, that on some clients the mode may not be respected. E.g. on touch
+     * based devices CTRL/SHIFT base selection method is invalid, so touch based
+     * browsers always use the {@link MultiSelectMode#SIMPLE}.
+     * 
+     * @param mode
+     *            The select mode of the table
+     */
+    public void setMultiSelectMode(MultiSelectMode mode) {
+        multiSelectMode = mode;
+        markAsDirty();
+    }
+
+    /**
+     * Returns the select mode in which multi-select is used.
+     * 
+     * @return The multi select mode
+     */
+    public MultiSelectMode getMultiSelectMode() {
+        return multiSelectMode;
+    }
+
+    /**
+     * Lazy loading accept criterion for CustomTable. Accepted target rows are
+     * loaded from server once per drag and drop operation. Developer must
+     * override one method that decides on which rows the currently dragged data
+     * can be dropped.
+     * 
+     * <p>
+     * Initially pretty much no data is sent to client. On first required
+     * criterion check (per drag request) the client side data structure is
+     * initialized from server and no subsequent requests requests are needed
+     * during that drag and drop operation.
+     */
+    public static abstract class TableDropCriterion extends ServerSideCriterion {
+
+        /** The table. */
+        private CustomTable table;
+
+        /** The allowed item ids. */
+        private Set<Object> allowedItemIds;
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see
+         * com.vaadin.event.dd.acceptcriteria.ServerSideCriterion#getIdentifier
+         * ()
+         */
+
+        @Override
+        protected String getIdentifier() {
+            return TableDropCriterion.class.getCanonicalName();
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see
+         * com.vaadin.event.dd.acceptcriteria.AcceptCriterion#accepts(com.vaadin
+         * .event.dd.DragAndDropEvent)
+         */
+        @Override
+        @SuppressWarnings("unchecked")
+        public boolean accept(DragAndDropEvent dragEvent) {
+            AbstractSelectTargetDetails dropTargetData = (AbstractSelectTargetDetails) dragEvent
+                    .getTargetDetails();
+            table = (CustomTable) dragEvent.getTargetDetails().getTarget();
+            Collection<?> visibleItemIds = table.getVisibleItemIds();
+            allowedItemIds = getAllowedItemIds(dragEvent, table,
+                    (Collection<Object>) visibleItemIds);
+
+            return allowedItemIds.contains(dropTargetData.getItemIdOver());
+        }
+
+        /*
+         * (non-Javadoc)
+         * 
+         * @see
+         * com.vaadin.event.dd.acceptcriteria.AcceptCriterion#paintResponse(
+         * com.vaadin.server.PaintTarget)
+         */
+
+        @Override
+        public void paintResponse(PaintTarget target) throws PaintException {
+            /*
+             * send allowed nodes to client so subsequent requests can be
+             * avoided
+             */
+            Object[] array = allowedItemIds.toArray();
+            for (int i = 0; i < array.length; i++) {
+                String key = table.itemIdMapper.key(array[i]);
+                array[i] = key;
+            }
+            target.addAttribute("allowedIds", array);
+        }
+
+        /** Gets the allowed item ids.
+		 *
+		 * @param dragEvent
+		 *            the drag event
+		 * @param table
+		 *            the table for which the allowed item identifiers are
+		 *            defined
+		 * @param visibleItemIds
+		 *            the list of currently rendered item identifiers, accepted
+		 *            item id's need to be detected only for these visible items
+		 * @return the set of identifiers for items on which the dragEvent will
+		 *         be accepted
+		 */
+        protected abstract Set<Object> getAllowedItemIds(
+                DragAndDropEvent dragEvent, CustomTable table,
+                Collection<Object> visibleItemIds);
+
+    }
+
+    /**
+     * Click event fired when clicking on the CustomTable headers. The event
+     * includes a reference the the CustomTable the event originated from, the
+     * property id of the column which header was pressed and details about the
+     * mouse event itself.
+     */
+    public static class HeaderClickEvent extends ClickEvent {
+        
+        /** The Constant HEADER_CLICK_METHOD. */
+        public static final Method HEADER_CLICK_METHOD;
+
+        static {
+            try {
+                // Set the header click method
+                HEADER_CLICK_METHOD = HeaderClickListener.class
+                        .getDeclaredMethod("headerClick",
+                                new Class[] { HeaderClickEvent.class });
+            } catch (final java.lang.NoSuchMethodException e) {
+                // This should never happen
+                throw new java.lang.RuntimeException(e);
+            }
+        }
+
+        /** The column property id. */
+        // The property id of the column which header was pressed
+        private final Object columnPropertyId;
+
+        /** Instantiates a new header click event.
+		 *
+		 * @param source
+		 *            the source
+		 * @param propertyId
+		 *            the property id
+		 * @param details
+		 *            the details
+		 */
+        public HeaderClickEvent(Component source, Object propertyId,
+                MouseEventDetails details) {
+            super(source, details);
+            columnPropertyId = propertyId;
+        }
+
+        /** Gets the property id of the column which header was pressed.
+		 *
+		 * @return The column propety id
+		 */
+        public Object getPropertyId() {
+            return columnPropertyId;
+        }
+    }
+
+    /**
+     * Click event fired when clicking on the CustomTable footers. The event
+     * includes a reference the the CustomTable the event originated from, the
+     * property id of the column which header was pressed and details about the
+     * mouse event itself.
+     */
+    public static class FooterClickEvent extends ClickEvent {
+        
+        /** The Constant FOOTER_CLICK_METHOD. */
+        public static final Method FOOTER_CLICK_METHOD;
+
+        static {
+            try {
+                // Set the header click method
+                FOOTER_CLICK_METHOD = FooterClickListener.class
+                        .getDeclaredMethod("footerClick",
+                                new Class[] { FooterClickEvent.class });
+            } catch (final java.lang.NoSuchMethodException e) {
+                // This should never happen
+                throw new java.lang.RuntimeException(e);
+            }
+        }
+
+        /** The column property id. */
+        // The property id of the column which header was pressed
+        private final Object columnPropertyId;
+
+        /** Constructor.
+		 *
+		 * @param source
+		 *            The source of the component
+		 * @param propertyId
+		 *            The propertyId of the column
+		 * @param details
+		 *            The mouse details of the click
+		 */
+        public FooterClickEvent(Component source, Object propertyId,
+                MouseEventDetails details) {
+            super(source, details);
+            columnPropertyId = propertyId;
+        }
+
+        /** Gets the property id of the column which header was pressed.
+		 *
+		 * @return The column propety id
+		 */
+        public Object getPropertyId() {
+            return columnPropertyId;
+        }
+    }
+
+    /** Interface for the listener for column header mouse click events. The
+	 * headerClick method is called when the user presses a header column cell.
+	 *
+	 * @see HeaderClickEvent
+	 */
+    public interface HeaderClickListener extends Serializable {
+
+        /** Called when a user clicks a header column cell.
+		 *
+		 * @param event
+		 *            The event which contains information about the column and
+		 *            the mouse click event
+		 */
+        public void headerClick(HeaderClickEvent event);
+    }
+
+    /** Interface for the listener for column footer mouse click events. The
+	 * footerClick method is called when the user presses a footer column cell.
+	 *
+	 * @see FooterClickEvent
+	 */
+    public interface FooterClickListener extends Serializable {
+
+        /** Called when a user clicks a footer column cell.
+		 *
+		 * @param event
+		 *            The event which contains information about the column and
+		 *            the mouse click event
+		 */
+        public void footerClick(FooterClickEvent event);
+    }
+
+    /**
+     * Adds a header click listener which handles the click events when the user
+     * clicks on a column header cell in the CustomTable.
+     * <p>
+     * The listener will receive events which contain information about which
+     * column was clicked and some details about the mouse event.
+     * 
+     * 
+     * @param listener
+     *            The handler which should handle the header click events.
+     */
+    public void addHeaderClickListener(HeaderClickListener listener) {
+        addListener(TableConstants.HEADER_CLICK_EVENT_ID,
+                HeaderClickEvent.class, listener,
+                HeaderClickEvent.HEADER_CLICK_METHOD);
+    }
+
+    /** Adds the listener.
+	 *
+	 * @param listener
+	 *            the listener
+	 * @deprecated As of 7.0, replaced by
+	 *             {@link #addHeaderClickListener(HeaderClickListener)}
+	 */
+    @Deprecated
+    public void addListener(HeaderClickListener listener) {
+        addHeaderClickListener(listener);
+    }
+
+    /** Removes a header click listener.
+	 *
+	 * @param listener
+	 *            The listener to remove.
+	 */
+    public void removeHeaderClickListener(HeaderClickListener listener) {
+        removeListener(TableConstants.HEADER_CLICK_EVENT_ID,
+                HeaderClickEvent.class, listener);
+    }
+
+    /** Removes the listener.
+	 *
+	 * @param listener
+	 *            the listener
+	 * @deprecated As of 7.0, replaced by
+	 *             {@link #removeHeaderClickListener(HeaderClickListener)}
+	 */
+    @Deprecated
+    public void removeListener(HeaderClickListener listener) {
+        removeHeaderClickListener(listener);
+    }
+
+    /**
+     * Adds a footer click listener which handles the click events when the user
+     * clicks on a column footer cell in the CustomTable.
+     * <p>
+     * The listener will receive events which contain information about which
+     * column was clicked and some details about the mouse event.
+     * 
+     * 
+     * @param listener
+     *            The handler which should handle the footer click events.
+     */
+    public void addFooterClickListener(FooterClickListener listener) {
+        addListener(TableConstants.FOOTER_CLICK_EVENT_ID,
+                FooterClickEvent.class, listener,
+                FooterClickEvent.FOOTER_CLICK_METHOD);
+    }
+
+    /** Adds the listener.
+	 *
+	 * @param listener
+	 *            the listener
+	 * @deprecated As of 7.0, replaced by
+	 *             {@link #addFooterClickListener(FooterClickListener)}
+	 */
+    @Deprecated
+    public void addListener(FooterClickListener listener) {
+        addFooterClickListener(listener);
+    }
+
+    /** Removes a footer click listener.
+	 *
+	 * @param listener
+	 *            The listener to remove.
+	 */
+    public void removeFooterClickListener(FooterClickListener listener) {
+        removeListener(TableConstants.FOOTER_CLICK_EVENT_ID,
+                FooterClickEvent.class, listener);
+    }
+
+    /** Removes the listener.
+	 *
+	 * @param listener
+	 *            the listener
+	 * @deprecated As of 7.0, replaced by
+	 *             {@link #removeFooterClickListener(FooterClickListener)}
+	 */
+    @Deprecated
+    public void removeListener(FooterClickListener listener) {
+        removeFooterClickListener(listener);
+    }
+
+    /** Gets the footer caption beneath the rows.
+	 *
+	 * @param propertyId
+	 *            The propertyId of the column *
+	 * @return The caption of the footer or NULL if not set
+	 */
+    public String getColumnFooter(Object propertyId) {
+        return columnFooters.get(propertyId);
+    }
+
+    /**
+     * Sets the column footer caption. The column footer caption is the text
+     * displayed beneath the column if footers have been set visible.
+     * 
+     * @param propertyId
+     *            The properyId of the column
+     * 
+     * @param footer
+     *            The caption of the footer
+     */
+    public void setColumnFooter(Object propertyId, String footer) {
+        if (footer == null) {
+            columnFooters.remove(propertyId);
+        } else {
+            columnFooters.put(propertyId, footer);
+        }
+
+        markAsDirty();
+    }
+
+    /**
+     * Sets the footer visible in the bottom of the table.
+     * <p>
+     * The footer can be used to add column related data like sums to the bottom
+     * of the CustomTable using setColumnFooter(Object propertyId, String
+     * footer).
+     * 
+     * 
+     * @param visible
+     *            Should the footer be visible
+     */
+    public void setFooterVisible(boolean visible) {
+        if (visible != columnFootersVisible) {
+            columnFootersVisible = visible;
+            markAsDirty();
+        }
+    }
+
+    /** Is the footer currently visible?.
+	 *
+	 * @return Returns true if visible else false
+	 */
+    public boolean isFooterVisible() {
+        return columnFootersVisible;
+    }
+
+    /**
+     * This event is fired when a column is resized. The event contains the
+     * columns property id which was fired, the previous width of the column and
+     * the width of the column after the resize.
+     */
+    public static class ColumnResizeEvent extends Component.Event {
+        
+        /** The Constant COLUMN_RESIZE_METHOD. */
+        public static final Method COLUMN_RESIZE_METHOD;
+
+        static {
+            try {
+                COLUMN_RESIZE_METHOD = ColumnResizeListener.class
+                        .getDeclaredMethod("columnResize",
+                                new Class[] { ColumnResizeEvent.class });
+            } catch (final java.lang.NoSuchMethodException e) {
+                // This should never happen
+                throw new java.lang.RuntimeException(e);
+            }
+        }
+
+        /** The previous width. */
+        private final int previousWidth;
+        
+        /** The current width. */
+        private final int currentWidth;
+        
+        /** The column property id. */
+        private final Object columnPropertyId;
+
+        /** Constructor.
+		 *
+		 * @param source
+		 *            The source of the event
+		 * @param propertyId
+		 *            The columns property id
+		 * @param previous
+		 *            The width in pixels of the column before the resize event
+		 * @param current
+		 *            The width in pixels of the column after the resize event
+		 */
+        public ColumnResizeEvent(Component source, Object propertyId,
+                int previous, int current) {
+            super(source);
+            previousWidth = previous;
+            currentWidth = current;
+            columnPropertyId = propertyId;
+        }
+
+        /**
+         * Get the column property id of the column that was resized.
+         * 
+         * @return The column property id
+         */
+        public Object getPropertyId() {
+            return columnPropertyId;
+        }
+
+        /** Get the width in pixels of the column before the resize event.
+		 *
+		 * @return Width in pixels
+		 */
+        public int getPreviousWidth() {
+            return previousWidth;
+        }
+
+        /** Get the width in pixels of the column after the resize event.
+		 *
+		 * @return Width in pixels
+		 */
+        public int getCurrentWidth() {
+            return currentWidth;
+        }
+    }
+
+    /** Interface for listening to column resize events.
+	 *
+	 * @see ColumnResizeEvent
+	 */
+    public interface ColumnResizeListener extends Serializable {
+
+        /** This method is triggered when the column has been resized.
+		 *
+		 * @param event
+		 *            The event which contains the column property id, the
+		 *            previous width of the column and the current width of the
+		 *            column
+		 */
+        public void columnResize(ColumnResizeEvent event);
+    }
+
+    /**
+     * Adds a column resize listener to the CustomTable. A column resize
+     * listener is called when a user resizes a columns width.
+     * 
+     * @param listener
+     *            The listener to attach to the CustomTable
+     */
+    public void addColumnResizeListener(ColumnResizeListener listener) {
+        addListener(TableConstants.COLUMN_RESIZE_EVENT_ID,
+                ColumnResizeEvent.class, listener,
+                ColumnResizeEvent.COLUMN_RESIZE_METHOD);
+    }
+
+    /** Adds the listener.
+	 *
+	 * @param listener
+	 *            the listener
+	 * @deprecated As of 7.0, replaced by
+	 *             {@link #addColumnResizeListener(ColumnResizeListener)}
+	 */
+    @Deprecated
+    public void addListener(ColumnResizeListener listener) {
+        addColumnResizeListener(listener);
+    }
+
+    /**
+     * Removes a column resize listener from the CustomTable.
+     * 
+     * @param listener
+     *            The listener to remove
+     */
+    public void removeColumnResizeListener(ColumnResizeListener listener) {
+        removeListener(TableConstants.COLUMN_RESIZE_EVENT_ID,
+                ColumnResizeEvent.class, listener);
+    }
+
+    /** Removes the listener.
+	 *
+	 * @param listener
+	 *            the listener
+	 * @deprecated As of 7.0, replaced by
+	 *             {@link #removeColumnResizeListener(ColumnResizeListener)}
+	 */
+    @Deprecated
+    public void removeListener(ColumnResizeListener listener) {
+        removeColumnResizeListener(listener);
+    }
+
+    /**
+     * This event is fired when a columns are reordered by the end user user.
+     */
+    public static class ColumnReorderEvent extends Component.Event {
+        
+        /** The Constant METHOD. */
+        public static final Method METHOD;
+
+        static {
+            try {
+                METHOD = ColumnReorderListener.class.getDeclaredMethod(
+                        "columnReorder",
+                        new Class[] { ColumnReorderEvent.class });
+            } catch (final java.lang.NoSuchMethodException e) {
+                // This should never happen
+                throw new java.lang.RuntimeException(e);
+            }
+        }
+
+        /** Constructor.
+		 *
+		 * @param source
+		 *            The source of the event
+		 */
+        public ColumnReorderEvent(Component source) {
+            super(source);
+        }
+
+    }
+
+    /** Interface for listening to column reorder events.
+	 *
+	 * @see ColumnReorderEvent
+	 */
+    public interface ColumnReorderListener extends Serializable {
+
+        /** This method is triggered when the column has been reordered.
+		 *
+		 * @param event
+		 *            the event
+		 */
+        public void columnReorder(ColumnReorderEvent event);
+    }
+
+    /**
+     * Adds a column reorder listener to the CustomTable. A column reorder
+     * listener is called when a user reorders columns.
+     * 
+     * @param listener
+     *            The listener to attach to the CustomTable
+     */
+    public void addColumnReorderListener(ColumnReorderListener listener) {
+        addListener(TableConstants.COLUMN_REORDER_EVENT_ID,
+                ColumnReorderEvent.class, listener, ColumnReorderEvent.METHOD);
+    }
+
+    /** Adds the listener.
+	 *
+	 * @param listener
+	 *            the listener
+	 * @deprecated As of 7.0, replaced by
+	 *             {@link #addColumnReorderListener(ColumnReorderListener)}
+	 */
+    @Deprecated
+    public void addListener(ColumnReorderListener listener) {
+        addColumnReorderListener(listener);
+    }
+
+    /**
+     * Removes a column reorder listener from the CustomTable.
+     * 
+     * @param listener
+     *            The listener to remove
+     */
+    public void removeColumnReorderListener(ColumnReorderListener listener) {
+        removeListener(TableConstants.COLUMN_REORDER_EVENT_ID,
+                ColumnReorderEvent.class, listener);
+    }
+
+    /** Removes the listener.
+	 *
+	 * @param listener
+	 *            the listener
+	 * @deprecated As of 7.0, replaced by
+	 *             {@link #removeColumnReorderListener(ColumnReorderListener)}
+	 */
+    @Deprecated
+    public void removeListener(ColumnReorderListener listener) {
+        removeColumnReorderListener(listener);
+    }
+
+    /** Set the item description generator which generates tooltips for cells
+	 * and rows in the CustomTable.
+	 *
+	 * @param generator
+	 *            The generator to use or null to disable
+	 */
+    public void setItemDescriptionGenerator(ItemDescriptionGenerator generator) {
+        if (generator != itemDescriptionGenerator) {
+            itemDescriptionGenerator = generator;
+            // Assures the visual refresh. No need to reset the page buffer
+            // before as the content has not changed, only the descriptions
+            refreshRenderedCells();
+        }
+    }
+
+    /** Get the item description generator which generates tooltips for cells
+	 * and rows in the CustomTable.
+	 *
+	 * @return the customTable cell specific tooltip generator
+	 */
+    public ItemDescriptionGenerator getItemDescriptionGenerator() {
+        return itemDescriptionGenerator;
+    }
+
+    /**
+     * Row generators can be used to replace certain items in a table with a
+     * generated string. The generator is called each time the table is
+     * rendered, which means that new strings can be generated each time.
+     * 
+     * Row generators can be used for e.g. summary rows or grouping of items.
+     */
+    public interface RowGenerator extends Serializable {
+        /**
+         * Called for every row that is painted in the CustomTable. Returning a
+         * GeneratedRow object will cause the row to be painted based on the
+         * contents of the GeneratedRow. A generated row is by default styled
+         * similarly to a header or footer row.
+         * <p>
+         * The GeneratedRow data object contains the text that should be
+         * rendered in the row. The itemId in the container thus works only as a
+         * placeholder.
+         * <p>
+         * If GeneratedRow.setSpanColumns(true) is used, there will be one
+         * String spanning all columns (use setText("Spanning text")). Otherwise
+         * you can define one String per visible column.
+         * <p>
+         * If GeneratedRow.setRenderAsHtml(true) is used, the strings can
+         * contain HTML markup, otherwise all strings will be rendered as text
+         * (the default).
+         * <p>
+         * A "v-table-generated-row" CSS class is added to all generated rows.
+         * For custom styling of a generated row you can combine a RowGenerator
+         * with a CellStyleGenerator.
+         * <p>
+         * 
+         * @param table
+         *            The CustomTable that is being painted
+         * @param itemId
+         *            The itemId for the row
+         * @return A GeneratedRow describing how the row should be painted or
+         *         null to paint the row with the contents from the container
+         */
+        public GeneratedRow generateRow(CustomTable table, Object itemId);
+    }
+
+    /** The Class GeneratedRow.
+	 */
+    public static class GeneratedRow implements Serializable {
+        
+        /** The html content allowed. */
+        private boolean htmlContentAllowed = false;
+        
+        /** The span columns. */
+        private boolean spanColumns = false;
+        
+        /** The text. */
+        private String[] text = null;
+
+        /** Creates a new generated row. If only one string is passed in,
+		 * columns are automatically spanned.
+		 *
+		 * @param text
+		 *            the text
+		 */
+        public GeneratedRow(String... text) {
+            setHtmlContentAllowed(false);
+            setSpanColumns(text == null || text.length == 1);
+            setText(text);
+        }
+
+        /** Pass one String if spanColumns is used, one String for each
+		 * visible column otherwise.
+		 *
+		 * @param text
+		 *            the new text
+		 */
+        public void setText(String... text) {
+            if (text == null || (text.length == 1 && text[0] == null)) {
+                text = new String[] { "" };
+            }
+            this.text = text;
+        }
+
+        /** Gets the text.
+		 *
+		 * @return the text
+		 */
+        protected String[] getText() {
+            return text;
+        }
+
+        /** Gets the value.
+		 *
+		 * @return the value
+		 */
+        protected Object getValue() {
+            return getText();
+        }
+
+        /** Checks if is html content allowed.
+		 *
+		 * @return true, if is html content allowed
+		 */
+        protected boolean isHtmlContentAllowed() {
+            return htmlContentAllowed;
+        }
+
+        /** If set to true, all strings passed to {@link #setText(String...)}
+		 * will be rendered as HTML.
+		 *
+		 * @param htmlContentAllowed
+		 *            the new html content allowed
+		 */
+        public void setHtmlContentAllowed(boolean htmlContentAllowed) {
+            this.htmlContentAllowed = htmlContentAllowed;
+        }
+
+        /** Checks if is span columns.
+		 *
+		 * @return true, if is span columns
+		 */
+        protected boolean isSpanColumns() {
+            return spanColumns;
+        }
+
+        /** If set to true, only one string will be rendered, spanning the
+		 * entire row.
+		 *
+		 * @param spanColumns
+		 *            the new span columns
+		 */
+        public void setSpanColumns(boolean spanColumns) {
+            this.spanColumns = spanColumns;
+        }
+    }
+
+    /**
+     * Assigns a row generator to the table. The row generator will be able to
+     * replace rows in the table when it is rendered.
+     * 
+     * @param generator
+     *            the new row generator
+     */
+    public void setRowGenerator(RowGenerator generator) {
+        rowGenerator = generator;
+        refreshRowCache();
+    }
+
+    /** Gets the row generator.
+	 *
+	 * @return the current row generator
+	 */
+    public RowGenerator getRowGenerator() {
+        return rowGenerator;
+    }
+
+    /**
+     * Sets a converter for a property id.
+     * <p>
+     * The converter is used to format the the data for the given property id
+     * before displaying it in the table.
+     * 
+     * 
+     * @param propertyId
+     *            The propertyId to format using the converter
+     * @param converter
+     *            The converter to use for the property id
+     */
+    public void setConverter(Object propertyId, Converter<String, ?> converter) {
+        if (!getContainerPropertyIds().contains(propertyId)) {
+            throw new IllegalArgumentException("PropertyId " + propertyId
+                    + " must be in the container");
+        }
+
+        if (!typeIsCompatible(converter.getModelType(), getType(propertyId))) {
+            throw new IllegalArgumentException("Property type ("
+                    + getType(propertyId)
+                    + ") must match converter source type ("
+                    + converter.getModelType() + ")");
+        }
+        propertyValueConverters.put(propertyId,
+                (Converter<String, Object>) converter);
+        refreshRowCache();
+    }
+
+    /**
+     * Checks if there is a converter set explicitly for the given property id.
+     * 
+     * @param propertyId
+     *            The propertyId to check
+     * @return true if a converter has been set for the property id, false
+     *         otherwise
+     */
+    protected boolean hasConverter(Object propertyId) {
+        return propertyValueConverters.containsKey(propertyId);
+    }
+
+    /**
+     * Returns the converter used to format the given propertyId.
+     * 
+     * @param propertyId
+     *            The propertyId to check
+     * @return The converter used to format the propertyId or null if no
+     *         converter has been set
+     */
+    public Converter<String, Object> getConverter(Object propertyId) {
+        return propertyValueConverters.get(propertyId);
+    }
+
+    /* (non-Javadoc)
+     * @see com.vaadin.ui.AbstractComponent#setVisible(boolean)
+     */
+    @Override
+    public void setVisible(boolean visible) {
+        if (visible) {
+            // We need to ensure that the rows are sent to the client when the
+            // CustomTable is made visible if it has been rendered as invisible.
+            setRowCacheInvalidated(true);
+        }
+        super.setVisible(visible);
+    }
+
+    /* (non-Javadoc)
+     * @see com.vaadin.ui.HasComponents#iterator()
+     */
+    @Override
+    public Iterator<Component> iterator() {
+        if (visibleComponents == null) {
+            Collection<Component> empty = Collections.emptyList();
+            return empty.iterator();
+        }
+        return visibleComponents.iterator();
+    }
+
+    /** Gets the component iterator.
+	 *
+	 * @return the component iterator
+	 * @deprecated As of 7.0, use {@link #iterator()} instead.
+	 */
+    @Deprecated
+    public Iterator<Component> getComponentIterator() {
+        return iterator();
+    }
+
+    /** Gets the logger.
+	 *
+	 * @return the logger
+	 */
+    private final Logger getLogger() {
+        if (logger == null) {
+            logger = Logger.getLogger(CustomTable.class.getName());
+        }
+        return logger;
+    }
+}
diff --git a/org.eclipse.osbp.fork.vaadin.addon.filteringtable/src/com/vaadin/ui/CustomTreeTable.java b/org.eclipse.osbp.fork.vaadin.addon.filteringtable/src/com/vaadin/ui/CustomTreeTable.java
new file mode 100644
index 0000000..3fcf910
--- /dev/null
+++ b/org.eclipse.osbp.fork.vaadin.addon.filteringtable/src/com/vaadin/ui/CustomTreeTable.java
@@ -0,0 +1,894 @@
+/*
+ * Copyright 2000-2014 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.ui;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.vaadin.data.Collapsible;
+import com.vaadin.data.Container;
+import com.vaadin.data.Container.Hierarchical;
+import com.vaadin.data.util.ContainerHierarchicalWrapper;
+import com.vaadin.data.util.HierarchicalContainer;
+import com.vaadin.data.util.HierarchicalContainerOrderedWrapper;
+import com.vaadin.server.PaintException;
+import com.vaadin.server.PaintTarget;
+import com.vaadin.server.Resource;
+import com.vaadin.shared.ui.treetable.TreeTableConstants;
+import com.vaadin.ui.Tree.CollapseEvent;
+import com.vaadin.ui.Tree.CollapseListener;
+import com.vaadin.ui.Tree.ExpandEvent;
+import com.vaadin.ui.Tree.ExpandListener;
+
+/**
+ * TreeTable extends the {@link Table} component so that it can also visualize a
+ * hierarchy of its Items in a similar manner that {@link Tree} does. The tree
+ * hierarchy is always displayed in the first actual column of the TreeTable.
+ * <p>
+ * The TreeTable supports the usual {@link Table} features like lazy loading, so
+ * it should be no problem to display lots of items at once. Only required rows
+ * and some cache rows are sent to the client.
+ * <p>
+ * TreeTable supports standard {@link Hierarchical} container interfaces, but
+ * also a more fine tuned version - {@link Collapsible}. A container
+ * implementing the {@link Collapsible} interface stores the collapsed/expanded
+ * state internally and can this way scale better on the server side than with
+ * standard Hierarchical implementations. Developer must however note that
+ * {@link Collapsible} containers can not be shared among several users as they
+ * share UI state in the container.
+ */
+@SuppressWarnings({ "serial", "deprecation" })
+public class CustomTreeTable extends CustomTable implements Hierarchical {
+
+    private interface ContainerStrategy extends Serializable {
+        public int size();
+
+        public boolean isNodeOpen(Object itemId);
+
+        public int getDepth(Object itemId);
+
+        public void toggleChildVisibility(Object itemId);
+
+        public Object getIdByIndex(int index);
+
+        public int indexOfId(Object id);
+
+        public Object nextItemId(Object itemId);
+
+        public Object lastItemId();
+
+        public Object prevItemId(Object itemId);
+
+        public boolean isLastId(Object itemId);
+
+        public Collection<?> getItemIds();
+
+        public void containerItemSetChange(ItemSetChangeEvent event);
+    }
+
+    private abstract class AbstractStrategy implements ContainerStrategy {
+
+        /**
+         * Consider adding getDepth to {@link Collapsible}, might help
+         * scalability with some container implementations.
+         */
+
+        @Override
+        public int getDepth(Object itemId) {
+            int depth = 0;
+            Hierarchical hierarchicalContainer = getContainerDataSource();
+            while (!hierarchicalContainer.isRoot(itemId)) {
+                depth++;
+                itemId = hierarchicalContainer.getParent(itemId);
+            }
+            return depth;
+        }
+
+        @Override
+        public void containerItemSetChange(ItemSetChangeEvent event) {
+        }
+
+    }
+
+    /**
+     * This strategy is used if current container implements {@link Collapsible}
+     * .
+     * 
+     * open-collapsed logic diverted to container, otherwise use default
+     * implementations.
+     */
+    private class CollapsibleStrategy extends AbstractStrategy {
+
+        private Collapsible c() {
+            return (Collapsible) getContainerDataSource();
+        }
+
+        @Override
+        public void toggleChildVisibility(Object itemId) {
+            c().setCollapsed(itemId, !c().isCollapsed(itemId));
+        }
+
+        @Override
+        public boolean isNodeOpen(Object itemId) {
+            return !c().isCollapsed(itemId);
+        }
+
+        @Override
+        public int size() {
+            return CustomTreeTable.super.size();
+        }
+
+        @Override
+        public Object getIdByIndex(int index) {
+            return CustomTreeTable.super.getIdByIndex(index);
+        }
+
+        @Override
+        public int indexOfId(Object id) {
+            return CustomTreeTable.super.indexOfId(id);
+        }
+
+        @Override
+        public boolean isLastId(Object itemId) {
+            // using the default impl
+            return CustomTreeTable.super.isLastId(itemId);
+        }
+
+        @Override
+        public Object lastItemId() {
+            // using the default impl
+            return CustomTreeTable.super.lastItemId();
+        }
+
+        @Override
+        public Object nextItemId(Object itemId) {
+            return CustomTreeTable.super.nextItemId(itemId);
+        }
+
+        @Override
+        public Object prevItemId(Object itemId) {
+            return CustomTreeTable.super.prevItemId(itemId);
+        }
+
+        @Override
+        public Collection<?> getItemIds() {
+            return CustomTreeTable.super.getItemIds();
+        }
+
+    }
+
+    /**
+     * Strategy for Hierarchical but not Collapsible container like
+     * {@link HierarchicalContainer}.
+     * 
+     * Store collapsed/open states internally, fool Table to use preorder when
+     * accessing items from container via Ordered/Indexed methods.
+     */
+    private class HierarchicalStrategy extends AbstractStrategy {
+
+        private final HashSet<Object> openItems = new HashSet<Object>();
+
+        @Override
+        public boolean isNodeOpen(Object itemId) {
+            return openItems.contains(itemId);
+        }
+
+        @Override
+        public int size() {
+            return getPreOrder().size();
+        }
+
+        @Override
+        public Collection<Object> getItemIds() {
+            return Collections.unmodifiableCollection(getPreOrder());
+        }
+
+        @Override
+        public boolean isLastId(Object itemId) {
+            if (itemId == null) {
+                return false;
+            }
+
+            return itemId.equals(lastItemId());
+        }
+
+        @Override
+        public Object lastItemId() {
+            if (getPreOrder().size() > 0) {
+                return getPreOrder().get(getPreOrder().size() - 1);
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        public Object nextItemId(Object itemId) {
+            int indexOf = getPreOrder().indexOf(itemId);
+            if (indexOf == -1) {
+                return null;
+            }
+            indexOf++;
+            if (indexOf == getPreOrder().size()) {
+                return null;
+            } else {
+                return getPreOrder().get(indexOf);
+            }
+        }
+
+        @Override
+        public Object prevItemId(Object itemId) {
+            int indexOf = getPreOrder().indexOf(itemId);
+            indexOf--;
+            if (indexOf < 0) {
+                return null;
+            } else {
+                return getPreOrder().get(indexOf);
+            }
+        }
+
+        @Override
+        public void toggleChildVisibility(Object itemId) {
+            boolean removed = openItems.remove(itemId);
+            if (!removed) {
+                openItems.add(itemId);
+                getLogger().log(Level.FINEST, "Item {0} is now expanded",
+                        itemId);
+            } else {
+                getLogger().log(Level.FINEST, "Item {0} is now collapsed",
+                        itemId);
+            }
+            clearPreorderCache();
+        }
+
+        private void clearPreorderCache() {
+            preOrder = null; // clear preorder cache
+        }
+
+        List<Object> preOrder;
+
+        /**
+         * Preorder of ids currently visible
+         * 
+         * @return
+         */
+        private List<Object> getPreOrder() {
+            if (preOrder == null) {
+                preOrder = new ArrayList<Object>();
+                Collection<?> rootItemIds = getContainerDataSource()
+                        .rootItemIds();
+                for (Object id : rootItemIds) {
+                    preOrder.add(id);
+                    addVisibleChildTree(id);
+                }
+            }
+            return preOrder;
+        }
+
+        private void addVisibleChildTree(Object id) {
+            if (isNodeOpen(id)) {
+                Collection<?> children = getContainerDataSource().getChildren(
+                        id);
+                if (children != null) {
+                    for (Object childId : children) {
+                        preOrder.add(childId);
+                        addVisibleChildTree(childId);
+                    }
+                }
+            }
+
+        }
+
+        @Override
+        public int indexOfId(Object id) {
+            return getPreOrder().indexOf(id);
+        }
+
+        @Override
+        public Object getIdByIndex(int index) {
+            return getPreOrder().get(index);
+        }
+
+        @Override
+        public void containerItemSetChange(ItemSetChangeEvent event) {
+            // preorder becomes invalid on sort, item additions etc.
+            clearPreorderCache();
+            super.containerItemSetChange(event);
+        }
+
+    }
+
+    /**
+     * Creates an empty TreeTable with a default container.
+     */
+    public CustomTreeTable() {
+        super(null, new HierarchicalContainer());
+    }
+
+    /**
+     * Creates an empty TreeTable with a default container.
+     * 
+     * @param caption
+     *            the caption for the TreeTable
+     */
+    public CustomTreeTable(String caption) {
+        this();
+        setCaption(caption);
+    }
+
+    /**
+     * Creates a TreeTable instance with given captions and data source.
+     * 
+     * @param caption
+     *            the caption for the component
+     * @param dataSource
+     *            the dataSource that is used to list items in the component
+     */
+    public CustomTreeTable(String caption, Container dataSource) {
+        super(caption, dataSource);
+    }
+
+    private ContainerStrategy cStrategy;
+    private Object focusedRowId = null;
+    private Object hierarchyColumnId;
+
+    /**
+     * The item id that was expanded or collapsed during this request. Reset at
+     * the end of paint and only used for determining if a partial or full paint
+     * should be done.
+     * 
+     * Can safely be reset to null whenever a change occurs that would prevent a
+     * partial update from rendering the correct result, e.g. rows added or
+     * removed during an expand operation.
+     */
+    private Object toggledItemId;
+    private boolean animationsEnabled;
+    private boolean clearFocusedRowPending;
+
+    /**
+     * If the container does not send item set change events, always do a full
+     * repaint instead of a partial update when expanding/collapsing nodes.
+     */
+    private boolean containerSupportsPartialUpdates;
+
+    private ContainerStrategy getContainerStrategy() {
+        if (cStrategy == null) {
+            if (getContainerDataSource() instanceof Collapsible) {
+                cStrategy = new CollapsibleStrategy();
+            } else {
+                cStrategy = new HierarchicalStrategy();
+            }
+        }
+        return cStrategy;
+    }
+
+    @Override
+    protected void paintRowAttributes(PaintTarget target, Object itemId)
+            throws PaintException {
+        super.paintRowAttributes(target, itemId);
+        target.addAttribute("depth", getContainerStrategy().getDepth(itemId));
+        if (getContainerDataSource().areChildrenAllowed(itemId)) {
+            target.addAttribute("ca", true);
+            target.addAttribute("open",
+                    getContainerStrategy().isNodeOpen(itemId));
+        }
+    }
+
+    @Override
+    protected void paintRowIcon(PaintTarget target, Object[][] cells,
+            int indexInRowbuffer) throws PaintException {
+        // always paint if present (in parent only if row headers visible)
+        if (getRowHeaderMode() == ROW_HEADER_MODE_HIDDEN) {
+            Resource itemIcon = getItemIcon(cells[CELL_ITEMID][indexInRowbuffer]);
+            if (itemIcon != null) {
+                target.addAttribute("icon", itemIcon);
+            }
+        } else if (cells[CELL_ICON][indexInRowbuffer] != null) {
+            target.addAttribute("icon",
+                    (Resource) cells[CELL_ICON][indexInRowbuffer]);
+        }
+    }
+
+    @Override
+    public void changeVariables(Object source, Map<String, Object> variables) {
+        super.changeVariables(source, variables);
+
+        if (variables.containsKey("toggleCollapsed")) {
+            String object = (String) variables.get("toggleCollapsed");
+            Object itemId = itemIdMapper.get(object);
+            toggledItemId = itemId;
+            toggleChildVisibility(itemId, false);
+            if (variables.containsKey("selectCollapsed")) {
+                // ensure collapsed is selected unless opened with selection
+                // head
+                if (isSelectable()) {
+                    select(itemId);
+                }
+            }
+        } else if (variables.containsKey("focusParent")) {
+            String key = (String) variables.get("focusParent");
+            Object refId = itemIdMapper.get(key);
+            Object itemId = getParent(refId);
+            focusParent(itemId);
+        }
+    }
+
+    private void focusParent(Object itemId) {
+        boolean inView = false;
+        Object inPageId = getCurrentPageFirstItemId();
+        for (int i = 0; inPageId != null && i < getPageLength(); i++) {
+            if (inPageId.equals(itemId)) {
+                inView = true;
+                break;
+            }
+            inPageId = nextItemId(inPageId);
+            i++;
+        }
+        if (!inView) {
+            setCurrentPageFirstItemId(itemId);
+        }
+        // Select the row if it is selectable.
+        if (isSelectable()) {
+            if (isMultiSelect()) {
+                setValue(Collections.singleton(itemId));
+            } else {
+                setValue(itemId);
+            }
+        }
+        setFocusedRow(itemId);
+    }
+
+    private void setFocusedRow(Object itemId) {
+        focusedRowId = itemId;
+        if (focusedRowId == null) {
+            // Must still inform the client that the focusParent request has
+            // been processed
+            clearFocusedRowPending = true;
+        }
+        markAsDirty();
+    }
+
+    @Override
+    public void paintContent(PaintTarget target) throws PaintException {
+        if (focusedRowId != null) {
+            target.addAttribute("focusedRow", itemIdMapper.key(focusedRowId));
+            focusedRowId = null;
+        } else if (clearFocusedRowPending) {
+            // Must still inform the client that the focusParent request has
+            // been processed
+            target.addAttribute("clearFocusPending", true);
+            clearFocusedRowPending = false;
+        }
+        target.addAttribute("animate", animationsEnabled);
+        if (hierarchyColumnId != null) {
+            Object[] visibleColumns2 = getVisibleColumns();
+            for (int i = 0; i < visibleColumns2.length; i++) {
+                Object object = visibleColumns2[i];
+                if (hierarchyColumnId.equals(object)) {
+                    target.addAttribute(
+                            TreeTableConstants.ATTRIBUTE_HIERARCHY_COLUMN_INDEX,
+                            i);
+                    break;
+                }
+            }
+        }
+        super.paintContent(target);
+        toggledItemId = null;
+    }
+
+    /*
+     * Override methods for partial row updates and additions when expanding /
+     * collapsing nodes.
+     */
+
+    @Override
+    protected boolean isPartialRowUpdate() {
+        return toggledItemId != null && containerSupportsPartialUpdates
+                && !isRowCacheInvalidated();
+    }
+
+    @Override
+    protected int getFirstAddedItemIndex() {
+        return indexOfId(toggledItemId) + 1;
+    }
+
+    @Override
+    protected int getAddedRowCount() {
+        return countSubNodesRecursively(getContainerDataSource(), toggledItemId);
+    }
+
+    private int countSubNodesRecursively(Hierarchical hc, Object itemId) {
+        int count = 0;
+        // we need the number of children for toggledItemId no matter if its
+        // collapsed or expanded. Other items' children are only counted if the
+        // item is expanded.
+        if (getContainerStrategy().isNodeOpen(itemId)
+                || itemId == toggledItemId) {
+            Collection<?> children = hc.getChildren(itemId);
+            if (children != null) {
+                count += children != null ? children.size() : 0;
+                for (Object id : children) {
+                    count += countSubNodesRecursively(hc, id);
+                }
+            }
+        }
+        return count;
+    }
+
+    @Override
+    protected int getFirstUpdatedItemIndex() {
+        return indexOfId(toggledItemId);
+    }
+
+    @Override
+    protected int getUpdatedRowCount() {
+        return 1;
+    }
+
+    @Override
+    protected boolean shouldHideAddedRows() {
+        return !getContainerStrategy().isNodeOpen(toggledItemId);
+    }
+
+    private void toggleChildVisibility(Object itemId, boolean forceFullRefresh) {
+        getContainerStrategy().toggleChildVisibility(itemId);
+        // ensure that page still has first item in page, DON'T clear the
+        // caches.
+        setCurrentPageFirstItemIndex(getCurrentPageFirstItemIndex(), false);
+
+        if (isCollapsed(itemId)) {
+            fireCollapseEvent(itemId);
+        } else {
+            fireExpandEvent(itemId);
+        }
+
+        if (containerSupportsPartialUpdates && !forceFullRefresh) {
+            markAsDirty();
+        } else {
+            // For containers that do not send item set change events, always do
+            // full repaint instead of partial row update.
+            refreshRowCache();
+        }
+    }
+
+    @Override
+    public int size() {
+        return getContainerStrategy().size();
+    }
+
+    @Override
+    public Hierarchical getContainerDataSource() {
+        return (Hierarchical) super.getContainerDataSource();
+    }
+
+    @Override
+    public void setContainerDataSource(Container newDataSource) {
+        cStrategy = null;
+
+        // FIXME: This disables partial updates until TreeTable is fixed so it
+        // does not change component hierarchy during paint
+        containerSupportsPartialUpdates = (newDataSource instanceof ItemSetChangeNotifier) && false;
+
+        if (newDataSource != null && !(newDataSource instanceof Hierarchical)) {
+            newDataSource = new ContainerHierarchicalWrapper(newDataSource);
+        }
+
+        if (newDataSource != null && !(newDataSource instanceof Ordered)) {
+            newDataSource = new HierarchicalContainerOrderedWrapper(
+                    (Hierarchical) newDataSource);
+        }
+
+        super.setContainerDataSource(newDataSource);
+    }
+
+    @Override
+    public void containerItemSetChange(
+            com.vaadin.data.Container.ItemSetChangeEvent event) {
+        // Can't do partial repaints if items are added or removed during the
+        // expand/collapse request
+        toggledItemId = null;
+        getContainerStrategy().containerItemSetChange(event);
+        super.containerItemSetChange(event);
+    }
+
+    @Override
+    protected Object getIdByIndex(int index) {
+        return getContainerStrategy().getIdByIndex(index);
+    }
+
+    @Override
+    protected int indexOfId(Object itemId) {
+        return getContainerStrategy().indexOfId(itemId);
+    }
+
+    @Override
+    public Object nextItemId(Object itemId) {
+        return getContainerStrategy().nextItemId(itemId);
+    }
+
+    @Override
+    public Object lastItemId() {
+        return getContainerStrategy().lastItemId();
+    }
+
+    @Override
+    public Object prevItemId(Object itemId) {
+        return getContainerStrategy().prevItemId(itemId);
+    }
+
+    @Override
+    public boolean isLastId(Object itemId) {
+        return getContainerStrategy().isLastId(itemId);
+    }
+
+    @Override
+    public Collection<?> getItemIds() {
+        return getContainerStrategy().getItemIds();
+    }
+
+    @Override
+    public boolean areChildrenAllowed(Object itemId) {
+        return getContainerDataSource().areChildrenAllowed(itemId);
+    }
+
+    @Override
+    public Collection<?> getChildren(Object itemId) {
+        return getContainerDataSource().getChildren(itemId);
+    }
+
+    @Override
+    public Object getParent(Object itemId) {
+        return getContainerDataSource().getParent(itemId);
+    }
+
+    @Override
+    public boolean hasChildren(Object itemId) {
+        return getContainerDataSource().hasChildren(itemId);
+    }
+
+    @Override
+    public boolean isRoot(Object itemId) {
+        return getContainerDataSource().isRoot(itemId);
+    }
+
+    @Override
+    public Collection<?> rootItemIds() {
+        return getContainerDataSource().rootItemIds();
+    }
+
+    @Override
+    public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed)
+            throws UnsupportedOperationException {
+        return getContainerDataSource().setChildrenAllowed(itemId,
+                areChildrenAllowed);
+    }
+
+    @Override
+    public boolean setParent(Object itemId, Object newParentId)
+            throws UnsupportedOperationException {
+        return getContainerDataSource().setParent(itemId, newParentId);
+    }
+
+    /**
+     * Sets the Item specified by given identifier as collapsed or expanded. If
+     * the Item is collapsed, its children are not displayed to the user.
+     * 
+     * @param itemId
+     *            the identifier of the Item
+     * @param collapsed
+     *            true if the Item should be collapsed, false if expanded
+     */
+    public void setCollapsed(Object itemId, boolean collapsed) {
+        if (isCollapsed(itemId) != collapsed) {
+            if (null == toggledItemId && !isRowCacheInvalidated()
+                    && getVisibleItemIds().contains(itemId)) {
+                // optimization: partial refresh if only one item is
+                // collapsed/expanded
+                toggledItemId = itemId;
+                toggleChildVisibility(itemId, false);
+            } else {
+                // make sure a full refresh takes place - otherwise neither
+                // partial nor full repaint of table content is performed
+                toggledItemId = null;
+                toggleChildVisibility(itemId, true);
+            }
+        }
+    }
+
+    /**
+     * Checks if Item with given identifier is collapsed in the UI.
+     * 
+     * <p>
+     * 
+     * @param itemId
+     *            the identifier of the checked Item
+     * @return true if the Item with given id is collapsed
+     * @see Collapsible#isCollapsed(Object)
+     */
+    public boolean isCollapsed(Object itemId) {
+        return !getContainerStrategy().isNodeOpen(itemId);
+    }
+
+    /** Explicitly sets the column in which the TreeTable visualizes the
+	 * hierarchy. If hierarchyColumnId is not set, the hierarchy is visualized
+	 * in the first visible column.
+	 *
+	 * @param hierarchyColumnId
+	 *            the new hierarchy column
+	 */
+    public void setHierarchyColumn(Object hierarchyColumnId) {
+        this.hierarchyColumnId = hierarchyColumnId;
+    }
+
+    /**
+     * @return the identifier of column into which the hierarchy will be
+     *         visualized or null if the column is not explicitly defined.
+     */
+    public Object getHierarchyColumnId() {
+        return hierarchyColumnId;
+    }
+
+    /**
+     * Adds an expand listener.
+     * 
+     * @param listener
+     *            the Listener to be added.
+     */
+    public void addExpandListener(ExpandListener listener) {
+        addListener(ExpandEvent.class, listener, ExpandListener.EXPAND_METHOD);
+    }
+
+    /** Adds the listener.
+	 *
+	 * @param listener
+	 *            the listener
+	 * @deprecated As of 7.0, replaced by
+	 *             {@link #addExpandListener(ExpandListener)}
+	 */
+    @Deprecated
+    public void addListener(ExpandListener listener) {
+        addExpandListener(listener);
+    }
+
+    /**
+     * Removes an expand listener.
+     * 
+     * @param listener
+     *            the Listener to be removed.
+     */
+    public void removeExpandListener(ExpandListener listener) {
+        removeListener(ExpandEvent.class, listener,
+                ExpandListener.EXPAND_METHOD);
+    }
+
+    /** Removes the listener.
+	 *
+	 * @param listener
+	 *            the listener
+	 * @deprecated As of 7.0, replaced by
+	 *             {@link #removeExpandListener(ExpandListener)}
+	 */
+    @Deprecated
+    public void removeListener(ExpandListener listener) {
+        removeExpandListener(listener);
+    }
+
+    /**
+     * Emits an expand event.
+     * 
+     * @param itemId
+     *            the item id.
+     */
+    protected void fireExpandEvent(Object itemId) {
+        fireEvent(new ExpandEvent(this, itemId));
+    }
+
+    /**
+     * Adds a collapse listener.
+     * 
+     * @param listener
+     *            the Listener to be added.
+     */
+    public void addCollapseListener(CollapseListener listener) {
+        addListener(CollapseEvent.class, listener,
+                CollapseListener.COLLAPSE_METHOD);
+    }
+
+    /** Adds the listener.
+	 *
+	 * @param listener
+	 *            the listener
+	 * @deprecated As of 7.0, replaced by
+	 *             {@link #addCollapseListener(CollapseListener)}
+	 */
+    @Deprecated
+    public void addListener(CollapseListener listener) {
+        addCollapseListener(listener);
+    }
+
+    /**
+     * Removes a collapse listener.
+     * 
+     * @param listener
+     *            the Listener to be removed.
+     */
+    public void removeCollapseListener(CollapseListener listener) {
+        removeListener(CollapseEvent.class, listener,
+                CollapseListener.COLLAPSE_METHOD);
+    }
+
+    /** Removes the listener.
+	 *
+	 * @param listener
+	 *            the listener
+	 * @deprecated As of 7.0, replaced by
+	 *             {@link #removeCollapseListener(CollapseListener)}
+	 */
+    @Deprecated
+    public void removeListener(CollapseListener listener) {
+        removeCollapseListener(listener);
+    }
+
+    /**
+     * Emits a collapse event.
+     * 
+     * @param itemId
+     *            the item id.
+     */
+    protected void fireCollapseEvent(Object itemId) {
+        fireEvent(new CollapseEvent(this, itemId));
+    }
+
+    /**
+     * @return true if animations are enabled
+     */
+    public boolean isAnimationsEnabled() {
+        return animationsEnabled;
+    }
+
+    /**
+     * Animations can be enabled by passing true to this method. Currently
+     * expanding rows slide in from the top and collapsing rows slide out the
+     * same way. NOTE! not supported in Internet Explorer 6 or 7.
+     * 
+     * @param animationsEnabled
+     *            true or false whether to enable animations or not.
+     */
+    public void setAnimationsEnabled(boolean animationsEnabled) {
+        this.animationsEnabled = animationsEnabled;
+        markAsDirty();
+    }
+
+    private static final Logger getLogger() {
+        return Logger.getLogger(TreeTable.class.getName());
+    }
+
+    @Override
+    protected List<Object> getItemIds(int firstIndex, int rows) {
+        List<Object> itemIds = new ArrayList<Object>();
+        for (int i = firstIndex; i < firstIndex + rows; i++) {
+            itemIds.add(getIdByIndex(i));
+        }
+        return itemIds;
+    }
+}
