]> source.dussan.org Git - vaadin-framework.git/commitdiff
opening some parts of table implementation + some refactoring
authorMatti Tahvonen <matti.tahvonen@itmill.com>
Wed, 12 May 2010 15:37:33 +0000 (15:37 +0000)
committerMatti Tahvonen <matti.tahvonen@itmill.com>
Wed, 12 May 2010 15:37:33 +0000 (15:37 +0000)
svn changeset:13172/svn branch:6.4

src/com/vaadin/terminal/gwt/client/ui/VScrollTable.java
src/com/vaadin/ui/Table.java

index e470288d1ed745d2f8fad50f6369fe45f3fa676a..bd30bac7390ba007a9738cab80e93a24d98a489e 100644 (file)
@@ -131,8 +131,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
 
     private String[] columnOrder;
 
-    private ApplicationConnection client;
-    private String paintableId;
+    protected ApplicationConnection client;
+    protected String paintableId;
 
     private boolean immediate;
 
@@ -441,7 +441,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
     /**
      * Sends the selection to the server
      */
-    private void sendSelectedRows(){
+    private void sendSelectedRows() {
         // Don't send anything if selection has not changed
         if (!selectionChanged) {
             return;
@@ -462,25 +462,13 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
             }
 
             // Send the selected row ranges
-            client
-                    .updateVariable(
-                            paintableId,
-                            "selectedRanges",
-                            ranges
-                                    .toArray(new String[selectedRowRanges
-                                            .size()]),
-                            false);
+            client.updateVariable(paintableId, "selectedRanges", ranges
+                    .toArray(new String[selectedRowRanges.size()]), false);
         }
 
         // Send the selected rows
-        client
-                .updateVariable(
-                        paintableId,
-                        "selected",
-                        selectedRowKeys
-                                .toArray(new String[selectedRowKeys
-                                        .size()]),
-                        immediate);
+        client.updateVariable(paintableId, "selected", selectedRowKeys
+                .toArray(new String[selectedRowKeys.size()]), immediate);
 
     }
 
@@ -754,7 +742,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
                 scrollBody.removeFromParent();
                 lazyUnregistryBag.add(scrollBody);
             }
-            scrollBody = new VScrollTableBody();
+            scrollBody = createScrollBody();
 
             scrollBody.renderInitialRows(rowData, uidl
                     .getIntAttribute("firstrow"), uidl.getIntAttribute("rows"));
@@ -807,6 +795,10 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
         headerChangedDuringUpdate = false;
     }
 
+    protected VScrollTableBody createScrollBody() {
+        return new VScrollTableBody();
+    }
+
     /**
      * Selects the last rendered row in the table
      * 
@@ -1078,16 +1070,16 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
         VScrollTableRow r = null;
         while (it.hasNext()) {
             r = (VScrollTableRow) it.next();
-            if(r == row){
+            if (r == row) {
                 r = null;
                 while (offset >= 0 && it.hasNext()) {
                     r = (VScrollTableRow) it.next();
                     offset--;
                 }
                 return r;
-            }            
+            }
         }
-        
+
         return null;
     }
 
@@ -2980,9 +2972,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
 
         private char[] aligns;
 
-        VScrollTableBody() {
+        protected VScrollTableBody() {
             constructDOM();
-
             setElement(container);
         }
 
@@ -3022,8 +3013,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
             final Iterator<?> it = rowData.getChildIterator();
             aligns = tHead.getColumnAlignments();
             while (it.hasNext()) {
-                final VScrollTableRow row = new VScrollTableRow((UIDL) it
-                        .next(), aligns);
+                final VScrollTableRow row = createRow((UIDL) it.next(), aligns);
                 addRow(row);
             }
             if (isAttached()) {
@@ -3037,7 +3027,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
             final Iterator<?> it = rowData.getChildIterator();
             if (firstIndex == lastRendered + 1) {
                 while (it.hasNext()) {
-                    final VScrollTableRow row = createRow((UIDL) it.next());
+                    final VScrollTableRow row = prepareRow((UIDL) it.next());
                     addRow(row);
                     lastRendered++;
                 }
@@ -3047,7 +3037,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
                 int i = rows;
                 while (it.hasNext()) {
                     i--;
-                    rowArray[i] = createRow((UIDL) it.next());
+                    rowArray[i] = prepareRow((UIDL) it.next());
                 }
                 for (i = 0; i < rows; i++) {
                     addRowBeforeFirstRendered(rowArray[i]);
@@ -3058,7 +3048,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
                 while (lastRendered + 1 > firstRendered) {
                     unlinkRow(false);
                 }
-                final VScrollTableRow row = createRow((UIDL) it.next());
+                final VScrollTableRow row = prepareRow((UIDL) it.next());
                 firstRendered = firstIndex;
                 lastRendered = firstIndex - 1;
                 addRow(row);
@@ -3066,7 +3056,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
                 setContainerHeight();
                 fixSpacers();
                 while (it.hasNext()) {
-                    addRow(createRow((UIDL) it.next()));
+                    addRow(prepareRow((UIDL) it.next()));
                     lastRendered++;
                 }
                 fixSpacers();
@@ -3112,8 +3102,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
          * 
          * @param uidl
          */
-        private VScrollTableRow createRow(UIDL uidl) {
-            final VScrollTableRow row = new VScrollTableRow(uidl, aligns);
+        private VScrollTableRow prepareRow(UIDL uidl) {
+            final VScrollTableRow row = createRow(uidl, aligns);
             final int cells = DOM.getChildCount(row.getElement());
             for (int i = 0; i < cells; i++) {
                 final Element cell = DOM.getChild(row.getElement(), i);
@@ -3128,6 +3118,10 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
             return row;
         }
 
+        protected VScrollTableRow createRow(UIDL uidl, char[] aligns2) {
+            return new VScrollTableRow(uidl, aligns);
+        }
+
         private void addRowBeforeFirstRendered(VScrollTableRow row) {
             VScrollTableRow first = null;
             if (renderedRows.size() > 0) {
@@ -3344,7 +3338,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
                     // for measuring
                     noCells = true;
                     VScrollTableRow next = (VScrollTableRow) iterator().next();
-                    next.addCell("", ALIGN_LEFT, "", true);
+                    next.addCell(null, "", ALIGN_LEFT, "", true);
                     firstTD = item.getCells().getItem(0);
                 }
                 com.google.gwt.dom.client.Element wrapper = firstTD
@@ -3404,9 +3398,9 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
                 Container {
 
             private static final int DRAGMODE_MULTIROW = 2;
-            ArrayList<Widget> childWidgets = new ArrayList<Widget>();
+            protected ArrayList<Widget> childWidgets = new ArrayList<Widget>();
             private boolean selected = false;
-            private final int rowKey;
+            protected final int rowKey;
             private List<UIDL> pendingComponentPaints;
 
             private String[] actionKeys = null;
@@ -3474,8 +3468,8 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
 
                 // row header
                 if (showRowHeaders) {
-                    addCell(buildCaptionHtmlSnippet(uidl), aligns[col++], "",
-                            true);
+                    addCell(uidl, buildCaptionHtmlSnippet(uidl), aligns[col++],
+                            "", true);
                 }
 
                 if (uidl.hasAttribute("al")) {
@@ -3495,12 +3489,14 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
                     }
 
                     if (cell instanceof String) {
-                        addCell(cell.toString(), aligns[col++], style, false);
+                        addCell(uidl, cell.toString(), aligns[col++], style,
+                                false);
                     } else {
                         final Paintable cellContent = client
                                 .getPaintable((UIDL) cell);
 
-                        addCell((Widget) cellContent, aligns[col++], style);
+                        addCell(uidl, (Widget) cellContent, aligns[col++],
+                                style);
                         paintComponent(cellContent, (UIDL) cell);
                     }
                 }
@@ -3515,11 +3511,11 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
             public VScrollTableRow() {
                 this(0);
                 addStyleName(CLASSNAME + "-row");
-                addCell("_", 'b', "", true);
+                addCell(null, "_", 'b', "", true);
             }
 
-            public void addCell(String text, char align, String style,
-                    boolean textIsHTML) {
+            public void addCell(UIDL rowUidl, String text, char align,
+                    String style, boolean textIsHTML) {
                 // String only content is optimized by not using Label widget
                 final Element td = DOM.createTD();
                 final Element container = DOM.createDiv();
@@ -3549,7 +3545,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
                 getElement().appendChild(td);
             }
 
-            public void addCell(Widget w, char align, String style) {
+            public void addCell(UIDL rowUidl, Widget w, char align, String style) {
                 final Element td = DOM.createTD();
                 final Element container = DOM.createDiv();
                 String className = CLASSNAME + "-cell-content";
@@ -3609,7 +3605,6 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
                     client.updateVariable(paintableId, "clickedKey", ""
                             + rowKey, false);
 
-
                     if (getElement() == targetTdOrTr.getParentElement()) {
                         /* A specific column was clicked */
                         int childIndex = DOM.getChildIndex(getElement(),
@@ -3883,8 +3878,6 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
                 removeKeyFromSelectedRange(rowKey);
             }
 
-
-
             /**
              * Is called when a user clicks an item when holding SHIFT key down.
              * This will select a new range from the last cell clicked
@@ -4696,8 +4689,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
         }
 
         // Down navigation
-        if (selectMode == SELECT_MODE_NONE
- && keycode == getNavigationDownKey()) {
+        if (selectMode == SELECT_MODE_NONE && keycode == getNavigationDownKey()) {
             bodyContainer.setScrollPosition(bodyContainer.getScrollPosition()
                     + scrollingVelocity);
         } else if (keycode == getNavigationDownKey()) {
@@ -4711,8 +4703,7 @@ public class VScrollTable extends FlowPanel implements Table, ScrollHandler,
         }
 
         // Up navigation
-        if (selectMode == SELECT_MODE_NONE
- && keycode == getNavigationUpKey()) {
+        if (selectMode == SELECT_MODE_NONE && keycode == getNavigationUpKey()) {
             bodyContainer.setScrollPosition(bodyContainer.getScrollPosition()
                     - scrollingVelocity);
         } else if (keycode == getNavigationUpKey()) {
index 4fde62d4bdaff4698de49be44b46dcae26aa1dcb..32cb5f4a96fbbf73d327b24afc10a7b1bb68afa5 100644 (file)
@@ -889,7 +889,7 @@ public class Table extends AbstractSelect implements Action.Container,
             final int index = getCurrentPageFirstItemIndex();
             Object id = null;
             if (index >= 0 && index < size()) {
-                id = ((Container.Indexed) items).getIdByIndex(index);
+                id = getIdByIndex(index);
             }
             if (id != null && !id.equals(currentPageFirstItemId)) {
                 currentPageFirstItemId = id;
@@ -898,12 +898,16 @@ public class Table extends AbstractSelect implements Action.Container,
 
         // If there is no item id at all, use the first one
         if (currentPageFirstItemId == null) {
-            currentPageFirstItemId = ((Container.Ordered) items).firstItemId();
+            currentPageFirstItemId = firstItemId();
         }
 
         return currentPageFirstItemId;
     }
 
+    protected Object getIdByIndex(int index) {
+        return ((Container.Indexed) items).getIdByIndex(index);
+    }
+
     /**
      * Setter for property currentPageFirstItemId.
      * 
@@ -915,15 +919,14 @@ public class Table extends AbstractSelect implements Action.Container,
         // Gets the corresponding index
         int index = -1;
         if (items instanceof Container.Indexed) {
-            index = ((Container.Indexed) items)
-                    .indexOfId(currentPageFirstItemId);
+            index = indexOfId(currentPageFirstItemId);
         } else {
             // If the table item container does not have index, we have to
             // calculates the index by hand
-            Object id = ((Container.Ordered) items).firstItemId();
+            Object id = firstItemId();
             while (id != null && !id.equals(currentPageFirstItemId)) {
                 index++;
-                id = ((Container.Ordered) items).nextItemId(id);
+                id = nextItemId(id);
             }
             if (id == null) {
                 index = -1;
@@ -957,6 +960,10 @@ public class Table extends AbstractSelect implements Action.Container,
 
     }
 
+    protected int indexOfId(Object itemId) {
+        return ((Container.Indexed) items).indexOfId(itemId);
+    }
+
     /**
      * Gets the icon Resource for the specified column.
      * 
@@ -1241,8 +1248,7 @@ public class Table extends AbstractSelect implements Action.Container,
         // Refresh first item id
         if (items instanceof Container.Indexed) {
             try {
-                currentPageFirstItemId = ((Container.Indexed) items)
-                        .getIdByIndex(newIndex);
+                currentPageFirstItemId = getIdByIndex(newIndex);
             } catch (final IndexOutOfBoundsException e) {
                 currentPageFirstItemId = null;
             }
@@ -1253,48 +1259,42 @@ public class Table extends AbstractSelect implements Action.Container,
             // container forwards / backwards
             // next available item forward or backward
 
-            currentPageFirstItemId = ((Container.Ordered) items).firstItemId();
+            currentPageFirstItemId = firstItemId();
 
             // Go forwards in the middle of the list (respect borders)
             while (currentPageFirstItemIndex < newIndex
-                    && !((Container.Ordered) items)
-                            .isLastId(currentPageFirstItemId)) {
+                    && !isLastId(currentPageFirstItemId)) {
                 currentPageFirstItemIndex++;
-                currentPageFirstItemId = ((Container.Ordered) items)
-                        .nextItemId(currentPageFirstItemId);
+                currentPageFirstItemId = nextItemId(currentPageFirstItemId);
             }
 
             // If we did hit the border
-            if (((Container.Ordered) items).isLastId(currentPageFirstItemId)) {
+            if (isLastId(currentPageFirstItemId)) {
                 currentPageFirstItemIndex = size - 1;
             }
 
             // Go backwards in the middle of the list (respect borders)
             while (currentPageFirstItemIndex > newIndex
-                    && !((Container.Ordered) items)
-                            .isFirstId(currentPageFirstItemId)) {
+                    && !isFirstId(currentPageFirstItemId)) {
                 currentPageFirstItemIndex--;
-                currentPageFirstItemId = ((Container.Ordered) items)
-                        .prevItemId(currentPageFirstItemId);
+                currentPageFirstItemId = prevItemId(currentPageFirstItemId);
             }
 
             // If we did hit the border
-            if (((Container.Ordered) items).isFirstId(currentPageFirstItemId)) {
+            if (isFirstId(currentPageFirstItemId)) {
                 currentPageFirstItemIndex = 0;
             }
 
             // Go forwards once more
             while (currentPageFirstItemIndex < newIndex
-                    && !((Container.Ordered) items)
-                            .isLastId(currentPageFirstItemId)) {
+                    && !isLastId(currentPageFirstItemId)) {
                 currentPageFirstItemIndex++;
-                currentPageFirstItemId = ((Container.Ordered) items)
-                        .nextItemId(currentPageFirstItemId);
+                currentPageFirstItemId = nextItemId(currentPageFirstItemId);
             }
 
             // If for some reason we do hit border again, override
             // the user index request
-            if (((Container.Ordered) items).isLastId(currentPageFirstItemId)) {
+            if (isLastId(currentPageFirstItemId)) {
                 newIndex = currentPageFirstItemIndex = size - 1;
             }
         }
@@ -1398,7 +1398,7 @@ public class Table extends AbstractSelect implements Action.Container,
     /**
      * Refreshes rendered rows
      */
-    private void refreshRenderedCells() {
+    protected void refreshRenderedCells() {
         if (getParent() == null) {
             return;
         }
@@ -1459,11 +1459,11 @@ public class Table extends AbstractSelect implements Action.Container,
 
             // Gets the first item id
             if (items instanceof Container.Indexed) {
-                id = ((Container.Indexed) items).getIdByIndex(firstIndex);
+                id = getIdByIndex(firstIndex);
             } else {
-                id = ((Container.Ordered) items).firstItemId();
+                id = firstItemId();
                 for (int i = 0; i < firstIndex; i++) {
-                    id = ((Container.Ordered) items).nextItemId(id);
+                    id = nextItemId(id);
                 }
             }
 
@@ -1571,15 +1571,14 @@ public class Table extends AbstractSelect implements Action.Container,
 
                 // Gets the next item id
                 if (items instanceof Container.Indexed) {
-                    Container.Indexed indexed = (Container.Indexed) items;
                     int index = firstIndex + i + 1;
-                    if (index < indexed.size()) {
-                        id = indexed.getIdByIndex(index);
+                    if (index < totalRows) {
+                        id = getIdByIndex(index);
                     } else {
                         id = null;
                     }
                 } else {
-                    id = ((Container.Ordered) items).nextItemId(id);
+                    id = nextItemId(id);
                 }
 
                 filledRows++;
@@ -2332,8 +2331,8 @@ public class Table extends AbstractSelect implements Action.Container,
             start = 0;
         }
 
-        for (int i = start; i < end; i++) {
-            final Object itemId = cells[CELL_ITEMID][i];
+        for (int indexInRowbuffer = start; indexInRowbuffer < end; indexInRowbuffer++) {
+            final Object itemId = cells[CELL_ITEMID][indexInRowbuffer];
 
             if (!isNullSelectionAllowed() && getNullSelectionItemId() != null
                     && itemId == getNullSelectionItemId()) {
@@ -2341,93 +2340,8 @@ public class Table extends AbstractSelect implements Action.Container,
                 continue;
             }
 
-            target.startTag("tr");
-
-            // tr attributes
-            if (rowheads) {
-                if (cells[CELL_ICON][i] != null) {
-                    target.addAttribute("icon", (Resource) cells[CELL_ICON][i]);
-                }
-                if (cells[CELL_HEADER][i] != null) {
-                    target.addAttribute("caption",
-                            (String) cells[CELL_HEADER][i]);
-                }
-            }
-            target.addAttribute("key", Integer.parseInt(cells[CELL_KEY][i]
-                    .toString()));
-
-            if (isSelected(itemId)) {
-                target.addAttribute("selected", true);
-            }
-
-            // Actions
-            if (actionHandlers != null) {
-                final ArrayList<String> keys = new ArrayList<String>();
-                for (final Iterator<Handler> ahi = actionHandlers.iterator(); ahi
-                        .hasNext();) {
-                    final Action[] aa = (ahi.next()).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(itemId, null);
-                if (rowStyle != null && !rowStyle.equals("")) {
-                    target.addAttribute("rowstyle", rowStyle);
-                }
-            }
-
-            // 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(itemId,
-                            columnId);
-                    if (cellStyle != null && !cellStyle.equals("")) {
-                        target.addAttribute("style-"
-                                + columnIdMap.key(columnId), cellStyle);
-                    }
-                }
-                if ((iscomponent[currentColumn] || iseditable)
-                        && Component.class.isInstance(cells[CELL_FIRSTCOL
-                                + currentColumn][i])) {
-                    final Component c = (Component) cells[CELL_FIRSTCOL
-                            + currentColumn][i];
-                    if (c == null) {
-                        target.addText("");
-                    } else {
-                        c.paint(target);
-                    }
-                } else {
-                    target
-                            .addText((String) cells[CELL_FIRSTCOL
-                                    + currentColumn][i]);
-                }
-            }
-
-            target.endTag("tr");
+            paintRow(target, rowheads, cells, iseditable, actionSet,
+                    iscomponent, indexInRowbuffer, itemId);
         }
         target.endTag("rows");
 
@@ -2552,6 +2466,120 @@ public class Table extends AbstractSelect implements Action.Container,
         }
     }
 
+    private void paintRow(PaintTarget target, final boolean rowheads,
+            final Object[][] cells, final boolean iseditable,
+            final Set<Action> actionSet, final boolean[] iscomponent,
+            int indexInRowbuffer, final Object itemId) throws PaintException {
+        target.startTag("tr");
+
+        renderRowAttributes(target, rowheads, 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(itemId, columnId);
+                if (cellStyle != null && !cellStyle.equals("")) {
+                    target.addAttribute("style-" + columnIdMap.key(columnId),
+                            cellStyle);
+                }
+            }
+            if ((iscomponent[currentColumn] || iseditable)
+                    && Component.class.isInstance(cells[CELL_FIRSTCOL
+                            + currentColumn][indexInRowbuffer])) {
+                final Component c = (Component) cells[CELL_FIRSTCOL
+                        + currentColumn][indexInRowbuffer];
+                if (c == null) {
+                    target.addText("");
+                } else {
+                    c.paint(target);
+                }
+            } else {
+                target
+                        .addText((String) cells[CELL_FIRSTCOL + currentColumn][indexInRowbuffer]);
+            }
+        }
+
+        target.endTag("tr");
+    }
+
+    private void renderRowAttributes(PaintTarget target,
+            final boolean rowheads, final Object[][] cells,
+            final Set<Action> actionSet, int indexInRowbuffer,
+            final Object itemId) throws PaintException {
+        // tr attributes
+        if (rowheads) {
+            if (cells[CELL_ICON][indexInRowbuffer] != null) {
+                target.addAttribute("icon",
+                        (Resource) cells[CELL_ICON][indexInRowbuffer]);
+            }
+            if (cells[CELL_HEADER][indexInRowbuffer] != null) {
+                target.addAttribute("caption",
+                        (String) cells[CELL_HEADER][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 (final Iterator<Handler> ahi = actionHandlers.iterator(); ahi
+                    .hasNext();) {
+                final Action[] aa = (ahi.next()).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(itemId, null);
+            if (rowStyle != null && !rowStyle.equals("")) {
+                target.addAttribute("rowstyle", rowStyle);
+            }
+        }
+        renderRowAttributes(target, itemId);
+    }
+
+    /**
+     * A method where extended Table implementations may add their custom
+     * attributes for rows.
+     * 
+     * @param target
+     * @param itemId
+     */
+    protected void renderRowAttributes(PaintTarget target, Object itemId)
+            throws PaintException {
+
+    }
+
     /**
      * Gets the cached visible table contents.
      * 
@@ -2690,7 +2718,7 @@ public class Table extends AbstractSelect implements Action.Container,
         requestRepaint();
     }
 
-    private void resetPageBuffer() {
+    protected void resetPageBuffer() {
         firstToBeRenderedInClient = -1;
         lastToBeRenderedInClient = -1;
         reqFirstRowToPaint = -1;
@@ -2753,8 +2781,7 @@ public class Table extends AbstractSelect implements Action.Container,
      */
     @Override
     public boolean removeItem(Object itemId) {
-        final Object nextItemId = ((Container.Ordered) items)
-                .nextItemId(itemId);
+        final Object nextItemId = nextItemId(itemId);
         final boolean ret = super.removeItem(itemId);
         if (ret && (itemId != null) && (itemId.equals(currentPageFirstItemId))) {
             currentPageFirstItemId = nextItemId;