Fixes for issues 4447, 4366.
Adds setFloat(), et al to Style, along with cross-browser abstractions
for both float and opacity.
Changes TabLayoutPanel to use the Style.setFloat(), along with a test to
ensure this causes the correct layout for tabs.
Review: http://gwt-code-reviews.appspot.com/132806

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7399 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/dom/client/DOMImpl.java b/user/src/com/google/gwt/dom/client/DOMImpl.java
index b9ba351..445449d 100644
--- a/user/src/com/google/gwt/dom/client/DOMImpl.java
+++ b/user/src/com/google/gwt/dom/client/DOMImpl.java
@@ -69,6 +69,18 @@
     return select;
   }
 
+  public native void cssClearOpacity(Style style) /*-{
+    style.opacity = '';
+  }-*/;
+
+  public String cssFloatPropertyName() {
+    return "cssFloat";
+  }
+
+  public native void cssSetOpacity(Style style, double value) /*-{
+    style.opacity = value;
+  }-*/;
+
   public abstract void dispatchEvent(Element target, NativeEvent evt);
 
   public native boolean eventGetAltKey(NativeEvent evt) /*-{
diff --git a/user/src/com/google/gwt/dom/client/DOMImplIE6.java b/user/src/com/google/gwt/dom/client/DOMImplIE6.java
index f0581be..10d32be 100644
--- a/user/src/com/google/gwt/dom/client/DOMImplIE6.java
+++ b/user/src/com/google/gwt/dom/client/DOMImplIE6.java
@@ -22,6 +22,21 @@
 class DOMImplIE6 extends DOMImplTrident {
 
   @Override
+  public native void cssClearOpacity(Style style) /*-{
+    style.filter = '';
+  }-*/;
+
+  @Override
+  public String cssFloatPropertyName() {
+    return "styleFloat";
+  }
+
+  @Override
+  public native void cssSetOpacity(Style style, double value) /*-{
+    style.filter = 'alpha(opacity=' + (value * 100) + ')';
+  }-*/;
+
+  @Override
   public int getAbsoluteLeft(Element elem) {
     Document doc = elem.getOwnerDocument();
     return (int) Math.floor(getBoundingClientRectLeft(elem)
diff --git a/user/src/com/google/gwt/dom/client/Style.java b/user/src/com/google/gwt/dom/client/Style.java
index 3b16c6a..07cf3b7 100644
--- a/user/src/com/google/gwt/dom/client/Style.java
+++ b/user/src/com/google/gwt/dom/client/Style.java
@@ -94,6 +94,7 @@
 
     public abstract String getType();
   }
+
   /**
    * Enum for the border-style property.
    */
@@ -248,6 +249,27 @@
   }
 
   /**
+   * Enum for the float property.
+   */
+  public enum Float implements HasCssName {
+    LEFT {
+      public String getCssName() {
+        return FLOAT_LEFT;
+      }
+    },
+    RIGHT {
+      public String getCssName() {
+        return FLOAT_RIGHT;
+      }
+    },
+    NONE {
+      public String getCssName() {
+        return FLOAT_NONE;
+      }
+    },
+  }
+
+  /**
    * Enum for the font-style property.
    */
   public enum FontStyle implements HasCssName {
@@ -515,6 +537,10 @@
   private static final String DISPLAY_BLOCK = "block";
   private static final String DISPLAY_NONE = "none";
 
+  private static final String FLOAT_LEFT = "left";
+  private static final String FLOAT_RIGHT = "right";
+  private static final String FLOAT_NONE = "none";
+
   private static final String FONT_STYLE_OBLIQUE = "oblique";
   private static final String FONT_STYLE_ITALIC = "italic";
   private static final String FONT_STYLE_NORMAL = "normal";
@@ -676,9 +702,16 @@
   /**
    * Clear the font-size css property.
    */
+  public final void clearFloat() {
+    clearProperty(DOMImpl.impl.cssFloatPropertyName());
+  }
+
+  /**
+   * Clear the font-size css property.
+   */
   public final void clearFontSize() {
-     clearProperty(STYLE_FONT_SIZE);
-   }
+    clearProperty(STYLE_FONT_SIZE);
+  }
 
   /**
    * Clears the font-style CSS property.
@@ -754,8 +787,8 @@
    * Clear the opacity css property.
    */
   public final void clearOpacity() {
-     clearProperty(STYLE_OPACITY);
-   }
+    DOMImpl.impl.cssClearOpacity(this);
+  }
 
   /**
    * Clears the overflow CSS property.
@@ -1172,6 +1205,13 @@
   }
 
   /**
+   * Set the float css property.
+   */
+  public final void setFloat(Float value) {
+    setProperty(DOMImpl.impl.cssFloatPropertyName(), value.getCssName());
+  }
+
+  /**
    * Set the font-size css property.
    */
   public final void setFontSize(double value, Unit unit) {
@@ -1252,7 +1292,7 @@
    * Set the opacity css property.
    */
   public final void setOpacity(double value) {
-    setProperty(STYLE_OPACITY, value + "");
+    DOMImpl.impl.cssSetOpacity(this, value);
   }
 
   /**
diff --git a/user/src/com/google/gwt/user/client/ui/TabLayoutPanel.java b/user/src/com/google/gwt/user/client/ui/TabLayoutPanel.java
index 8cccb78..affa84b 100644
--- a/user/src/com/google/gwt/user/client/ui/TabLayoutPanel.java
+++ b/user/src/com/google/gwt/user/client/ui/TabLayoutPanel.java
@@ -17,6 +17,7 @@
 
 import com.google.gwt.dom.client.Document;
 import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.Style;
 import com.google.gwt.dom.client.Style.Unit;
 import com.google.gwt.dom.client.Style.Visibility;
 import com.google.gwt.event.dom.client.ClickEvent;
@@ -104,11 +105,11 @@
       setStyleName("gwt-TabLayoutPanelTab");
       inner.setClassName("gwt-TabLayoutPanelTabInner");
 
-      // TODO: float:left may not be enough. If there are tabs of differeing
+      // TODO: float:left may not be enough. If there are tabs of differing
       // heights, the shorter ones will top-align, rather than bottom-align,
       // which is what we would want. display:inline-block fixes this, but
       // needs lots of cross-browser hacks to work properly.
-      getElement().getStyle().setProperty("cssFloat", "left");
+      getElement().getStyle().setFloat(Style.Float.LEFT);
     }
 
     public HandlerRegistration addClickHandler(ClickHandler handler) {
diff --git a/user/test/com/google/gwt/user/client/ui/TabLayoutPanelTest.java b/user/test/com/google/gwt/user/client/ui/TabLayoutPanelTest.java
index 344c4fd..3f46153 100644
--- a/user/test/com/google/gwt/user/client/ui/TabLayoutPanelTest.java
+++ b/user/test/com/google/gwt/user/client/ui/TabLayoutPanelTest.java
@@ -172,4 +172,19 @@
     delayTestFinish(1000);
     p.selectTab(1);
   }
+
+  /**
+   * Tests that tabs actually line up properly (see issue 4447).
+   */
+  public void testTabLayout() {
+    TabLayoutPanel p = new TabLayoutPanel(2, Unit.EM);
+    RootPanel.get().add(p);
+
+    p.add(new Button("foo"), new Label("foo"));
+    p.add(new Button("bar"), new Label("bar"));
+
+    assertEquals(
+        p.getTabWidget(0).getElement().getOffsetTop(),
+        p.getTabWidget(1).getElement().getOffsetTop());
+  }
 }