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>