/* VariableHeightLayoutCache.java --
   Copyright (C) 2002, 2004, 2006,  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package javax.swing.tree;

import gnu.javax.swing.tree.GnuPath;

import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.Set;
import java.util.Vector;

import javax.swing.event.TreeModelEvent;

/**
 * The fixed height tree layout. This class requires the NodeDimensions to be
 * set and ignores the row height property.
 *
 * @specnote the methods, of this class, returning TreePath, actually returns
 * the derived class GnuPath that provides additional information for optimized
 * painting. See the GnuPath code for details.
 *
 * @author Audrius Meskauskas
 */
public class VariableHeightLayoutCache
  extends AbstractLayoutCache
{

  private static final Rectangle RECT_CACHE = new Rectangle();

  /**
   * The cached node record.
   */
  class NodeRecord
  {
    NodeRecord(int aRow, int aDepth, Object aNode, Object aParent)
    {
      row = aRow;
      depth = aDepth;
      parent = aParent;
      node = aNode;
      isExpanded = expanded.contains(aNode);
      bounds = new Rectangle(0, -1, 0, 0);
    }

    /**
     * The row, where the tree node is displayed.
     */
    final int row;

    /**
     * The nesting depth
     */
    final int depth;

    /**
     * The parent of the given node, null for the root node.
     */
    final Object parent;

    /**
     * This node.
     */
    final Object node;

    /**
     * True for the expanded nodes. The value is calculated in constructor.
     * Using this field saves one hashtable access operation.
     */
    final boolean isExpanded;

    /**
     * The cached bounds of the tree row.
     */
    Rectangle bounds;

    /**
     * The path from the tree top to the given node (computed under first
     * demand)
     */
    private TreePath path;

    /**
     * Get the path for this node. The derived class is returned, making check
     * for the last child of some parent easier.
     */
    TreePath getPath()
    {
      if (path == null)
        {
          boolean lastChild = false;
          if (parent != null)
            {
              int nc = treeModel.getChildCount(parent);
              if (nc > 0)
                {
                  int n = treeModel.getIndexOfChild(parent, node);
                  if (n == nc - 1)
                    lastChild = true;
                }
            }

          LinkedList<Object> lpath = new LinkedList<Object>();
          NodeRecord rp = this;
          while (rp != null)
            {
              lpath.addFirst(rp.node);
              if (rp.parent != null)
                {
                  Object parent = rp.parent;
                  rp = nodes.get(parent);
                  // Add the root node, even if it is not visible.
                  if (rp == null)
                    lpath.addFirst(parent);
                }
              else
                rp = null;
            }
          path = new GnuPath(lpath.toArray(), lastChild);
        }
      return path;
    }

    /**
     * Get the rectangle bounds (compute, if required).
     */
    Rectangle getBounds()
    {
      return bounds;
    }
  }

  /**
   * The set of all expanded tree nodes.
   */
  Set<Object> expanded = new HashSet<Object>();

  /**
   * Maps nodes to the row numbers.
   */
  Hashtable<Object,NodeRecord> nodes = new Hashtable<Object,NodeRecord>();

  /**
   * Maps row numbers to nodes.
   */
  ArrayList<Object> row2node = new ArrayList<Object>();

  /**
   * If true, the row map must be recomputed before using.
   */
  boolean dirty;

  /**
   * The cumulative height of all rows.
   */
  int totalHeight;

  /**
   * The maximal width.
   */
  int maximalWidth;

  /**
   * Creates the unitialised instance. Before using the class, the row height
   * must be set with the {@link #setRowHeight(int)} and the model must be set
   * with {@link #setModel(TreeModel)}. The node dimensions may not be set.
   */
  public VariableHeightLayoutCache()
  {
    // Nothing to do here.
  }

  /**
   * Get the total number of rows in the tree. Every displayed node occupies the
   * single row. The root node row is included if the root node is set as
   * visible (false by default).
   *
   * @return int the number of the displayed rows.
   */
  public int getRowCount()
  {
    if (dirty) update();
    return row2node.size();
  }

  /**
   * Refresh the row map.
   */
  private final void update()
  {
    nodes.clear();
    row2node.clear();

    totalHeight = maximalWidth = 0;

    if (treeModel == null)
      return;

    Object root = treeModel.getRoot();
    countRows(root, null, 0, 0);
    dirty = false;
  }

  /**
   * Recursively counts all rows in the tree.
   */
  private final int countRows(Object node, Object parent, int depth, int y)
  {
    boolean visible = node != treeModel.getRoot() || rootVisible;
    int row = row2node.size();
    if (visible)
      {
        row2node.add(node);
      }
    NodeRecord nr = new NodeRecord(row, depth, node, parent);
    NodeDimensions d = getNodeDimensions();
    Rectangle r = RECT_CACHE;
    if (d != null)
      r = d.getNodeDimensions(node, row, depth, nr.isExpanded, r);
    else
      r.setBounds(0, 0, 0, 0);

    if (! visible)
      r.y = -1;
    else
      r.y = Math.max(0, y);

    if (isFixedRowHeight())
      r.height = getRowHeight();

    nr.bounds.setBounds(r);
    nodes.put(node, nr);

    if (visible)
      y += r.height;

    int sc = treeModel.getChildCount(node);
    int deeper = depth + 1;
    if (expanded.contains(node))
      {
        for (int i = 0; i < sc; i++)
          {
            Object child = treeModel.getChild(node, i);
            y = countRows(child, node, deeper, y);
          }
      }
    return y;
  }

  /**
   * Discard the bound information for the given path.
   *
   * @param path the path, for that the bound information must be recomputed.
   */
  public void invalidatePathBounds(TreePath path)
  {
    NodeRecord r = nodes.get(path.getLastPathComponent());
    if (r != null)
      r.bounds = null;
  }

  /**
   * Mark all cached information as invalid.
   */
  public void invalidateSizes()
  {
    dirty = true;
  }

  /**
   * Set the expanded state of the given path. The expansion states must be
   * always updated when expanding and colapsing the tree nodes. Otherwise
   * other methods will not work correctly after the nodes are collapsed or
   * expanded.
   *
   * @param path the tree path, for that the state is being set.
   * @param isExpanded the expanded state of the given path.
   */
  public void setExpandedState(TreePath path, boolean isExpanded)
  {
    if (isExpanded)
      {
        int length = path.getPathCount();
        for (int i = 0; i < length; i++)
          expanded.add(path.getPathComponent(i));
      }
    else
      expanded.remove(path.getLastPathComponent());

    dirty = true;
  }

  /**
   * Get the expanded state for the given tree path.
   *
   * @return true if the given path is expanded, false otherwise.
   */
  public boolean isExpanded(TreePath path)
  {
    return expanded.contains(path.getLastPathComponent());
  }

  /**
   * Get bounds for the given tree path.
   *
   * @param path the tree path
   * @param rect the rectangle that will be reused to return the result.
   * @return Rectangle the bounds of the last line, defined by the given path.
   */
  public Rectangle getBounds(TreePath path, Rectangle rect)
  {
    if (path == null)
      return null;
    if (dirty)
      update();

    Object last = path.getLastPathComponent();
    Rectangle result = null;
    NodeRecord r = nodes.get(last);
    if (r != null)
      {
        // The RI allows null arguments for rect, in which case a new Rectangle
        // is created.
        result = rect;
        if (result == null)
          result = new Rectangle(r.bounds);
        else
          result.setBounds(r.bounds);
      }
    return result;
  }

  /**
   * Get the path, the last element of that is displayed in the given row.
   *
   * @param row the row
   * @return TreePath the path
   */
  public TreePath getPathForRow(int row)
  {
    if (dirty)
      update();

    TreePath path = null;
    // Search row in the nodes map. TODO: This is inefficient, optimize this.
    Enumeration<NodeRecord> nodesEnum = nodes.elements();
    while (nodesEnum.hasMoreElements() && path == null)
      {
        NodeRecord record = nodesEnum.nextElement();
        if (record.row == row)
          path = record.getPath();
      }
    return path;
  }

  /**
   * Get the row, displaying the last node of the given path.
   *
   * @param path the path
   * @return int the row number or -1 if the end of the path is not visible.
   */
  public int getRowForPath(TreePath path)
  {
    if (path == null)
      return -1;

    if (dirty)
      update();

    NodeRecord r = nodes.get(path.getLastPathComponent());
    if (r == null)
      return - 1;
    else
      return r.row;
  }

  /**
   * Get the path, closest to the given point.
   *
   * @param x the point x coordinate
   * @param y the point y coordinate
   * @return the tree path, closest to the the given point
   */
  public TreePath getPathClosestTo(int x, int y)
  {
    if (dirty)
      update();

    // As the rows have arbitrary height, we need to iterate.
    NodeRecord best = null;
    NodeRecord r;
    Enumeration<NodeRecord> en = nodes.elements();

    int dist = Integer.MAX_VALUE;

    while (en.hasMoreElements() && dist > 0)
      {
        r = en.nextElement();
        if (best == null)
          {
            best = r;
            dist = distance(r.getBounds(), x, y);
          }
        else
          {
            int rr = distance(r.getBounds(), x, y);
            if (rr < dist)
              {
                best = r;
                dist = rr;
              }
          }
      }

    if (best == null)
      return null;
    else
      return best.getPath();
  }

  /**
   * Get the closest distance from this point till the given rectangle. Only
   * vertical distance is taken into consideration.
   */
  int distance(Rectangle r, int x, int y)
  {
    if (y < r.y)
      return r.y - y;
    else if (y > r.y + r.height - 1)
      return y - (r.y + r.height - 1);
    else
      return 0;
  }

  /**
   * Get the number of the visible childs for the given tree path. If the node
   * is not expanded, 0 is returned. Otherwise, the number of children is
   * obtained from the model as the number of children for the last path
   * component.
   *
   * @param path the tree path
   * @return int the number of the visible childs (for row).
   */
  public int getVisibleChildCount(TreePath path)
  {
    if (! isExpanded(path) || treeModel == null)
      return 0;
    else
      return treeModel.getChildCount(path.getLastPathComponent());
  }

  /**
   * Get the enumeration over all visible paths that start from the given
   * parent path.
   *
   * @param parentPath the parent path
   * @return the enumeration over pathes
   */
  public Enumeration<TreePath> getVisiblePathsFrom(TreePath parentPath)
  {
    if (dirty)
      update();
    Vector<TreePath> p = new Vector<TreePath>(parentPath.getPathCount());
    Object node;
    NodeRecord nr;

    for (int i = 0; i < parentPath.getPathCount(); i++)
      {
        node = parentPath.getPathComponent(i);
        nr = nodes.get(node);
        if (nr != null && nr.row >= 0)
          p.add((TreePath) node);
      }
    return p.elements();
  }

  /**
   * Return the expansion state of the given tree path. The expansion state
   * must be previously set with the
   * {@link #setExpandedState(TreePath, boolean)}
   *
   * @param path the path being checked
   * @return true if the last node of the path is expanded, false otherwise.
   */
  public boolean getExpandedState(TreePath path)
  {
    return expanded.contains(path.getLastPathComponent());
  }

  /**
   * The listener method, called when the tree nodes are changed.
   *
   * @param event the change event
   */
  public void treeNodesChanged(TreeModelEvent event)
  {
    dirty = true;
  }

  /**
   * The listener method, called when the tree nodes are inserted.
   *
   * @param event the change event
   */
  public void treeNodesInserted(TreeModelEvent event)
  {
    dirty = true;
  }

  /**
   * The listener method, called when the tree nodes are removed.
   *
   * @param event the change event
   */
  public void treeNodesRemoved(TreeModelEvent event)
  {
    dirty = true;
  }

  /**
   * Called when the tree structure has been changed.
   *
   * @param event the change event
   */
  public void treeStructureChanged(TreeModelEvent event)
  {
    dirty = true;
  }

  /**
   * Set the tree model that will provide the data.
   */
  public void setModel(TreeModel newModel)
  {
    treeModel = newModel;
    dirty = true;
    if (treeModel != null)
      {
        // The root node is expanded by default.
        expanded.add(treeModel.getRoot());
      }
  }

  /**
   * Inform the instance if the tree root node is visible. If this method
   * is not called, it is assumed that the tree root node is not visible.
   *
   * @param visible true if the tree root node is visible, false
   * otherwise.
   */
  public void setRootVisible(boolean visible)
  {
    rootVisible = visible;
    dirty = true;
  }

  /**
   * Get the sum of heights for all rows.
   */
  public int getPreferredHeight()
  {
    if (dirty)
      update();
    int height = 0;
    int rowCount = getRowCount();
    if (rowCount > 0)
      {
        NodeRecord last = nodes.get(row2node.get(rowCount - 1));
        height = last.bounds.y + last.bounds.height;
      }
    return height;
  }

  /**
   * Get the maximal width.
   */
  public int getPreferredWidth(Rectangle value)
  {
    if (dirty)
      update();

    maximalWidth = 0;
    Enumeration<NodeRecord> en = nodes.elements();
    while (en.hasMoreElements())
      {
        NodeRecord nr = en.nextElement();
        if (nr != null)
          {
            Rectangle r = nr.getBounds();
            int width = r.x + r.width;
            if (width > maximalWidth)
              maximalWidth = width;
          }
      }
    return maximalWidth;
  }

  /**
   * Sets the node dimensions and invalidates the cached layout.
   *
   * @param dim the dimensions to set
   */
  public void setNodeDimensions(NodeDimensions dim)
  {
    super.setNodeDimensions(dim);
    dirty = true;
  }

  /**
   * Sets the row height and marks the layout as invalid.
   *
   * @param height the row height to set
   */
  public void setRowHeight(int height)
  {
    super.setRowHeight(height);
    dirty = true;
  }
}
