Package org.waveprotocol.wave.client.wavepanel.view.dom.full

Source Code of org.waveprotocol.wave.client.wavepanel.view.dom.full.BlipMetaViewBuilder

/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you 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.wavepanel.view.dom.full;

import static org.waveprotocol.wave.client.uibuilder.BuilderHelper.nonNull;
import static org.waveprotocol.wave.client.uibuilder.OutputHelper.close;
import static org.waveprotocol.wave.client.uibuilder.OutputHelper.closeSpan;
import static org.waveprotocol.wave.client.uibuilder.OutputHelper.image;
import static org.waveprotocol.wave.client.uibuilder.OutputHelper.open;
import static org.waveprotocol.wave.client.uibuilder.OutputHelper.openSpanWith;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;

import org.waveprotocol.wave.client.common.safehtml.EscapeUtils;
import org.waveprotocol.wave.client.common.safehtml.SafeHtml;
import org.waveprotocol.wave.client.common.safehtml.SafeHtmlBuilder;
import org.waveprotocol.wave.client.uibuilder.BuilderHelper.Component;
import org.waveprotocol.wave.client.uibuilder.UiBuilder;
import org.waveprotocol.wave.client.wavepanel.view.IntrinsicBlipMetaView;
import org.waveprotocol.wave.client.wavepanel.view.View.Type;
import org.waveprotocol.wave.client.wavepanel.view.dom.full.i18n.BlipMessages;
import org.waveprotocol.wave.model.util.CollectionUtils;
import org.waveprotocol.wave.model.util.StringMap;

import java.util.Arrays;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
*/
public final class BlipMetaViewBuilder implements UiBuilder, IntrinsicBlipMetaView {


  /** An enum for all the components of a blip view. */
  public enum Components implements Component {
    /** The avatar element. */
    AVATAR("A"),
    /** The text inside the information bar. */
    METALINE("M"),
    /** The element for the information bar. */
    METABAR("B"),
    /** The element containing the time text. */
    TIME("T"),
    /** The element containing the document. */
    CONTENT("C"),
    /** The element containing menu options. */
    MENU("N"), ;

    private final String postfix;

    Components(String postfix) {
      this.postfix = postfix;
    }

    @Override
    public String getDomId(String baseId) {
      return baseId + postfix;
    }
  }

  // The consistent iterator ordering of EnumMap is relied upon, to ensure that
  // the same menu options are always rendered in the same order.
  private final static Map<MenuOption, SafeHtml> MENU_CODES =
      new EnumMap<MenuOption, SafeHtml>(MenuOption.class);

  private final static Map<MenuOption, SafeHtml> MENU_LABELS =
      new EnumMap<MenuOption, SafeHtml>(MenuOption.class);

  private final static StringMap<MenuOption> MENU_OPTIONS = CollectionUtils.createStringMap();

  public static final String OPTION_ID_ATTRIBUTE = "o";
  public static final String OPTION_SELECTED_ATTRIBUTE = "s";
  private static final EnumSet<MenuOption> MENU_OPTIONS_BEFORE_EDITING = EnumSet.of(
      IntrinsicBlipMetaView.MenuOption.REPLY, IntrinsicBlipMetaView.MenuOption.DELETE,
      IntrinsicBlipMetaView.MenuOption.EDIT,
      IntrinsicBlipMetaView.MenuOption.LINK);
  public final static Set<MenuOption> ENABLED_WHILE_EDITING_MENU_OPTIONS_SET = EnumSet.of(
      IntrinsicBlipMetaView.MenuOption.EDIT_DONE);
  public final static Set<MenuOption> DISABLED_WHILE_EDITING_MENU_OPTIONS_SET = MENU_OPTIONS_BEFORE_EDITING;

  /**
   * A unique id for this builder.
   */
  private final String id;
  private final BlipViewBuilder.Css css;

  //
  // Intrinsic state.
  //

  private String time;
  private String metaline;
  private String avatarUrl;
  private boolean read = true;
  private final Set<MenuOption> options = MENU_OPTIONS_BEFORE_EDITING;
  private final Set<MenuOption> selected = EnumSet.noneOf(MenuOption.class);

  //
  // Structural components.
  //

  private final UiBuilder content;

  /**
   * Creates a new blip view builder with the given id.
   *
   * @param id unique id for this builder, it must only contains alphanumeric
   *        characters
   */
  public static BlipMetaViewBuilder create(String id, UiBuilder content) {
    return new BlipMetaViewBuilder(WavePanelResourceLoader.getBlip().css(),
        WavePanelResourceLoader.getBlipMessages(), id, nonNull(content));
  }

  @VisibleForTesting
  BlipMetaViewBuilder(BlipViewBuilder.Css css, BlipMessages messages, String id, UiBuilder content) {
    // must not contain ', it is especially troublesome because it cause
    // security issues.
    Preconditions.checkArgument(!id.contains("\'"));
    this.css = css;
    this.id = id;
    this.content = content;
    buildMenuModel(messages);
  }

  @Override
  public void setAvatar(String avatarUrl) {
    this.avatarUrl = avatarUrl;
  }

  @Override
  public void setTime(String time) {
    this.time = time;
  }

  @Override
  public void setMetaline(String metaline) {
    this.metaline = metaline;
  }

  @Override
  public void setRead(boolean read) {
    this.read = read;
  }

  @Override
  public void enable(Set<MenuOption> options) {
    this.options.addAll(options);
  }

  @Override
  public void disable(Set<MenuOption> options) {
    this.options.removeAll(options);
    this.selected.removeAll(options);
  }

  @Override
  public void select(MenuOption option) {
    this.selected.add(option);
  }

  @Override
  public void deselect(MenuOption option) {
    this.selected.remove(option);
  }

  //
  // DomImpl nature.
  //

  @Override
  public void outputHtml(SafeHtmlBuilder output) {
    // HACK HACK HACK
    // This code should be automatically generated from UiBinder template, not
    // hand written.

    open(output, id, css.meta(), TypeCodes.kind(Type.META));
    {
      // Author avatar.
      image(output, Components.AVATAR.getDomId(id), css.avatar(), EscapeUtils.fromString(avatarUrl),
          EscapeUtils.fromPlainText("author"), null);

      // Metabar.
      open(output, Components.METABAR.getDomId(id),
          css.metabar() + " " + (read ? css.read() : css.unread()), null);
      {
        open(output, Components.MENU.getDomId(id), css.menu(), null);
        menuBuilder(options, selected, css).outputHtml(output);
        close(output);

        // Time.
        open(output, Components.TIME.getDomId(id), css.time(), null);
        if (time != null) {
          output.appendEscaped(time);
        }
        close(output);

        // Metaline.
        open(output, Components.METALINE.getDomId(id), css.metaline(), null);
        if (metaline != null) {
          output.appendEscaped(metaline);
        }
        close(output);
      }
      close(output);

      // Content.
      open(output, Components.CONTENT.getDomId(id), css.contentContainer(), "document");
      content.outputHtml(output);
      close(output);
    }
    close(output);
  }

  /**
   * Creates a builder for a blip menu.
   */
  public static UiBuilder menuBuilder(final Set<MenuOption> options, final Set<MenuOption> selected,
      final BlipViewBuilder.Css css) {
    return new UiBuilder() {
      @Override
      public void outputHtml(SafeHtmlBuilder out) {
        for (MenuOption option : options) {
          out.append(EscapeUtils.fromSafeConstant("|"));
          String style = selected.contains(option) //
              ? css.menuOption() + css.menuOptionSelected() : css.menuOption();
          String extra = OPTION_ID_ATTRIBUTE + "='" + MENU_CODES.get(option).asString() + "'"
              + (selected.contains(option) ? " " + OPTION_SELECTED_ATTRIBUTE + "='s'" : "");
          openSpanWith(out, null, style, TypeCodes.kind(Type.MENU_ITEM), extra);
          out.append(MENU_LABELS.get(option));
          closeSpan(out);
        }
      }
    };
  }

  public static MenuOption getMenuOption(String id) {
    MenuOption option = MENU_OPTIONS.get(id);
    if (option == null) {
      throw new IllegalArgumentException("No such option: " + id);
    }
    return option;
  }

  public static SafeHtml getMenuOptionId(MenuOption option) {
    SafeHtml code = MENU_CODES.get(option);
    if (code == null) {
      throw new IllegalArgumentException("No such option: " + option);
    }
    return code;
  }

  private static void buildMenuModel(BlipMessages messages) {
    MENU_CODES.put(MenuOption.EDIT, EscapeUtils.fromSafeConstant("e"));
    MENU_CODES.put(MenuOption.EDIT_DONE, EscapeUtils.fromSafeConstant("x"));
    MENU_CODES.put(MenuOption.REPLY, EscapeUtils.fromSafeConstant("r"));
    MENU_CODES.put(MenuOption.DELETE, EscapeUtils.fromSafeConstant("d"));
    MENU_CODES.put(MenuOption.LINK, EscapeUtils.fromSafeConstant("l"));
    MENU_LABELS.put(MenuOption.EDIT, EscapeUtils.fromSafeConstant(messages.edit()));
    MENU_LABELS.put(MenuOption.EDIT_DONE, EscapeUtils.fromSafeConstant(messages.done()));
    MENU_LABELS.put(MenuOption.REPLY, EscapeUtils.fromSafeConstant(messages.reply()));
    MENU_LABELS.put(MenuOption.DELETE, EscapeUtils.fromSafeConstant(messages.delete()));
    MENU_LABELS.put(MenuOption.LINK, EscapeUtils.fromSafeConstant(messages.link()));
    for (MenuOption option : MENU_CODES.keySet()) {
      MENU_OPTIONS.put(MENU_CODES.get(option).asString(), option);
    }
    assert MENU_CODES.keySet().equals(MENU_LABELS.keySet());
    assert MENU_OPTIONS.countEntries() == MENU_CODES.size();
    assert new HashSet<MenuOption>(Arrays.asList(MenuOption.values())).equals(MENU_LABELS.keySet());
  }
}
TOP

Related Classes of org.waveprotocol.wave.client.wavepanel.view.dom.full.BlipMetaViewBuilder

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.