Updating the number of cols in the colgroup when Grid.resizeColumns() is called.

Patch by: jlabanca
Review by: jgw



git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7373 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/ui/Grid.java b/user/src/com/google/gwt/user/client/ui/Grid.java
index 72b44e0..ad99641 100644
--- a/user/src/com/google/gwt/user/client/ui/Grid.java
+++ b/user/src/com/google/gwt/user/client/ui/Grid.java
@@ -198,6 +198,9 @@
       }
     }
     numColumns = columns;
+
+    // Update the size of the colgroup.
+    getColumnFormatter().resizeColumnGroup(columns);
   }
 
   /**
@@ -268,11 +271,7 @@
    */
   @Override
   protected void prepareColumn(int column) {
-    // Ensure that the indices are not negative.
-    if (column < 0) {
-      throw new IndexOutOfBoundsException(
-          "Cannot access a column with a negative index: " + column);
-    }
+    super.prepareColumn(column);
 
     /**
      * Grid does not lazily create cells, so simply ensure that the requested
diff --git a/user/src/com/google/gwt/user/client/ui/HTMLTable.java b/user/src/com/google/gwt/user/client/ui/HTMLTable.java
index 2527b01..e4b4d1b 100644
--- a/user/src/com/google/gwt/user/client/ui/HTMLTable.java
+++ b/user/src/com/google/gwt/user/client/ui/HTMLTable.java
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.dom.client.Document;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.HasClickHandlers;
@@ -395,6 +396,16 @@
     }
 
     /**
+     * Get the col element for the column.
+     * 
+     * @param column the column index
+     * @return the col element
+     */
+    public Element getElement(int column) {
+      return ensureColumn(column);
+    }
+
+    /**
      * Gets the style of the specified column.
      * 
      * @param column the column to be queried
@@ -465,20 +476,33 @@
       DOM.setElementProperty(ensureColumn(column), "width", width);
     }
 
+    /**
+     * Resize the column group element.
+     * 
+     * @param columns the number of columns
+     */
+    void resizeColumnGroup(int columns) {
+      // The colgroup should always have at least one element.  See
+      // prepareColumnGroup() for more details.
+      columns = Math.max(columns, 1);
+
+      int num = columnGroup.getChildCount();
+      if (num < columns) {
+        for (int i = num; i < columns; i++) {
+          columnGroup.appendChild(Document.get().createColElement());
+        }
+      } else if (num > columns) {
+        for (int i = num; i > columns; i--) {
+          columnGroup.removeChild(columnGroup.getLastChild());
+        }
+      }
+    }
+
     private Element ensureColumn(int col) {
       prepareColumn(col);
       prepareColumnGroup();
-
-      int num = DOM.getChildCount(columnGroup);
-      if (num <= col) {
-        Element colElement = null;
-        for (int i = num; i <= col; i++) {
-          colElement = DOM.createElement("col");
-          DOM.appendChild(columnGroup, colElement);
-        }
-        return colElement;
-      }
-      return DOM.getChild(columnGroup, col);
+      resizeColumnGroup(col + 1);
+      return columnGroup.getChild(col).cast();
     }
 
     /**
@@ -1302,7 +1326,11 @@
    * @throws IndexOutOfBoundsException
    */
   protected void prepareColumn(int column) {
-    // By default, do nothing.
+    // Ensure that the indices are not negative.
+    if (column < 0) {
+      throw new IndexOutOfBoundsException(
+          "Cannot access a column with a negative index: " + column);
+    }
   }
 
   /**
@@ -1352,6 +1380,11 @@
   }
 
   protected void setColumnFormatter(ColumnFormatter formatter) {
+    // Copy the columnGroup element to the new formatter so we don't create a
+    // second colgroup element.
+    if (columnFormatter != null) {
+      formatter.columnGroup = columnFormatter.columnGroup;
+    }
     columnFormatter = formatter;
     columnFormatter.prepareColumnGroup();
   }
diff --git a/user/test/com/google/gwt/user/client/ui/GridTest.java b/user/test/com/google/gwt/user/client/ui/GridTest.java
index 7274436..0112482 100644
--- a/user/test/com/google/gwt/user/client/ui/GridTest.java
+++ b/user/test/com/google/gwt/user/client/ui/GridTest.java
@@ -17,6 +17,7 @@
 
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.HTMLTable.ColumnFormatter;
 
 /**
  * Tests for {@link Grid}.
@@ -59,7 +60,18 @@
     }
   }
 
-  public void testColumnFormatter() {
+  public void testColumnFormatterIndexTooHigh() {
+    HTMLTable table = getTable(4, 4);
+    ColumnFormatter formatter = table.getColumnFormatter();
+    try {
+      formatter.getElement(4);
+      fail("Expected IndexOutOfBoundsException");
+    } catch (IndexOutOfBoundsException e) {
+      // Expected.
+    }
+  }
+
+  public void testColumnFormatterStyleName() {
     Grid r = new Grid(4, 5);
     Grid.ColumnFormatter columns = r.getColumnFormatter();
     columns.setStyleName(0, "base");
@@ -150,4 +162,19 @@
       assertEquals(3, r.getDOMRowCount());
     }
   }
+
+  public void testResizeColumnGroup() {
+    Grid grid = new Grid(2, 2);
+    Element colGroup = grid.getColumnFormatter().columnGroup;
+    assertEquals(2, grid.getColumnCount());
+    assertEquals(2, colGroup.getChildCount());
+
+    grid.resizeColumns(5);
+    assertEquals(5, grid.getColumnCount());
+    assertEquals(5, colGroup.getChildCount());
+
+    grid.resizeColumns(1);
+    assertEquals(1, grid.getColumnCount());
+    assertEquals(1, colGroup.getChildCount());
+  }
 }
diff --git a/user/test/com/google/gwt/user/client/ui/HTMLTableTestBase.java b/user/test/com/google/gwt/user/client/ui/HTMLTableTestBase.java
index c8467e0..4fd1c30 100644
--- a/user/test/com/google/gwt/user/client/ui/HTMLTableTestBase.java
+++ b/user/test/com/google/gwt/user/client/ui/HTMLTableTestBase.java
@@ -18,6 +18,7 @@
 import com.google.gwt.junit.client.GWTTestCase;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
+import com.google.gwt.user.client.ui.HTMLTable.ColumnFormatter;
 import com.google.gwt.user.client.ui.HTMLTable.RowFormatter;
 
 import java.util.Arrays;
@@ -115,6 +116,24 @@
     }
   }
 
+  public void testColumnFormatter() {
+    HTMLTable table = getTable(4, 4);
+    ColumnFormatter formatter = table.getColumnFormatter();
+    Element colGroup = formatter.columnGroup;
+
+    // getElement.
+    Element col0 = formatter.getElement(0);
+    assertEquals(colGroup.getChild(0), col0);
+    Element col3 = formatter.getElement(3);
+    assertEquals(colGroup.getChild(3), col3);
+    try {
+      formatter.getElement(-1);
+      fail("Expected IndexOutOfBoundsException");
+    } catch (IndexOutOfBoundsException e) {
+      // Expected.
+    }
+  }
+
   public void testDebugId() {
     HTMLTable table = getTable(4, 3);
     for (int row = 0; row < 4; row++) {
@@ -177,6 +196,17 @@
     assertFalse(iter5.hasNext());
   }
 
+  public void testSetColumnFormatter() {
+    HTMLTable t = getTable(1, 1);
+    Element columnGroup = t.getColumnFormatter().columnGroup;
+    assertNotNull(columnGroup);
+
+    ColumnFormatter formatter = t.new ColumnFormatter();
+    assertNull(formatter.columnGroup);
+    t.setColumnFormatter(formatter);
+    assertEquals(columnGroup, formatter.columnGroup);
+  }
+
   public void testSettingCellAttributes() {
     // These tests simple test for errors while setting these fields. The
     // Patient sample under the survey project has the visual part of the test.