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

Source Code of org.waveprotocol.wave.client.wavepanel.view.dom.BlipMetaDomImpl

/**
* 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;


import static org.waveprotocol.wave.client.uibuilder.BuilderHelper.KIND_ATTRIBUTE;
import static org.waveprotocol.wave.client.wavepanel.view.dom.DomViewHelper.load;

import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.ImageElement;

import org.waveprotocol.wave.client.common.safehtml.SafeHtmlBuilder;
import org.waveprotocol.wave.client.common.util.StringSequence;
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.BlipMetaViewBuilder;
import org.waveprotocol.wave.client.wavepanel.view.dom.full.BlipMetaViewBuilder.Components;
import org.waveprotocol.wave.client.wavepanel.view.dom.full.BlipViewBuilder;
import org.waveprotocol.wave.client.wavepanel.view.dom.full.CollapsibleBuilder;
import org.waveprotocol.wave.client.wavepanel.view.dom.full.TypeCodes;
import org.waveprotocol.wave.client.wavepanel.view.dom.full.WavePanelResourceLoader;
import org.waveprotocol.wave.model.util.Pair;

import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Set;

/**
* BlipViewDomImpl of the blip view.
*
*/
public final class BlipMetaDomImpl implements DomView, IntrinsicBlipMetaView {

  /**
   * The INLINE_LOCATOR_ATTRIBUTE is the dom element attribute that contains the
   * serialized string of the inline locator.
   * The INLINE_LOCATOR_PROPERTY is a the dom element property that contains the deserialized
   * inline locator object.
   * The two must be different since in IE, property and attribute are not namespaced separately.
   */
  private static final String INLINE_LOCATOR_PROPERTY = "inlineSequence";
  public static final String INLINE_LOCATOR_ATTRIBUTE = "inline";

  /** The DOM element of this view. */
  private final Element self;

  /** The HTML id of {@code self}. */
  private final String id;
 
  /** The CSS classes used to manipulate style based on state changes. */
  private final BlipViewBuilder.Css css;

  //
  // UI fields for both intrinsic and structural elements.
  // Element references are loaded lazily and cached.
  //

  private Element time;
  private Element contentContainer;
  private ImageElement avatar;
  private Element metaline;
  private Element metabar;
  private Element menu;

  private StringSequence inlineLocators;

  BlipMetaDomImpl(Element self, String id, BlipViewBuilder.Css css) {
    this.self = self;
    this.id = id;
    this.css = css;
  }

  public static BlipMetaDomImpl of(Element e, BlipViewBuilder.Css css) {
    return new BlipMetaDomImpl(e, e.getId(), css);
  }

  @Override
  public void setTime(String time) {
    getTime().setInnerText(time);
  }

  @Override
  public void setAvatar(String avatarUrl) {
    getAvatar().setSrc(avatarUrl);
  }

  @Override
  public void setMetaline(String metaline) {
    getMetaline().setInnerText(metaline);
  }

  @Override
  public void setRead(boolean read) {
    // The entire set of class names is always replaced, because
    // server-generated and client-generated classes do not mix.
    if (read) {
      getMetabar().setClassName(css.metabar() + " " + css.read());
    } else {
      getMetabar().setClassName(css.metabar() + " " + css.unread());
    }
  }

  @Override
  public void enable(Set<MenuOption> toEnable) {
    Pair<EnumMap<MenuOption, BlipMenuItemDomImpl>, EnumSet<MenuOption>>  state = getMenuState();
    EnumSet<MenuOption> options = EnumSet.copyOf(state.first.keySet());
    EnumSet<MenuOption> selected = state.second;
    options.addAll(toEnable);
    setMenuState(options, selected);
  }

  @Override
  public void disable(Set<MenuOption> toDisable) {
    Pair<EnumMap<MenuOption, BlipMenuItemDomImpl>, EnumSet<MenuOption>>  state = getMenuState();
    EnumSet<MenuOption> options = EnumSet.copyOf(state.first.keySet());
    EnumSet<MenuOption> selected = state.second;
    options.removeAll(toDisable);
    selected.removeAll(toDisable);
    setMenuState(options, selected);
  }

  @Override
  public void select(MenuOption option) {
    BlipMenuItemDomImpl item = getMenuState().first.get(option);
    if (item != null) {
      item.select();
    }
  }

  @Override
  public void deselect(MenuOption option) {
    BlipMenuItemDomImpl item = getMenuState().first.get(option);
    if (item != null) {
      item.deselect();
    }
  }

  /**
   * Scrapes the menu state from the DOM. The menu state describes what options
   * exist, and which, if any, are currently selected.
   *
   * @return a mapping from available options to their UI objects, and the
   *         subset of those options that are currently selected.
   */
  private Pair<EnumMap<MenuOption, BlipMenuItemDomImpl>, EnumSet<MenuOption>> getMenuState() {
    EnumMap<MenuOption, BlipMenuItemDomImpl> options =
        new EnumMap<MenuOption, BlipMenuItemDomImpl>(MenuOption.class);
    EnumSet<MenuOption> selected = EnumSet.noneOf(MenuOption.class);
    Element e = getMenu().getFirstChildElement();
    while (e != null) {
      if (e.hasAttribute(KIND_ATTRIBUTE)
          && e.getAttribute(KIND_ATTRIBUTE).equals(TypeCodes.kind(Type.MENU_ITEM))) {
        BlipMenuItemDomImpl item = BlipMenuItemDomImpl.of(e, css);
        MenuOption option = item.getOption();
        options.put(option, item);
        if (item.isSelected()) {
          selected.add(option);
        }
      }
      e = e.getNextSiblingElement();
    }
    return Pair.of(options, selected);
  }

  /**
   * Replaces the current menu DOM with a new menu.
   *
   * @param options options to include in the menu
   * @param selected which options, if any, are to be selected.
   */
  private void setMenuState(Set<MenuOption> options, Set<MenuOption> selected) {
    UiBuilder builder = BlipMetaViewBuilder.menuBuilder(options, selected, css);
    SafeHtmlBuilder  out = new SafeHtmlBuilder();
    builder.outputHtml(out);
    getMenu().setInnerHTML(out.toSafeHtml().asString());
  }

  public void clearContent() {
    getInlineLocators().clear();
    getContentContainer().getFirstChildElement().setInnerHTML("");
  }

  public void setContent(Element document) {
    // Server-side document rendering is not correct - it leaves off the crucial
    // "document" class.
    document.addClassName("document");
    getContentContainer().getFirstChildElement().appendChild(document);
  }

  public StringSequence getInlineLocators() {
    if (inlineLocators == null) {
      Element content = getContentContainer().getFirstChildElement();
      if (content != null) {
        inlineLocators = (StringSequence) content.getPropertyObject(INLINE_LOCATOR_PROPERTY);
        if (inlineLocators == null) {
          // Note: getAttribute() of a missing attribute does not return null on
          // all browsers.
          if (content.hasAttribute(INLINE_LOCATOR_ATTRIBUTE)) {
            String serial = content.getAttribute(INLINE_LOCATOR_ATTRIBUTE);
            inlineLocators = StringSequence.create(serial);
          } else {
            inlineLocators = StringSequence.create();
          }
          content.setPropertyObject(INLINE_LOCATOR_PROPERTY, inlineLocators);
        }
      } else {
        // Leave inlineLocators as null, since the document is not here yet.
      }
    }
    return inlineLocators;
  }

  //
  // Generated code. There is no informative content in the code below.
  //

  private Element getTime() {
    if (time == null) {
      time = load(id, Components.TIME);
    }
    return time;
  }

  private ImageElement getAvatar() {
    if (avatar == null) {
      avatar = load(id, Components.AVATAR).cast();
    }
    return avatar;
  }

  private Element getMetaline() {
    if (metaline == null) {
      metaline = load(id, Components.METALINE);
    }
    return metaline;
  }

  private Element getMetabar() {
    if (metabar == null) {
      metabar = load(id, Components.METABAR);
    }
    return metabar;
  }

  private Element getMenu() {
    if (menu == null) {
      menu = load(id, Components.MENU);
    }
    return menu;
  }

  //
  // Structural elements are public, in order to export structural control.
  //

  public Element getContentContainer() {
    if (contentContainer == null) {
      contentContainer = load(id, Components.CONTENT);
    }
    return contentContainer;
  }

  public void remove() {
    getElement().removeFromParent();
  }

  //
  // DomView nature.
  //

  @Override
  public Element getElement() {
    return self;
  }

  @Override
  public String getId() {
    return id;
  }

  //
  // DOM-specific structural knowledge.
  //

  Element getInlineAnchorAfter(Element ref) {
    String id = ref != null ? ref.getId() : null;
    String nextId = getInlineLocators().getNext(id);
    return Document.get().getElementById(nextId);
  }

  Element getInlineAnchorBefore(Element ref) {
    String id = ref != null ? ref.getId() : null;
    String nextId = getInlineLocators().getPrevious(id);
    return Document.get().getElementById(nextId);
  }

  void insertInlineLocatorBefore(Element ref, Element x) {
    String id = ref != null ? ref.getId() : null;
    getInlineLocators().insertBefore(id, x.getId());
  }

  void removeInlineLocator(Element x) {
    getInlineLocators().remove(x.getId());
  }

  @Override
  public boolean equals(Object obj) {
    return DomViewHelper.equals(this, obj);
  }

  @Override
  public int hashCode() {
    return DomViewHelper.hashCode(this);
  }
}
TOP

Related Classes of org.waveprotocol.wave.client.wavepanel.view.dom.BlipMetaDomImpl

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.