Detaching the table section in CellTable before setting the innerHTML to replace the rows. This is a well known performance enhancement that CellTable isn't taking advantage of.

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

Review by: rchandia@google.com

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10218 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/dom/client/DOMImplMozilla.java b/user/src/com/google/gwt/dom/client/DOMImplMozilla.java
index bced2ef..6b306fc 100644
--- a/user/src/com/google/gwt/dom/client/DOMImplMozilla.java
+++ b/user/src/com/google/gwt/dom/client/DOMImplMozilla.java
@@ -51,6 +51,16 @@
   }
 
   /**
+   * Return true if using Gecko 1.9.2 (Firefox 3.6) or earlier.
+   * 
+   * @return true if using Gecko 1.9.2 (Firefox 3.6) or earlier
+   */
+  private static boolean isGecko192OrBefore() {
+    int geckoVersion = getGeckoVersion();
+    return (geckoVersion != -1) && (geckoVersion <= 1009002);
+  }
+
+  /**
    * Return true if using Gecko 2.0.0 (Firefox 4.0) or earlier.
    * 
    * @return true if using Gecko 2.0.0 (Firefox 4.0) or earlier
diff --git a/user/src/com/google/gwt/user/cellview/CellView.gwt.xml b/user/src/com/google/gwt/user/cellview/CellView.gwt.xml
index 5108725..33c45e2 100644
--- a/user/src/com/google/gwt/user/cellview/CellView.gwt.xml
+++ b/user/src/com/google/gwt/user/cellview/CellView.gwt.xml
@@ -48,6 +48,14 @@
     </any>
   </replace-with>
 
+  <!-- Mozilla-specific CellTable implementation. -->
+  <replace-with class="com.google.gwt.user.cellview.client.CellTable.ImplMozilla">
+    <when-type-is class="com.google.gwt.user.cellview.client.CellTable.Impl"/>
+    <any>
+      <when-property-is name="user.agent" value="gecko1_8"/>
+    </any>
+  </replace-with>
+
   <!-- IE-specific CellTable implementation. -->
   <replace-with class="com.google.gwt.user.cellview.client.CellTable.ImplTrident">
     <when-type-is class="com.google.gwt.user.cellview.client.CellTable.Impl"/>
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 0e935c1..0a74012 100644
--- a/user/src/com/google/gwt/user/cellview/client/CellTable.java
+++ b/user/src/com/google/gwt/user/cellview/client/CellTable.java
@@ -116,6 +116,7 @@
     /**
      * The styles used in this widget.
      */
+    @Override
     @Source(BasicStyle.DEFAULT_CSS)
     BasicStyle cellTableStyle();
   }
@@ -411,6 +412,27 @@
     }
 
     /**
+     * Detach a table section element from its parent.
+     * 
+     * @param section the element to detach
+     */
+    protected void detachSectionElement(TableSectionElement section) {
+      section.removeFromParent();
+    }
+
+    /**
+     * Reattach a table section element from its parent.
+     * 
+     * @param parent the parent element
+     * @param section the element to reattach
+     * @param nextSection the next section
+     */
+    protected void reattachSectionElement(Element parent, TableSectionElement section,
+        Element nextSection) {
+      parent.insertBefore(section, nextSection);
+    }
+
+    /**
      * Render a table section in the table.
      * 
      * @param table the {@link CellTable}
@@ -425,9 +447,20 @@
         DOM.setEventListener(table.getElement(), table);
       }
 
+      // Remove the section from the tbody.
+      Element parent = section.getParentElement();
+      Element nextSection = section.getNextSiblingElement();
+      detachSectionElement(section);
+
       // Render the html.
       section.setInnerHTML(html.asString());
 
+      /*
+       * Reattach the section. If next section is null, the section will be
+       * appended instead.
+       */
+      reattachSectionElement(parent, section, nextSection);
+
       // Detach the event listener.
       if (!table.isAttached()) {
         DOM.setEventListener(table.getElement(), null);
@@ -436,6 +469,40 @@
   }
 
   /**
+   * Implementation of {@link CellTable} used by Firefox.
+   */
+  @SuppressWarnings("unused")
+  private static class ImplMozilla extends Impl {
+    /**
+     * Firefox 3.6 and earlier convert td elements to divs if the tbody is
+     * removed from the table element.
+     */
+    @Override
+    protected void detachSectionElement(TableSectionElement section) {
+      if (isGecko192OrBefore()) {
+        return;
+      }
+      super.detachSectionElement(section);
+    }
+
+    @Override
+    protected void reattachSectionElement(Element parent, TableSectionElement section,
+        Element nextSection) {
+      if (isGecko192OrBefore()) {
+        return;
+      }
+      super.reattachSectionElement(parent, section, nextSection);
+    }
+
+    /**
+     * Return true if using Gecko 1.9.2 (Firefox 3.6) or earlier.
+     */
+    private native boolean isGecko192OrBefore() /*-{
+      return @com.google.gwt.dom.client.DOMImplMozilla::isGecko192OrBefore()();
+    }-*/;
+  }
+
+  /**
    * Implementation of {@link CellTable} used by IE.
    */
   @SuppressWarnings("unused")
@@ -644,6 +711,7 @@
 
     // Create the ColumnSortList and delegate.
     sortList = new ColumnSortList(new ColumnSortList.Delegate() {
+      @Override
       public void onModification() {
         if (!updatingSortList) {
           createHeaders(false);
@@ -1601,6 +1669,7 @@
       TableCellElement td = tr.getCells().getItem(keyboardSelectedColumn);
       final com.google.gwt.user.client.Element cellParent = getCellParent(td).cast();
       CellBasedWidgetImpl.get().resetFocus(new Scheduler.ScheduledCommand() {
+        @Override
         public void execute() {
           cellParent.focus();
         }
@@ -1871,6 +1940,7 @@
       cellIsEditing = cell.isEditing(context, parentElem, cellValue);
       if (cellWasEditing && !cellIsEditing) {
         CellBasedWidgetImpl.get().resetFocus(new Scheduler.ScheduledCommand() {
+          @Override
           public void execute() {
             setFocus(true);
           }