Adding methods to insert columns, get the column count, and get columns by index in a CellTable. Thesemethods are very useful for changing the visible Columns. Currently, users must remove all columns, then re-add them just to insert a single column. Review at http://gwt-code-reviews.appspot.com/1181801 Review by: sbrubaker@google.com git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@9355 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/cellview/client/CellTable.java b/user/src/com/google/gwt/user/cellview/client/CellTable.java index 0c5e6a6..1ba3f08 100644 --- a/user/src/com/google/gwt/user/cellview/client/CellTable.java +++ b/user/src/com/google/gwt/user/cellview/client/CellTable.java
@@ -592,42 +592,198 @@ } /** - * Adds a column to the table. + * Adds a column to the end of the table. * * @param col the column to be added */ public void addColumn(Column<T, ?> col) { - addColumn(col, (Header<?>) null, (Header<?>) null); + insertColumn(getColumnCount(), col); } /** - * Adds a column to the table with an associated header. + * Adds a column to the end of the table with an associated header. * * @param col the column to be added * @param header the associated {@link Header} */ public void addColumn(Column<T, ?> col, Header<?> header) { - addColumn(col, header, null); + insertColumn(getColumnCount(), col, header); } /** - * Adds a column to the table with an associated header and footer. + * Adds a column to the end of the table with an associated header and footer. * * @param col the column to be added * @param header the associated {@link Header} * @param footer the associated footer (as a {@link Header} object) */ public void addColumn(Column<T, ?> col, Header<?> header, Header<?> footer) { - headers.add(header); - footers.add(footer); - columns.add(col); + insertColumn(getColumnCount(), col, header, footer); + } + + /** + * Adds a column to the end of the table with an associated String header. + * + * @param col the column to be added + * @param headerString the associated header text, as a String + */ + public void addColumn(Column<T, ?> col, String headerString) { + insertColumn(getColumnCount(), col, headerString); + } + + /** + * Adds a column to the end of the table with an associated {@link SafeHtml} + * header. + * + * @param col the column to be added + * @param headerHtml the associated header text, as safe HTML + */ + public void addColumn(Column<T, ?> col, SafeHtml headerHtml) { + insertColumn(getColumnCount(), col, headerHtml); + } + + /** + * Adds a column to the end of the table with an associated String header and + * footer. + * + * @param col the column to be added + * @param headerString the associated header text, as a String + * @param footerString the associated footer text, as a String + */ + public void addColumn(Column<T, ?> col, String headerString, + String footerString) { + insertColumn(getColumnCount(), col, headerString, footerString); + } + + /** + * Adds a column to the end of the table with an associated {@link SafeHtml} + * header and footer. + * + * @param col the column to be added + * @param headerHtml the associated header text, as safe HTML + * @param footerHtml the associated footer text, as safe HTML + */ + public void addColumn(Column<T, ?> col, SafeHtml headerHtml, + SafeHtml footerHtml) { + insertColumn(getColumnCount(), col, headerHtml, footerHtml); + } + + /** + * Add a style name to the {@link TableColElement} at the specified index, + * creating it if necessary. + * + * @param index the column index + * @param styleName the style name to add + */ + public void addColumnStyleName(int index, String styleName) { + ensureTableColElement(index).addClassName(styleName); + } + + /** + * Return the height of the table body. + * + * @return an int representing the body height + */ + public int getBodyHeight() { + int height = getClientHeight(tbody); + return height; + } + + /** + * Get the column at the specified index. + * + * @param col the index of the column to retrieve + * @return the {@link Column} at the index + */ + public Column<T, ?> getColumn(int col) { + checkColumnBounds(col); + return columns.get(col); + } + + /** + * Get the number of columns in the table. + * + * @return the column count + */ + public int getColumnCount() { + return columns.size(); + } + + /** + * Return the height of the table header. + * + * @return an int representing the header height + */ + public int getHeaderHeight() { + int height = getClientHeight(thead); + return height; + } + + /** + * Get the {@link TableRowElement} for the specified row. If the row element + * has not been created, null is returned. + * + * @param row the row index + * @return the row element, or null if it doesn't exists + * @throws IndexOutOfBoundsException if the row index is outside of the + * current page + */ + public TableRowElement getRowElement(int row) { + getPresenter().flush(); + checkRowBounds(row); + NodeList<TableRowElement> rows = tbody.getRows(); + return rows.getLength() > row ? rows.getItem(row) : null; + } + + /** + * Inserts a column into the table at the specified index. + * + * @param beforeIndex the index to insert the column + * @param col the column to be added + */ + public void insertColumn(int beforeIndex, Column<T, ?> col) { + insertColumn(beforeIndex, col, (Header<?>) null, (Header<?>) null); + } + + /** + * Inserts a column into the table at the specified index with an associated + * header. + * + * @param beforeIndex the index to insert the column + * @param col the column to be added + * @param header the associated {@link Header} + */ + public void insertColumn(int beforeIndex, Column<T, ?> col, Header<?> header) { + insertColumn(beforeIndex, col, header, null); + } + + /** + * Inserts a column into the table at the specified index with an associated + * header and footer. + * + * @param beforeIndex the index to insert the column + * @param col the column to be added + * @param header the associated {@link Header} + * @param footer the associated footer (as a {@link Header} object) + * @throws IndexOutOfBoundsException if the index is out of range + */ + public void insertColumn(int beforeIndex, Column<T, ?> col, Header<?> header, + Header<?> footer) { + // Allow insert at the end. + if (beforeIndex != getColumnCount()) { + checkColumnBounds(beforeIndex); + } + + headers.add(beforeIndex, header); + footers.add(beforeIndex, footer); + columns.add(beforeIndex, col); boolean wasinteractive = isInteractive; updateDependsOnSelection(); // Move the keyboard selected column if the current column is not // interactive. if (!wasinteractive && isInteractive) { - keyboardSelectedColumn = columns.size() - 1; + keyboardSelectedColumn = beforeIndex; } // Sink events used by the new column. @@ -656,96 +812,59 @@ } /** - * Adds a column to the table with an associated String header. + * Inserts a column into the table at the specified index with an associated + * String header. * + * @param beforeIndex the index to insert the column * @param col the column to be added * @param headerString the associated header text, as a String */ - public void addColumn(Column<T, ?> col, String headerString) { - addColumn(col, new TextHeader(headerString), null); + public void insertColumn(int beforeIndex, Column<T, ?> col, + String headerString) { + insertColumn(beforeIndex, col, new TextHeader(headerString), null); } /** - * Adds a column to the table with an associated {@link SafeHtml} header. + * Inserts a column into the table at the specified index with an associated + * {@link SafeHtml} header. * + * @param beforeIndex the index to insert the column * @param col the column to be added * @param headerHtml the associated header text, as safe HTML */ - public void addColumn(Column<T, ?> col, SafeHtml headerHtml) { - addColumn(col, new SafeHtmlHeader(headerHtml), null); + public void insertColumn(int beforeIndex, Column<T, ?> col, + SafeHtml headerHtml) { + insertColumn(beforeIndex, col, new SafeHtmlHeader(headerHtml), null); } /** - * Adds a column to the table with an associated String header and footer. + * Inserts a column into the table at the specified index with an associated + * String header and footer. * + * @param beforeIndex the index to insert the column * @param col the column to be added * @param headerString the associated header text, as a String * @param footerString the associated footer text, as a String */ - public void addColumn(Column<T, ?> col, String headerString, - String footerString) { - addColumn(col, new TextHeader(headerString), new TextHeader(footerString)); + public void insertColumn(int beforeIndex, Column<T, ?> col, + String headerString, String footerString) { + insertColumn(beforeIndex, col, new TextHeader(headerString), + new TextHeader(footerString)); } /** - * Adds a column to the table with an associated {@link SafeHtml} header and - * footer. + * Inserts a column into the table at the specified index with an associated + * {@link SafeHtml} header and footer. * + * @param beforeIndex the index to insert the column * @param col the column to be added * @param headerHtml the associated header text, as safe HTML * @param footerHtml the associated footer text, as safe HTML */ - public void addColumn(Column<T, ?> col, SafeHtml headerHtml, - SafeHtml footerHtml) { - addColumn(col, new SafeHtmlHeader(headerHtml), new SafeHtmlHeader( - footerHtml)); - } - - /** - * Add a style name to the {@link TableColElement} at the specified index, - * creating it if necessary. - * - * @param index the column index - * @param styleName the style name to add - */ - public void addColumnStyleName(int index, String styleName) { - ensureTableColElement(index).addClassName(styleName); - } - - /** - * Return the height of the table body. - * - * @return an int representing the body height - */ - public int getBodyHeight() { - int height = getClientHeight(tbody); - return height; - } - - /** - * Return the height of the table header. - * - * @return an int representing the header height - */ - public int getHeaderHeight() { - int height = getClientHeight(thead); - return height; - } - - /** - * Get the {@link TableRowElement} for the specified row. If the row element - * has not been created, null is returned. - * - * @param row the row index - * @return the row element, or null if it doesn't exists - * @throws IndexOutOfBoundsException if the row index is outside of the - * current page - */ - public TableRowElement getRowElement(int row) { - getPresenter().flush(); - checkRowBounds(row); - NodeList<TableRowElement> rows = tbody.getRows(); - return rows.getLength() > row ? rows.getItem(row) : null; + public void insertColumn(int beforeIndex, Column<T, ?> col, + SafeHtml headerHtml, SafeHtml footerHtml) { + insertColumn(beforeIndex, col, new SafeHtmlHeader(headerHtml), + new SafeHtmlHeader(footerHtml)); } /** @@ -1198,6 +1317,19 @@ } /** + * Check that the specified column is within bounds. + * + * @param col the column index + * @throws IndexOutOfBoundsException if the column is out of bounds + */ + private void checkColumnBounds(int col) { + if (col < 0 || col >= getColumnCount()) { + throw new IndexOutOfBoundsException("Column index is out of bounds: " + + col); + } + } + + /** * Render the header or footer. * * @param isFooter true if this is the footer table, false if the header table @@ -1357,8 +1489,7 @@ * Fire an event to the Cell within the specified {@link TableCellElement}. */ private <C> void fireEventToCell(Event event, String eventType, - TableCellElement tableCell, T value, Context context, - Column<T, C> column) { + TableCellElement tableCell, T value, Context context, Column<T, C> column) { Cell<C> cell = column.getCell(); if (cellConsumesEventType(cell, eventType)) { C cellValue = column.getValue(value);
diff --git a/user/test/com/google/gwt/user/cellview/client/CellTableTest.java b/user/test/com/google/gwt/user/cellview/client/CellTableTest.java index 535bcd8..6d3115c 100644 --- a/user/test/com/google/gwt/user/cellview/client/CellTableTest.java +++ b/user/test/com/google/gwt/user/cellview/client/CellTableTest.java
@@ -15,6 +15,7 @@ */ package com.google.gwt.user.cellview.client; +import com.google.gwt.cell.client.AbstractCell; import com.google.gwt.cell.client.Cell; import com.google.gwt.cell.client.TextCell; import com.google.gwt.core.client.GWT; @@ -25,6 +26,7 @@ import com.google.gwt.dom.client.TableRowElement; import com.google.gwt.dom.client.TableSectionElement; import com.google.gwt.safehtml.shared.SafeHtml; +import com.google.gwt.safehtml.shared.SafeHtmlBuilder; import com.google.gwt.user.cellview.client.CellTable.Resources; import com.google.gwt.user.cellview.client.CellTable.Style; import com.google.gwt.user.client.ui.HasHorizontalAlignment; @@ -40,6 +42,28 @@ public class CellTableTest extends AbstractHasDataTestBase { /** + * A concrete column that implements a getter that always returns null. + * + * @param <T> the row type + * @param <C> the column type + */ + private static class MockColumn<T, C> extends Column<T, C> { + + public MockColumn() { + super(new AbstractCell<C>() { + @Override + public void render(Context context, C value, SafeHtmlBuilder sb) { + } + }); + } + + @Override + public C getValue(T object) { + return null; + } + } + + /** * Test that calls to addColumn results in only one redraw. */ public void testAddColumnSingleRedraw() { @@ -138,6 +162,38 @@ RootPanel.get().remove(table); } + public void testGetColumnOutOfBounds() { + CellTable<String> table = new CellTable<String>(); + + // Get column when there are no columns. + try { + table.getColumn(0); + fail("Expected IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + // Expected. + } + + // Add some columns. + table.addColumn(new MockColumn<String, String>()); + table.addColumn(new MockColumn<String, String>()); + + // Negative index. + try { + table.getColumn(-1); + fail("Expected IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + // Expected. + } + + // Index too high. + try { + table.getColumn(2); + fail("Expected IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException e) { + // Expected. + } + } + public void testGetRowElement() { CellTable<String> table = createAbstractHasData(new TextCell()); table.setRowData(0, createData(0, 10)); @@ -146,6 +202,55 @@ assertNotNull(table.getRowElement(9)); } + public void testInsertColumn() { + CellTable<String> table = new CellTable<String>(); + assertEquals(0, table.getColumnCount()); + + // Insert first column. + Column<String, ?> a = new MockColumn<String, String>(); + table.insertColumn(0, a); + assertEquals(1, table.getColumnCount()); + assertEquals(a, table.getColumn(0)); + + // Insert column at beginning. + Column<String, ?> b = new MockColumn<String, String>(); + table.insertColumn(0, b); + assertEquals(2, table.getColumnCount()); + assertEquals(b, table.getColumn(0)); + assertEquals(a, table.getColumn(1)); + + // Insert column at end. + Column<String, ?> c = new MockColumn<String, String>(); + table.insertColumn(2, c); + assertEquals(3, table.getColumnCount()); + assertEquals(b, table.getColumn(0)); + assertEquals(a, table.getColumn(1)); + assertEquals(c, table.getColumn(2)); + + // Insert column in middle. + Column<String, ?> d = new MockColumn<String, String>(); + table.insertColumn(1, d); + assertEquals(4, table.getColumnCount()); + assertEquals(b, table.getColumn(0)); + assertEquals(d, table.getColumn(1)); + assertEquals(a, table.getColumn(2)); + assertEquals(c, table.getColumn(3)); + + // Insert column at invalid index. + try { + table.insertColumn(-1, d); + fail("Expected IndexOutOfBoundsExecltion"); + } catch (IndexOutOfBoundsException e) { + // Expected. + } + try { + table.insertColumn(6, d); + fail("Expected IndexOutOfBoundsExecltion"); + } catch (IndexOutOfBoundsException e) { + // Expected. + } + } + /** * Test headers that span multiple columns. */