Makes UiBinder able to deal with mixed content in ui:msg.
E.g.:
<p><ui:msg>
You can mix both widgets and named dom fields within a
<gwt:HTML ui:field='mixedMessageWidget'>single
translatable message</gwt:HTML>, another source
<span ui:field='mixedMessageSpan'>exciting and
subtle</span> bugs.
</ui:msg></p>
Reviewed by bobv
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@6750 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/uibinder/parsers/WidgetPlaceholderInterpreter.java b/user/src/com/google/gwt/uibinder/parsers/WidgetPlaceholderInterpreter.java
index 009ea0e..5a74b5f 100644
--- a/user/src/com/google/gwt/uibinder/parsers/WidgetPlaceholderInterpreter.java
+++ b/user/src/com/google/gwt/uibinder/parsers/WidgetPlaceholderInterpreter.java
@@ -118,6 +118,11 @@
uiWriter.addInitStatement("%1$s.addAndReplaceElement(%2$s, %3$s);",
fieldName, childField, idHolder);
}
+ /*
+ * We get used recursively, so this will be called again. Empty the map
+ * or else we'll re-register things.
+ */
+ idToWidgetElement.clear();
return super.postProcess(consumed);
}
diff --git a/user/src/com/google/gwt/uibinder/rebind/Tokenator.java b/user/src/com/google/gwt/uibinder/rebind/Tokenator.java
index 60824bc..9cf6d0c 100644
--- a/user/src/com/google/gwt/uibinder/rebind/Tokenator.java
+++ b/user/src/com/google/gwt/uibinder/rebind/Tokenator.java
@@ -20,7 +20,9 @@
/**
* Methods to dispense unique text tokens to be stitched into text, and
- * to help replace the tokens with arbitrary content.
+ * to help replace the tokens with arbitrary content. Multiple tokenators
+ * can be used across the same body of text without fear of the tokens they
+ * vend colliding with each other.
*/
public class Tokenator {
/**
diff --git a/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java b/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
index 9a6e5ae..6da0b4d 100644
--- a/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
+++ b/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
@@ -263,12 +263,13 @@
}
/**
- * Statements to be excuted right after the current attached element is
+ * Add a statement to be executed right after the current attached element is
* detached. This is useful for doing things that might be expensive while the
* element is attached to the DOM.
*
* @param format
* @param args
+ * @see #beginAttachedSection(String)
*/
public void addDetachStatement(String format, Object... args) {
detachStatementsStack.getFirst().add(String.format(format, args));
@@ -291,10 +292,17 @@
}
/**
- * Begin a section where a new attachable element is being parsed. Note that
- * attachment is only done when actually needed.
+ * Begin a section where a new attachable element is being parsed--that is,
+ * one that will be constructed as a big innerHTML string, and then briefly
+ * attached to the dom to allow fields accessing its to be filled (at the
+ * moment, HasHTMLParser, HTMLPanelParser, and DomElementParser.).
+ * <p>
+ * Succeeding calls made to {@link #ensureAttached} and
+ * {@link #ensureFieldAttached} must refer to children of this element, until
+ * {@link #endAttachedSection} is called.
*
- * @param element to be attached for this section
+ * @param element Java expression for the generated code that will return the
+ * dom element to be attached.
*/
public void beginAttachedSection(String element) {
attachSectionElements.addFirst(element);
@@ -414,6 +422,7 @@
/**
* End the current attachable section. This will detach the element if it was
* ever attached and execute any detach statements.
+ * @see #beginAttachedSection(String)
*/
public void endAttachedSection() {
String elementVar = attachSectionElements.removeFirst();
@@ -431,6 +440,7 @@
* Ensure that the specified element is attached to the DOM.
*
* @param element variable name of element to be attached
+ * @see #beginAttachedSection(String)
*/
public void ensureAttached(String element) {
String attachSectionElement = attachSectionElements.getFirst();
@@ -445,9 +455,12 @@
}
/**
- * Ensure that the specified field is attached to the DOM.
+ * Ensure that the specified field is attached to the DOM. The field
+ * must hold an object that responds to Element getElement(). Convenience
+ * wrapper for {@link ensureAttached}<code>(field + ".getElement()")</code>.
*
* @param field variable name of the field to be attached
+ * @see #beginAttachedSection(String)
*/
public void ensureFieldAttached(String field) {
ensureAttached(field + ".getElement()");
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 46437e0..420cf4e 100644
--- a/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java
+++ b/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java
@@ -181,6 +181,11 @@
+ "translation: funny characters \" \" ' ' & < > > { }", t);
}
+ public void testMixOfWidgetsAndElementsInUiMsg() {
+ assertEquals("single translatable message", widgetUi.mixedMessageWidget.getText());
+ assertEquals("exciting and subtle", widgetUi.mixedMessageSpan.getInnerText());
+ }
+
public void testEnums() {
Suffix expected = EnumeratedLabel.Suffix.tail;
assertTrue("Should end with suffix \"" + expected + "\"",
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 c79a9b5..3036ea5 100644
--- a/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java
+++ b/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java
@@ -35,6 +35,7 @@
import com.google.gwt.user.client.ui.DisclosurePanel;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.HTMLPanel;
+import com.google.gwt.user.client.ui.HasHTML;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.MenuBar;
@@ -124,7 +125,9 @@
@UiField EnumeratedLabel enumLabel;
@UiField PushButton pushButton;
@UiField Label lblDebugId;
-
+ @UiField HasHTML mixedMessageWidget;
+ @UiField SpanElement mixedMessageSpan;
+
public WidgetBasedUi() {
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 d4f1dbf..a00a977 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
@@ -172,7 +172,8 @@
adopters should recognize themselves as such, and be prepared to have the
api rug yanked out from under them.</ui:msg></p>
<p ui:field="main">
- &point-right; <span ui:field="messageInMain"><ui:msg>This is the main area. It's an <b>HTMLPanel</b>, which allows you to mix
+ &point-right; <span ui:field="messageInMain"><ui:msg>This is the main area.
+ It's an <b>HTMLPanel</b>, which allows you to mix
&point-right; • XHTML • &point-left; and regular GWT widgets, more or less with
impunity. Take the following button for example.</ui:msg></span> &point-left;
</p>
@@ -481,6 +482,13 @@
with widgets <demo:MyDatePicker/> as well, whether they <gwt:Label>HasText<ui:ph name="tm">*TM*</ui:ph></gwt:Label>
or <gwt:HTML>HasHTML<ui:ph name="TM2"><sup ui:field="tmElementJr"
class="{external.style.tmText}">TM</sup></ui:ph></gwt:HTML></ui:msg></p>
+
+ <p><ui:msg>
+ You can mix both widgets and named dom fields within a
+ <gwt:HTML ui:field='mixedMessageWidget'>single translatable message</gwt:HTML>, another source
+ <span ui:field='mixedMessageSpan'>exciting and subtle</span>
+ bugs.
+ </ui:msg></p>
<h2>Any Widget You Like</h2>
<p><demo:AnnotatedStrictLabel text="This widget is not default instantiable." ui:field="strictLabel"/></p>