Package com.google.gwt.uibinder.elementparsers

Source Code of com.google.gwt.uibinder.elementparsers.WidgetPlaceholderInterpreter

/*
* Copyright 2008 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.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.uibinder.rebind.UiBinderWriter;
import com.google.gwt.uibinder.rebind.XMLElement;
import com.google.gwt.uibinder.rebind.messages.MessageWriter;
import com.google.gwt.uibinder.rebind.messages.MessagesWriter;
import com.google.gwt.user.client.ui.HasHTML;
import com.google.gwt.user.client.ui.HasText;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
* Used by {@link HTMLPanelParser}. Refines {@link HtmlPlaceholderInterpreter}
* to allow widgets to appear inside msg elements in an HTMLPanel.
* <p>
* HasText and HasHTML get special treatment, where their innerText or innerHTML
* become part of the {@literal @}Default value of the message being generated.
* E.g., this markup in an HTMLPanel:
*
* <pre>
* <m:msg>Hello &lt;gwt:HyperLink&gt;click here&lt;/gwt:HyperLink&gt; thank you.</m:msg></pre>
*
* becomes a message like this: <pre>
* {@literal @}Default("Hello {0}click here{1} thank you.")
* String getMessage1(
*   {@literal @}Example("&lt;span&gt;") String widget1Begin,
*   {@literal @}Example("&lt;/span&gt;") String widget1End
* );</pre>
*
* <p>
* The contents of other widget types are opaque to the message, and are covered
* by a single placeholder. One implication of this is that the content of an
* HTMLPanel inside a msg in another HTMLPanel must always be in a separate
* message.
*/
class WidgetPlaceholderInterpreter extends HtmlPlaceholderInterpreter {
  /*
   * Could break this up into three further classes, for HasText, HasHTML and
   * Other, but that seems more trouble than it's worth.
   */

  private int serial = 0;
  private final String ancestorExpression;
  private final String fieldName;
  private final Map<String, XMLElement> idToWidgetElement =
    new HashMap<String, XMLElement>();
  private final Set<String> idIsHasHTML = new HashSet<String>();
  private final Set<String> idIsHasText = new HashSet<String>();

  WidgetPlaceholderInterpreter(String fieldName, UiBinderWriter writer,
      MessageWriter message, String ancestorExpression) {
    super(writer, message, ancestorExpression);
    this.fieldName = fieldName;
    this.ancestorExpression = ancestorExpression;
}

  @Override
  public String interpretElement(XMLElement elem)
      throws UnableToCompleteException {

    if (!uiWriter.isWidgetElement(elem)) {
      return super.interpretElement(elem);
    }

    JClassType type = uiWriter.findFieldType(elem);
    TypeOracle oracle = uiWriter.getOracle();

    MessagesWriter mw = uiWriter.getMessages();
    String name = mw.consumeMessageAttribute("ph", elem);
    if ("".equals(name)) {
      name = "widget" + (++serial);
    }

    String idHolder = uiWriter.declareDomIdHolder();
    idToWidgetElement.put(idHolder, elem);

    if (oracle.findType(HasHTML.class.getName()).isAssignableFrom(type)) {
      return handleHasHTMLPlaceholder(elem, name, idHolder);
    }

    if (oracle.findType(HasText.class.getName()).isAssignableFrom(type)) {
      return handleHasTextPlaceholder(elem, name, idHolder);
   }

    return handleOpaqueWidgetPlaceholder(name, idHolder);
  }

  /**
   * Called by {@link XMLElement#consumeInnerHtml} after all elements
   * have been handed to {@link #interpretElement}.
   */
  @Override
  public String postProcess(String consumed) throws UnableToCompleteException {
    for (String idHolder : idToWidgetElement.keySet()) {
      XMLElement childElem = idToWidgetElement.get(idHolder);
      String childField = uiWriter.parseElementToField(childElem);

      genSetWidgetTextCall(idHolder, childField);
      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);
  }

  private String genCloseTag(String name) {
    String closePlaceholder = nextClosePlaceholder(name + "End", "</span>");
    return closePlaceholder;
  }

  private String genOpenTag(String name, String idHolder) {
    if (uiWriter.useSafeHtmlTemplates()) {
      idHolder = uiWriter.tokenForStringExpression(idHolder);
    } else {
      idHolder = "\" + " + idHolder + " + \"";
    }
    String openTag = String.format("<span id='%s'>", idHolder);
    String openPlaceholder = nextOpenPlaceholder(name + "Begin", openTag);
    return openPlaceholder;
  }

  private void genSetWidgetTextCall(String idHolder, String childField) {
    if (idIsHasText.contains(idHolder)) {
      uiWriter.addInitStatement(
          "%s.setText(%s.getElementById(%s).getInnerText());", childField,
          fieldName, idHolder);
    }
    if (idIsHasHTML.contains(idHolder)) {
      uiWriter.addInitStatement(
          "%s.setHTML(%s.getElementById(%s).getInnerHTML());", childField,
          fieldName, idHolder);
    }
  }

  private String handleHasHTMLPlaceholder(XMLElement elem, String name,
      String idHolder) throws UnableToCompleteException {
    idIsHasHTML.add(idHolder);
    String openPlaceholder = genOpenTag(name, idHolder);

    String body =
        elem.consumeInnerHtml(new HtmlPlaceholderInterpreter(uiWriter,
            message, ancestorExpression));
    String bodyToken = tokenator.nextToken(body);

    String closePlaceholder = genCloseTag(name);
    return openPlaceholder + bodyToken + closePlaceholder;
  }

  private String handleHasTextPlaceholder(XMLElement elem, String name,
      String idHolder) throws UnableToCompleteException {
    idIsHasText.add(idHolder);
    String openPlaceholder = genOpenTag(name, idHolder);

    String body =
        elem.consumeInnerText(new TextPlaceholderInterpreter(uiWriter,
            message));
    String bodyToken = tokenator.nextToken(body);

    String closePlaceholder = genCloseTag(name);
    return openPlaceholder + bodyToken + closePlaceholder;
  }

  private String handleOpaqueWidgetPlaceholder(String name, String idHolder) {
    if (uiWriter.useSafeHtmlTemplates()) {
      idHolder = uiWriter.tokenForStringExpression(idHolder);
    } else {
      idHolder = "\" + " + idHolder + " + \"";
    }
    String tag = String.format("<span id='%s'></span>", idHolder);
    String placeholder = nextPlaceholder(name, "<span></span>", tag);
    return placeholder;
  }
}
TOP

Related Classes of com.google.gwt.uibinder.elementparsers.WidgetPlaceholderInterpreter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.