/*
 * 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 com.google.gwt.user.cellview.client;

import com.google.gwt.animation.client.Animation;
import com.google.gwt.cell.client.Cell;
import com.google.gwt.cell.client.Cell.Context;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.BrowserEvents;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Overflow;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.Style.Visibility;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.CssResource.ImportedWithPrefix;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.resources.client.ImageResource.ImageOptions;
import com.google.gwt.resources.client.ImageResource.RepeatStyle;
import com.google.gwt.safecss.shared.SafeStyles;
import com.google.gwt.safecss.shared.SafeStylesBuilder;
import com.google.gwt.safecss.shared.SafeStylesUtils;
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HasAnimation;
import com.google.gwt.user.client.ui.ProvidesResize;
import com.google.gwt.user.client.ui.RequiresResize;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SplitLayoutPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.HasData;
import com.google.gwt.view.client.HasRows;
import com.google.gwt.view.client.ProvidesKey;
import com.google.gwt.view.client.SelectionModel;
import com.google.gwt.view.client.TreeViewModel;
import com.google.gwt.view.client.TreeViewModel.NodeInfo;

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

/**
 * A "browsable" view of a tree in which only a single node per level may be
 * open at one time.
 * 
 * <p>
 * This widget will <em>only</em> work in standards mode, which requires that
 * the HTML page in which it is run have an explicit &lt;!DOCTYPE&gt;
 * declaration.
 * </p>
 * 
 * <p>
 * <h3>Example</h3>
 * <dl>
 * <dt>Trivial example</dt>
 * <dd>{@example com.google.gwt.examples.cellview.CellBrowserExample}</dd>
 * <dt>Complex example</dt>
 * <dd>{@example com.google.gwt.examples.cellview.CellBrowserExample2}</dd>
 * </dl>
 */
public class CellBrowser extends AbstractCellTree implements ProvidesResize, RequiresResize,
    HasAnimation {

  /**
   * A ClientBundle that provides images for this widget.
   */
  public interface Resources extends ClientBundle {
    /**
     * An image indicating a closed branch.
     */
    @ImageOptions(flipRtl = true)
    ImageResource cellBrowserClosed();

    /**
     * An image indicating an open branch.
     */
    @ImageOptions(flipRtl = true)
    ImageResource cellBrowserOpen();

    /**
     * The background used for open items.
     */
    // Use RepeatStyle.BOTH to ensure that we do not bundle the image.
    @ImageOptions(repeatStyle = RepeatStyle.Both, flipRtl = true)
    ImageResource cellBrowserOpenBackground();

    /**
     * The background used for selected items.
     */
    // Use RepeatStyle.BOTH to ensure that we do not bundle the image.
    @Source("cellTreeSelectedBackground.png")
    @ImageOptions(repeatStyle = RepeatStyle.Both, flipRtl = true)
    ImageResource cellBrowserSelectedBackground();

    /**
     * The styles used in this widget.
     */
    @Source(Style.DEFAULT_CSS)
    Style cellBrowserStyle();
  }

  /**
   * Styles used by this widget.
   */
  @ImportedWithPrefix("gwt-CellBrowser")
  public interface Style extends CssResource {
    /**
     * The path to the default CSS styles used by this resource.
     */
    String DEFAULT_CSS = "com/google/gwt/user/cellview/client/CellBrowser.css";

    /**
     * Applied to all columns.
     */
    String cellBrowserColumn();

    /**
     * Applied to even list items.
     */
    String cellBrowserEvenItem();

    /**
     * Applied to the first column.
     */
    String cellBrowserFirstColumn();

    /***
     * Applied to keyboard selected items.
     */
    String cellBrowserKeyboardSelectedItem();

    /**
     * Applied to odd list items.
     */
    String cellBrowserOddItem();

    /***
     * Applied to open items.
     */
    String cellBrowserOpenItem();

    /***
     * Applied to selected items.
     */
    String cellBrowserSelectedItem();

    /**
     * Applied to the widget.
     */
    String cellBrowserWidget();
  }

  interface Template extends SafeHtmlTemplates {
    @Template("<div onclick=\"\" __idx=\"{0}\" class=\"{1}\""
        + " style=\"{2}position:relative;outline:none;\">{3}<div>{4}</div></div>")
    SafeHtml div(int idx, String classes, SafeStyles padding, SafeHtml imageHtml,
        SafeHtml cellContents);

    @Template("<div onclick=\"\" __idx=\"{0}\" class=\"{1}\""
        + " style=\"{2}position:relative;outline:none;\" tabindex=\"{3}\">{4}<div>{5}</div></div>")
    SafeHtml divFocusable(int idx, String classes, SafeStyles padding, int tabIndex,
        SafeHtml imageHtml, SafeHtml cellContents);

    @Template("<div onclick=\"\" __idx=\"{0}\" class=\"{1}\""
        + " style=\"{2}position:relative;outline:none;\" tabindex=\"{3}\" accessKey=\"{4}\">{5}<div>{6}</div></div>")
    SafeHtml divFocusableWithKey(int idx, String classes, SafeStyles padding, int tabIndex,
        char accessKey, SafeHtml imageHtml, SafeHtml cellContents);

    @Template("<div style=\"{0}position:absolute;\">{1}</div>")
    SafeHtml imageWrapper(SafeStyles css, SafeHtml image);
  }

  /**
   * A custom version of cell list used by the browser. Visible for testing.
   * 
   * @param <T> the data type of list items
   */
  class BrowserCellList<T> extends CellList<T> {

    /**
     * The level of this list view.
     */
    private final int level;

    /**
     * The key of the currently focused item.
     */
    private Object focusedKey;

    /**
     * The currently selected value in this list.
     */
    private T selectedValue;

    /**
     * A boolean indicating that this widget is no longer used.
     */
    private boolean isDestroyed;

    /**
     * Indicates whether or not the focused value is open.
     */
    private boolean isFocusedOpen;

    /**
     * Temporary element used to create elements from HTML.
     */
    private final Element tmpElem = Document.get().createDivElement();

    public BrowserCellList(final Cell<T> cell, int level, ProvidesKey<T> keyProvider) {
      super(cell, cellListResources, keyProvider);
      this.level = level;
    }

    protected void deselectValue() {
      SelectionModel<? super T> selectionModel = getSelectionModel();
      if (selectionModel != null && selectedValue != null) {
        selectionModel.setSelected(selectedValue, false);
      }
    }

    @Override
    protected Element getCellParent(Element item) {
      return item.getFirstChildElement().getNextSiblingElement();
    }

    @Override
    protected boolean isKeyboardNavigationSuppressed() {
      /*
       * Keyboard selection is never disabled in this list because we use it to
       * track the open node, but we want to suppress keyboard navigation if the
       * user disables it.
       */
      return KeyboardSelectionPolicy.DISABLED == CellBrowser.this.getKeyboardSelectionPolicy()
          || super.isKeyboardNavigationSuppressed();
    }

    @Override
    protected void onBrowserEvent2(Event event) {
      super.onBrowserEvent2(event);

      // Handle keyboard navigation between lists.
      String eventType = event.getType();
      if (BrowserEvents.KEYDOWN.equals(eventType) && !isKeyboardNavigationSuppressed()) {
        int keyCode = event.getKeyCode();
        boolean isRtl = LocaleInfo.getCurrentLocale().isRTL();
        keyCode = KeyCodes.maybeSwapArrowKeysForRtl(keyCode, isRtl);
        switch (keyCode) {
          case KeyCodes.KEY_LEFT:
            keyboardNavigateShallow();
            return;
          case KeyCodes.KEY_RIGHT:
            keyboardNavigateDeep();
            return;
        }
      }
    }

    @Override
    protected void renderRowValues(SafeHtmlBuilder sb, List<T> values, int start,
        SelectionModel<? super T> selectionModel) {
      Cell<T> cell = getCell();
      String keyboardSelectedItem = " " + style.cellBrowserKeyboardSelectedItem();
      String selectedItem = " " + style.cellBrowserSelectedItem();
      String openItem = " " + style.cellBrowserOpenItem();
      String evenItem = style.cellBrowserEvenItem();
      String oddItem = style.cellBrowserOddItem();
      int keyboardSelectedRow = getKeyboardSelectedRow() + getPageStart();
      int length = values.size();
      int end = start + length;
      for (int i = start; i < end; i++) {
        T value = values.get(i - start);
        boolean isSelected = selectionModel == null ? false : selectionModel.isSelected(value);
        boolean isOpen = isOpen(i);
        StringBuilder classesBuilder = new StringBuilder();
        classesBuilder.append(i % 2 == 0 ? evenItem : oddItem);
        if (isOpen) {
          classesBuilder.append(openItem);
        }
        if (isSelected) {
          classesBuilder.append(selectedItem);
        }

        SafeHtmlBuilder cellBuilder = new SafeHtmlBuilder();
        Context context = new Context(i, 0, getValueKey(value));
        cell.render(context, value, cellBuilder);

        // Figure out which image to use.
        SafeHtml image;
        if (isOpen) {
          image = openImageHtml;
        } else if (isLeaf(value)) {
          image = LEAF_IMAGE;
        } else {
          image = closedImageHtml;
        }

        SafeStyles padding =
            SafeStylesUtils.fromTrustedString("padding-right: " + imageWidth + "px;");
        if (i == keyboardSelectedRow) {
          // This is the focused item.
          if (isFocused) {
            classesBuilder.append(keyboardSelectedItem);
          }
          char accessKey = getAccessKey();
          if (accessKey != 0) {
            sb.append(template.divFocusableWithKey(i, classesBuilder.toString(), padding,
                getTabIndex(), getAccessKey(), image, cellBuilder.toSafeHtml()));
          } else {
            sb.append(template.divFocusable(i, classesBuilder.toString(), padding, getTabIndex(),
                image, cellBuilder.toSafeHtml()));
          }
        } else {
          sb.append(template.div(i, classesBuilder.toString(), padding, image, cellBuilder
              .toSafeHtml()));
        }
      }

      // Update the child state.
      updateChildState(this, true);
    }

    @Override
    protected void setKeyboardSelected(int index, boolean selected, boolean stealFocus) {
      super.setKeyboardSelected(index, selected, stealFocus);
      if (!isRowWithinBounds(index)) {
        return;
      }

      // Update the style.
      Element elem = getRowElement(index);
      T value = getPresenter().getVisibleItem(index);
      boolean isOpen = selected && isOpen(index);
      setStyleName(elem, style.cellBrowserOpenItem(), isOpen);

      // Update the image.
      SafeHtml image = null;
      if (isOpen) {
        image = openImageHtml;
      } else if (getTreeViewModel().isLeaf(value)) {
        image = LEAF_IMAGE;
      } else {
        image = closedImageHtml;
      }
      tmpElem.setInnerSafeHtml(image);
      elem.replaceChild(tmpElem.getFirstChildElement(), elem.getFirstChildElement());

      // Update the open state.
      updateChildState(this, true);
    }

    /**
     * Set the selected value in this list. If there is already a selected
     * value, the old value will be deselected.
     * 
     * @param value the selected value
     */
    protected void setSelectedValue(T value) {
      // Early exit if the value is unchanged.
      Object oldKey = getValueKey(selectedValue);
      Object newKey = getValueKey(value);
      if (newKey != null && newKey.equals(oldKey)) {
        return;
      }

      // Deselect the current value. Only one thing is selected at a time.
      deselectValue();

      // Select the new value.
      SelectionModel<? super T> selectionModel = getSelectionModel();
      if (selectionModel != null) {
        selectedValue = value;
        selectionModel.setSelected(selectedValue, true);
      }
    }

    /**
     * Check if the specified index is currently open. An index is open if it is
     * the keyboard selected index, there is an associated keyboard selected
     * value, and the value is not a leaf.
     * 
     * @param index the index
     * @return true if open, false if not
     */
    private boolean isOpen(int index) {
      T value = getPresenter().getKeyboardSelectedRowValue();
      return index == getKeyboardSelectedRow() && value != null
          && !getTreeViewModel().isLeaf(value);
    }

    /**
     * Navigate to a deeper node.
     */
    private void keyboardNavigateDeep() {
      if (isKeyboardSelectionDisabled()) {
        return;
      }

      // Move to the child node.
      if (level < treeNodes.size() - 1) {
        TreeNodeImpl<?> treeNode = treeNodes.get(level + 1);
        treeNode.display.getPresenter().setKeyboardSelectedRow(
            treeNode.display.getKeyboardSelectedRow(), true, true);
      }
    }

    /**
     * Navigate to a shallower node.
     */
    private void keyboardNavigateShallow() {
      if (isKeyboardSelectionDisabled()) {
        return;
      }

      // Move to the parent node.
      if (level > 0) {
        TreeNodeImpl<?> treeNode = treeNodes.get(level - 1);
        treeNode.display.setFocus(true);
      }
    }
  }

  /**
   * A node in the tree.
   * 
   * @param <C> the data type of the children of the node
   */
  class TreeNodeImpl<C> implements TreeNode {
    private final BrowserCellList<C> display;
    private NodeInfo<C> nodeInfo;
    private final Object value;
    private final HandlerRegistration valueChangeHandler;
    private final Widget widget;

    /**
     * Construct a new {@link TreeNodeImpl}.
     * 
     * @param nodeInfo the nodeInfo for the children nodes
     * @param value the value of the node
     * @param display the display associated with the node
     * @param widget the widget that wraps the display
     */
    public TreeNodeImpl(final NodeInfo<C> nodeInfo, Object value, final BrowserCellList<C> display,
        Widget widget) {
      this.display = display;
      this.nodeInfo = nodeInfo;
      this.value = value;
      this.widget = widget;

      // Trim to the current level if the open node disappears.
      valueChangeHandler = display.addValueChangeHandler(new ValueChangeHandler<List<C>>() {
        @Override
        public void onValueChange(ValueChangeEvent<List<C>> event) {
          Object focusedKey = display.focusedKey;
          if (focusedKey != null) {
            boolean stillExists = false;
            List<C> displayValues = event.getValue();
            for (C displayValue : displayValues) {
              if (focusedKey.equals(display.getValueKey(displayValue))) {
                stillExists = true;
                break;
              }
            }
            if (!stillExists) {
              trimToLevel(display.level);
            }
          }
        }
      });
    }

    @Override
    public int getChildCount() {
      assertNotDestroyed();
      return display.getPresenter().getVisibleItemCount();
    }

    @Override
    public C getChildValue(int index) {
      assertNotDestroyed();
      checkChildBounds(index);
      return display.getVisibleItem(index);
    }

    @Override
    public int getIndex() {
      assertNotDestroyed();
      TreeNodeImpl<?> parent = getParent();
      return (parent == null) ? 0 : parent.getOpenIndex();
    }

    @Override
    public TreeNodeImpl<?> getParent() {
      assertNotDestroyed();
      return getParentImpl();
    }

    @Override
    public Object getValue() {
      return value;
    }

    @Override
    public boolean isChildLeaf(int index) {
      assertNotDestroyed();
      checkChildBounds(index);
      return isLeaf(getChildValue(index));
    }

    @Override
    public boolean isChildOpen(int index) {
      assertNotDestroyed();
      checkChildBounds(index);
      return (display.focusedKey == null || !display.isFocusedOpen) ? false : display.focusedKey
          .equals(display.getValueKey(getChildValue(index)));
    }

    @Override
    public boolean isDestroyed() {
      if (nodeInfo != null) {
        /*
         * Flush the parent display because the user may have replaced this
         * node, which would destroy it.
         */
        TreeNodeImpl<?> parent = getParentImpl();
        if (parent != null && !parent.isDestroyed()) {
          parent.display.getPresenter().flush();
        }
      }
      return nodeInfo == null;
    }

    @Override
    public TreeNode setChildOpen(int index, boolean open) {
      return setChildOpen(index, open, true);
    }

    @Override
    public TreeNode setChildOpen(int index, boolean open, boolean fireEvents) {
      assertNotDestroyed();
      checkChildBounds(index);
      if (open) {
        // Open the child node.
        display.getPresenter().setKeyboardSelectedRow(index, false, true);
        return updateChildState(display, fireEvents);
      } else {
        // Close the child node if it is currently open.
        if (index == display.getKeyboardSelectedRow()) {
          display.getPresenter().clearKeyboardSelectedRowValue();
          updateChildState(display, fireEvents);
        }
        return null;
      }
    }

    BrowserCellList<C> getDisplay() {
      return display;
    }

    /**
     * Return the key of the value that is focused in this node's display.
     */
    Object getFocusedKey() {
      return display.focusedKey;
    }

    /**
     * Return true if the focused value is open, false if not.
     */
    boolean isFocusedOpen() {
      return display.isFocusedOpen;
    }

    /**
     * Assert that the node has not been destroyed.
     */
    private void assertNotDestroyed() {
      if (isDestroyed()) {
        throw new IllegalStateException("TreeNode no longer exists.");
      }
    }

    /**
     * Check the child bounds.
     * 
     * @param index the index of the child
     * @throws IndexOutOfBoundsException if the child is not in range
     */
    private void checkChildBounds(int index) {
      if ((index < 0) || (index >= getChildCount())) {
        throw new IndexOutOfBoundsException();
      }
    }

    /**
     * Unregister the list view and remove it from the widget.
     */
    private void destroy() {
      display.isDestroyed = true;
      valueChangeHandler.removeHandler();
      display.deselectValue();
      display.setSelectionModel(null);
      nodeInfo.unsetDataDisplay();
      getSplitLayoutPanel().remove(widget);
      nodeInfo = null;
    }

    /**
     * Get the index of the open item.
     * 
     * @return the index of the open item, or -1 if not found
     */
    private int getOpenIndex() {
      return display.isFocusedOpen ? display.getKeyboardSelectedRow() : -1;
    }

    /**
     * Get the parent node without checking if this node is destroyed.
     * 
     * @return the parent node, or null if the node has no parent
     */
    private TreeNodeImpl<?> getParentImpl() {
      return (display.level == 0) ? null : treeNodes.get(display.level - 1);
    }
  }

  /**
   * An implementation of {@link CellList.Resources} that delegates to
   * {@link CellBrowser.Resources}.
   */
  private static class CellListResourcesImpl implements CellList.Resources {

    private final CellBrowser.Resources delegate;
    private final CellListStyleImpl style;

    public CellListResourcesImpl(CellBrowser.Resources delegate) {
      this.delegate = delegate;
      this.style = new CellListStyleImpl(delegate.cellBrowserStyle());
    }

    @Override
    public ImageResource cellListSelectedBackground() {
      return delegate.cellBrowserSelectedBackground();
    }

    @Override
    public CellList.Style cellListStyle() {
      return style;
    }
  }

  /**
   * An implementation of {@link CellList.Style} that delegates to
   * {@link CellBrowser.Style}.
   */
  private static class CellListStyleImpl implements CellList.Style {

    private final CellBrowser.Style delegate;

    public CellListStyleImpl(CellBrowser.Style delegate) {
      this.delegate = delegate;
    }

    @Override
    public String cellListEvenItem() {
      return delegate.cellBrowserEvenItem();
    }

    @Override
    public String cellListKeyboardSelectedItem() {
      return delegate.cellBrowserKeyboardSelectedItem();
    }

    @Override
    public String cellListOddItem() {
      return delegate.cellBrowserOddItem();
    }

    @Override
    public String cellListSelectedItem() {
      return delegate.cellBrowserSelectedItem();
    }

    @Override
    public String cellListWidget() {
      // Do not apply any style to the list itself.
      return null;
    }

    @Override
    public boolean ensureInjected() {
      return delegate.ensureInjected();
    }

    @Override
    public String getName() {
      return delegate.getName();
    }

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

  /**
   * The animation used to scroll to the newly added list view.
   */
  private class ScrollAnimation extends Animation {

    /**
     * The starting scroll position.
     */
    private int startScrollLeft;

    /**
     * The ending scroll position.
     */
    private int targetScrollLeft;

    @Override
    protected void onComplete() {
      getElement().setScrollLeft(targetScrollLeft);
    }

    @Override
    protected void onUpdate(double progress) {
      int diff = targetScrollLeft - startScrollLeft;
      getElement().setScrollLeft(startScrollLeft + (int) (diff * progress));
    }

    void scrollToEnd() {
      Element elem = getElement();
      targetScrollLeft = elem.getScrollWidth() - elem.getClientWidth();
      if (LocaleInfo.getCurrentLocale().isRTL()) {
        targetScrollLeft *= -1;
      }

      if (isAnimationEnabled()) {
        // Animate the scrolling.
        startScrollLeft = elem.getScrollLeft();
        run(250, elem);
      } else {
        // Scroll instantly.
        onComplete();
      }
    }
  }

  /**
   * Pager factory used to create pagers for each {@link CellList} of the
   * {@link CellBrowser}.
   */
  public static interface PagerFactory {
    AbstractPager create(HasRows display);
  }

  /**
   * Default pager.
   */
  private static class PageSizePagerFactory implements PagerFactory {
    @Override
    public AbstractPager create(HasRows display) {
      return new PageSizePager(display.getVisibleRange().getLength());
    }
  }

  /**
   * Builder object to create CellBrowser.
   *
   * @param <T> the type of data in the root node
   */
  public static class Builder<T> {
    private final TreeViewModel viewModel;
    private final T rootValue;
    private Widget loadingIndicator;
    private PagerFactory pagerFactory = new PageSizePagerFactory();
    private Integer pageSize;
    private Resources resources;

    /**
    * Construct a new {@link Builder}.
    *
    * @param viewModel the {@link TreeViewModel} that backs the tree
    * @param rootValue the hidden root value of the tree
    */
    public Builder(TreeViewModel viewModel, T rootValue) {
      this.viewModel = viewModel;
      this.rootValue = rootValue;
    }

    /**
     * Creates a new {@link CellBrowser}.
     *
     * @return new {@link CellBrowser}
     */
    public CellBrowser build() {
      return new CellBrowser(this);
    }

    /**
     * Set the widget to display when the data is loading.
     *
     * @param widget the loading indicator
     * @return this
     */
    public Builder<T> loadingIndicator(Widget widget) {
      this.loadingIndicator = widget;
      return this;
    }

    /**
     * Set the pager factory used to create pagers for each {@link CellList}.
     * Defaults to {@link PageSizePagerFactory} if not set.
     *
     * Can be set to null if no pager should be used. You should also set pageSize
     * big enough to hold all your data then.
     *
     * @param factory the pager factory
     * @return this
     */
    public Builder<T> pagerFactory(PagerFactory factory) {
      this.pagerFactory = factory;
      return this;
    }

    /**
     * Set the pager size for each {@link CellList}.
     *
     * @param pageSize the page size
     * @return this
     */
    public Builder<T> pageSize(int pageSize) {
      this.pageSize = pageSize;
      return this;
    }

    /**
     * Set resources used for images.
     *
     * @param resources the {@link Resources} used for images
     * @return this
     */
    public Builder<T> resources(Resources resources) {
      this.resources = resources;
      return this;
    }

    private Resources resources() {
      if (resources == null) {
        resources = getDefaultResources();
      }
      return resources;
    }
  }

  private static Resources DEFAULT_RESOURCES;

  /**
   * The element used in place of an image when a node has no children.
   */
  private static final SafeHtml LEAF_IMAGE = SafeHtmlUtils
      .fromSafeConstant("<div style='position:absolute;display:none;'></div>");

  private static Template template;

  private static Resources getDefaultResources() {
    if (DEFAULT_RESOURCES == null) {
      DEFAULT_RESOURCES = GWT.create(Resources.class);
    }
    return DEFAULT_RESOURCES;
  }

  /**
   * The visible {@link TreeNodeImpl}s. Visible for testing.
   */
  final List<TreeNodeImpl<?>> treeNodes = new ArrayList<TreeNodeImpl<?>>();

  /**
   * The animation used for scrolling.
   */
  private final ScrollAnimation animation = new ScrollAnimation();

  /**
   * The resources used by the {@link CellList}.
   */
  private final CellList.Resources cellListResources;

  /**
   * The HTML used to generate the closed image.
   */
  private final SafeHtml closedImageHtml;

  /**
   * The default width of new columns.
   */
  private int defaultWidth = 200;

  /**
   * The maximum width of the open and closed images.
   */
  private final int imageWidth;

  /**
   * A boolean indicating whether or not animations are enabled.
   */
  private boolean isAnimationEnabled;

  /**
   * Widget passed to CellLists.
   */
  private final Widget loadingIndicator;

  /**
   * The minimum width of new columns.
   */
  private int minWidth;

  /**
   * The HTML used to generate the open image.
   */
  private final SafeHtml openImageHtml;

  /**
   * Factory used to create pagers for CellLists.
   */
  private final PagerFactory pagerFactory;

  /**
   * Page size for CellLists.
   */
  private final Integer pageSize;

  /**
   * The element used to maintain the scrollbar when columns are removed.
   */
  private Element scrollLock;

  /**
   * The styles used by this widget.
   */
  private final Style style;

  /**
   * Construct a new {@link CellBrowser}.
   * 
   * @param <T> the type of data in the root node
   * @param viewModel the {@link TreeViewModel} that backs the tree
   * @param rootValue the hidden root value of the tree
   *
   * @deprecated please use {@link Builder}
   */
  @Deprecated
  public <T> CellBrowser(TreeViewModel viewModel, T rootValue) {
    this(new Builder<T>(viewModel, rootValue));
  }

  /**
   * Construct a new {@link CellBrowser} with the specified {@link Resources}.
   * 
   * @param <T> the type of data in the root node
   * @param viewModel the {@link TreeViewModel} that backs the tree
   * @param rootValue the hidden root value of the tree
   * @param resources the {@link Resources} used for images
   *
   * @deprecated please use {@link Builder}
   */
  @Deprecated
  public <T> CellBrowser(TreeViewModel viewModel, T rootValue, Resources resources) {
    this(new Builder<T>(viewModel, rootValue).resources(resources));
  }

  protected <T> CellBrowser(Builder<T> builder) {
    super(builder.viewModel);
    if (template == null) {
      template = GWT.create(Template.class);
    }
    Resources resources = builder.resources();
    this.style = resources.cellBrowserStyle();
    this.style.ensureInjected();
    this.cellListResources = new CellListResourcesImpl(resources);
    this.loadingIndicator = builder.loadingIndicator;
    this.pagerFactory = builder.pagerFactory;
    this.pageSize = builder.pageSize;
    initWidget(new SplitLayoutPanel());
    getElement().getStyle().setOverflow(Overflow.AUTO);
    setStyleName(this.style.cellBrowserWidget());

    // Initialize the open and close images strings.
    ImageResource treeOpen = resources.cellBrowserOpen();
    ImageResource treeClosed = resources.cellBrowserClosed();
    openImageHtml = getImageHtml(treeOpen);
    closedImageHtml = getImageHtml(treeClosed);
    imageWidth = Math.max(treeOpen.getWidth(), treeClosed.getWidth());
    minWidth = imageWidth + 20;

    // Add a placeholder to maintain the scroll width.
    scrollLock = Document.get().createDivElement();
    scrollLock.getStyle().setPosition(Position.ABSOLUTE);
    scrollLock.getStyle().setVisibility(Visibility.HIDDEN);
    scrollLock.getStyle().setZIndex(-32767);
    scrollLock.getStyle().setTop(0, Unit.PX);
    if (LocaleInfo.getCurrentLocale().isRTL()) {
      scrollLock.getStyle().setRight(0, Unit.PX);
    } else {
      scrollLock.getStyle().setLeft(0, Unit.PX);
    }
    scrollLock.getStyle().setHeight(1, Unit.PX);
    scrollLock.getStyle().setWidth(1, Unit.PX);
    getElement().appendChild(scrollLock);

    // Associate the first view with the rootValue.
    appendTreeNode(getNodeInfo(builder.rootValue), builder.rootValue);

    // Catch scroll events.
    sinkEvents(Event.ONSCROLL);
  }

  /**
   * Get the default width of new columns.
   * 
   * @return the default width in pixels
   * @see #setDefaultColumnWidth(int)
   */
  public int getDefaultColumnWidth() {
    return defaultWidth;
  }

  /**
   * Get the minimum width of columns.
   * 
   * @return the minimum width in pixels
   * @see #setMinimumColumnWidth(int)
   */
  public int getMinimumColumnWidth() {
    return minWidth;
  }

  @Override
  public TreeNode getRootTreeNode() {
    return treeNodes.get(0);
  }

  @Override
  public boolean isAnimationEnabled() {
    return isAnimationEnabled;
  }

  @Override
  public void onBrowserEvent(Event event) {
    switch (DOM.eventGetType(event)) {
      case Event.ONSCROLL:
        // Shorten the scroll bar is possible.
        adjustScrollLock();
        break;
    }
    super.onBrowserEvent(event);
  }

  @Override
  public void onResize() {
    getSplitLayoutPanel().onResize();
  }

  @Override
  public void setAnimationEnabled(boolean enable) {
    this.isAnimationEnabled = enable;
  }

  /**
   * Set the default width of new columns.
   * 
   * @param width the default width in pixels
   * @see #getDefaultColumnWidth()
   */
  public void setDefaultColumnWidth(int width) {
    this.defaultWidth = width;
  }

  /**
   * Set the minimum width of columns.
   * 
   * @param minWidth the minimum width in pixels
   * @see #getMinimumColumnWidth()
   */
  public void setMinimumColumnWidth(int minWidth) {
    this.minWidth = minWidth;
  }

  /**
   * Create a pager to control the list view.
   * 
   * @param <C> the item type in the list view
   * @param display the list view to add paging too
   * @return the pager
   */
  protected <C> Widget createPager(HasData<C> display) {
    if (pagerFactory == null) {
      return null;
    }
    AbstractPager pager = pagerFactory.create(display);
    pager.setDisplay(display);
    return pager;
  }

  /**
   * Adjust the size of the scroll lock element based on the new position of the
   * scroll bar.
   */
  private void adjustScrollLock() {
    int scrollLeft = Math.abs(getElement().getScrollLeft());
    if (scrollLeft > 0) {
      int clientWidth = getElement().getClientWidth();
      scrollLock.getStyle().setWidth(scrollLeft + clientWidth, Unit.PX);
    } else {
      scrollLock.getStyle().setWidth(1.0, Unit.PX);
    }
  }

  /**
   * Create a new {@link TreeNodeImpl} and append it to the end of the
   * LayoutPanel.
   * 
   * @param <C> the data type of the children
   * @param nodeInfo the info about the node
   * @param value the value of the open node
   */
  private <C> TreeNode appendTreeNode(final NodeInfo<C> nodeInfo, Object value) {
    // Create the list view.
    final int level = treeNodes.size();
    final BrowserCellList<C> view = createDisplay(nodeInfo, level);

    // Create a pager and wrap the components in a scrollable container. Set the
    // tabIndex to -1 so the user can tab between lists without going through
    // the scrollable.
    ScrollPanel scrollable = new ScrollPanel();
    scrollable.getElement().setTabIndex(-1);
    final Widget pager = createPager(view);
    if (pager != null) {
      FlowPanel flowPanel = new FlowPanel();
      flowPanel.add(view);
      flowPanel.add(pager);
      scrollable.setWidget(flowPanel);
    } else {
      scrollable.setWidget(view);
    }
    scrollable.setStyleName(style.cellBrowserColumn());
    if (level == 0) {
      scrollable.addStyleName(style.cellBrowserFirstColumn());
    }

    // Create a TreeNode.
    TreeNodeImpl<C> treeNode = new TreeNodeImpl<C>(nodeInfo, value, view, scrollable);
    treeNodes.add(treeNode);

    /*
     * Attach the view to the selection model and node info. Nullify the default
     * selection manager because it is provided by the node info.
     */
    view.setSelectionModel(nodeInfo.getSelectionModel(), null);
    nodeInfo.setDataDisplay(view);

    // Add the view to the LayoutPanel.
    SplitLayoutPanel splitPanel = getSplitLayoutPanel();
    splitPanel.insertLineStart(scrollable, defaultWidth, null);
    splitPanel.setWidgetMinSize(scrollable, minWidth);
    splitPanel.forceLayout();

    // Scroll to the right.
    animation.scrollToEnd();
    return treeNode;
  }

  /**
   * Create a {@link HasData} that will display items. The {@link HasData} must
   * extend {@link Widget}.
   * 
   * @param <C> the item type in the list view
   * @param nodeInfo the node info with child data
   * @param level the level of the list
   * @return the {@link HasData}
   */
  private <C> BrowserCellList<C> createDisplay(NodeInfo<C> nodeInfo, int level) {
    BrowserCellList<C> display =
        new BrowserCellList<C>(nodeInfo.getCell(), level, nodeInfo.getProvidesKey());
    if (loadingIndicator != null) {
      display.setLoadingIndicator(loadingIndicator);
    }
    if (pageSize != null) {
      display.setPageSize(pageSize);
    }
    display.setValueUpdater(nodeInfo.getValueUpdater());

    /*
     * A CellBrowser has a single keyboard selection policy and multiple lists,
     * so we're not using the selection policy in each list. Leave them on all
     * the time because we use keyboard selection to keep track of which item is
     * open (selected) at each level.
     */
    display.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
    return display;
  }

  /**
   * Get the HTML representation of an image.
   * 
   * @param res the {@link ImageResource} to render as HTML
   * @return the rendered HTML
   */
  private SafeHtml getImageHtml(ImageResource res) {
    // Right-justify image if LTR, left-justify if RTL
    AbstractImagePrototype proto = AbstractImagePrototype.create(res);
    SafeHtml image = proto.getSafeHtml();

    SafeStylesBuilder cssBuilder = new SafeStylesBuilder();
    if (LocaleInfo.getCurrentLocale().isRTL()) {
      cssBuilder.appendTrustedString("left:0px;");
    } else {
      cssBuilder.appendTrustedString("right:0px;");
    }
    cssBuilder.appendTrustedString("width: " + res.getWidth() + "px;");
    cssBuilder.appendTrustedString("height: " + res.getHeight() + "px;");
    return template.imageWrapper(cssBuilder.toSafeStyles(), image);
  }

  /**
   * Get the {@link SplitLayoutPanel} used to lay out the views.
   * 
   * @return the {@link SplitLayoutPanel}
   */
  private SplitLayoutPanel getSplitLayoutPanel() {
    return (SplitLayoutPanel) getWidget();
  }

  /**
   * Reduce the number of {@link HasData}s down to the specified level.
   * 
   * @param level the level to trim to
   */
  private void trimToLevel(int level) {
    // Add a placeholder to maintain the same scroll width.
    adjustScrollLock();

    // Remove the views that are no longer needed.
    int curLevel = treeNodes.size() - 1;
    while (curLevel > level) {
      TreeNodeImpl<?> removed = treeNodes.remove(curLevel);
      removed.destroy();
      curLevel--;
    }

    // Nullify the focused key at the level.
    if (level < treeNodes.size()) {
      TreeNodeImpl<?> node = treeNodes.get(level);
      node.display.focusedKey = null;
      node.display.isFocusedOpen = false;
    }
  }

  /**
   * Update the state of a child node based on the keyboard selection of the
   * specified {@link BrowserCellList}. This method will open/close child
   * {@link TreeNode}s as needed.
   * 
   * @param cellList the CellList that changed state.
   * @param fireEvents true to fireEvents
   * @return the open {@link TreeNode}, or null if not opened
   */
  private <C> TreeNode updateChildState(BrowserCellList<C> cellList, boolean fireEvents) {
    /*
     * Verify that the specified list is still in the browser. It possible for
     * the list to receive deferred updates after it has been removed
     */
    if (cellList.isDestroyed) {
      return null;
    }

    // Get the key of the value to open.
    C newValue = cellList.getPresenter().getKeyboardSelectedRowValue();
    Object newKey = cellList.getValueKey(newValue);

    // Close the current open node.
    TreeNode closedNode = null;
    if (cellList.focusedKey != null && cellList.isFocusedOpen
        && !cellList.focusedKey.equals(newKey)) {
      // Get the node to close.
      closedNode =
          (treeNodes.size() > cellList.level + 1) ? treeNodes.get(cellList.level + 1) : null;

      // Close the node.
      trimToLevel(cellList.level);
    }

    // Open the new node.
    TreeNode openNode = null;
    boolean justOpenedNode = false;
    if (newKey != null) {
      if (newKey.equals(cellList.focusedKey)) {
        // The node is already open.
        openNode = cellList.isFocusedOpen ? treeNodes.get(cellList.level + 1) : null;
      } else {
        // Select this value.
        if (KeyboardSelectionPolicy.BOUND_TO_SELECTION == getKeyboardSelectionPolicy()) {
          cellList.setSelectedValue(newValue);
        }

        // Add the child node if this node has children.
        cellList.focusedKey = newKey;
        NodeInfo<?> childNodeInfo = isLeaf(newValue) ? null : getNodeInfo(newValue);
        if (childNodeInfo != null) {
          cellList.isFocusedOpen = true;
          justOpenedNode = true;
          openNode = appendTreeNode(childNodeInfo, newValue);
        }
      }
    }

    /*
     * Fire event. We fire events after updating the view in case user event
     * handlers modify the open state of nodes, which would interrupt the
     * process.
     */
    if (fireEvents) {
      if (closedNode != null) {
        CloseEvent.fire(this, closedNode);
      }
      if (openNode != null && justOpenedNode) {
        OpenEvent.fire(this, openNode);
      }
    }

    // Return the open node if it is still open.
    return (openNode == null || openNode.isDestroyed()) ? null : openNode;
  }
}
