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;&nbsp;<span ui:field="messageInMain"><ui:msg>This is the main area. It's an <b>HTMLPanel</b>, which allows you to mix 
+        &point-right;&nbsp;<span ui:field="messageInMain"><ui:msg>This is the main area. 
+        It's an <b>HTMLPanel</b>, which allows you to mix 
           &point-right; &bull; XHTML &bull; &point-left; and regular GWT widgets, more or less with 
           impunity. Take the following button for example.</ui:msg></span>&nbsp;&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>