Fixes Issue 4415 "uibinder Image class with resource attribute, removes styles
on that image", by adding a custom parser for Image.

http://code.google.com/p/google-web-toolkit/issues/detail?id=4415

Review by jgw
http://gwt-code-reviews.appspot.com/130811

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@7411 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/uibinder/elementparsers/ImageParser.java b/user/src/com/google/gwt/uibinder/elementparsers/ImageParser.java
new file mode 100644
index 0000000..ea3d122
--- /dev/null
+++ b/user/src/com/google/gwt/uibinder/elementparsers/ImageParser.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2010 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.uibinder.elementparsers;
+
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.uibinder.rebind.UiBinderWriter;
+import com.google.gwt.uibinder.rebind.XMLElement;
+import com.google.gwt.user.client.ui.Image;
+
+/**
+ * Custom parsing of Image widgets. Sets ImageResource via constructor, because
+ * {@link Image#setResource} clobbers most setter values.
+ */
+public class ImageParser implements ElementParser {
+
+  public void parse(XMLElement elem, String fieldName, JClassType type,
+      UiBinderWriter writer) throws UnableToCompleteException {
+    String resource = elem.consumeImageResourceAttribute("resource");
+    if (null != resource) {
+      writer.setFieldInitializerAsConstructor(fieldName,
+          writer.getOracle().findType(Image.class.getName()),
+          resource);
+    }
+  }
+}
diff --git a/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java b/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
index 7cdc2b7..118b22d 100644
--- a/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
+++ b/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
@@ -626,6 +626,10 @@
   /**
    * Instructs the writer to initialize the field with a specific contructor
    * invocaction, instead of the default GWT.create call.
+   * 
+   * @param fieldName the field to intialize
+   * @param type the type of the field
+   * @param arguments to the constructor call
    */
   public void setFieldInitializerAsConstructor(String fieldName,
       JClassType type, String... args) {
@@ -944,6 +948,7 @@
     addWidgetParser("DockLayoutPanel");
     addWidgetParser("StackLayoutPanel");
     addWidgetParser("TabLayoutPanel");
+    addWidgetParser("Image");
   }
 
   /**
diff --git a/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java b/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java
index d049ad5..f61d522 100644
--- a/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java
+++ b/user/test/com/google/gwt/uibinder/UiBinderJreSuite.java
@@ -23,6 +23,7 @@
 import com.google.gwt.uibinder.attributeparsers.StringAttributeParserTest;
 import com.google.gwt.uibinder.elementparsers.DialogBoxParserTest;
 import com.google.gwt.uibinder.elementparsers.DockLayoutPanelParserTest;
+import com.google.gwt.uibinder.elementparsers.ImageParserTest;
 import com.google.gwt.uibinder.elementparsers.IsEmptyParserTest;
 import com.google.gwt.uibinder.elementparsers.LayoutPanelParserTest;
 import com.google.gwt.uibinder.elementparsers.StackLayoutPanelParserTest;
@@ -70,6 +71,7 @@
     // elementparsers
     suite.addTestSuite(DialogBoxParserTest.class);
     suite.addTestSuite(DockLayoutPanelParserTest.class);
+    suite.addTestSuite(ImageParserTest.class);
     suite.addTestSuite(IsEmptyParserTest.class);
     suite.addTestSuite(LayoutPanelParserTest.class);
     suite.addTestSuite(StackLayoutPanelParserTest.class);
diff --git a/user/test/com/google/gwt/uibinder/elementparsers/ImageParserTest.java b/user/test/com/google/gwt/uibinder/elementparsers/ImageParserTest.java
new file mode 100644
index 0000000..d2793ea
--- /dev/null
+++ b/user/test/com/google/gwt/uibinder/elementparsers/ImageParserTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2010 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.uibinder.elementparsers;
+
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.uibinder.rebind.FieldWriter;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+
+/**
+ * Eponymous unit test.
+ */
+public class ImageParserTest extends TestCase {
+  private static final String PARSED_TYPE = "com.google.gwt.user.client.ui.Image";
+
+  private ElementParserTester tester;
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp();
+    tester = new ElementParserTester(PARSED_TYPE, new ImageParser());
+  }
+
+  public void testHappyWithResource() throws UnableToCompleteException,
+      SAXException, IOException {
+    StringBuffer b = new StringBuffer();
+    b.append("<ui:Image field='someImageResource' />");
+    b.append("<g:Image resource='{someImageResource}' >");
+    b.append("</g:Image>");
+
+    FieldWriter w = tester.parse(b.toString());
+    assertEquals("new " + PARSED_TYPE + "(someImageResource)",
+        w.getInitializer());
+
+    assertTrue(tester.writer.statements.isEmpty());
+    assertNull(tester.logger.died);
+  }
+
+  public void testHappyWithNoResource() throws UnableToCompleteException,
+      SAXException, IOException {
+    StringBuffer b = new StringBuffer();
+    b.append("<g:Image>");
+    b.append("</g:Image>");
+
+    FieldWriter w = tester.parse(b.toString());
+    assertNull(w.getInitializer());
+
+    assertTrue(tester.writer.statements.isEmpty());
+    assertNull(tester.logger.died);
+  }
+
+  public void testChokeOnNonResource() throws SAXException, IOException {
+    StringBuffer b = new StringBuffer();
+    b.append("<g:Image resource='someString' >");
+    b.append("</g:Image>");
+
+    try {
+      tester.parse(b.toString());
+      fail();
+    } catch (UnableToCompleteException e) {
+      assertTrue("Expect to hear about ImageResource",
+          tester.logger.died.contains("ImageResource"));
+    }
+  }
+}
diff --git a/user/test/com/google/gwt/uibinder/test/UiJavaResources.java b/user/test/com/google/gwt/uibinder/test/UiJavaResources.java
index 905b914..cb93041 100644
--- a/user/test/com/google/gwt/uibinder/test/UiJavaResources.java
+++ b/user/test/com/google/gwt/uibinder/test/UiJavaResources.java
@@ -168,6 +168,30 @@
       return code;
     }
   };
+  public static final MockJavaResource IMAGE = new MockJavaResource(
+      "com.google.gwt.user.client.ui.Image") {
+    @Override
+    protected CharSequence getContent() {
+      StringBuffer code = new StringBuffer();
+      code.append("package com.google.gwt.user.client.ui;\n");
+      code.append("public class Image extends Widget {\n");
+      code.append("  public Image() {} ");
+      code.append("}\n");
+      return code;
+    }
+  };
+  public static final MockJavaResource IMAGE_RESOURCE = new MockJavaResource(
+      "com.google.gwt.resources.client.ImageResource") {
+    @Override
+    protected CharSequence getContent() {
+      StringBuffer code = new StringBuffer();
+      code.append("package com.google.gwt.resources.client;\n");
+      code.append("public class ImageResource  {\n");
+      code.append("  public ImageResource() {} ");
+      code.append("}\n");
+      return code;
+    }
+  };
   public static final MockJavaResource LABEL = new MockJavaResource(
       "com.google.gwt.user.client.ui.Label") {
     @Override
@@ -328,6 +352,8 @@
     rtn.add(DOCK_LAYOUT_PANEL);
     rtn.add(EVENT_HANDLER);
     rtn.add(GWT_EVENT);
+    rtn.add(IMAGE);
+    rtn.add(IMAGE_RESOURCE);
     rtn.add(HANDLER_REGISTRATION);
     rtn.add(HAS_CLICK_HANDLERS);
     rtn.add(HAS_HORIZONTAL_ALIGNMENT);
diff --git a/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java b/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java
index 1072cc3..630137b 100644
--- a/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java
+++ b/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java
@@ -25,6 +25,7 @@
 import com.google.gwt.junit.Platform;
 import com.google.gwt.junit.client.GWTTestCase;
 import com.google.gwt.resources.client.ClientBundle;
+import com.google.gwt.resources.client.ImageResource;
 import com.google.gwt.resources.client.CssResource.NotStrict;
 import com.google.gwt.uibinder.test.client.EnumeratedLabel.Suffix;
 import com.google.gwt.user.client.DOM;
@@ -32,6 +33,7 @@
 import com.google.gwt.user.client.ui.DockPanel;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.HTMLPanel;
+import com.google.gwt.user.client.ui.Image;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.RadioButton;
 import com.google.gwt.user.client.ui.RootPanel;
@@ -440,14 +442,15 @@
   }
 
   public void testImageResourceInImageWidget() {
-    assertEquals(widgetUi.prettyImage.getWidth(),
-        widgetUi.babyWidget.getOffsetWidth());
-    assertEquals(widgetUi.prettyImage.getHeight(),
-        widgetUi.babyWidget.getOffsetHeight());
-    assertEquals(widgetUi.prettyImage.getTop(),
-        widgetUi.babyWidget.getOriginTop());
-    assertEquals(widgetUi.prettyImage.getLeft(),
-        widgetUi.babyWidget.getOriginLeft());
+    ImageResource resource = widgetUi.prettyImage;
+    Image widget = widgetUi.babyWidget;
+    assertEquals(resource.getWidth(), widget.getOffsetWidth());
+    assertEquals(resource.getHeight(), widget.getOffsetHeight());
+    assertEquals(resource.getTop(), widget.getOriginTop());
+    assertEquals(resource.getLeft(), widget.getOriginLeft());
+    
+    assertEquals("expected alt text", widget.getAltText());
+    assertEquals("expected style name", widget.getStyleName());
   }
 
   public void testDataResource() {
diff --git a/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml b/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml
index 47e9f74..bb063e0 100644
--- a/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml
+++ b/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml
@@ -195,7 +195,9 @@
 
       <p>I bet you like babies in your Image widgets.</p>
       <div class='{cursorifficStyle.cursor}'>
-      <gwt:Image ui:field='babyWidget' resource='{prettyImage}'/>
+      <gwt:Image ui:field='babyWidget' resource='{prettyImage}'
+          altText='expected alt text' styleName='expected style name'
+      />
       </div>
 
       <p ui:field='simpleSpriteParagraph'