/*
 * 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.user.client.ui;

import com.google.gwt.animation.client.Animation;
import com.google.gwt.aria.client.Roles;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.safehtml.client.HasSafeHtml;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.annotations.IsSafeHtml;
import com.google.gwt.user.client.DOM;

import java.util.ArrayList;
import java.util.List;

/**
 * An item that can be contained within a
 * {@link com.google.gwt.user.client.ui.Tree}.
 *
 * Each tree item is assigned a unique DOM id in order to support ARIA. See
 * {@link com.google.gwt.user.client.ui.Accessibility} for more information.
 *
 * <p>
 * <h3>Example</h3>
 * {@example com.google.gwt.examples.TreeExample}
 * </p>
 */
public class TreeItem extends UIObject implements IsTreeItem, HasTreeItems,
    HasHTML, HasSafeHtml {
  /*
   * For compatibility with UiBinder interface HasTreeItems should be declared
   * before HasHTML, so that children items and widgets are processed before
   * interpreting HTML.
   */

  /**
   * The margin applied to child items.
   */
  private static final double CHILD_MARGIN = 16.0;

  /**
   * Implementation class for {@link TreeItem}.
   */
  public static class TreeItemImpl {
    public TreeItemImpl() {
      initializeClonableElements();
    }

    void convertToFullNode(TreeItem item) {
      if (item.imageHolder == null) {
        // Extract the Elements from the object
        Element itemTable = DOM.clone(BASE_INTERNAL_ELEM, true);
        DOM.appendChild(item.getElement(), itemTable);
        Element tr = DOM.getFirstChild(DOM.getFirstChild(itemTable));
        Element tdImg = DOM.getFirstChild(tr);
        Element tdContent = DOM.getNextSibling(tdImg);

        // Undoes padding from table element.
        item.getElement().getStyle().setProperty("padding", "0px");
        DOM.appendChild(tdContent, item.contentElem);
        item.imageHolder = tdImg;
      }
    }

    /**
     * Setup clonable elements.
     */
    void initializeClonableElements() {
      if (GWT.isClient()) {
        // Create the base table element that will be cloned.
        BASE_INTERNAL_ELEM = DOM.createTable();
        Element contentElem = DOM.createDiv();
        Element tbody = DOM.createTBody(), tr = DOM.createTR();
        Element tdImg = DOM.createTD(), tdContent = DOM.createTD();
        DOM.appendChild(BASE_INTERNAL_ELEM, tbody);
        DOM.appendChild(tbody, tr);
        DOM.appendChild(tr, tdImg);
        DOM.appendChild(tr, tdContent);
        tdImg.getStyle().setProperty("verticalAlign", "middle");
        tdContent.getStyle().setProperty("verticalAlign", "middle");
        DOM.appendChild(tdContent, contentElem);
        contentElem.getStyle().setProperty("display", "inline");
        setStyleName(contentElem, "gwt-TreeItem");
        BASE_INTERNAL_ELEM.getStyle().setProperty("whiteSpace", "nowrap");

        // Create the base element that will be cloned
        BASE_BARE_ELEM = DOM.createDiv();

        // Simulates padding from table element.
        BASE_BARE_ELEM.getStyle().setProperty("padding", "3px");
        DOM.appendChild(BASE_BARE_ELEM, contentElem);
        Roles.getTreeitemRole().set(contentElem);
      }
    }
  }

  /**
   * IE specific implementation class for {@link TreeItem}.
   */
  public static class TreeItemImplIE8ToIE10 extends TreeItemImpl {
    @Override
    void convertToFullNode(TreeItem item) {
      super.convertToFullNode(item);
      item.getElement().getStyle().setProperty("marginBottom", "0px");
    }
  }

  /**
   * An {@link Animation} used to open the child elements. If a {@link TreeItem}
   * is in the process of opening, it will immediately be opened and the new
   * {@link TreeItem} will use this animation.
   */
  private static class TreeItemAnimation extends Animation {

    /**
     * The {@link TreeItem} currently being affected.
     */
    private TreeItem curItem = null;

    /**
     * Whether the item is being opened or closed.
     */
    private boolean opening = true;

    /**
     * The target height of the child items.
     */
    private int scrollHeight = 0;

    /**
     * Open the specified {@link TreeItem}.
     *
     * @param item the {@link TreeItem} to open
     * @param animate true to animate, false to open instantly
     */
    public void setItemState(TreeItem item, boolean animate) {
      // Immediately complete previous open
      cancel();

      // Open the new item
      if (animate) {
        curItem = item;
        opening = item.open;
        run(Math.min(ANIMATION_DURATION, ANIMATION_DURATION_PER_ITEM
            * curItem.getChildCount()));
      } else {
        UIObject.setVisible(item.childSpanElem, item.open);
      }
    }

    @Override
    protected void onComplete() {
      if (curItem != null) {
        if (opening) {
          UIObject.setVisible(curItem.childSpanElem, true);
          onUpdate(1.0);
          curItem.childSpanElem.getStyle().setProperty("height", "auto");
        } else {
          UIObject.setVisible(curItem.childSpanElem, false);
        }
        curItem.childSpanElem.getStyle().setProperty("overflow", "visible");
        curItem.childSpanElem.getStyle().setProperty("width", "auto");
        curItem = null;
      }
    }

    @Override
    protected void onStart() {
      scrollHeight = 0;

      // If the TreeItem is already open, we can get its scrollHeight
      // immediately.
      if (!opening) {
        scrollHeight = curItem.childSpanElem.getScrollHeight();
      }
      curItem.childSpanElem.getStyle().setProperty("overflow", "hidden");

      // If the TreeItem is already open, onStart will set its height to its
      // natural height. If the TreeItem is currently closed, onStart will set
      // its height to 1px (see onUpdate below), and then we make the TreeItem
      // visible so we can get its correct scrollHeight.
      super.onStart();

      // If the TreeItem is currently closed, we need to make it visible before
      // we can get its height.
      if (opening) {
        UIObject.setVisible(curItem.childSpanElem, true);
        scrollHeight = curItem.childSpanElem.getScrollHeight();
      }
    }

    @Override
    protected void onUpdate(double progress) {
      int height = (int) (progress * scrollHeight);
      if (!opening) {
        height = scrollHeight - height;
      }

      // Issue 2338: If the height is 0px, IE7 will display all of the children
      // instead of hiding them completely.
      height = Math.max(height, 1);

      curItem.childSpanElem.getStyle().setProperty("height", height + "px");

      // We need to set the width explicitly of the item might be cropped
      int scrollWidth = curItem.childSpanElem.getPropertyInt("scrollWidth");
      curItem.childSpanElem.getStyle().setProperty("width", scrollWidth + "px");
    }
  }

  // By not overwriting the default tree padding and spacing, we traditionally
  // added 7 pixels between our image and content.
  // <2>|<1>image<1>|<2>|<1>content
  // So to preserve the current spacing we must add a 7 pixel pad when no image
  // is supplied.
  static final int IMAGE_PAD = 7;

  /**
   * The duration of the animation.
   */
  private static final int ANIMATION_DURATION = 200;

  /**
   * The duration of the animation per child {@link TreeItem}. If the per item
   * duration times the number of child items is less than the duration above,
   * the smaller duration will be used.
   */
  private static final int ANIMATION_DURATION_PER_ITEM = 75;

  /**
   * The static animation used to open {@link TreeItem TreeItems}.
   */
  private static TreeItemAnimation itemAnimation = new TreeItemAnimation();

  /**
   * The structured table to hold images.
   */

  private static Element BASE_INTERNAL_ELEM;
  /**
   * The base tree item element that will be cloned.
   */
  private static Element BASE_BARE_ELEM;

  private static TreeItemImpl impl = GWT.create(TreeItemImpl.class);

  private ArrayList<TreeItem> children;
  private Element contentElem, childSpanElem, imageHolder;

  /**
   * Indicates that this item is a root item in a tree.
   */
  private boolean isRoot;

  private boolean open;
  private TreeItem parent;
  private boolean selected;

  private Object userObject;

  private Tree tree;

  private Widget widget;

  /**
   * Creates an empty tree item.
   */
  public TreeItem() {
    this(false);
  }

  /**
   * Constructs a tree item with the given HTML.
   *
   * @param html the item's HTML
   */
  public TreeItem(SafeHtml html) {
    this();
    setHTML(html);
  }

  /**
   * Constructs a tree item with the given <code>Widget</code>.
   *
   * @param widget the item's widget
   */
  public TreeItem(Widget widget) {
    this();
    setWidget(widget);
  }

  /**
   * Creates an empty tree item.
   *
   * @param isRoot true if this item is the root of a tree
   */
  TreeItem(boolean isRoot) {
    this.isRoot = isRoot;
    Element elem = DOM.clone(BASE_BARE_ELEM, true);
    setElement(elem);
    contentElem = DOM.getFirstChild(elem);
    contentElem.setAttribute("id", DOM.createUniqueId());

    // The root item always has children.
    if (isRoot) {
      initChildren();
    }
  }

  /**
   * Adds a child tree item containing the specified html.
   *
   * @param itemHtml the item's HTML
   * @return the item that was added
   */
  @Override
  public TreeItem addItem(SafeHtml itemHtml) {
    TreeItem ret = new TreeItem(itemHtml);
    addItem(ret);
    return ret;
  }

  /**
   * Adds another item as a child to this one.
   *
   * @param item the item to be added
   */
  @Override
  public void addItem(TreeItem item) {
    // If this is the item's parent, removing the item will affect the child
    // count.
    maybeRemoveItemFromParent(item);
    insertItem(getChildCount(), item);
  }

  /**
   * Adds another item as a child to this one.
   *
   * @param isItem the wrapper of item to be added
   */
  @Override
  public void addItem(IsTreeItem isItem) {
    TreeItem item = isItem.asTreeItem();
    addItem(item);
  }

  /**
   * Adds a child tree item containing the specified widget.
   *
   * @param widget the widget to be added
   * @return the item that was added
   */
  @Override
  public TreeItem addItem(Widget widget) {
    TreeItem ret = new TreeItem(widget);
    addItem(ret);
    return ret;
  }

  /**
   * Adds a child tree item containing the specified text.
   *
   * @param itemText the text of the item to be added
   * @return the item that was added
   */
  @Override
  public TreeItem addTextItem(String itemText) {
    TreeItem ret = new TreeItem();
    ret.setText(itemText);
    addItem(ret);
    return ret;
  }

  @Override
  public TreeItem asTreeItem() {
    return this;
  }

  /**
   * Gets the child at the specified index.
   *
   * @param index the index to be retrieved
   * @return the item at that index
   */

  public TreeItem getChild(int index) {
    if ((index < 0) || (index >= getChildCount())) {
      return null;
    }

    return children.get(index);
  }

  /**
   * Gets the number of children contained in this item.
   *
   * @return this item's child count.
   */

  public int getChildCount() {
    if (children == null) {
      return 0;
    }
    return children.size();
  }

  /**
   * Gets the index of the specified child item.
   *
   * @param child the child item to be found
   * @return the child's index, or <code>-1</code> if none is found
   */

  public int getChildIndex(TreeItem child) {
    if (children == null) {
      return -1;
    }
    return children.indexOf(child);
  }

  @Override
  public String getHTML() {
    return contentElem.getInnerHTML();
  }

  /**
   * Gets this item's parent.
   *
   * @return the parent item
   */
  public TreeItem getParentItem() {
    return parent;
  }

  /**
   * Gets whether this item's children are displayed.
   *
   * @return <code>true</code> if the item is open
   */
  public boolean getState() {
    return open;
  }

  @Override
  public String getText() {
    return contentElem.getInnerText();
  }

  /**
   * Gets the tree that contains this item.
   *
   * @return the containing tree
   */
  public final Tree getTree() {
    return tree;
  }

  /**
   * Gets the user-defined object associated with this item.
   *
   * @return the item's user-defined object
   */
  public Object getUserObject() {
    return userObject;
  }

  /**
   * Gets the <code>Widget</code> associated with this tree item.
   *
   * @return the widget
   */
  public Widget getWidget() {
    return widget;
  }

  @Override
  public String getTitle() {
    return contentElem.getTitle();
  }

  @Override
  public void setTitle(String title) {
    contentElem.setTitle(title);
  }

  /**
   * Inserts a child tree item at the specified index containing the specified
   * html.
   *
   * @param beforeIndex the index where the item will be inserted
   * @param itemHtml the item's HTML
   * @return the item that was added
   * @throws IndexOutOfBoundsException if the index is out of range
   */
  public TreeItem insertItem(int beforeIndex, SafeHtml itemHtml)
      throws IndexOutOfBoundsException {
    TreeItem ret = new TreeItem(itemHtml);
    insertItem(beforeIndex, ret);
    return ret;
  }

  /**
   * Inserts an item as a child to this one.
   *
   * @param beforeIndex the index where the item will be inserted
   * @param item the item to be added
   * @throws IndexOutOfBoundsException if the index is out of range
   */
  public void insertItem(int beforeIndex, TreeItem item)
      throws IndexOutOfBoundsException {
    // Detach item from existing parent.
    maybeRemoveItemFromParent(item);

    // Check the index after detaching in case this item was already the parent.
    int childCount = getChildCount();
    if (beforeIndex < 0 || beforeIndex > childCount) {
      throw new IndexOutOfBoundsException();
    }

    if (children == null) {
      initChildren();
    }

    // Set the margin.
    // Use no margin on top-most items.
    double margin = isRoot ? 0.0 : CHILD_MARGIN;
    if (LocaleInfo.getCurrentLocale().isRTL()) {
      item.getElement().getStyle().setMarginRight(margin, Unit.PX);
    } else {
      item.getElement().getStyle().setMarginLeft(margin, Unit.PX);
    }

    // Physical attach.
    Element childContainer = isRoot ? tree.getElement() : childSpanElem;
    if (beforeIndex == childCount) {
      childContainer.appendChild(item.getElement());
    } else {
      Element beforeElem = getChild(beforeIndex).getElement();
      childContainer.insertBefore(item.getElement(), beforeElem);
    }

    // Logical attach.
    // Explicitly set top-level items' parents to null if this is root.
    item.setParentItem(isRoot ? null : this);
    children.add(beforeIndex, item);

    // Adopt.
    item.setTree(tree);

    if (!isRoot && children.size() == 1) {
      updateState(false, false);
    }
  }

  /**
   * Inserts a child tree item at the specified index containing the specified
   * widget.
   *
   * @param beforeIndex the index where the item will be inserted
   * @param widget the widget to be added
   * @return the item that was added
   * @throws IndexOutOfBoundsException if the index is out of range
   */
  public TreeItem insertItem(int beforeIndex, Widget widget)
      throws IndexOutOfBoundsException {
    TreeItem ret = new TreeItem(widget);
    insertItem(beforeIndex, ret);
    return ret;
  }

  /**
   * Inserts a child tree item at the specified index containing the specified
   * text.
   * 
   * @param beforeIndex the index where the item will be inserted
   * @param itemText the item's text
   * @return the item that was added
   * @throws IndexOutOfBoundsException if the index is out of range
   */
  public TreeItem insertTextItem(int beforeIndex, String itemText) {
    TreeItem ret = new TreeItem();
    ret.setText(itemText);
    insertItem(beforeIndex, ret);
    return ret;
  }

  /**
   * Determines whether this item is currently selected.
   *
   * @return <code>true</code> if it is selected
   */
  public boolean isSelected() {
    return selected;
  }

  /**
   * Removes this item from its tree.
   */
  public void remove() {
    if (parent != null) {
      // If this item has a parent, remove self from it.
      parent.removeItem(this);
    } else if (tree != null) {
      // If the item has no parent, but is in the Tree, it must be a top-level
      // element.
      tree.removeItem(this);
    }
  }

  /**
   * Removes one of this item's children.
   *
   * @param item the item to be removed
   */
  @Override
  public void removeItem(TreeItem item) {
    // Validate.
    if (children == null || !children.contains(item)) {
      return;
    }

    // Orphan.
    Tree oldTree = tree;
    item.setTree(null);

    // Physical detach.
    if (isRoot) {
      oldTree.getElement().removeChild(item.getElement());
    } else {
      childSpanElem.removeChild(item.getElement());
    }

    // Logical detach.
    item.setParentItem(null);
    children.remove(item);

    if (!isRoot && children.size() == 0) {
      updateState(false, false);
    }
  }

  /**
   * Removes one of this item's children.
   *
   * @param isItem the wrapper of item to be removed
   */
  @Override
  public void removeItem(IsTreeItem isItem) {
    if (isItem != null) {
      TreeItem item = isItem.asTreeItem();
      removeItem(item);
    }
  }

  /**
   * Removes all of this item's children.
   */
  @Override
  public void removeItems() {
    while (getChildCount() > 0) {
      removeItem(getChild(0));
    }
  }

  @Override
  public void setHTML(@IsSafeHtml String html) {
    setWidget(null);
    contentElem.setInnerHTML(html);
  }

  @Override
  public void setHTML(SafeHtml html) {
    setHTML(html.asString());
  }

  /**
   * Selects or deselects this item.
   *
   * @param selected <code>true</code> to select the item, <code>false</code> to
   *          deselect it
   */
  public void setSelected(boolean selected) {
    if (this.selected == selected) {
      return;
    }
    this.selected = selected;
    setStyleName(getContentElem(), "gwt-TreeItem-selected", selected);
  }

  /**
   * Sets whether this item's children are displayed.
   *
   * @param open whether the item is open
   */
  public void setState(boolean open) {
    setState(open, true);
  }

  /**
   * Sets whether this item's children are displayed.
   *
   * @param open whether the item is open
   * @param fireEvents <code>true</code> to allow open/close events to be
   */
  public void setState(boolean open, boolean fireEvents) {
    if (open && getChildCount() == 0) {
      return;
    }

    // Only do the physical update if it changes
    if (this.open != open) {
      this.open = open;
      updateState(true, true);

      if (fireEvents && tree != null) {
        tree.fireStateChanged(this, open);
      }
    }
  }

  @Override
  public void setText(String text) {
    setWidget(null);
    contentElem.setInnerText(text);
  }

  /**
   * Sets the user-defined object associated with this item.
   *
   * @param userObj the item's user-defined object
   */
  public void setUserObject(Object userObj) {
    userObject = userObj;
  }

  /**
   * Sets the current widget. Any existing child widget will be removed.
   *
   * @param newWidget Widget to set
   */
  public void setWidget(Widget newWidget) {
    // Detach new child from old parent.
    if (newWidget != null) {
      newWidget.removeFromParent();
    }

    // Detach old child from tree.
    if (widget != null) {
      try {
        if (tree != null) {
          tree.orphan(widget);
        }
      } finally {
        // Physical detach old child.
        contentElem.removeChild(widget.getElement());
        widget = null;
      }
    }

    // Clear out any existing content before adding a widget.
    contentElem.setInnerHTML("");

    // Logical detach old/attach new.
    widget = newWidget;

    if (newWidget != null) {
      // Physical attach new.
      DOM.appendChild(contentElem, newWidget.getElement());

      // Attach child to tree.
      if (tree != null) {
        tree.adopt(widget, this);
      }

      // Set tabIndex on the widget to -1, so that it doesn't mess up the tab
      // order of the entire tree

      if (Tree.shouldTreeDelegateFocusToElement(widget.getElement())) {
        widget.getElement().setAttribute("tabIndex", "-1");
      }
    }
  }

  /**
   * Returns a suggested {@link Focusable} instance to use when this tree item
   * is selected. The tree maintains focus if this method returns null. By
   * default, if the tree item contains a focusable widget, that widget is
   * returned.
   *
   * Note, the {@link Tree} will ignore this value if the user clicked on an
   * input element such as a button or text area when selecting this item.
   *
   * @return the focusable item
   */
  protected Focusable getFocusable() {
    Focusable focus = getFocusableWidget();
    if (focus == null) {
      Widget w = getWidget();
      if (w instanceof Focusable) {
        focus = (Focusable) w;
      }
    }
    return focus;
  }

  /**
   * Returns the widget, if any, that should be focused on if this TreeItem is
   * selected.
   *
   * @return widget to be focused.
   * @deprecated use {@link #getFocusable()} instead
   */
  @Deprecated
  protected HasFocus getFocusableWidget() {
    Widget w = getWidget();
    if (w instanceof HasFocus) {
      return (HasFocus) w;
    } else {
      return null;
    }
  }

  /**
   * <b>Affected Elements:</b>
   * <ul>
   * <li>-content = The text or {@link Widget} next to the image.</li>
   * <li>-child# = The child at the specified index.</li>
   * </ul>
   *
   * @see UIObject#onEnsureDebugId(String)
   */
  @Override
  protected void onEnsureDebugId(String baseID) {
    super.onEnsureDebugId(baseID);
    ensureDebugId(contentElem, baseID, "content");
    if (imageHolder != null) {
      // The image itself may or may not exist.
      ensureDebugId(imageHolder, baseID, "image");
    }

    if (children != null) {
      int childCount = 0;
      for (TreeItem child : children) {
        child.ensureDebugId(baseID + "-child" + childCount);
        childCount++;
      }
    }
  }

  void addTreeItems(List<TreeItem> accum) {
    int size = getChildCount();
    for (int i = 0; i < size; i++) {
      TreeItem item = children.get(i);
      accum.add(item);
      item.addTreeItems(accum);
    }
  }

  ArrayList<TreeItem> getChildren() {
    return children;
  }

  Element getContentElem() {
    return contentElem;
  }

  Element getImageElement() {
    return DOM.getFirstChild(getImageHolderElement());
  }

  Element getImageHolderElement() {
    if (!isFullNode()) {
      convertToFullNode();
    }
    return imageHolder;
  }

  void initChildren() {
    convertToFullNode();
    childSpanElem = DOM.createDiv();
    DOM.appendChild(getElement(), childSpanElem);
    childSpanElem.getStyle().setProperty("whiteSpace", "nowrap");
    children = new ArrayList<TreeItem>();
  }

  boolean isFullNode() {
    return imageHolder != null;
  }

  /**
   * Remove a tree item from its parent if it has one.
   *
   * @param item the tree item to remove from its parent
   */
  void maybeRemoveItemFromParent(TreeItem item) {
    if ((item.getParentItem() != null) || (item.getTree() != null)) {
      item.remove();
    }
  }

  void setParentItem(TreeItem parent) {
    this.parent = parent;
  }

  void setTree(Tree newTree) {
    // Early out.
    if (tree == newTree) {
      return;
    }

    // Remove this item from existing tree.
    if (tree != null) {
      if (tree.getSelectedItem() == this) {
        tree.setSelectedItem(null);
      }

      if (widget != null) {
        tree.orphan(widget);
      }
    }

    tree = newTree;
    for (int i = 0, n = getChildCount(); i < n; ++i) {
      children.get(i).setTree(newTree);
    }
    updateState(false, true);

    if (newTree != null) {
      if (widget != null) {
        // Add my widget to the new tree.
        newTree.adopt(widget, this);
      }
    }
  }

  void updateState(boolean animate, boolean updateTreeSelection) {
    // If the tree hasn't been set, there is no visual state to update.
    // If the tree is not attached, then update will be called on attach.
    if (tree == null || tree.isAttached() == false) {
      return;
    }

    if (getChildCount() == 0) {
      if (childSpanElem != null) {
        UIObject.setVisible(childSpanElem, false);
      }
      tree.showLeafImage(this);
      return;
    }

    // We must use 'display' rather than 'visibility' here,
    // or the children will always take up space.
    if (animate && (tree != null) && (tree.isAttached())) {
      itemAnimation.setItemState(this, tree.isAnimationEnabled());
    } else {
      itemAnimation.setItemState(this, false);
    }

    // Change the status image
    if (open) {
      tree.showOpenImage(this);
    } else {
      tree.showClosedImage(this);
    }

    // We may need to update the tree's selection in response to a tree state
    // change. For example, if the tree's currently selected item is a
    // descendant of an item whose branch was just collapsed, then the item
    // itself should become the newly-selected item.
    if (updateTreeSelection) {
      tree.maybeUpdateSelection(this, this.open);
    }
  }

  void updateStateRecursive() {
    updateStateRecursiveHelper();
    tree.maybeUpdateSelection(this, this.open);
  }

  private void convertToFullNode() {
    impl.convertToFullNode(this);
  }

  private void updateStateRecursiveHelper() {
    updateState(false, false);
    for (int i = 0, n = getChildCount(); i < n; ++i) {
      children.get(i).updateStateRecursiveHelper();
    }
  }
}
