Introduces EnumAttributeParser, makes XMLElement use it, and makes the layout
panel parsers use that.
Review by jgw
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@6598 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/uibinder/parsers/DockLayoutPanelParser.java b/user/src/com/google/gwt/uibinder/parsers/DockLayoutPanelParser.java
index a5ab01f..71dd0ac 100644
--- a/user/src/com/google/gwt/uibinder/parsers/DockLayoutPanelParser.java
+++ b/user/src/com/google/gwt/uibinder/parsers/DockLayoutPanelParser.java
@@ -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
@@ -17,6 +17,7 @@
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.core.ext.typeinfo.JEnumType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.uibinder.rebind.UiBinderWriter;
@@ -48,31 +49,16 @@
DOCK_NAMES.put("center", "add");
}
- /**
- * TODO(jgw): This will be moved into EnumAttributeParser as soon as I get
- * around to building it.
- */
- static String getFullyQualifiedEnumName(Enum<?> e) {
- Class<?> cls = e.getClass();
- String clsName = cls.getCanonicalName();
- if (clsName == null) {
- // A synthesized enum subtype (e.g., Unit$3) will have no canonical name
- // (yet will not be marked as synthetic). Its superclass will be the
- // one we want (e.g., Unit).
- clsName = cls.getSuperclass().getCanonicalName();
- }
- return clsName + "." + e.name();
- }
-
public void parse(XMLElement elem, String fieldName, JClassType type,
UiBinderWriter writer) throws UnableToCompleteException {
// Generate instantiation (requires a 'unit' ctor param).
// (Don't generate a ctor for the SplitLayoutPanel; it's implicitly PX).
if (type != getSplitLayoutPanelType(writer)) {
- Unit unit = elem.consumeEnumAttribute("unit", Unit.class);
+ JEnumType unitEnumType = writer.getOracle().findType(
+ Unit.class.getCanonicalName()).isEnum();
+ String unit = elem.consumeEnumAttribute("unit", unitEnumType);
writer.setFieldInitializerAsConstructor(fieldName,
- writer.getOracle().findType(DockLayoutPanel.class.getName()),
- getFullyQualifiedEnumName(unit));
+ writer.getOracle().findType(DockLayoutPanel.class.getName()), unit);
}
// Parse children.
diff --git a/user/src/com/google/gwt/uibinder/parsers/EnumAttributeParser.java b/user/src/com/google/gwt/uibinder/parsers/EnumAttributeParser.java
new file mode 100644
index 0000000..19ebbb1
--- /dev/null
+++ b/user/src/com/google/gwt/uibinder/parsers/EnumAttributeParser.java
@@ -0,0 +1,48 @@
+/*
+ * 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.parsers;
+
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.typeinfo.JEnumConstant;
+import com.google.gwt.core.ext.typeinfo.JEnumType;
+import com.google.gwt.uibinder.rebind.MortalLogger;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Parses an enum attribute.
+ */
+public class EnumAttributeParser extends StrictAttributeParser {
+ private final Map<String, JEnumConstant> values = new HashMap<String, JEnumConstant>();
+
+ public EnumAttributeParser(JEnumType enumType) {
+ JEnumConstant[] constants = enumType.getEnumConstants();
+ for (JEnumConstant c : constants) {
+ values.put(c.getName(), c);
+ }
+ }
+
+ public String parse(String value, MortalLogger logger)
+ throws UnableToCompleteException {
+ JEnumConstant c = values.get(value);
+ if (c != null) {
+ return String.format("%s.%s", c.getEnclosingType().getQualifiedSourceName(),
+ value);
+ }
+ return super.parse(value, logger);
+ }
+}
diff --git a/user/src/com/google/gwt/uibinder/parsers/StackLayoutPanelParser.java b/user/src/com/google/gwt/uibinder/parsers/StackLayoutPanelParser.java
index 1e93be7..00395c9 100644
--- a/user/src/com/google/gwt/uibinder/parsers/StackLayoutPanelParser.java
+++ b/user/src/com/google/gwt/uibinder/parsers/StackLayoutPanelParser.java
@@ -17,6 +17,7 @@
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.core.ext.typeinfo.JEnumType;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.uibinder.rebind.UiBinderWriter;
import com.google.gwt.uibinder.rebind.XMLElement;
@@ -32,11 +33,12 @@
public void parse(XMLElement elem, String fieldName, JClassType type,
UiBinderWriter writer) throws UnableToCompleteException {
- // StackLayoutPanel requires a unit ctor.
- Unit unit = elem.consumeEnumAttribute("unit", Unit.class);
+ JEnumType unitEnumType = writer.getOracle().findType(
+ Unit.class.getCanonicalName()).isEnum();
+ String unit = elem.consumeEnumAttribute("unit", unitEnumType);
writer.setFieldInitializerAsConstructor(fieldName,
writer.getOracle().findType(StackLayoutPanel.class.getName()),
- DockLayoutPanelParser.getFullyQualifiedEnumName(unit));
+ unit);
// Parse children.
for (XMLElement child : elem.consumeChildElements()) {
diff --git a/user/src/com/google/gwt/uibinder/parsers/TabLayoutPanelParser.java b/user/src/com/google/gwt/uibinder/parsers/TabLayoutPanelParser.java
index 3d0e42c..a5b3343 100644
--- a/user/src/com/google/gwt/uibinder/parsers/TabLayoutPanelParser.java
+++ b/user/src/com/google/gwt/uibinder/parsers/TabLayoutPanelParser.java
@@ -17,6 +17,7 @@
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
+import com.google.gwt.core.ext.typeinfo.JEnumType;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.uibinder.rebind.UiBinderWriter;
import com.google.gwt.uibinder.rebind.XMLElement;
@@ -39,15 +40,17 @@
public void parse(XMLElement panelElem, String fieldName, JClassType type,
UiBinderWriter writer) throws UnableToCompleteException {
+ JEnumType unitEnumType = writer.getOracle().findType(
+ Unit.class.getCanonicalName()).isEnum();
+
// TabLayoutPanel requires tabBar size and unit ctor args.
String size = panelElem.consumeDoubleAttribute("barHeight");
- Unit unit = panelElem.consumeEnumAttribute("barUnit", Unit.class);
+ String unit = panelElem.consumeEnumAttribute("barUnit", unitEnumType);
- String enumName = DockLayoutPanelParser.getFullyQualifiedEnumName(unit);
JClassType tlpType = writer.getOracle().findType(
TabLayoutPanel.class.getName());
writer.setFieldInitializerAsConstructor(fieldName, tlpType,
- size, enumName);
+ size, unit);
// Parse children.
for (XMLElement tabElem : panelElem.consumeChildElements()) {
diff --git a/user/src/com/google/gwt/uibinder/rebind/AttributeParsers.java b/user/src/com/google/gwt/uibinder/rebind/AttributeParsers.java
index b5c65d8..3b5963d 100644
--- a/user/src/com/google/gwt/uibinder/rebind/AttributeParsers.java
+++ b/user/src/com/google/gwt/uibinder/rebind/AttributeParsers.java
@@ -15,8 +15,11 @@
*/
package com.google.gwt.uibinder.rebind;
+import com.google.gwt.core.ext.typeinfo.JEnumType;
import com.google.gwt.core.ext.typeinfo.JType;
+import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.uibinder.parsers.AttributeParser;
+import com.google.gwt.uibinder.parsers.EnumAttributeParser;
import com.google.gwt.uibinder.parsers.StrictAttributeParser;
import java.util.HashMap;
@@ -49,8 +52,11 @@
* keyed by method parameter signatures.
*/
private final Map<String, String> parsers = new HashMap<String, String>();
+ private final TypeOracle oracle;
- public AttributeParsers() {
+ public AttributeParsers(TypeOracle oracle) {
+ this.oracle = oracle;
+
addAttributeParser(BOOLEAN,
"com.google.gwt.uibinder.parsers.BooleanAttributeParser");
@@ -73,11 +79,23 @@
public AttributeParser get(JType... types) {
AttributeParser rtn = getForKey(getParametersKey(types));
- if (rtn == null && types.length == 1) {
- rtn = new StrictAttributeParser();
+ if (rtn != null || types.length > 1) {
+ return rtn;
+ }
+
+ /* A couple of special cases when we're asked to handle a single type */
+
+ /* Maybe it's an enum */
+ JEnumType enumType = types[0].isEnum();
+ if (enumType != null) {
+ return new EnumAttributeParser(enumType);
}
- return rtn;
+ /*
+ * Dunno what it is, so let a StrictAttributeParser look for
+ * a {field.reference}
+ */
+ return new StrictAttributeParser();
}
public AttributeParser getBooleanParser() {
diff --git a/user/src/com/google/gwt/uibinder/rebind/UiBinderGenerator.java b/user/src/com/google/gwt/uibinder/rebind/UiBinderGenerator.java
index 7f4045b..5bd718a 100644
--- a/user/src/com/google/gwt/uibinder/rebind/UiBinderGenerator.java
+++ b/user/src/com/google/gwt/uibinder/rebind/UiBinderGenerator.java
@@ -96,15 +96,15 @@
PrintWriter printWriter = writers.tryToMakePrintWriterFor(implName);
if (printWriter != null) {
- generateOnce(interfaceType, implName, packageName, printWriter, logger,
- oracle, writers);
+ generateOnce(interfaceType, implName, printWriter, logger, oracle,
+ writers);
}
return packageName + "." + implName;
}
private void generateOnce(JClassType interfaceType, String implName,
- String packageName, PrintWriter binderPrintWrier, TreeLogger treeLogger,
- TypeOracle oracle, PrintWriterManager writerManager)
+ PrintWriter binderPrintWrier, TreeLogger treeLogger, TypeOracle oracle,
+ PrintWriterManager writerManager)
throws UnableToCompleteException {
MortalLogger logger = new MortalLogger(treeLogger);
diff --git a/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java b/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
index e094e7e..4a767df 100644
--- a/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
+++ b/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
@@ -271,7 +271,7 @@
handlerEvaluator = new HandlerEvaluator(ownerClass, logger, oracle);
fieldManager = new FieldManager(logger);
- attributeParsers = new AttributeParsers();
+ attributeParsers = new AttributeParsers(oracle);
bundleParsers = new BundleAttributeParsers(oracle, gwtPrefix, logger,
getOwnerClass(), templatePath, uiOwnerType);
}
diff --git a/user/src/com/google/gwt/uibinder/rebind/XMLElement.java b/user/src/com/google/gwt/uibinder/rebind/XMLElement.java
index 6e9babc..fcced5a 100644
--- a/user/src/com/google/gwt/uibinder/rebind/XMLElement.java
+++ b/user/src/com/google/gwt/uibinder/rebind/XMLElement.java
@@ -16,6 +16,7 @@
package com.google.gwt.uibinder.rebind;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.typeinfo.JEnumType;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
@@ -234,26 +235,10 @@
* @return the attribute's value
* @throws UnableToCompleteException
*/
- public <T extends Enum<T>> T consumeEnumAttribute(String attr, Class<T> type)
+ public String consumeEnumAttribute(String name, JEnumType enumType)
throws UnableToCompleteException {
- String strValue = consumeRawAttribute(attr);
-
- // Get the enum value. Enum.valueOf() throws IAE if the specified string is
- // not valid.
- T value = null;
- try {
- // Enum.valueOf() doesn't accept null arguments.
- if (strValue != null) {
- value = Enum.valueOf(type, strValue);
- }
- } catch (IllegalArgumentException e) {
- }
-
- if (value == null) {
- logger.die(String.format("Error parsing \"%s\" attribute of \"%s\" "
- + "as a %s enum", attr, this, type.getSimpleName()));
- }
- return value;
+ String value = consumeRawAttribute(name);
+ return attributeParsers.get(enumType).parse(value, logger);
}
/**
diff --git a/user/test/com/google/gwt/uibinder/rebind/XMLElementTest.java b/user/test/com/google/gwt/uibinder/rebind/XMLElementTest.java
index 28f20c9..8f224b4 100644
--- a/user/test/com/google/gwt/uibinder/rebind/XMLElementTest.java
+++ b/user/test/com/google/gwt/uibinder/rebind/XMLElementTest.java
@@ -226,7 +226,7 @@
item = (Element) doc.getDocumentElement().getElementsByTagName("elm").item(
0);
- elemProvider = new XMLElementProviderImpl(new AttributeParsers(), null,
+ elemProvider = new XMLElementProviderImpl(new AttributeParsers(null), null,
new DummyMortalLogger());
elm = elemProvider.get(item);
}
diff --git a/user/test/com/google/gwt/uibinder/test/client/EnumeratedLabel.java b/user/test/com/google/gwt/uibinder/test/client/EnumeratedLabel.java
new file mode 100644
index 0000000..790cb2c
--- /dev/null
+++ b/user/test/com/google/gwt/uibinder/test/client/EnumeratedLabel.java
@@ -0,0 +1,25 @@
+package com.google.gwt.uibinder.test.client;
+
+import com.google.gwt.user.client.ui.Label;
+
+public class EnumeratedLabel extends Label {
+ public enum Suffix { ending, suffix, tail}
+
+ private Suffix suffix = Suffix.ending;
+ private String value = "";
+
+ @Override
+ public void setText(String text) {
+ this.value = text;
+ update();
+ }
+
+ public void setSuffix(Suffix suffix) {
+ this.suffix = suffix;
+ update();
+ }
+
+ private void update() {
+ super.setText(value + ": " + suffix);
+ }
+}
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 465ff75..d40617a 100644
--- a/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java
+++ b/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java
@@ -26,6 +26,7 @@
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource.NotStrict;
+import com.google.gwt.uibinder.test.client.EnumeratedLabel.Suffix;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.DisclosurePanel;
import com.google.gwt.user.client.ui.DockPanel;
@@ -81,10 +82,10 @@
}
public void testBraceEscaping() {
- assertEquals("blah di blah {foo: \"bar\"} di blah",
+ assertEquals("blah di blah {foo: \"bar\"} di blah",
widgetUi.bracedParagraph.getAttribute("fnord"));
}
-
+
public void testBundle() {
assertEquals(getCenter(), widgetUi.bundledLabel.getParent());
assertEquals(new FakeBundle().helloText(), widgetUi.bundledLabel.getText());
@@ -168,6 +169,12 @@
+ "translation: funny characters \" \" ' ' & < > > { }", t);
}
+ public void testEnums() {
+ Suffix expected = EnumeratedLabel.Suffix.tail;
+ assertTrue("Should end with suffix \"" + expected + "\"",
+ widgetUi.enumLabel.getText().endsWith(expected.toString()));
+ }
+
public void testProtectedDomTextMessageWithFunnyChars() {
String t = widgetUi.funnyCharsProtectedMessageParagraph.getInnerText();
assertEquals("Don't forget about protected untranslatable blocks: "
@@ -236,7 +243,7 @@
}
interface Bundle extends ClientBundle {
- @Source({"WidgetBasedUi.css", "Menu.css"})
+ @Source( {"WidgetBasedUi.css", "Menu.css"})
@NotStrict
WidgetBasedUi.Style style();
}
diff --git a/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java b/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java
index 39500f2..3ca675e 100644
--- a/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java
+++ b/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java
@@ -22,7 +22,6 @@
import com.google.gwt.dom.client.OListElement;
import com.google.gwt.dom.client.ParagraphElement;
import com.google.gwt.dom.client.SpanElement;
-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;
@@ -63,13 +62,11 @@
}
private static final Binder binder = GWT.create(Binder.class);
- private static boolean stylesInjected = false;
+ @UiField(provided = true)
+ final WidgetBasedUiExternalResources external = GWT.create(WidgetBasedUiExternalResources.class);
@UiField(provided = true)
- final WidgetBasedUiExternalResources external;
-
- @UiField(provided = true)
- final Label bundledLabel;
+ final Label bundledLabel = new Label();
@UiField Style myStyle;
@UiField ClickyLink customLinkWidget;
@@ -123,17 +120,10 @@
@UiField DataResource heartCursorResource;
@UiField CssImportScopeSample cssImportScopeSample;
@UiField ParagraphElement bracedParagraph;
+ @UiField EnumeratedLabel enumLabel;
public WidgetBasedUi() {
- this.bundledLabel = new Label();
- this.external = GWT.create(WidgetBasedUiExternalResources.class);
-
- // Inject only once.
- if (!stylesInjected) {
- StyleInjector.injectStylesheet(external.style().getText());
- stylesInjected = true;
- }
-
+ external.style().ensureInjected();
initWidget(binder.createAndBindUi(this));
}
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 9c3ed83..7bb97de 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
@@ -495,6 +495,7 @@
<p><demo:NeedlesslyAnnotatedLabel ui:field="needlessLabel"
text="Sometimes people do things they don't need to do. Don't punish them."/></p>
<demo:FooLabel ui:field='theFoo' pojo="{values.pojo}"/>
+ <demo:EnumeratedLabel ui:field='enumLabel' suffix='tail'>This label uses an enum for its</demo:EnumeratedLabel>
<h2>How to use the debugId, addStyleNames, addDependentStyleNames attributes</h2>
<p>You can use the <strong>debugId</strong>, <strong>addStyleNames</strong>, and <strong>addDependentStyleNames</strong>