Revision: 9355
Author: jlaba...@google.com
Date: Fri Dec  3 05:16:36 2010
Log: 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: sbruba...@google.com
http://code.google.com/p/google-web-toolkit/source/detail?r=9355

Modified:
 /trunk/user/src/com/google/gwt/user/cellview/client/CellTable.java
 /trunk/user/test/com/google/gwt/user/cellview/client/CellTableTest.java

=======================================
--- /trunk/user/src/com/google/gwt/user/cellview/client/CellTable.java Wed Dec 1 05:40:20 2010 +++ /trunk/user/src/com/google/gwt/user/cellview/client/CellTable.java Fri Dec 3 05:16:36 2010
@@ -592,91 +592,59 @@
   }

   /**
-   * 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);
-    boolean wasinteractive = isInteractive;
-    updateDependsOnSelection();
-
-    // Move the keyboard selected column if the current column is not
-    // interactive.
-    if (!wasinteractive && isInteractive) {
-      keyboardSelectedColumn = columns.size() - 1;
-    }
-
-    // Sink events used by the new column.
-    Set<String> consumedEvents = new HashSet<String>();
-    {
-      Set<String> cellEvents = col.getCell().getConsumedEvents();
-      if (cellEvents != null) {
-        consumedEvents.addAll(cellEvents);
-      }
-    }
-    if (header != null) {
-      Set<String> headerEvents = header.getCell().getConsumedEvents();
-      if (headerEvents != null) {
-        consumedEvents.addAll(headerEvents);
-      }
-    }
-    if (footer != null) {
-      Set<String> footerEvents = footer.getCell().getConsumedEvents();
-      if (footerEvents != null) {
-        consumedEvents.addAll(footerEvents);
-      }
-    }
-    CellBasedWidgetImpl.get().sinkEvents(this, consumedEvents);
-
-    redraw();
+    insertColumn(getColumnCount(), col, header, footer);
   }

   /**
-   * Adds a column to the table with an associated String header.
+ * 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) {
-    addColumn(col, new TextHeader(headerString), null);
+    insertColumn(getColumnCount(), col, headerString);
   }

   /**
-   * Adds a column to the table with an associated {...@link SafeHtml} header.
+ * 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) {
-    addColumn(col, new SafeHtmlHeader(headerHtml), null);
+    insertColumn(getColumnCount(), col, headerHtml);
   }

   /**
- * Adds a column to the table with an associated String header and footer. + * 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
@@ -684,12 +652,12 @@
    */
   public void addColumn(Column<T, ?> col, String headerString,
       String footerString) {
- addColumn(col, new TextHeader(headerString), new TextHeader(footerString));
+    insertColumn(getColumnCount(), col, headerString, footerString);
   }

   /**
- * Adds a column to the table with an associated {...@link SafeHtml} header and
-   * footer.
+ * 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
@@ -697,8 +665,7 @@
    */
   public void addColumn(Column<T, ?> col, SafeHtml headerHtml,
       SafeHtml footerHtml) {
-    addColumn(col, new SafeHtmlHeader(headerHtml), new SafeHtmlHeader(
-        footerHtml));
+    insertColumn(getColumnCount(), col, headerHtml, footerHtml);
   }

   /**
@@ -721,6 +688,26 @@
     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.
@@ -747,6 +734,138 @@
     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 = beforeIndex;
+    }
+
+    // Sink events used by the new column.
+    Set<String> consumedEvents = new HashSet<String>();
+    {
+      Set<String> cellEvents = col.getCell().getConsumedEvents();
+      if (cellEvents != null) {
+        consumedEvents.addAll(cellEvents);
+      }
+    }
+    if (header != null) {
+      Set<String> headerEvents = header.getCell().getConsumedEvents();
+      if (headerEvents != null) {
+        consumedEvents.addAll(headerEvents);
+      }
+    }
+    if (footer != null) {
+      Set<String> footerEvents = footer.getCell().getConsumedEvents();
+      if (footerEvents != null) {
+        consumedEvents.addAll(footerEvents);
+      }
+    }
+    CellBasedWidgetImpl.get().sinkEvents(this, consumedEvents);
+
+    redraw();
+  }
+
+  /**
+ * 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 insertColumn(int beforeIndex, Column<T, ?> col,
+      String headerString) {
+    insertColumn(beforeIndex, col, new TextHeader(headerString), null);
+  }
+
+  /**
+ * 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 insertColumn(int beforeIndex, Column<T, ?> col,
+      SafeHtml headerHtml) {
+    insertColumn(beforeIndex, col, new SafeHtmlHeader(headerHtml), null);
+  }
+
+  /**
+ * 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 insertColumn(int beforeIndex, Column<T, ?> col,
+      String headerString, String footerString) {
+    insertColumn(beforeIndex, col, new TextHeader(headerString),
+        new TextHeader(footerString));
+  }
+
+  /**
+ * 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 insertColumn(int beforeIndex, Column<T, ?> col,
+      SafeHtml headerHtml, SafeHtml footerHtml) {
+    insertColumn(beforeIndex, col, new SafeHtmlHeader(headerHtml),
+        new SafeHtmlHeader(footerHtml));
+  }

   /**
    * Redraw the table's footers.
@@ -1196,6 +1315,19 @@
   void setLoadingState(LoadingState state) {
     setLoadingIconVisible(state == LoadingState.LOADING);
   }
+
+  /**
+   * 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.
@@ -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);
=======================================
--- /trunk/user/test/com/google/gwt/user/cellview/client/CellTableTest.java Wed Dec 1 05:40:20 2010 +++ /trunk/user/test/com/google/gwt/user/cellview/client/CellTableTest.java Fri Dec 3 05:16:36 2010
@@ -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;
@@ -38,6 +40,28 @@
  * Tests for {...@link CellTable}.
  */
 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.
@@ -137,6 +161,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());
@@ -145,6 +201,55 @@
     // Ensure that calling getRowElement() flushes all pending changes.
     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.

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to