Revision: 6351 Author: [email protected] Date: Mon Oct 12 15:15:47 2009 Log: Restores "Introduces support for DataResource to UiBinder...", now with IE-proof testing and tidier UiBinderParser
Review by: bobv http://gwt-code-reviews.appspot.com/78808 http://code.google.com/p/google-web-toolkit/source/detail?r=6351 Added: /trunk/user/src/com/google/gwt/uibinder/rebind/model/ImplicitDataResource.java /trunk/user/src/com/google/gwt/uibinder/sample/client/heart.cur Modified: /trunk/user/src/com/google/gwt/uibinder/rebind/BundleWriter.java /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java /trunk/user/src/com/google/gwt/uibinder/rebind/model/ImplicitClientBundle.java /trunk/user/src/com/google/gwt/uibinder/rebind/model/ImplicitCssResource.java /trunk/user/src/com/google/gwt/uibinder/rebind/model/ImplicitImageResource.java /trunk/user/src/com/google/gwt/uibinder/sample/client/WidgetBasedUi.java /trunk/user/src/com/google/gwt/uibinder/sample/client/WidgetBasedUi.ui.xml /trunk/user/test/com/google/gwt/uibinder/sample/client/UiBinderTest.java ======================================= --- /dev/null +++ /trunk/user/src/com/google/gwt/uibinder/rebind/model/ImplicitDataResource.java Mon Oct 12 15:15:47 2009 @@ -0,0 +1,37 @@ +/* + * Copyright 2009 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.rebind.model; + +/** + * Models a method returning a DataResource on a generated ClientBundle. + */ +public class ImplicitDataResource { + private final String name; + private final String source; + + ImplicitDataResource(String name, String source) { + this.name = name; + this.source = source; + } + + public String getName() { + return name; + } + + public String getSource() { + return source; + } +} ======================================= --- /dev/null +++ /trunk/user/src/com/google/gwt/uibinder/sample/client/heart.cur Mon Oct 12 15:15:47 2009 Binary file, no diff available. ======================================= --- /trunk/user/src/com/google/gwt/uibinder/rebind/BundleWriter.java Sat Oct 10 13:50:11 2009 +++ /trunk/user/src/com/google/gwt/uibinder/rebind/BundleWriter.java Mon Oct 12 15:15:47 2009 @@ -19,11 +19,13 @@ import com.google.gwt.core.ext.typeinfo.JClassType; import com.google.gwt.core.ext.typeinfo.TypeOracle; import com.google.gwt.resources.client.ClientBundle; +import com.google.gwt.resources.client.DataResource; import com.google.gwt.resources.client.ImageResource; import com.google.gwt.resources.client.ImageResource.ImageOptions; import com.google.gwt.resources.client.ImageResource.RepeatStyle; import com.google.gwt.uibinder.rebind.model.ImplicitClientBundle; import com.google.gwt.uibinder.rebind.model.ImplicitCssResource; +import com.google.gwt.uibinder.rebind.model.ImplicitDataResource; import com.google.gwt.uibinder.rebind.model.ImplicitImageResource; /** @@ -37,6 +39,7 @@ private final TypeOracle oracle; private final JClassType clientBundleType; + private final JClassType dataResourceType; private final JClassType imageOptionType; private final JClassType imageResourceType; private final JClassType repeatStyleType; @@ -51,6 +54,7 @@ this.oracle = oracle; clientBundleType = oracle.findType(ClientBundle.class.getName()); + dataResourceType = oracle.findType(DataResource.class.getCanonicalName()); imageOptionType = oracle.findType(ImageOptions.class.getCanonicalName()); imageResourceType = oracle.findType(ImageResource.class.getCanonicalName()); repeatStyleType = oracle.findType(RepeatStyle.class.getCanonicalName()); @@ -76,6 +80,7 @@ writer.write("import %s;", imageResourceType.getQualifiedSourceName()); writer.write("import %s;", imageOptionType.getQualifiedSourceName()); writer.write("import %s;", clientBundleType.getQualifiedSourceName()); + writer.write("import %s;", dataResourceType.getQualifiedSourceName()); writer.newline(); // Open interface @@ -89,8 +94,14 @@ writer.write("%s %s();", css.getClassName(), css.getName()); writer.newline(); } - - writer.newline(); + + // Write data methods + for (ImplicitDataResource data : bundleClass.getDataMethods()) { + writer.write("@Source(\"%s\")", data.getSource()); + writer.write("%s %s();", dataResourceType.getName(), data.getName()); + writer.newline(); + } + writeImageMethods(); // Close interface. ======================================= --- /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java Fri Oct 9 22:09:58 2009 +++ /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java Mon Oct 12 15:15:47 2009 @@ -20,11 +20,13 @@ import com.google.gwt.core.ext.typeinfo.JMethod; import com.google.gwt.core.ext.typeinfo.TypeOracle; import com.google.gwt.resources.client.CssResource; +import com.google.gwt.resources.client.DataResource; import com.google.gwt.resources.client.ImageResource; import com.google.gwt.resources.client.ImageResource.RepeatStyle; import com.google.gwt.uibinder.rebind.messages.MessagesWriter; import com.google.gwt.uibinder.rebind.model.ImplicitClientBundle; import com.google.gwt.uibinder.rebind.model.ImplicitCssResource; +import com.google.gwt.uibinder.rebind.model.ImplicitDataResource; import com.google.gwt.uibinder.rebind.model.ImplicitImageResource; import com.google.gwt.uibinder.rebind.model.OwnerField; @@ -50,6 +52,7 @@ private final ImplicitClientBundle bundleClass; private final JClassType cssResourceType; private final JClassType imageResourceType; + private final JClassType dataResourceType; public UiBinderParser(UiBinderWriter writer, MessagesWriter messagesWriter, FieldManager fieldManager, TypeOracle oracle, @@ -61,6 +64,37 @@ this.bundleClass = bundleClass; this.cssResourceType = oracle.findType(CssResource.class.getCanonicalName()); this.imageResourceType = oracle.findType(ImageResource.class.getCanonicalName()); + this.dataResourceType = oracle.findType(DataResource.class.getCanonicalName()); + } + + private enum Resource { + data { + void create(UiBinderParser parser, XMLElement elem) + throws UnableToCompleteException { + parser.createData(elem); + } + }, + image { + void create(UiBinderParser parser, XMLElement elem) + throws UnableToCompleteException { + parser.createImage(elem); + } + }, + style { + void create(UiBinderParser parser, XMLElement elem) + throws UnableToCompleteException { + parser.createStyle(elem); + } + }, + with { + void create(UiBinderParser parser, XMLElement elem) + throws UnableToCompleteException { + parser.createResource(elem); + } + }; + + abstract void create(UiBinderParser parser, XMLElement elem) + throws UnableToCompleteException; } /** @@ -70,9 +104,7 @@ public String parse(XMLElement elem) throws UnableToCompleteException { // TODO(rjrjr) Clearly need to break these find* methods out into their own // parsers, an so need a registration scheme for uibinder-specific parsers - findStyles(elem); findResources(elem); - findImages(elem); messagesWriter.findMessagesConfig(elem); XMLElement uiRoot = elem.consumeSingleChildElement(); return writer.parseElementToField(uiRoot); @@ -109,16 +141,28 @@ return resourceType; } + + /** + * Interprets <ui:data> elements + */ + private void createData(XMLElement elem) throws UnableToCompleteException { + String name = elem.consumeRequiredAttribute(FIELD_ATTRIBUTE); + String source = elem.consumeRequiredAttribute(SOURCE_ATTRIBUTE); + ImplicitDataResource dataMethod = bundleClass.createDataResource(name, + source); + FieldWriter field = fieldManager.registerField(dataResourceType, + dataMethod.getName()); + field.setInitializer(String.format("%s.%s()", bundleClass.getFieldName(), + dataMethod.getName())); + } /** * Interprets <ui:image> elements */ private void createImage(XMLElement elem) throws UnableToCompleteException { String name = elem.consumeRequiredAttribute(FIELD_ATTRIBUTE); - String source = elem.consumeAttribute(SOURCE_ATTRIBUTE, null); // @source is - // optional - // on - // ImageResource + // @source is optional on ImageResource + String source = elem.consumeAttribute(SOURCE_ATTRIBUTE, null); Boolean flipRtl = null; if (elem.hasAttribute(FLIP_RTL_ATTRIBUTE)) { @@ -208,51 +252,25 @@ field.setInitializer(String.format("%s.%s()", bundleClass.getFieldName(), cssMethod.getName())); } - - private void findImages(XMLElement binderElement) - throws UnableToCompleteException { - binderElement.consumeChildElements(new XMLElement.Interpreter<Boolean>() { - public Boolean interpretElement(XMLElement elem) - throws UnableToCompleteException { - if (!(writer.isBinderElement(elem) && "image".equals(elem.getLocalName()))) { - return false; // Not of interest, do not consume - } - - createImage(elem); - - return true; // Yum - } - }); - } private void findResources(XMLElement binderElement) throws UnableToCompleteException { binderElement.consumeChildElements(new XMLElement.Interpreter<Boolean>() { public Boolean interpretElement(XMLElement elem) throws UnableToCompleteException { - if (!(writer.isBinderElement(elem) && "with".equals(elem.getLocalName()))) { - return false; // Not of interest, do not consume - } - - createResource(elem); - - return true; // Yum - } - }); - } - - private void findStyles(XMLElement binderElement) - throws UnableToCompleteException { - binderElement.consumeChildElements(new XMLElement.Interpreter<Boolean>() { - public Boolean interpretElement(XMLElement elem) - throws UnableToCompleteException { - if (!(writer.isBinderElement(elem) && "style".equals(elem.getLocalName()))) { - return false; // Not of interest, do not consume - } - - createStyle(elem); - - return true; // consume + + if (writer.isBinderElement(elem)) { + try { + Resource.valueOf(elem.getLocalName()).create(UiBinderParser.this, + elem); + } catch (IllegalArgumentException e) { + writer.die( + "%s has unknown tag %s, or is not appropriate as a top level element", + elem, elem.getLocalName()); + } + return true; + } + return false; // leave it be } }); } ======================================= --- /trunk/user/src/com/google/gwt/uibinder/rebind/model/ImplicitClientBundle.java Fri Oct 9 22:09:58 2009 +++ /trunk/user/src/com/google/gwt/uibinder/rebind/model/ImplicitClientBundle.java Mon Oct 12 15:15:47 2009 @@ -20,16 +20,17 @@ import com.google.gwt.uibinder.rebind.MortalLogger; import java.util.Collections; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Set; /** * Models the ClientBundle to be generated from a ui.xml. */ public class ImplicitClientBundle { - - private final Set<ImplicitCssResource> cssMethods = new HashSet<ImplicitCssResource>(); - private final Set<ImplicitImageResource> imageMethods = new HashSet<ImplicitImageResource>(); + // LinkedHashSets for consistent order across recompiles + private final LinkedHashSet<ImplicitCssResource> cssMethods = new LinkedHashSet<ImplicitCssResource>(); + private final LinkedHashSet<ImplicitImageResource> imageMethods = new LinkedHashSet<ImplicitImageResource>(); + private final LinkedHashSet<ImplicitDataResource> dataMethods = new LinkedHashSet<ImplicitDataResource>(); private final String packageName; private final String className; private final String fieldName; @@ -54,7 +55,7 @@ /** * Called to declare a new CssResource accessor on this bundle. * - * @param name the method name + * @param name the method name and the ui:field name * @param source path to the .css file resource * @param extendedInterface the public interface implemented by this * CssResource, or null @@ -68,12 +69,26 @@ cssMethods.add(css); return css; } + + /** + * Called to declare a new DataResource accessor on this bundle. All params + * must be non-null + * + * @param name the method name and the ui:field name + * @param source path to the resource + * @return + */ + public ImplicitDataResource createDataResource(String name, String source) { + ImplicitDataResource data = new ImplicitDataResource(name, source); + dataMethods.add(data); + return data; + } /** * Called to declare a new ImageResource accessor on this bundle. * - * @param name the method name - * @param source path the image resource, or null if none was specified + * @param name the method name and the ui:field name + * @param source path to the image resource, or null if none was specified * @param flipRtl value for the flipRtl ImageOption, or null if none was * specified * @param repeatStyle value of the RepeatStyle ImageOption, or null if none @@ -82,7 +97,8 @@ */ public ImplicitImageResource createImageResource(String name, String source, Boolean flipRtl, RepeatStyle repeatStyle) { - ImplicitImageResource image = new ImplicitImageResource(name, source, flipRtl, repeatStyle); + ImplicitImageResource image = new ImplicitImageResource(name, source, + flipRtl, repeatStyle); imageMethods.add(image); return image; } @@ -94,6 +110,10 @@ public Set<ImplicitCssResource> getCssMethods() { return Collections.unmodifiableSet(cssMethods); } + + public Set<ImplicitDataResource> getDataMethods() { + return Collections.unmodifiableSet(dataMethods); + } public String getFieldName() { return fieldName; ======================================= --- /trunk/user/src/com/google/gwt/uibinder/rebind/model/ImplicitCssResource.java Sat Oct 10 13:50:44 2009 +++ /trunk/user/src/com/google/gwt/uibinder/rebind/model/ImplicitCssResource.java Mon Oct 12 15:15:47 2009 @@ -44,7 +44,7 @@ private final MortalLogger logger; private File generatedFile; - public ImplicitCssResource(String packageName, String className, String name, + ImplicitCssResource(String packageName, String className, String name, String source, JClassType extendedInterface, String body, MortalLogger logger) { this.packageName = packageName; ======================================= --- /trunk/user/src/com/google/gwt/uibinder/rebind/model/ImplicitImageResource.java Fri Oct 9 22:09:58 2009 +++ /trunk/user/src/com/google/gwt/uibinder/rebind/model/ImplicitImageResource.java Mon Oct 12 15:15:47 2009 @@ -26,7 +26,7 @@ private final Boolean flipRtl; private final RepeatStyle repeatStyle; - public ImplicitImageResource( + ImplicitImageResource( String name, String source, Boolean flipRtl, RepeatStyle repeatStyle) { this.name = name; this.source = source; ======================================= --- /trunk/user/src/com/google/gwt/uibinder/sample/client/WidgetBasedUi.java Fri Oct 9 22:09:58 2009 +++ /trunk/user/src/com/google/gwt/uibinder/sample/client/WidgetBasedUi.java Mon Oct 12 15:15:47 2009 @@ -25,6 +25,7 @@ import com.google.gwt.dom.client.StyleInjector; import com.google.gwt.dom.client.TableElement; import com.google.gwt.resources.client.CssResource; +import com.google.gwt.resources.client.DataResource; import com.google.gwt.resources.client.ImageResource; import com.google.gwt.resources.client.CssResource.Shared; import com.google.gwt.uibinder.client.UiBinder; @@ -119,6 +120,7 @@ @UiField ImageResource prettyTilingImage; @UiField Image babyWidget; @UiField ParagraphElement simpleSpriteParagraph; + @UiField DataResource heartCursorResource; public WidgetBasedUi() { this.bundledLabel = new Label(); ======================================= --- /trunk/user/src/com/google/gwt/uibinder/sample/client/WidgetBasedUi.ui.xml Fri Oct 9 22:09:58 2009 +++ /trunk/user/src/com/google/gwt/uibinder/sample/client/WidgetBasedUi.ui.xml Mon Oct 12 15:15:47 2009 @@ -96,6 +96,14 @@ } </ui:style> +<ui:style field='cursorifficStyle'> + @url cursor heartCursorResource; + .cursor { + cursor:cursor,pointer; + } +</ui:style> +<ui:data field='heartCursorResource' src='heart.cur'/> + <ui:style field='mySpritelyStyle'> @sprite .simpleSprite { gwt-image: "prettyImage"; @@ -174,14 +182,18 @@ </p> <p>I bet you like babies in your Image widgets.</p> + <div class='{cursorifficStyle.cursor}'> <gwt:Image ui:field='babyWidget' resource='{prettyImage}'/> + </div> <p ui:field='simpleSpriteParagraph' - class='{mySpritelyStyle.simpleSprite} {mySpritelyStyle.garish}' > + class='{mySpritelyStyle.simpleSprite} {mySpritelyStyle.garish} + {cursorifficStyle.cursor}' > And sprites too </p> - <p class='{mySpritelyStyle.tilingSprite} {mySpritelyStyle.garish}'> + <p class='{mySpritelyStyle.tilingSprite} {mySpritelyStyle.garish} + {cursorifficStyle.cursor}'> Well how do you like <br/> tiled sprited images...of babies!! <br/> Well of course you do. Who wouldn't? @@ -442,10 +454,12 @@ <b>HTML:</b> <pre style="border: 1px dashed #666; padding: 5px 0;"> <div id="gwt-debug-joe" - class="gwt-Label newStyle anotherStyle gwt-Label-dependentStyle gwt-Label-anotherDependentStyle"> + class="gwt-Label newStyle anotherStyle gwt-Label-dependentStyle + gwt-Label-anotherDependentStyle"> A label with a debug id </div> - <button id="gwt-debug-myButton" class="gwt-Button buttonStyle" tabindex="0" type="button">Go</button></pre> + <button id="gwt-debug-myButton" class="gwt-Button buttonStyle" tabindex="0" + type="button">Go</button></pre> <gwt:FlowPanel> <gwt:Label ui:field="lblDebugId" debugId="joe" addStyleNames="newStyle, anotherStyle" addStyleDependentNames="dependentStyle, anotherDependentStyle"> ======================================= --- /trunk/user/test/com/google/gwt/uibinder/sample/client/UiBinderTest.java Sat Oct 10 13:50:11 2009 +++ /trunk/user/test/com/google/gwt/uibinder/sample/client/UiBinderTest.java Mon Oct 12 15:15:47 2009 @@ -1,12 +1,12 @@ /* * Copyright 2009 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 @@ -82,12 +82,10 @@ public void testBundle() { assertEquals(getCenter(), widgetUi.bundledLabel.getParent()); - assertEquals(new FakeBundle().helloText(), - widgetUi.bundledLabel.getText()); + assertEquals(new FakeBundle().helloText(), widgetUi.bundledLabel.getText()); WidgetBasedUiExternalResources resources = GWT.create(WidgetBasedUiExternalResources.class); assertEquals("bundledLabel should have styleName", - resources.style().prettyText(), - widgetUi.bundledLabel.getStyleName()); + resources.style().prettyText(), widgetUi.bundledLabel.getStyleName()); Element pretty = DOM.getElementById("prettyPara"); assertEquals(resources.style().prettyText(), pretty.getClassName()); @@ -120,8 +118,7 @@ public void testComputedStyleInAPlaceholder() { WidgetBasedUiExternalResources resources = GWT.create(WidgetBasedUiExternalResources.class); - assertEquals(resources.style().tmText(), - widgetUi.tmElement.getClassName()); + assertEquals(resources.style().tmText(), widgetUi.tmElement.getClassName()); } public void testDomAccessAndComputedAttributeOnPlaceholderedElement() { @@ -149,8 +146,7 @@ } public void testDomAttributeMessageWithFunnyChars() { - ParagraphElement p = - widgetUi.funnyCharsMessageDomAttributeParagraph; + ParagraphElement p = widgetUi.funnyCharsMessageDomAttributeParagraph; String t = p.getAttribute("title"); assertEquals("funny characters \" ' ' & < > > { }", t); } @@ -164,8 +160,7 @@ public void testDomTextMessageWithFunnyChars() { String t = widgetUi.funnyCharsMessageParagraph.getInnerText(); assertEquals("They might show up in body text that has been marked for " - + "translation: funny characters \" \" ' ' & < > > { }", - t); + + "translation: funny characters \" \" ' ' & < > > { }", t); } public void testProtectedDomTextMessageWithFunnyChars() { @@ -230,11 +225,9 @@ } public void testNestedBundle() { - DomBasedUi.Resources resources = - GWT.create(DomBasedUi.Resources.class); - assertEquals(resources.style().bodyColor() - + " " + resources.style().bodyFont() , - domUi.root.getClassName()); + DomBasedUi.Resources resources = GWT.create(DomBasedUi.Resources.class); + assertEquals(resources.style().bodyColor() + " " + + resources.style().bodyFont(), domUi.root.getClassName()); } interface Bundle extends ClientBundle { @@ -269,7 +262,8 @@ public void testPrivateStyleFromExternalCss() { ParagraphElement p = widgetUi.privateStyleParagraph; - assertTrue("Some kind of class should be set", p.getClassName().length() > 0); + assertTrue("Some kind of class should be set", + p.getClassName().length() > 0); } public void testPrivateStylesFromInlineCss() { @@ -319,8 +313,8 @@ // Assumes setPopupText() is overloaded such that there is a static // setPopupText(Foo, String) method. ClickyLink clicky = widgetUi.customLinkWidget; - assertEquals("overloaded setter should have been called", - "That tickles!", clicky.getPopupText()); + assertEquals("overloaded setter should have been called", "That tickles!", + clicky.getPopupText()); } public void testStringAttributeWithFormatChars() { @@ -346,17 +340,27 @@ String t = clicky.getPopupText(); assertEquals("funny characters \" ' ' & < > > { }", t); } - + 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()); + 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()); + } + + public void testDataResource() { + assertNotNull(widgetUi.heartCursorResource.getUrl()); } public void testSpritedElement() { - assertEquals(widgetUi.prettyImage.getWidth(), widgetUi.simpleSpriteParagraph.getOffsetWidth()); - assertEquals(widgetUi.prettyImage.getHeight(), widgetUi.simpleSpriteParagraph.getOffsetHeight()); + assertEquals(widgetUi.prettyImage.getWidth(), + widgetUi.simpleSpriteParagraph.getOffsetWidth()); + assertEquals(widgetUi.prettyImage.getHeight(), + widgetUi.simpleSpriteParagraph.getOffsetHeight()); } public void suppressForIEfail_testBizarrelyElementedWidgets() { --~--~---------~--~----~------------~-------~--~----~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~----------~----~----~----~------~----~------~--~---
