Introducing a new CellTableBuilder API, which allows users to customize the structure of a CellTable by building zero or more table rows per row value and adding zero or more Cells per TD.  The table rows are built using the generic ElementBuilder API, which allows for colspans and rowspans.  The CellTableBuilder interface defines one method #buildRow(T, int, Utility) that takes the row value and row index to build, as well as a Utility class.  The Utility class defines a #startRow() method to append a DOM row and associate it with the row value.  Using this API, you can define multiple rows per row value, such as an "error row" that spans all of the columns, or a set of "child rows" to simulate a tree table.  The Utility also contains a method #renderCell(ElementBuilder, Context, Column, T rowValue) that renders a Cell into the row.  The TableBuilder can be swapped out using setTableBuilder(), and the default tableBuilder renders a grid based on the Columns defined in the CellTable.  This change only applies to the data portion of the CellTable.  A subsequent change will add a similar HeaderBuilder that applies to the header and footer.

This API change required a significant refactor of CellTable because CellTable assumed a grid structure with one row per row value, one cell per column, and a structure consisting of a div inside of a td for every Cell.  Now that the structure is open ended, CellTable sets the ID of the row value on the TR and assigns a unique ID to Cells that is set as a DOM attribute of the cell's parent element.  Instead of looking for the TD that contains the cell, we walk up from the event target looking for the cell ID attribute and the row attribute on the TR. We then look up the cell by its ID in a Map.

In addition, there is an internal concept of "subrows", which occurs when a row value is rendered into multiple rows.  The subrow is now included in the Context that is passed to Cells when they handle events. There is nothing special about rendering one row versus five, we just consider the one row to be the 0th subrow.  The entire set of subrows rendered with a row value are considered a block associated with the row value. If the row value changes, the entire block of subrows is re-rendered as well.

Keyboard selection is also affected, and in particular there are different ways that users might want to handle keyboard selection depending on the existance of subrows.  So, I abstracted the keyboard selection code out to a CellPreviewEvent.Handler, which is how normal Selection works.  This abstraction cleans up some of the code, and it allows users to override how keyboard selection works (say, by changing the keys or actions) using #setKeyboardSelectionHandler().  In addition, we now expose methods like get/setKeyboardSelectionRow() to allow users to programatically change the keyboard selected row.  The default implementation of the handler navigates between interactive cells in the first row of each row value.  It does not navigate into subrows unless the user actually clicks on the subrow.

Currently, TableBuilder is implemented using HtmlBuilder because it still seems faster than DOM manipulation.  I added a TODO to test DomBuilder in more depth.  The TableBuilder API is generic enough that we can switch out the implementation without affecting user code.

There is a legacy code path to provide a decent level of backward compatibility for users who are overriding the protected method AbstractCellTable#renderRowValues(SafeHtmlBuilder), which is now deprecated and no longer used. We still call #renderRowValues(), but we expect it to throw an UnsupportedOperationException, which we detect and continue.  If it does not throw an UnsupportedOperationException, then we pass the rendered html to replaceChildren().  The only way it would not throw an UnsupportedOperationException is if the user overrides #renderRowValues().  I also added an unused method AbstractCellTable#renderRowValuesLegacy() in case users want to revert to the old style.

I also added a sample to Showcase. Demo availabale at http://showcase2.jlabanca-testing.appspot.com/#!CwCustomDataGrid

Review at http://gwt-code-reviews.appspot.com/1501803

Review by: pengzhuang@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10476 8db76d5a-ed1c-0410-87a9-c151d255dfc7
32 files changed