This change is to update <ui:with> to support setting property values on the
provided type by using a nested <ui:attributes/> element.
There are many times in which non-widget objects are needed in the UiBinder XML.
It's not always convenient to construct these objects in the owner class. In
some organizations where there are separate teams that write the Java code and
the UiBinder XML, it may not be ideal to distribute, what is considered view
logic/data, across the Java class and the XML file.
This is especially useful for @UiChild methods where one of the parameter types
is a complex type that supplement the Widget being passed to the @UiChild
method.
For example:
<ui:with type="some.LayoutData" field="layoutData">
<ui:attributes left="15" row="3" color="#f0f0f0">
</ui:with>
<foo:SomeWidget>
<foo:child layoutData="{layoutData}">
<foo:ChildWidget />
</foo:child>
</foo:SomeWidget>
Review by rjrjr: http://gwt-code-reviews.appspot.com/1524803/
Review by: rdcastro@google.com
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10686 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/uibinder/elementparsers/NullInterpreter.java b/user/src/com/google/gwt/uibinder/elementparsers/SimpleInterpeter.java
similarity index 67%
copy from user/src/com/google/gwt/uibinder/elementparsers/NullInterpreter.java
copy to user/src/com/google/gwt/uibinder/elementparsers/SimpleInterpeter.java
index 3bc6cfe..cbedb5c 100644
--- a/user/src/com/google/gwt/uibinder/elementparsers/NullInterpreter.java
+++ b/user/src/com/google/gwt/uibinder/elementparsers/SimpleInterpeter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2008 Google Inc.
+ * Copyright 2011 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
@@ -16,13 +16,22 @@
package com.google.gwt.uibinder.elementparsers;
import com.google.gwt.uibinder.rebind.XMLElement;
+import com.google.gwt.uibinder.rebind.XMLElement.Interpreter;
/**
- * An no-op interpreter.
- * @param <T> The type of null to return
+ * A simple {@link Interpreter} that returns a given value to every
+ * request.
+ *
+ * @param <T>
*/
-public final class NullInterpreter<T> implements XMLElement.Interpreter<T> {
+public class SimpleInterpeter<T> implements Interpreter<T> {
+ private final T rtn;
+
+ public SimpleInterpeter(T rtn) {
+ this.rtn = rtn;
+ }
+
public T interpretElement(XMLElement elem) {
- return null;
+ return rtn;
}
}
diff --git a/user/src/com/google/gwt/uibinder/elementparsers/TextPlaceholderInterpreter.java b/user/src/com/google/gwt/uibinder/elementparsers/TextPlaceholderInterpreter.java
index ff0bf14..14c7b0c 100644
--- a/user/src/com/google/gwt/uibinder/elementparsers/TextPlaceholderInterpreter.java
+++ b/user/src/com/google/gwt/uibinder/elementparsers/TextPlaceholderInterpreter.java
@@ -16,6 +16,7 @@
package com.google.gwt.uibinder.elementparsers;
import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.uibinder.rebind.NullInterpreter;
import com.google.gwt.uibinder.rebind.UiBinderWriter;
import com.google.gwt.uibinder.rebind.XMLElement;
import com.google.gwt.uibinder.rebind.messages.MessageWriter;
diff --git a/user/src/com/google/gwt/uibinder/elementparsers/NullInterpreter.java b/user/src/com/google/gwt/uibinder/rebind/NullInterpreter.java
similarity index 88%
rename from user/src/com/google/gwt/uibinder/elementparsers/NullInterpreter.java
rename to user/src/com/google/gwt/uibinder/rebind/NullInterpreter.java
index 3bc6cfe..fa5e7b9 100644
--- a/user/src/com/google/gwt/uibinder/elementparsers/NullInterpreter.java
+++ b/user/src/com/google/gwt/uibinder/rebind/NullInterpreter.java
@@ -13,9 +13,7 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
-package com.google.gwt.uibinder.elementparsers;
-
-import com.google.gwt.uibinder.rebind.XMLElement;
+package com.google.gwt.uibinder.rebind;
/**
* An no-op interpreter.
diff --git a/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java b/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java
index f74cf54..d513f09 100644
--- a/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java
+++ b/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java
@@ -27,6 +27,8 @@
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.elementparsers.BeanParser;
+import com.google.gwt.uibinder.elementparsers.SimpleInterpeter;
import com.google.gwt.uibinder.rebind.messages.MessagesWriter;
import com.google.gwt.uibinder.rebind.model.ImplicitClientBundle;
import com.google.gwt.uibinder.rebind.model.ImplicitCssResource;
@@ -105,15 +107,17 @@
private final JClassType dataResourceType;
private final String binderUri;
+ private final UiBinderContext uiBinderContext;
public UiBinderParser(UiBinderWriter writer, MessagesWriter messagesWriter,
FieldManager fieldManager, TypeOracle oracle,
- ImplicitClientBundle bundleClass, String binderUri) {
+ ImplicitClientBundle bundleClass, String binderUri, UiBinderContext uiBinderContext) {
this.writer = writer;
this.oracle = oracle;
this.messagesWriter = messagesWriter;
this.fieldManager = fieldManager;
this.bundleClass = bundleClass;
+ this.uiBinderContext = uiBinderContext;
this.cssResourceType = oracle.findType(CssResource.class.getCanonicalName());
this.imageResourceType = oracle.findType(ImageResource.class.getCanonicalName());
this.dataResourceType = oracle.findType(DataResource.class.getCanonicalName());
@@ -319,6 +323,22 @@
} else {
writer.die(elem, "Could not infer type for field %s.", resourceName);
}
+
+ // process ui:attributes child for property setting
+ boolean attributesChildFound = false;
+ // Use consumeChildElements(Interpreter) so no assertEmpty check is performed
+ for (XMLElement child : elem.consumeChildElements(new SimpleInterpeter<Boolean>(true))) {
+ if (attributesChildFound) {
+ writer.die(child, "<ui:with> can only contain a single <ui:attributes> child Element.");
+ }
+ attributesChildFound = true;
+
+ if (!elem.getNamespaceUri().equals(child.getNamespaceUri()) || !"attributes".equals(child.getLocalName())) {
+ writer.die(child, "Found unknown child element.");
+ }
+
+ new BeanParser(uiBinderContext).parse(child, resourceName, resourceType, writer);
+ }
}
private void createResourceUiFactory(XMLElement elem, String resourceName, JClassType resourceType)
diff --git a/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java b/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
index 3a47e76..c9e873c 100644
--- a/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
+++ b/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
@@ -1378,8 +1378,8 @@
// Allow GWT.create() to init the field, the default behavior
- String rootField =
- new UiBinderParser(this, messages, fieldManager, oracle, bundleClass, binderUri).parse(elem);
+ String rootField = new UiBinderParser(this, messages, fieldManager, oracle, bundleClass,
+ binderUri, uiBinderCtx).parse(elem);
fieldManager.validate();
diff --git a/user/src/com/google/gwt/uibinder/rebind/XMLElement.java b/user/src/com/google/gwt/uibinder/rebind/XMLElement.java
index 211f4ee..99680f3 100644
--- a/user/src/com/google/gwt/uibinder/rebind/XMLElement.java
+++ b/user/src/com/google/gwt/uibinder/rebind/XMLElement.java
@@ -25,6 +25,7 @@
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.uibinder.attributeparsers.AttributeParser;
import com.google.gwt.uibinder.attributeparsers.AttributeParsers;
+import com.google.gwt.uibinder.elementparsers.SimpleInterpeter;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
@@ -71,18 +72,6 @@
String postProcess(String consumedText) throws UnableToCompleteException;
}
- private static class NoBrainInterpeter<T> implements Interpreter<T> {
- private final T rtn;
-
- public NoBrainInterpeter(T rtn) {
- this.rtn = rtn;
- }
-
- public T interpretElement(XMLElement elem) {
- return rtn;
- }
- }
-
/**
* Represents the source location where the XMLElement was declared.
*/
@@ -217,7 +206,7 @@
* @throws UnableToCompleteException if it isn't
*/
public void assertNoText() throws UnableToCompleteException {
- NoBrainInterpeter<String> nullInterpreter = new NoBrainInterpeter<String>(null);
+ SimpleInterpeter<String> nullInterpreter = new SimpleInterpeter<String>(null);
String s = consumeInnerTextEscapedAsHtmlStringLiteral(nullInterpreter);
if (!"".equals(s)) {
logger.die(this, "Unexpected text in element: \"%s\"", s);
@@ -823,7 +812,7 @@
private Iterable<XMLElement> consumeChildElementsNoEmptyCheck() {
try {
- Iterable<XMLElement> rtn = consumeChildElements(new NoBrainInterpeter<Boolean>(true));
+ Iterable<XMLElement> rtn = consumeChildElements(new SimpleInterpeter<Boolean>(true));
return rtn;
} catch (UnableToCompleteException e) {
throw new RuntimeException("Impossible exception", e);
diff --git a/user/test/com/google/gwt/uibinder/LazyWidgetBuilderSuite.java b/user/test/com/google/gwt/uibinder/LazyWidgetBuilderSuite.java
index eda89e4..e638632 100644
--- a/user/test/com/google/gwt/uibinder/LazyWidgetBuilderSuite.java
+++ b/user/test/com/google/gwt/uibinder/LazyWidgetBuilderSuite.java
@@ -19,6 +19,7 @@
import com.google.gwt.uibinder.test.client.IsRenderableIntegrationTest;
import com.google.gwt.uibinder.test.client.LazyWidgetBuilderSafeUriIntegrationTest;
import com.google.gwt.uibinder.test.client.SafeHtmlAsComponentsTest;
+import com.google.gwt.uibinder.test.client.UiBinderParserUiWithAttributesTest;
import com.google.gwt.uibinder.test.client.UiRendererTest;
import com.google.gwt.uibinder.test.client.UiRendererEventsTest;
@@ -35,6 +36,7 @@
suite.addTestSuite(IsRenderableIntegrationTest.class);
suite.addTestSuite(LazyWidgetBuilderSafeUriIntegrationTest.class);
suite.addTestSuite(SafeHtmlAsComponentsTest.class);
+ suite.addTestSuite(UiBinderParserUiWithAttributesTest.class);
suite.addTestSuite(UiRendererTest.class);
suite.addTestSuite(UiRendererEventsTest.class);
diff --git a/user/test/com/google/gwt/uibinder/rebind/AbstractUiBinderWriterTest.java b/user/test/com/google/gwt/uibinder/rebind/AbstractUiBinderWriterTest.java
index 9256187..e8fb5f3 100644
--- a/user/test/com/google/gwt/uibinder/rebind/AbstractUiBinderWriterTest.java
+++ b/user/test/com/google/gwt/uibinder/rebind/AbstractUiBinderWriterTest.java
@@ -176,7 +176,7 @@
writer =
new UiBinderWriter(aClass, "foo", "", types, logger, fieldManager, messages,
DesignTimeUtilsStub.EMPTY, uiBinderCtx, true, true, BINDER_URI);
- parser = new UiBinderParser(writer, messages, fieldManager, types, null, BINDER_URI);
+ parser = new UiBinderParser(writer, messages, fieldManager, types, null, BINDER_URI, new UiBinderContext());
designTime.rememberPathForElements(doc);
}
}
\ No newline at end of file
diff --git a/user/test/com/google/gwt/uibinder/rebind/UiBinderParserUiWithTest.java b/user/test/com/google/gwt/uibinder/rebind/UiBinderParserUiWithTest.java
index 3338168..cea41c0 100644
--- a/user/test/com/google/gwt/uibinder/rebind/UiBinderParserUiWithTest.java
+++ b/user/test/com/google/gwt/uibinder/rebind/UiBinderParserUiWithTest.java
@@ -276,7 +276,7 @@
writer =
new UiBinderWriter(aClass, "foo", "", types, logger, fieldManager, null,
DesignTimeUtilsStub.EMPTY, new UiBinderContext(), true, true, "");
- parser = new UiBinderParser(writer, null, fieldManager, types, null, "");
+ parser = new UiBinderParser(writer, null, fieldManager, types, null, "", new UiBinderContext());
designTime.rememberPathForElements(doc);
UiBinderParser.Resource.WITH.create(parser, elm);
}
diff --git a/user/test/com/google/gwt/uibinder/rebind/XMLElementTest.java b/user/test/com/google/gwt/uibinder/rebind/XMLElementTest.java
index 3627cc1..0b44b23 100644
--- a/user/test/com/google/gwt/uibinder/rebind/XMLElementTest.java
+++ b/user/test/com/google/gwt/uibinder/rebind/XMLElementTest.java
@@ -23,7 +23,6 @@
import com.google.gwt.dev.javac.testing.impl.MockResourceOracle;
import com.google.gwt.dev.util.log.PrintWriterTreeLogger;
import com.google.gwt.uibinder.attributeparsers.AttributeParsers;
-import com.google.gwt.uibinder.elementparsers.NullInterpreter;
import com.google.gwt.uibinder.test.UiJavaResources;
import junit.framework.TestCase;
diff --git a/user/test/com/google/gwt/uibinder/test/client/UiBinderParserUiWithAttributesTest.Ui.ui.xml b/user/test/com/google/gwt/uibinder/test/client/UiBinderParserUiWithAttributesTest.Ui.ui.xml
new file mode 100644
index 0000000..37c4866
--- /dev/null
+++ b/user/test/com/google/gwt/uibinder/test/client/UiBinderParserUiWithAttributesTest.Ui.ui.xml
@@ -0,0 +1,37 @@
+<!-- -->
+<!-- Copyright 2011 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 -->
+<!-- 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. License for the specific language governing permissions and -->
+<!-- limitations under the License. -->
+<ui:UiBinder
+ xmlns:ui='urn:ui:com.google.gwt.uibinder'
+ >
+
+ <ui:with type="com.google.gwt.uibinder.test.client.UiBinderParserUiWithAttributesTest.TestBeanA" field="test1" />
+
+ <ui:with type="com.google.gwt.uibinder.test.client.UiBinderParserUiWithAttributesTest.TestBeanA" field="test2" />
+
+ <ui:with type="com.google.gwt.uibinder.test.client.UiBinderParserUiWithAttributesTest.TestBeanB" field="test3">
+ <ui:attributes beanA="{test1}" />
+ </ui:with>
+
+ <ui:with type="com.google.gwt.uibinder.test.client.UiBinderParserUiWithAttributesTest.TestBeanC" field="test4">
+ <ui:attributes beanA="{test1}" />
+ </ui:with>
+
+ <ui:with type="com.google.gwt.uibinder.test.client.UiBinderParserUiWithAttributesTest.TestBeanC" field="test5">
+ <ui:attributes beanA="{test1}" beanB="{test3}" />
+ </ui:with>
+
+
+ <div />
+
+</ui:UiBinder>
diff --git a/user/test/com/google/gwt/uibinder/test/client/UiBinderParserUiWithAttributesTest.java b/user/test/com/google/gwt/uibinder/test/client/UiBinderParserUiWithAttributesTest.java
new file mode 100644
index 0000000..6a2ae4c
--- /dev/null
+++ b/user/test/com/google/gwt/uibinder/test/client/UiBinderParserUiWithAttributesTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2011 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.test.client;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.junit.client.GWTTestCase;
+import com.google.gwt.uibinder.client.UiBinder;
+import com.google.gwt.uibinder.client.UiConstructor;
+import com.google.gwt.uibinder.client.UiField;
+
+/**
+ * Tests <ui:attribute>.
+ */
+public class UiBinderParserUiWithAttributesTest extends GWTTestCase {
+
+ static class TestBeanA {
+ }
+
+ static class TestBeanB {
+ TestBeanA beanA;
+
+ public void setBeanA(TestBeanA beanA) {
+ this.beanA = beanA;
+ }
+ }
+
+ static class TestBeanC {
+ TestBeanA beanA;
+ TestBeanB beanB;
+
+ @UiConstructor
+ public TestBeanC(TestBeanA beanA) {
+ this.beanA = beanA;
+ }
+
+ public void setBeanB(TestBeanB beanB) {
+ this.beanB = beanB;
+ }
+ }
+
+
+ static class Ui {
+ interface Binder extends UiBinder<Element, Ui> {
+ }
+
+ static final Binder binder = GWT.create(Binder.class);
+
+ @UiField(provided = true)
+ TestBeanA test1 = new TestBeanA();
+
+ @UiField
+ TestBeanA test2;
+
+ @UiField
+ TestBeanB test3;
+
+ @UiField
+ TestBeanC test4;
+
+ @UiField
+ TestBeanC test5;
+
+ Ui() {
+ binder.createAndBindUi(this);
+ }
+ }
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.uibinder.test.LazyWidgetBuilderSuite";
+ }
+
+ public void testUiWith() {
+ Ui ui = new Ui();
+
+ assertNotNull(ui.test1);
+ assertNotNull(ui.test2);
+
+ assertNotNull(ui.test3);
+ assertNotNull(ui.test3.beanA);
+ assertSame(ui.test1, ui.test3.beanA);
+
+
+ assertNotNull(ui.test4);
+ assertSame(ui.test1, ui.test4.beanA);
+ assertNull(ui.test4.beanB);
+
+ assertNotNull(ui.test5);
+ assertSame(ui.test1, ui.test5.beanA);
+ assertSame(ui.test3, ui.test5.beanB);
+ }
+}