Fixes Issue #961.
Fixes a number of IE6 issues with VerticalSplitPanel and
HorizontalSplitPanel. Introduces a new deferred binding for
VerticalSplitPanel on IE6 that relies on getBoundingClientRect for
element height values. Changes some layout in HorizontalSplitPanel
to rely on CSS expressions.

Review by: jgw



git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1157 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/SplitPanel.gwt.xml b/user/src/com/google/gwt/user/SplitPanel.gwt.xml
index d30648a..83dbb55 100644
--- a/user/src/com/google/gwt/user/SplitPanel.gwt.xml
+++ b/user/src/com/google/gwt/user/SplitPanel.gwt.xml
@@ -1,12 +1,12 @@
 <!--
   Copyright 2007 Google Inc.
- 
+
   Licensed under the Apache License, Version 2.0 (the "License"); you may not
   use this file except in compliance with the License. You may obtain a copy of
   the License at
- 
+
   http://www.apache.org/licenses/LICENSE-2.0
- 
+
   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -29,4 +29,9 @@
 		<when-type-is class="com.google.gwt.user.client.ui.HorizontalSplitPanel.Impl"/>
 		<when-property-is name="user.agent" value="safari"/>
 	</replace-with>
-</module>
\ No newline at end of file
+	
+	<replace-with class="com.google.gwt.user.client.ui.VerticalSplitPanel.ImplIE6">
+		<when-type-is class="com.google.gwt.user.client.ui.VerticalSplitPanel.Impl" />
+		<when-property-is name="user.agent" value="ie6" />
+	</replace-with>
+</module>
diff --git a/user/src/com/google/gwt/user/client/ui/HorizontalSplitPanel.java b/user/src/com/google/gwt/user/client/ui/HorizontalSplitPanel.java
index b24b559..060731d 100644
--- a/user/src/com/google/gwt/user/client/ui/HorizontalSplitPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/HorizontalSplitPanel.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2007 Google Inc.
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
  * the License at
- * 
+ *
  * http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -26,11 +26,11 @@
  * user to interactively change the proportion of the width dedicated to each of
  * the two widgets. Widgets contained within a <code>HorizontalSplitPanel</code>
  * will be automatically decorated with scrollbars when necessary.
- * 
+ *
  * <p>
  * <img class='gallery' src='HorizontalSplitPanel.png'/>
  * </p>
- * 
+ *
  * <h3>CSS Style Rules</h3>
  * <ul class='css'>
  * <li>.gwt-HorizontalSplitPanel { the panel itself }</li>
@@ -56,7 +56,7 @@
 
     /**
      * Initializes css properties on the panels DOM structure.
-     * 
+     *
      * @param panel the panel
      */
     protected void init(HorizontalSplitPanel panel) {
@@ -67,7 +67,7 @@
 
     /**
      * Called on each mouse move event during drag resizing.
-     * 
+     *
      * @param panel the panel
      * @param pos the current horizontal mouse position relative to the panel
      */
@@ -96,7 +96,7 @@
 
     /**
      * Called whenever drag resizing begins.
-     * 
+     *
      * @param panel the panel
      * @param pos the current horizontal mouse position relative to the panel
      */
@@ -110,7 +110,7 @@
 
     /**
      * Sets the horizontal position of the splitter.
-     * 
+     *
      * @param panel the panel
      * @param pos the position as a css length
      */
@@ -131,6 +131,10 @@
    * The resizing implementation for IE6/7.
    */
   private static class ImplIE6 extends Impl {
+    private static native void addWidthExpression(Element elem) /*-{
+      elem.style.setExpression('width', '"100%"');
+    }-*/;
+
     protected void init(final HorizontalSplitPanel panel) {
       /*
        * Without fixed table layout, IE will not respected the table width
@@ -138,16 +142,10 @@
        */
       DOM.setStyleAttribute(panel.table, "tableLayout", "fixed");
 
-      /*
-       * Since the DOM structure will not have finished full layout, we must
-       * defer until later to ensure that the inner divs update to the proper
-       * size.
-       */
-      DeferredCommand.addCommand(new Command() {
-        public void execute() {
-          updateDivWidth(panel);
-        }
-      });
+      addWidthExpression(panel.leftDiv);
+      addWidthExpression(panel.rightDiv);
+      addWidthExpression(panel.getElement(LEFT));
+      addWidthExpression(panel.getElement(RIGHT));
     }
 
     protected void onSplitResizeStarted(final HorizontalSplitPanel panel,
@@ -165,21 +163,6 @@
       final Element leftTD = panel.leftTD;
       // adjust the width of the table cell instead of the inner div.
       setWidth(leftTD, pos);
-      updateDivWidth(panel);
-    }
-
-    /*
-     * IE6 will not properly auto size the inner divs unless we explicitly set
-     * their width to something that forces a layout. NOTE: 100% works for
-     * quirks mode but will be problematic for standards mode when there are
-     * margins, border or padding.
-     */
-    private void updateDivWidth(final HorizontalSplitPanel panel) {
-      final String size = "100%";
-      setWidth(panel.leftDiv, size);
-      setWidth(panel.rightDiv, size);
-      setWidth(panel.getElement(LEFT), size);
-      setWidth(panel.getElement(RIGHT), size);
     }
   }
 
@@ -244,7 +227,7 @@
   /**
    * DOM elements needed to support splitter dragging. The underlying DOM
    * structure is:
-   * 
+   *
    * <pre>
    *   table
    *     td (leftTD)
@@ -289,7 +272,7 @@
 
   /**
    * Gets the widget in the left side of the panel.
-   * 
+   *
    * @return the widget, <code>null</code> if there is not one.
    */
   public final Widget getLeftWidget() {
@@ -298,7 +281,7 @@
 
   /**
    * Gets the widget in the right side of the panel.
-   * 
+   *
    * @return the widget, <code>null</code> if there is not one.
    */
   public final Widget getRightWidget() {
@@ -312,7 +295,7 @@
 
   /**
    * Sets the widget in the left side of the panel.
-   * 
+   *
    * @param w the widget
    */
   public final void setLeftWidget(Widget w) {
@@ -321,7 +304,7 @@
 
   /**
    * Sets the widget in the right side of the panel.
-   * 
+   *
    * @param w the widget
    */
   public final void setRightWidget(Widget w) {
diff --git a/user/src/com/google/gwt/user/client/ui/VerticalSplitPanel.java b/user/src/com/google/gwt/user/client/ui/VerticalSplitPanel.java
index 2bfebe3..c4604ab 100644
--- a/user/src/com/google/gwt/user/client/ui/VerticalSplitPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/VerticalSplitPanel.java
@@ -1,12 +1,12 @@
 /*
  * Copyright 2007 Google Inc.
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
  * the License at
- * 
+ *
  * http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.core.client.GWT;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.DeferredCommand;
@@ -26,11 +27,11 @@
  * of the two widgets. Widgets contained within a
  * <code>VerticalSplitterPanel</code> will be automatically decorated with
  * scrollbars when neccessary.
- * 
+ *
  * <p>
  * <img class='gallery' src='VerticalSplitPanel.png'/>
  * </p>
- * 
+ *
  * <h3>CSS Style Rules</h3>
  * <ul class='css'>
  * <li>.gwt-VerticalSplitPanel { the panel itself }</li>
@@ -43,9 +44,32 @@
 
   private static final int TOP = 0;
   private static final int BOTTOM = 1;
+  private static final Impl impl = (Impl) GWT.create(Impl.class);
 
-  private static int getClientHeight(Element elem) {
-    return DOM.getElementPropertyInt(elem, "clientHeight");
+  /**
+   * Provides different implementations for retrieving an element's height. The
+   * default binding is based on DOM1 clientHeight.
+   */
+  private static class Impl {
+    /**
+     * Gets an element's height.
+     *
+     * @param elem an element
+     * @return the height of the element
+     */
+    protected int getElementHeight(Element elem) {
+      return DOM.getElementPropertyInt(elem, "clientHeight");
+    }
+  }
+
+  /**
+   * Provides an implementation for IE6 based on Element.getBoundingClientRect.
+   */
+  private static class ImplIE6 extends Impl {
+    protected native int getElementHeight(Element elem) /*-{
+      var box = elem.getBoundingClientRect();
+      return box.bottom - box.top;
+    }-*/;
   }
 
   private static int getOffsetTop(Element elem) {
@@ -113,7 +137,7 @@
 
   /**
    * Gets the widget in the bottom of the panel.
-   * 
+   *
    * @return the widget, <code>null</code> if there is not one
    */
   public final Widget getBottomWidget() {
@@ -122,7 +146,7 @@
 
   /**
    * Gets the widget in the top of the panel.
-   * 
+   *
    * @return the widget, <code>null</code> if there is not one
    */
   public final Widget getTopWidget() {
@@ -131,7 +155,7 @@
 
   /**
    * Sets the widget in the bottom of the panel.
-   * 
+   *
    * @param w the widget
    */
   public final void setBottomWidget(Widget w) {
@@ -145,7 +169,7 @@
 
   /**
    * Sets the widget in the top of the panel.
-   * 
+   *
    * @param w the widget
    */
   public final void setTopWidget(Widget w) {
@@ -163,8 +187,8 @@
 
     // Compute what the new top height should be.
     final int newTopHeight = initialTopHeight + (y - initialThumbPos);
-    final int newBotHeight = getClientHeight(botElem)
-        + getClientHeight(topElem) - newTopHeight;
+    final int newBotHeight = impl.getElementHeight(botElem)
+        + impl.getElementHeight(topElem) - newTopHeight;
 
     /*
      * NOTE: The bottom must be adjusted before the top due to FF bug which
@@ -184,7 +208,7 @@
 
   final void onSplitterResizeStarted(int x, int y) {
     initialThumbPos = y;
-    initialTopHeight = getClientHeight(getElement(TOP));
+    initialTopHeight = impl.getElementHeight(getElement(TOP));
   }
 
   /**
@@ -200,7 +224,7 @@
      * of the bottom div must change. We do this by comparing the clientHeight
      * of the root div with the offsetTop of a probe div under the bottom div.
      */
-    final int adjust = getClientHeight(thisElem)
+    final int adjust = impl.getElementHeight(thisElem)
         - (getOffsetTop(probeElem) - getOffsetTop(thisElem));
 
     /*
@@ -221,10 +245,10 @@
      * reported clientHeight. If that is non-zero, it tells us how much to
      * accomodate for margin, border and what not.
      */
-    final int curHeight = getClientHeight(bottomElem);
+    final int curHeight = impl.getElementHeight(bottomElem);
     final int newHeight = curHeight + adjust;
     setHeight(bottomElem, newHeight);
-    final int error = getClientHeight(bottomElem) - newHeight;
+    final int error = impl.getElementHeight(bottomElem) - newHeight;
 
     if (error == 0) {
       return;