Package org.waveprotocol.wave.client.editor.content.paragraph

Source Code of org.waveprotocol.wave.client.editor.content.paragraph.DefaultParagraphHtmlRenderer

/**
* 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 org.waveprotocol.wave.client.editor.content.paragraph;

import static org.waveprotocol.wave.client.editor.content.paragraph.constants.ParagraphRenderingConstants.INDENT_UNIT_SIZE_PX;

import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.FontWeight;
import com.google.gwt.dom.client.Style.Unit;

import org.waveprotocol.wave.client.common.util.DomHelper;
import org.waveprotocol.wave.client.editor.content.ContentElement;
import org.waveprotocol.wave.client.editor.content.HasImplNodelets;
import org.waveprotocol.wave.client.editor.content.Renderer;
import org.waveprotocol.wave.client.editor.content.paragraph.Paragraph.Alignment;
import org.waveprotocol.wave.client.editor.content.paragraph.Paragraph.Direction;

/**
* @author danilatos@google.com (Daniel Danilatos)
*/
public class DefaultParagraphHtmlRenderer implements ParagraphHtmlRenderer {
  // TODO(danilatos): Use CssResource
  private static final String NUMBERED_CLASSNAME = "numbered";

  private static final String[] BULLET_CLASSNAMES = new String[] {
    "bullet-type-0",
    "bullet-type-1",
    "bullet-type-2"
  };

  private static String bulletClassName(int indent) {
    return BULLET_CLASSNAMES[indent % 3];
  }

  /**
   * Size of the largest heading
   */
  public static final double MAX_HEADING_SIZE_EM = 1.75;

  /**
   * Size of the smallest heading
   */
  public static final double MIN_HEADING_SIZE_EM = 1.0;

  /**
   * Tag name to use for html implementation for paragraph element mode.
   */
  public static final String PARAGRAPH_IMPL_TAGNAME = "div";

  /**
   * Tag name to use for html implementation for list element mode.
   */
  public static final String LIST_IMPL_TAGNAME = "li";

  private final String implTagName;

  public DefaultParagraphHtmlRenderer() {
    this(PARAGRAPH_IMPL_TAGNAME);
  }

  public DefaultParagraphHtmlRenderer(String implTagName) {
    this.implTagName = implTagName;
  }

  /**
   * Unless very specific behaviour is wanted, it is better to override
   * {@link #createNodelet(Renderable)} if a different nodelet from a simple
   * named element is desired.
   */
  @Override
  public Element createDomImpl(Renderable element) {
    Element nodelet = createNodelet(element);

    assert nodelet.getFirstChild() == null : "was not given an empty nodelet";
    ParagraphHelper.INSTANCE.onEmpty(nodelet);

    return element.setAutoAppendContainer(nodelet);
  }

  @Override
  public void updateRendering(HasImplNodelets element,
      String type, String listStyle,
      int indent, Alignment alignment, Direction direction) {

    Element implNodelet = element.getImplNodelet();
    ParagraphBehaviour behaviour = ParagraphBehaviour.of(type);
    boolean toListItem = behaviour == ParagraphBehaviour.LIST;
    boolean isListItem = implNodelet.getTagName().equalsIgnoreCase(LIST_IMPL_TAGNAME);

    if (isListItem != toListItem) {
      Element newNodelet = createNodeletInner(toListItem);
      DomHelper.replaceElement(implNodelet, newNodelet);
      element.setBothNodelets(newNodelet);
      // Ideally onRepair shouldn't require a ContentElement
      ParagraphHelper.INSTANCE.onRepair((ContentElement) element);

      implNodelet = newNodelet;
    }


    //// Type logic ////

    double fontSize = -1;
    FontWeight fontWeight = null;
    implNodelet.removeClassName(NUMBERED_CLASSNAME);

    switch (behaviour) {
      case LIST:
        if (Paragraph.LIST_STYLE_DECIMAL.equals(listStyle)) {
          implNodelet.addClassName(NUMBERED_CLASSNAME);
        }
        break;
      case HEADING:
        fontWeight = FontWeight.BOLD;
        double headingNum = Integer.parseInt(type.substring(1));
        // Do this with CSS instead.
        // h1 -> 1.75, h4 -> 1, others linearly in between.
        double factor = 1 - (headingNum - 1) / (Paragraph.NUM_HEADING_SIZES - 1);
        fontSize = MIN_HEADING_SIZE_EM + factor * (MAX_HEADING_SIZE_EM - MIN_HEADING_SIZE_EM);
        break;
    }


    //// Indent logic ////

    for (String bulletType : BULLET_CLASSNAMES) {
      implNodelet.removeClassName(bulletType);
    }

    if (behaviour == ParagraphBehaviour.LIST) {
      if (listStyle == null) {
        implNodelet.addClassName(bulletClassName(indent));
      }
      indent++;
    }

    int margin = indent * INDENT_UNIT_SIZE_PX;

    //// Update actual values ////

    // NOTE(danilatos): For these, it might be more efficient to check that the
    // value has changed before changing it. This is not currently  known.

    Style style = implNodelet.getStyle();

    if (fontSize != -1) {
      style.setFontSize(fontSize, Unit.EM);
    } else {
      style.clearFontSize();
    }

    if (fontWeight != null) {
      style.setFontWeight(fontWeight);
    } else {
      style.clearFontWeight();
    }

    if (alignment != null) {
      style.setProperty("textAlign", alignment.cssValue());
    } else {
      style.clearProperty("textAlign");
    }

    if (direction != null) {
      style.setProperty("direction", direction.cssValue());
    } else {
      style.clearProperty("direction");
    }

    if (margin == 0) {
      style.clearMarginLeft();
      style.clearMarginRight();
    } else {
      if (direction == Direction.RTL) {
        style.setMarginRight(margin, Unit.PX);
        style.clearMarginLeft();
      } else {
        style.setMarginLeft(margin, Unit.PX);
        style.clearMarginRight();
      }
    }
  }

  @Override
  public void updateListValue(HasImplNodelets element, int value) {
    element.getImplNodelet().setAttribute("value", String.valueOf(value));
  }

  /**
   * Override this method to use something other than a simple named element.
   * (The tag name is parametrisable via the constructor).
   *
   * @param element See {@link Renderer#createDomImpl(Renderable)}
   * @return the nodelet to use for rendering, must not contain any children
   */
  protected Element createNodelet(Renderable element) {
    return createNodeletInner(false);
  }

  private Element createNodeletInner(boolean isListItem) {
    return Document.get().createElement(isListItem ? LIST_IMPL_TAGNAME : implTagName);
  }
}
TOP

Related Classes of org.waveprotocol.wave.client.editor.content.paragraph.DefaultParagraphHtmlRenderer

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.