Revision: 10217
Author:   gwt.mirror...@gmail.com
Date:     Tue May 24 13:12:43 2011
Log:      Adds a ui:safehtml tag to UiBinder

Review at http://gwt-code-reviews.appspot.com/1422812

Review by: rj...@google.com
http://code.google.com/p/google-web-toolkit/source/detail?r=10217

Added:
/trunk/user/src/com/google/gwt/uibinder/elementparsers/UiSafeHtmlInterpreter.java /trunk/user/test/com/google/gwt/uibinder/elementparsers/UiSafeHtmlInterpreterTest.java /trunk/user/test/com/google/gwt/uibinder/elementparsers/UiTextInterpreterTest.java
Modified:
/trunk/user/src/com/google/gwt/uibinder/elementparsers/ComputedAttributeInterpreter.java
 /trunk/user/src/com/google/gwt/uibinder/elementparsers/HtmlInterpreter.java
 /trunk/user/src/com/google/gwt/uibinder/elementparsers/TextInterpreter.java
/trunk/user/src/com/google/gwt/uibinder/elementparsers/UiTextInterpreter.java
 /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderGenerator.java
 /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java
 /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java
 /trunk/user/src/com/google/gwt/uibinder/rebind/XMLAttribute.java
 /trunk/user/src/com/google/gwt/uibinder/rebind/XMLElement.java
/trunk/user/test/com/google/gwt/uibinder/elementparsers/ElementParserTester.java /trunk/user/test/com/google/gwt/uibinder/elementparsers/MockUiBinderWriter.java
 /trunk/user/test/com/google/gwt/uibinder/test/UiJavaResources.java
 /trunk/user/test/com/google/gwt/uibinder/test/client/Constants.java
 /trunk/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java
 /trunk/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java
 /trunk/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml

=======================================
--- /dev/null
+++ /trunk/user/src/com/google/gwt/uibinder/elementparsers/UiSafeHtmlInterpreter.java Tue May 24 13:12:43 2011
@@ -0,0 +1,49 @@
+/*
+ * 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.elementparsers;
+
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.uibinder.rebind.UiBinderWriter;
+import com.google.gwt.uibinder.rebind.XMLAttribute;
+
+/**
+ * Interprets generic message tags like:
+ * <b>&lt;ui:safehtml from="{myMsg.message}" /&gt;</b>. It's called in HTML contexts.
+ */
+public class UiSafeHtmlInterpreter extends UiTextInterpreter {
+  /**
+ * Used in {@link #interpretElement} to invoke the {@link ComputedAttributeInterpreter}.
+   */
+  private class Delegate extends UiTextInterpreter.Delegate {
+    public String getAttributeToken(XMLAttribute attribute)
+      throws UnableToCompleteException {
+ return writer.tokenForSafeHtmlExpression(attribute.consumeSafeHtmlValue());
+    }
+  }
+
+  public UiSafeHtmlInterpreter(UiBinderWriter writer) {
+    super(writer);
+  }
+
+ protected ComputedAttributeInterpreter createComputedAttributeInterpreter() {
+    return new ComputedAttributeInterpreter(writer, new Delegate());
+  }
+
+  @Override
+  protected String getLocalName() {
+    return "safehtml";
+  }
+}
=======================================
--- /dev/null
+++ /trunk/user/test/com/google/gwt/uibinder/elementparsers/UiSafeHtmlInterpreterTest.java Tue May 24 13:12:43 2011
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2010 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.elementparsers;
+
+import com.google.gwt.core.ext.UnableToCompleteException;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.SAXException;
+
+/**
+ * Test for {@link UiSafeHtmlInterpreter}.
+ */
+public class UiSafeHtmlInterpreterTest extends TestCase {
+
+ private static final String PARSED_TYPE = "com.google.gwt.user.client.ui.HTMLPanel";
+
+  private ElementParserTester tester;
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp();
+    tester = new ElementParserTester(PARSED_TYPE, new HTMLPanelParser());
+  }
+
+  public void testNoFromAttribute() throws SAXException {
+    StringBuffer b = new StringBuffer();
+    b.append("<g:HTMLPanel><ui:safehtml/>");
+    b.append("</g:HTMLPanel>");
+
+    try {
+      tester.parse(b.toString());
+      fail();
+    } catch (UnableToCompleteException e) {
+      assertTrue("Expect no 'from' attribute error",
+          tester.logger.died.contains("Attribute 'from' not found."));
+    }
+  }
+
+  public void testNoComputedValue() throws SAXException {
+    StringBuffer b = new StringBuffer();
+    b.append("<g:HTMLPanel><ui:safehtml from='nope'/>");
+    b.append("</g:HTMLPanel>");
+
+    try {
+      tester.parse(b.toString());
+      fail();
+    } catch (UnableToCompleteException e) {
+      assertTrue("Expect no computed value error",
+ tester.logger.died.contains("Attribute 'from' does not have a computed value"));
+    }
+  }
+
+  public void testTooManyAttributes() throws SAXException {
+    StringBuffer b = new StringBuffer();
+    b.append("<g:HTMLPanel><ui:safehtml from='{foo}' foo='' bar='' />");
+    b.append("</g:HTMLPanel>");
+
+    try {
+      tester.parse(b.toString());
+      fail();
+    } catch (UnableToCompleteException e) {
+      assertTrue("Expect too many attributes attribute error",
+          tester.logger.died.contains("Unexpected attributes"));
+    }
+  }
+
+  public void testHappy() throws Exception {
+ String s = "<g:HTMLPanel>\n <ui:safehtml from='{foo}'/>\n </g:HTMLPanel>\n";
+
+    String interpretedValue = new UiSafeHtmlInterpreter(tester.writer)
+      .interpretElement(tester.getElem(tester.wrapXML(s).toString(), 
"ui:safehtml"));
+
+    assertEquals(interpretedValue, "\" + \"--token--1--token--\" + \"");
+  }
+}
=======================================
--- /dev/null
+++ /trunk/user/test/com/google/gwt/uibinder/elementparsers/UiTextInterpreterTest.java Tue May 24 13:12:43 2011
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2010 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.elementparsers;
+
+import com.google.gwt.core.ext.UnableToCompleteException;
+
+import junit.framework.TestCase;
+
+import org.xml.sax.SAXException;
+
+/**
+ * Test for {@link UiTextInterpreter}.
+ */
+public class UiTextInterpreterTest extends TestCase {
+
+ private static final String PARSED_TYPE = "com.google.gwt.user.client.ui.HTMLPanel";
+
+  private ElementParserTester tester;
+
+  @Override
+  public void setUp() throws Exception {
+    super.setUp();
+    tester = new ElementParserTester(PARSED_TYPE, new HTMLPanelParser());
+  }
+
+  public void testNoFromAttribute() throws SAXException {
+    StringBuffer b = new StringBuffer();
+    b.append("<g:HTMLPanel><ui:text/>");
+    b.append("</g:HTMLPanel>");
+
+    try {
+      tester.parse(b.toString());
+      fail();
+    } catch (UnableToCompleteException e) {
+      assertTrue("Expect no 'from' attribute error",
+          tester.logger.died.contains("Attribute 'from' not found."));
+    }
+  }
+
+  public void testNoComputedValue() throws SAXException {
+    StringBuffer b = new StringBuffer();
+    b.append("<g:HTMLPanel><ui:text from='nope'/>");
+    b.append("</g:HTMLPanel>");
+
+    try {
+      tester.parse(b.toString());
+      fail();
+    } catch (UnableToCompleteException e) {
+      assertTrue("Expect no computed value error",
+ tester.logger.died.contains("Attribute 'from' does not have a computed value"));
+    }
+  }
+
+  public void testTooManyAttributes() throws SAXException {
+    StringBuffer b = new StringBuffer();
+    b.append("<g:HTMLPanel><ui:text from='{foo}' foo='' bar='' />");
+    b.append("</g:HTMLPanel>");
+
+    try {
+      tester.parse(b.toString());
+      fail();
+    } catch (UnableToCompleteException e) {
+      assertTrue("Expect too many attributes attribute error",
+          tester.logger.died.contains("Unexpected attributes"));
+    }
+  }
+
+  public void testHappy() throws Exception {
+ String s = "<g:HTMLPanel>\n <ui:text from='{foo}'/>\n </g:HTMLPanel>\n";
+
+    String interpretedValue = new UiTextInterpreter(tester.writer)
+      .interpretElement(tester.getElem(tester.wrapXML(s).toString(), 
"ui:text"));
+
+    assertEquals(interpretedValue, "\" + \"--token--1--token--\" + \"");
+  }
+}
=======================================
--- /trunk/user/src/com/google/gwt/uibinder/elementparsers/ComputedAttributeInterpreter.java Wed Mar 9 09:01:28 2011 +++ /trunk/user/src/com/google/gwt/uibinder/elementparsers/ComputedAttributeInterpreter.java Tue May 24 13:12:43 2011
@@ -32,10 +32,29 @@
  */
class ComputedAttributeInterpreter implements XMLElement.Interpreter<String> {

+  interface Delegate {
+    String getAttributeToken(XMLAttribute attribute)
+      throws UnableToCompleteException;
+  }
+
+  class DefaultDelegate implements Delegate {
+    public String getAttributeToken(XMLAttribute attribute)
+    throws UnableToCompleteException {
+ return writer.tokenForStringExpression(attribute.consumeStringValue());
+    }
+  }
+
   private final UiBinderWriter writer;
+  private final Delegate delegate;

   public ComputedAttributeInterpreter(UiBinderWriter writer) {
     this.writer = writer;
+    this.delegate = new DefaultDelegate();
+  }
+
+ public ComputedAttributeInterpreter(UiBinderWriter writer, Delegate delegate) {
+    this.delegate = delegate;
+    this.writer = writer;
   }

   @SuppressWarnings("deprecation")
@@ -58,7 +77,7 @@
       }

       if (att.hasComputedValue()) {
- String attToken = writer.tokenForStringExpression(att.consumeStringValue());
+        String attToken = delegate.getAttributeToken(att);
         attNameToToken.put(att.getName(), attToken);
       } else {
         /*
=======================================
--- /trunk/user/src/com/google/gwt/uibinder/elementparsers/HtmlInterpreter.java Wed May 4 09:28:35 2011 +++ /trunk/user/src/com/google/gwt/uibinder/elementparsers/HtmlInterpreter.java Tue May 24 10:01:44 2011
@@ -74,9 +74,13 @@
     this.pipe = new InterpreterPipe<String>();

     pipe.add(new FieldInterpreter(writer, ancestorExpression));
+    /* UiTextInterpreter and UiSafeHtmlInterpreter must be invoked before
+     * ComputedAttributeInterpreter to function properly
+     */
+    pipe.add(new UiTextInterpreter(writer));
+    pipe.add(new UiSafeHtmlInterpreter(writer));
     pipe.add(new ComputedAttributeInterpreter(writer));
     pipe.add(new AttributeMessageInterpreter(writer));
-    pipe.add(new UiTextInterpreter(writer.getLogger()));
     pipe.add(messageInterpreter);
   }

=======================================
--- /trunk/user/src/com/google/gwt/uibinder/elementparsers/TextInterpreter.java Wed Mar 9 09:01:28 2011 +++ /trunk/user/src/com/google/gwt/uibinder/elementparsers/TextInterpreter.java Tue May 24 10:01:44 2011
@@ -46,7 +46,7 @@
       return writer.tokenForStringExpression(messageInvocation);
     }

- return new UiTextInterpreter(writer.getLogger()).interpretElement(elem);
+    return new UiTextInterpreter(writer).interpretElement(elem);
   }

private String consumeAsTextMessage(XMLElement elem, MessagesWriter messages)
=======================================
--- /trunk/user/src/com/google/gwt/uibinder/elementparsers/UiTextInterpreter.java Mon Jun 7 12:20:31 2010 +++ /trunk/user/src/com/google/gwt/uibinder/elementparsers/UiTextInterpreter.java Tue May 24 10:01:44 2011
@@ -17,35 +17,62 @@

 import com.google.gwt.core.ext.UnableToCompleteException;
 import com.google.gwt.uibinder.rebind.MortalLogger;
+import com.google.gwt.uibinder.rebind.UiBinderWriter;
+import com.google.gwt.uibinder.rebind.XMLAttribute;
 import com.google.gwt.uibinder.rebind.XMLElement;

 /**
  * Interprets generic message tags like:
- * <b>&lt;ui:text from="{myMsg.message}" /&gt;</b>. It's called in both hasText
- * and hasHTML context.
+ * <b>&lt;ui:text from="{myMsg.message}" /&gt;</b>. It's called in both text
+ * and HTML contexts.
  */
 public class UiTextInterpreter implements XMLElement.Interpreter<String> {
-
- private static final String BINDER_URI = "urn:ui:com.google.gwt.uibinder";
-  private static final String LOCAL_NAME = "text";
-
+  /**
+ * Used in {@link #interpretElement} to invoke the {@link ComputedAttributeInterpreter}.
+   */
+ protected class Delegate implements ComputedAttributeInterpreter.Delegate {
+    public String getAttributeToken(XMLAttribute attribute)
+      throws UnableToCompleteException {
+ return writer.tokenForStringExpression(attribute.consumeStringValue());
+    }
+  }
+
+  protected final UiBinderWriter writer;
+ protected final ComputedAttributeInterpreter computedAttributeInterpreter;
   private final MortalLogger logger;

-  public UiTextInterpreter(MortalLogger logger) {
-    this.logger = logger;
-  }
-
+  public UiTextInterpreter(UiBinderWriter writer) {
+    this.writer = writer;
+    this.logger = writer.getLogger();
+ this.computedAttributeInterpreter = createComputedAttributeInterpreter();
+  }
+
   public String interpretElement(XMLElement elem)
       throws UnableToCompleteException {
    // Must be in the format: <ui:string from="{myMsg.message}" />
-   if (BINDER_URI.equals(elem.getNamespaceUri())
-        && LOCAL_NAME.equals(elem.getLocalName())) {
-      String fieldRef = elem.consumeStringAttribute("from");
-      if (fieldRef == null) {
-        logger.die(elem, "Attribute 'from' not found.");
-      }
-      return "\" + " + fieldRef + " + \"";
-    }
-    return null;
+ if (writer.isBinderElement(elem) && getLocalName().equals(elem.getLocalName())) {
+     if (!elem.hasAttribute("from")) {
+       logger.die(elem, "Attribute 'from' not found.");
+     }
+     if (!elem.getAttribute("from").hasComputedValue()) {
+       logger.die(elem, "Attribute 'from' does not have a computed value");
+     }
+     // Make sure all computed attributes are interpreted first
+     computedAttributeInterpreter.interpretElement(elem);
+
+     String fieldRef = elem.consumeStringAttribute("from");
+     // Make sure that "from" was the only attribute
+     elem.assertNoAttributes();
+     return "\" + " + fieldRef + " + \"";
+   }
+   return null;
+  }
+
+ protected ComputedAttributeInterpreter createComputedAttributeInterpreter() {
+    return new ComputedAttributeInterpreter(writer);
+  }
+
+  protected String getLocalName() {
+    return "text";
   }
 }
=======================================
--- /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderGenerator.java Fri May 20 05:12:05 2011 +++ /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderGenerator.java Tue May 24 10:01:44 2011
@@ -43,7 +43,7 @@
  */
 public class UiBinderGenerator extends Generator {

-  static final String BINDER_URI = "urn:ui:com.google.gwt.uibinder";
+ private static final String BINDER_URI = "urn:ui:com.google.gwt.uibinder";

   private static final String TEMPLATE_SUFFIX = ".ui.xml";

@@ -166,7 +166,7 @@

UiBinderWriter uiBinderWriter = new UiBinderWriter(interfaceType, implName, templatePath, oracle, logger, fieldManager, messages, designTime, uiBinderCtx, - useSafeHtmlTemplates(logger, propertyOracle), useLazyWidgetBuilders); + useSafeHtmlTemplates(logger, propertyOracle), useLazyWidgetBuilders, BINDER_URI);

Document doc = getW3cDoc(logger, designTime, resourceOracle, templatePath);
     designTime.rememberPathForElements(doc);
=======================================
--- /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java Mon May 2 12:52:38 2011 +++ /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderParser.java Tue May 24 10:01:44 2011
@@ -103,10 +103,11 @@
   private final JClassType imageResourceType;

   private final JClassType dataResourceType;
+  private final String binderUri;

public UiBinderParser(UiBinderWriter writer, MessagesWriter messagesWriter,
       FieldManager fieldManager, TypeOracle oracle,
-      ImplicitClientBundle bundleClass) {
+      ImplicitClientBundle bundleClass, String binderUri) {
     this.writer = writer;
     this.oracle = oracle;
     this.messagesWriter = messagesWriter;
@@ -115,6 +116,7 @@
this.cssResourceType = oracle.findType(CssResource.class.getCanonicalName()); this.imageResourceType = oracle.findType(ImageResource.class.getCanonicalName()); this.dataResourceType = oracle.findType(DataResource.class.getCanonicalName());
+    this.binderUri = binderUri;
   }

   /**
@@ -126,7 +128,7 @@
writer.die(elem, "Bad prefix on <%s:%s>? The root element must be in "
           + "xml namespace \"%s\" (usually with prefix \"ui:\"), "
           + "but this has prefix \"%s\"", elem.getPrefix(),
- elem.getLocalName(), UiBinderGenerator.BINDER_URI, elem.getPrefix());
+          elem.getLocalName(), binderUri, elem.getPrefix());
     }

     if (!TAG.equals(elem.getLocalName())) {
=======================================
--- /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java Tue May 24 07:34:42 2011 +++ /trunk/user/src/com/google/gwt/uibinder/rebind/UiBinderWriter.java Tue May 24 10:01:44 2011
@@ -241,11 +241,14 @@

   private final UiBinderContext uiBinderCtx;

+  private final String binderUri;
+
   public UiBinderWriter(JClassType baseClass, String implClassName,
       String templatePath, TypeOracle oracle, MortalLogger logger,
       FieldManager fieldManager, MessagesWriter messagesWriter,
       DesignTimeUtils designTime, UiBinderContext uiBinderCtx,
-      boolean useSafeHtmlTemplates, boolean useLazyWidgetBuilders)
+      boolean useSafeHtmlTemplates, boolean useLazyWidgetBuilders,
+      String binderUri)
       throws UnableToCompleteException {
     this.baseClass = baseClass;
     this.implClassName = implClassName;
@@ -258,6 +261,7 @@
     this.uiBinderCtx = uiBinderCtx;
     this.useSafeHtmlTemplates = useSafeHtmlTemplates;
     this.useLazyWidgetBuilders = useLazyWidgetBuilders;
+    this.binderUri = binderUri;

     // Check for possible misuse 'GWT.create(UiBinder.class)'
JClassType uibinderItself = oracle.findType(UiBinder.class.getCanonicalName());
@@ -693,7 +697,7 @@

   public boolean isBinderElement(XMLElement elem) {
     String uri = elem.getNamespaceUri();
-    return uri != null && UiBinderGenerator.BINDER_URI.equals(uri);
+    return uri != null && binderUri.equals(uri);
   }

public boolean isElementAssignableTo(XMLElement elem, Class<?> possibleSuperclass)
@@ -942,7 +946,7 @@
     }

     Element documentElement = doc.getDocumentElement();
-    gwtPrefix = documentElement.lookupPrefix(UiBinderGenerator.BINDER_URI);
+    gwtPrefix = documentElement.lookupPrefix(binderUri);

     XMLElement elem = new XMLElementProviderImpl(attributeParsers,
         bundleParsers, oracle, logger, designTime).get(documentElement);
@@ -1169,7 +1173,7 @@
     // Allow GWT.create() to init the field, the default behavior

String rootField = new UiBinderParser(this, messages, fieldManager, oracle,
-        bundleClass).parse(elem);
+        bundleClass, binderUri).parse(elem);

     fieldManager.validate();

=======================================
--- /trunk/user/src/com/google/gwt/uibinder/rebind/XMLAttribute.java Mon Jun 7 12:20:31 2010 +++ /trunk/user/src/com/google/gwt/uibinder/rebind/XMLAttribute.java Tue May 24 10:01:44 2011
@@ -36,6 +36,10 @@
   public String consumeRawValue() {
     return xmlElem.consumeRawAttribute(w3cAttr.getName());
   }
+
+  public String consumeSafeHtmlValue() throws UnableToCompleteException {
+    return xmlElem.consumeSafeHtmlAttribute(w3cAttr.getName());
+  }

   public String consumeStringValue() throws UnableToCompleteException {
     return xmlElem.consumeStringAttribute(w3cAttr.getName());
=======================================
--- /trunk/user/src/com/google/gwt/uibinder/rebind/XMLElement.java Fri Mar 11 06:21:13 2011 +++ /trunk/user/src/com/google/gwt/uibinder/rebind/XMLElement.java Tue May 24 10:01:44 2011
@@ -22,6 +22,7 @@
 import com.google.gwt.core.ext.typeinfo.TypeOracleException;
 import com.google.gwt.dom.client.Style.Unit;
 import com.google.gwt.resources.client.ImageResource;
+import com.google.gwt.safehtml.shared.SafeHtml;
 import com.google.gwt.uibinder.attributeparsers.AttributeParser;
 import com.google.gwt.uibinder.attributeparsers.AttributeParsers;

@@ -145,7 +146,8 @@
   private JType doubleType;
   private JType intType;
   private JType stringType;
-
+  private JType safeHtmlType;
+
   {
     // from com/google/gxp/compiler/schema/html.xml
     NO_END_TAG.add("area");
@@ -647,7 +649,20 @@
     }
     return value;
   }
-
+
+  /**
+  * Convenience method for parsing the named attribute as a
+ * {@link com.google.gwt.safehtml.shared.SafeHtml SafeHtml} value or reference.
+  *
+  * @return an expression that will evaluate to a
+  * {@link com.google.gwt.safehtml.shared.SafeHtml SafeHtml} value in
+  * the generated code, or null if there is no such attribute
+  * @throws UnableToCompleteException on unparseable value
+  */
+  public String consumeSafeHtmlAttribute(String name)
+      throws UnableToCompleteException {
+    return consumeAttribute(name, getSafeHtmlType());
+  }
   /**
* Consumes a single child element, ignoring any text nodes and throwing an * exception if no child is found, or more than one child element is found.
@@ -933,6 +948,13 @@
     return rtn;
   }

+  private JType getSafeHtmlType() {
+    if (safeHtmlType == null) {
+      safeHtmlType = oracle.findType(SafeHtml.class.getName());
+    }
+    return safeHtmlType;
+  }
+
   private JType getStringType() {
     if (stringType == null) {
       stringType = oracle.findType(String.class.getCanonicalName());
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/elementparsers/ElementParserTester.java Fri May 20 05:12:05 2011 +++ /trunk/user/test/com/google/gwt/uibinder/elementparsers/ElementParserTester.java Tue May 24 10:01:44 2011
@@ -114,7 +114,7 @@
         templatePath, baseType.getPackage().getName(), implName);

writer = new MockUiBinderWriter(baseType, implName, templatePath, types,
-        logger, fieldManager, messages);
+        logger, fieldManager, messages, BINDER_URI);
     fieldManager.registerField(types.findType(parsedTypeName), FIELD_NAME);
     parsedType = types.findType(parsedTypeName);
   }
@@ -133,11 +133,7 @@
   public FieldWriter parse(String xml) throws UnableToCompleteException,
       SAXParseException {

-    StringBuffer b = new StringBuffer();
-    b.append("<ui:UiBinder xmlns:ui='" + BINDER_URI + "'");
-    b.append("    xmlns:g='urn:import:com.google.gwt.user.client.ui'>");
-    b.append(xml);
-    b.append("</ui:UiBinder>");
+    StringBuffer b = wrapXML(xml);

     // CHECKSTYLE_OFF
     String tag = "g:" + parsedType.getName();
@@ -151,4 +147,13 @@
     rtn.add(BINDER_OWNER_JAVA);
     return rtn;
   }
-}
+
+  public StringBuffer wrapXML(String xml) {
+    StringBuffer b = new StringBuffer();
+    b.append("<ui:UiBinder xmlns:ui='" + BINDER_URI + "'");
+    b.append("    xmlns:g='urn:import:com.google.gwt.user.client.ui'>");
+    b.append(xml);
+    b.append("</ui:UiBinder>");
+    return b;
+  }
+}
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/elementparsers/MockUiBinderWriter.java Tue May 24 07:34:42 2011 +++ /trunk/user/test/com/google/gwt/uibinder/elementparsers/MockUiBinderWriter.java Tue May 24 10:01:44 2011
@@ -34,9 +34,9 @@

public MockUiBinderWriter(JClassType baseClass, String implClassName, String templatePath,
       TypeOracle oracle, MortalLogger logger, FieldManager fieldManager,
-      MessagesWriter messagesWriter) throws UnableToCompleteException {
+ MessagesWriter messagesWriter, String binderUri) throws UnableToCompleteException { super(baseClass, implClassName, templatePath, oracle, logger, fieldManager, messagesWriter,
-        DesignTimeUtilsStub.EMPTY, new UiBinderContext(), true, false);
+ DesignTimeUtilsStub.EMPTY, new UiBinderContext(), true, false, binderUri);
   }

   @Override
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/test/UiJavaResources.java Wed May 4 09:28:35 2011 +++ /trunk/user/test/com/google/gwt/uibinder/test/UiJavaResources.java Tue May 24 10:01:44 2011
@@ -293,6 +293,17 @@
       code.append("}\n");
       return code;
     }
+  };
+  public static final MockJavaResource HTML_PANEL = new MockJavaResource(
+  "com.google.gwt.user.client.ui.HTMLPanel") {
+    @Override
+    public CharSequence getContent() {
+      StringBuffer code = new StringBuffer();
+      code.append("package com.google.gwt.user.client.ui;\n");
+      code.append("public class HTMLPanel extends Widget {\n");
+      code.append("}\n");
+      return code;
+    }
   };
   public static final MockJavaResource IMAGE = new MockJavaResource(
       "com.google.gwt.user.client.ui.Image") {
@@ -469,6 +480,17 @@
       code.append("}\n");
       return code;
     }
+  };
+  public static final MockJavaResource SAFEHTML = new MockJavaResource(
+  "com.google.gwt.safehtml.shared.SafeHtml") {
+    @Override
+    public CharSequence getContent() {
+      StringBuffer code = new StringBuffer();
+      code.append("package com.google.gwt.safehtml.shared;\n");
+      code.append("public interface SafeHtml {\n");
+      code.append("}\n");
+      return code;
+    }
   };
public static final MockJavaResource SPLIT_LAYOUT_PANEL = new MockJavaResource(
       "com.google.gwt.user.client.ui.SplitLayoutPanel") {
@@ -685,6 +707,7 @@
     rtn.add(HAS_CLICK_HANDLERS);
     rtn.add(HAS_HORIZONTAL_ALIGNMENT);
     rtn.add(HAS_VERTICAL_ALIGNMENT);
+    rtn.add(HTML_PANEL);
     rtn.add(LABEL);
     rtn.add(LAYOUT_PANEL);
     rtn.add(LIST_BOX);
@@ -696,6 +719,7 @@
     rtn.add(NUMBER_LABEL);
     rtn.add(NUMBER_FORMAT);
     rtn.add(RENDERER);
+    rtn.add(SAFEHTML);
     rtn.add(SPLIT_LAYOUT_PANEL);
     rtn.add(STACK_LAYOUT_PANEL);
     rtn.add(STACK_PANEL);
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/test/client/Constants.java Tue May 24 07:34:42 2011 +++ /trunk/user/test/com/google/gwt/uibinder/test/client/Constants.java Tue May 24 10:01:44 2011
@@ -15,6 +15,9 @@
  */
 package com.google.gwt.uibinder.test.client;

+import com.google.gwt.safehtml.shared.SafeHtml;
+import com.google.gwt.safehtml.shared.SafeHtmlUtils;
+
 /**
  * Used to test static imports in UiBinder templates.
  */
@@ -39,4 +42,16 @@
   }

   public static String CONST_FOO = "Foo";
-}
+
+  public SafeHtml getSafeHtml() {
+ return SafeHtmlUtils.fromSafeConstant("<b>This text should be bold!</b>");
+  }
+
+  public String getText() {
+    return "<b>This text won't be bold!</b>";
+  }
+
+  public String getRendererText() {
+    return "<b>Here's the text!</b>";
+  }
+}
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java Tue May 24 07:34:42 2011 +++ /trunk/user/test/com/google/gwt/uibinder/test/client/UiBinderTest.java Tue May 24 10:01:44 2011
@@ -627,6 +627,15 @@
   public void testUrlResource() {
     assertEquals(new FakeBundle().aUrl(), widgetUi.myImage.getSrc());
   }
+
+  public void testUiTextWithSafeHtml() {
+    assertEquals(widgetUi.htmlWithComputedSafeHtml.getHTML().toLowerCase(),
+        "<b>this text should be bold!</b>");
+    assertEquals(widgetUi.htmlWithComputedText.getHTML().toLowerCase(),
+        "&lt;b&gt;this text won't be bold!&lt;/b&gt;");
+    assertEquals(widgetUi.labelWithComputedText.getText().toLowerCase(),
+        "<b>this text won't be bold!</b>");
+  }

   /**
* Assert that the expect strings are found in body, and in the order given.
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java Wed Apr 20 12:03:38 2011 +++ /trunk/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.java Tue May 24 10:01:44 2011
@@ -198,6 +198,9 @@
   Renderer doubleRenderer = DoubleRenderer.instance();
   @UiField ValueLabel<Double> myValueLabel;
   @UiField ImageElement myImage;
+  @UiField HTML htmlWithComputedSafeHtml;
+  @UiField HTML htmlWithComputedText;
+  @UiField Label labelWithComputedText;

   public WidgetBasedUi() {
     external.style().ensureInjected();
=======================================
--- /trunk/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml Fri May 20 05:12:05 2011 +++ /trunk/user/test/com/google/gwt/uibinder/test/client/WidgetBasedUi.ui.xml Tue May 24 10:01:44 2011
@@ -79,6 +79,10 @@
   Used to test ValueLabel's @UiConstructor
 </ui:with>

+<ui:with field="constants" type="com.google.gwt.uibinder.test.client.Constants">
+  Used to test SafeHtml return type in ui:text context.
+</ui:with>
+
 <ui:import field='com.google.gwt.uibinder.test.client.Constants.CONST_FOO'>
   Tests the static import of a single constant into the local namespace.
 </ui:import>
@@ -678,6 +682,10 @@
<gwt3:google.gwt.user.client.ui.ValueLabel ui:field='myValueLabel' renderer='{doubleRenderer}' />

   <img src="{values.aUrl}" ui:field='myImage'/>
+
+ <gwt:HTML ui:field='htmlWithComputedSafeHtml'><ui:safehtml from="{constants.getSafeHtml}" /></gwt:HTML> + <gwt:HTML ui:field='htmlWithComputedText'><ui:text from="{constants.getText}" /></gwt:HTML> + <gwt:Label ui:field='labelWithComputedText'><ui:text from="{constants.getText}"/></gwt:Label>

    </gwt:HTMLPanel>
   </gwt:Dock>

--
http://groups.google.com/group/Google-Web-Toolkit-Contributors

Reply via email to