/* BasicListUI.java --
   Copyright (C) 2002, 2004, 2005, 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.plaf.basic;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.CellRendererPane;
import javax.swing.DefaultListSelectionModel;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.ListSelectionModel;
import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.TransferHandler;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.MouseInputListener;
import javax.swing.plaf.ActionMapUIResource;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.ListUI;
import javax.swing.plaf.UIResource;

/**
 * The Basic Look and Feel UI delegate for the 
 * JList.
 */
public class BasicListUI extends ListUI
{

  /**
   * A helper class which listens for {@link FocusEvent}s
   * from the JList.
   */
  public class FocusHandler implements FocusListener
  {
    /**
     * Called when the JList acquires focus.
     *
     * @param e The FocusEvent representing focus acquisition
     */
    public void focusGained(FocusEvent e)
    {
      repaintCellFocus();
    }

    /**
     * Called when the JList loses focus.
     *
     * @param e The FocusEvent representing focus loss
     */
    public void focusLost(FocusEvent e)
    {
      repaintCellFocus();
    }

    /**
     * Helper method to repaint the focused cell's 
     * lost or acquired focus state.
     */
    protected void repaintCellFocus()
    {
      // TODO: Implement this properly.
    }
  }

  /**
   * A helper class which listens for {@link ListDataEvent}s generated by
   * the {@link JList}'s {@link ListModel}.
   *
   * @see javax.swing.JList#getModel()
   */
  public class ListDataHandler implements ListDataListener
  {
    /**
     * Called when a general change has happened in the model which cannot
     * be represented in terms of a simple addition or deletion.
     *
     * @param e The event representing the change
     */
    public void contentsChanged(ListDataEvent e)
    {
      updateLayoutStateNeeded |= modelChanged;
      list.revalidate();
    }

    /**
     * Called when an interval of objects has been added to the model.
     *
     * @param e The event representing the addition
     */
    public void intervalAdded(ListDataEvent e)
    {
      updateLayoutStateNeeded |= modelChanged;
      list.revalidate();
    }

    /**
     * Called when an inteval of objects has been removed from the model.
     *
     * @param e The event representing the removal
     */
    public void intervalRemoved(ListDataEvent e)
    {
      updateLayoutStateNeeded |= modelChanged;
      list.revalidate();
    }
  }

  /**
   * A helper class which listens for {@link ListSelectionEvent}s
   * from the {@link JList}'s {@link ListSelectionModel}.
   */
  public class ListSelectionHandler implements ListSelectionListener
  {
    /**
     * Called when the list selection changes.  
     *
     * @param e The event representing the change
     */
    public void valueChanged(ListSelectionEvent e)
    {
      int index1 = e.getFirstIndex();
      int index2 = e.getLastIndex();
      Rectangle damaged = getCellBounds(list, index1, index2);
      if (damaged != null)
        list.repaint(damaged);
    }
  }

  /**
   * This class is used to mimmic the behaviour of the JDK when registering
   * keyboard actions.  It is the same as the private class used in JComponent
   * for the same reason.  This class receives an action event and dispatches
   * it to the true receiver after altering the actionCommand property of the
   * event.
   */
  private static class ActionListenerProxy
    extends AbstractAction
  {
    ActionListener target;
    String bindingCommandName;

    public ActionListenerProxy(ActionListener li, 
                               String cmd)
    {
      target = li;
      bindingCommandName = cmd;
    }

    public void actionPerformed(ActionEvent e)
    {
      ActionEvent derivedEvent = new ActionEvent(e.getSource(),
                                                 e.getID(),
                                                 bindingCommandName,
                                                 e.getModifiers());
      target.actionPerformed(derivedEvent);
    }
  }

  /**
   * Implements the action for the JList's keyboard commands.
   */
  private class ListAction
    extends AbstractAction
  {
    // TODO: Maybe make a couple of classes out of this bulk Action.
    // Form logical groups of Actions when doing this.

    /**
     * Creates a new ListAction for the specified command.
     *
     * @param cmd the actionCommand to set
     */
    ListAction(String cmd)
    {
      putValue(ACTION_COMMAND_KEY, cmd);
    }

    public void actionPerformed(ActionEvent e)
    {
      int lead = list.getLeadSelectionIndex();
      int max = list.getModel().getSize() - 1;
      DefaultListSelectionModel selModel 
          = (DefaultListSelectionModel) list.getSelectionModel();
      String command = e.getActionCommand();
      // Do nothing if list is empty
      if (max == -1)
        return;
      
      if (command.equals("selectNextRow"))
        {
          selectNextIndex();
        }
      else if (command.equals("selectPreviousRow"))
        {
          selectPreviousIndex();
        }
      else if (command.equals("clearSelection"))
        {
          list.clearSelection();
        }
      else if (command.equals("selectAll"))
        {
          list.setSelectionInterval(0, max);
          // this next line is to restore the lead selection index to the old
          // position, because select-all should not change the lead index
          list.addSelectionInterval(lead, lead);
        }
      else if (command.equals("selectLastRow"))
        {
          list.setSelectedIndex(list.getModel().getSize() - 1); 
        }
      else if (command.equals("selectLastRowChangeLead"))
        {
          selModel.moveLeadSelectionIndex(list.getModel().getSize() - 1);
        }
      else if (command.equals("scrollDownExtendSelection"))
        {
          int target;
          if (lead == list.getLastVisibleIndex())
            {
              target = Math.min(max, lead + (list.getLastVisibleIndex() 
                  - list.getFirstVisibleIndex() + 1));
            }
          else
            target = list.getLastVisibleIndex();
          selModel.setLeadSelectionIndex(target);
        }
      else if (command.equals("scrollDownChangeLead"))
        {
          int target;
          if (lead == list.getLastVisibleIndex())
            {
              target = Math.min(max, lead + (list.getLastVisibleIndex() 
                  - list.getFirstVisibleIndex() + 1));
            }
          else
            target = list.getLastVisibleIndex();
          selModel.moveLeadSelectionIndex(target);
        }
      else if (command.equals("scrollUpExtendSelection"))
        {
          int target;
          if (lead == list.getFirstVisibleIndex())
            {
              target = Math.max(0, lead - (list.getLastVisibleIndex() 
                  - list.getFirstVisibleIndex() + 1));
            }
          else
            target = list.getFirstVisibleIndex();
          selModel.setLeadSelectionIndex(target);
        }
      else if (command.equals("scrollUpChangeLead"))
        {
          int target;
          if (lead == list.getFirstVisibleIndex())
            {
              target = Math.max(0, lead - (list.getLastVisibleIndex() 
                  - list.getFirstVisibleIndex() + 1));
            }
          else
            target = list.getFirstVisibleIndex();
          selModel.moveLeadSelectionIndex(target);
        }
      else if (command.equals("selectNextRowExtendSelection"))
        {
          selModel.setLeadSelectionIndex(Math.min(lead + 1, max));
        }
      else if (command.equals("selectFirstRow"))
        {
          list.setSelectedIndex(0);
        }
      else if (command.equals("selectFirstRowChangeLead"))
        {
          selModel.moveLeadSelectionIndex(0);
        }
      else if (command.equals("selectFirstRowExtendSelection"))
        {
          selModel.setLeadSelectionIndex(0);
        }
      else if (command.equals("selectPreviousRowExtendSelection"))
        {
          selModel.setLeadSelectionIndex(Math.max(0, lead - 1));
        }
      else if (command.equals("scrollUp"))
        {
          int target;
          if (lead == list.getFirstVisibleIndex())
            {
              target = Math.max(0, lead - (list.getLastVisibleIndex() 
                  - list.getFirstVisibleIndex() + 1));
            }
          else
            target = list.getFirstVisibleIndex();
          list.setSelectedIndex(target);          
        }
      else if (command.equals("selectLastRowExtendSelection"))
        {
          selModel.setLeadSelectionIndex(list.getModel().getSize() - 1);
        }
      else if (command.equals("scrollDown"))
        {
          int target;
          if (lead == list.getLastVisibleIndex())
            {
              target = Math.min(max, lead + (list.getLastVisibleIndex() 
                  - list.getFirstVisibleIndex() + 1));
            }
          else
            target = list.getLastVisibleIndex();
          list.setSelectedIndex(target);
        }
      else if (command.equals("selectNextRowChangeLead"))
          {
            if (selModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)
              selectNextIndex();
            else
              {
                selModel.moveLeadSelectionIndex(Math.min(max, lead + 1));
              }
          }
      else if (command.equals("selectPreviousRowChangeLead"))
        {
          if (selModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION)
            selectPreviousIndex();
          else
            {
              selModel.moveLeadSelectionIndex(Math.max(0, lead - 1));
            }
        }      
      else if (command.equals("addToSelection"))
        {
          list.addSelectionInterval(lead, lead);
        }
      else if (command.equals("extendTo"))
        {
          selModel.setSelectionInterval(selModel.getAnchorSelectionIndex(),
                                        lead);
        }
      else if (command.equals("toggleAndAnchor"))
        {
          if (!list.isSelectedIndex(lead))
            list.addSelectionInterval(lead, lead);
          else
            list.removeSelectionInterval(lead, lead);
          selModel.setAnchorSelectionIndex(lead);
        }
      else 
        {
          // DEBUG: uncomment the following line to print out 
          // key bindings that aren't implemented yet
          
          // System.out.println ("not implemented: "+e.getActionCommand());
        }
      
      list.ensureIndexIsVisible(list.getLeadSelectionIndex());
    }
  }

  /**
   * A helper class which listens for {@link MouseEvent}s 
   * from the {@link JList}.
   */
  public class MouseInputHandler implements MouseInputListener
  {
    /**
     * Called when a mouse button press/release cycle completes
     * on the {@link JList}
     *
     * @param event The event representing the mouse click
     */
    public void mouseClicked(MouseEvent event)
    {
      Point click = event.getPoint();
      int index = locationToIndex(list, click);
      if (index == -1)
        return;
      if (event.isShiftDown())
        {
          if (list.getSelectionMode() == ListSelectionModel.SINGLE_SELECTION)
            list.setSelectedIndex(index);
          else if (list.getSelectionMode() == 
                   ListSelectionModel.SINGLE_INTERVAL_SELECTION)
            // COMPAT: the IBM VM is compatible with the following line of code.
            // However, compliance with Sun's VM would correspond to replacing 
            // getAnchorSelectionIndex() with getLeadSelectionIndex().This is 
            // both unnatural and contradictory to the way they handle other 
            // similar UI interactions.
            list.setSelectionInterval(list.getAnchorSelectionIndex(), index);
          else
            // COMPAT: both Sun and IBM are compatible instead with:
            // list.setSelectionInterval
            //     (list.getLeadSelectionIndex(),index);
            // Note that for IBM this is contradictory to what they did in 
            // the above situation for SINGLE_INTERVAL_SELECTION.  
            // The most natural thing to do is the following:
            if (list.isSelectedIndex(list.getAnchorSelectionIndex()))
              list.getSelectionModel().setLeadSelectionIndex(index);
            else
              list.addSelectionInterval(list.getAnchorSelectionIndex(), index);
        }
      else if (event.isControlDown())
        {
          if (list.getSelectionMode() == ListSelectionModel.SINGLE_SELECTION)
            list.setSelectedIndex(index);
          else if (list.isSelectedIndex(index))
            list.removeSelectionInterval(index, index);
          else
            list.addSelectionInterval(index, index);
        }
      else
        list.setSelectedIndex(index);
      
      list.ensureIndexIsVisible(list.getLeadSelectionIndex());
    }

    /**
     * Called when a mouse button is pressed down on the
     * {@link JList}.
     *
     * @param event The event representing the mouse press
     */
    public void mousePressed(MouseEvent event)
    {
      // We need to explicitly request focus.
      list.requestFocusInWindow();
    }

    /**
     * Called when a mouse button is released on
     * the {@link JList}
     *
     * @param event The event representing the mouse press
     */
    public void mouseReleased(MouseEvent event)
    {
      // TODO: What should be done here, if anything?
    }

    /**
     * Called when the mouse pointer enters the area bounded
     * by the {@link JList}
     *
     * @param event The event representing the mouse entry
     */
    public void mouseEntered(MouseEvent event)
    {
      // TODO: What should be done here, if anything?
    }

    /**
     * Called when the mouse pointer leaves the area bounded
     * by the {@link JList}
     *
     * @param event The event representing the mouse exit
     */
    public void mouseExited(MouseEvent event)
    {
      // TODO: What should be done here, if anything?
    }

    /**
     * Called when the mouse pointer moves over the area bounded
     * by the {@link JList} while a button is held down.
     *
     * @param event The event representing the mouse drag
     */
    public void mouseDragged(MouseEvent event)
    {
      Point click = event.getPoint();
      int index = locationToIndex(list, click);
      if (index == -1)
        return;
      if (!event.isShiftDown() && !event.isControlDown())
        list.setSelectedIndex(index);
      
      list.ensureIndexIsVisible(list.getLeadSelectionIndex());
    }

    /**
     * Called when the mouse pointer moves over the area bounded
     * by the {@link JList}.
     *
     * @param event The event representing the mouse move
     */
    public void mouseMoved(MouseEvent event)
    {
      // TODO: What should be done here, if anything?
    }
  }

  /**
   * Helper class which listens to {@link PropertyChangeEvent}s
   * from the {@link JList}.
   */
  public class PropertyChangeHandler implements PropertyChangeListener
  {
    /**
     * Called when the {@link JList} changes one of its bound properties.
     *
     * @param e The event representing the property change
     */
    public void propertyChange(PropertyChangeEvent e)
    {
      if (e.getPropertyName().equals("model"))
        {
          if (e.getOldValue() != null && e.getOldValue() instanceof ListModel)
            {
              ListModel oldModel = (ListModel) e.getOldValue();
              oldModel.removeListDataListener(listDataListener);
            }
          if (e.getNewValue() != null && e.getNewValue() instanceof ListModel)
            {
              ListModel newModel = (ListModel) e.getNewValue();
              newModel.addListDataListener(BasicListUI.this.listDataListener);
            }

          updateLayoutStateNeeded |= modelChanged;
        }
      else if (e.getPropertyName().equals("selectionModel"))
        updateLayoutStateNeeded |= selectionModelChanged;
      else if (e.getPropertyName().equals("font"))
        updateLayoutStateNeeded |= fontChanged;
      else if (e.getPropertyName().equals("fixedCellWidth"))
        updateLayoutStateNeeded |= fixedCellWidthChanged;
      else if (e.getPropertyName().equals("fixedCellHeight"))
        updateLayoutStateNeeded |= fixedCellHeightChanged;
      else if (e.getPropertyName().equals("prototypeCellValue"))
        updateLayoutStateNeeded |= prototypeCellValueChanged;
      else if (e.getPropertyName().equals("cellRenderer"))
        updateLayoutStateNeeded |= cellRendererChanged;
    }
  }

  /**
   * A constant to indicate that the model has changed.
   */
  protected static final int modelChanged = 1;

  /**
   * A constant to indicate that the selection model has changed.
   */
  protected static final int selectionModelChanged = 2;

  /**
   * A constant to indicate that the font has changed.
   */
  protected static final int fontChanged = 4;

  /**
   * A constant to indicate that the fixedCellWidth has changed.
   */
  protected static final int fixedCellWidthChanged = 8;

  /**
   * A constant to indicate that the fixedCellHeight has changed.
   */
  protected static final int fixedCellHeightChanged = 16;

  /**
   * A constant to indicate that the prototypeCellValue has changed.
   */
  protected static final int prototypeCellValueChanged = 32;

  /**
   * A constant to indicate that the cellRenderer has changed.
   */
  protected static final int cellRendererChanged = 64;

  /**
   * Creates a new BasicListUI for the component.
   *
   * @param c The component to create a UI for
   *
   * @return A new UI
   */
  public static ComponentUI createUI(final JComponent c)
  {
    return new BasicListUI();
  }

  /** The current focus listener. */
  protected FocusListener focusListener;

  /** The data listener listening to the model. */
  protected ListDataListener listDataListener;

  /** The selection listener listening to the selection model. */
  protected ListSelectionListener listSelectionListener;

  /** The mouse listener listening to the list. */
  protected MouseInputListener mouseInputListener;

  /** The property change listener listening to the list. */
  protected PropertyChangeListener propertyChangeListener;

  /** Saved reference to the list this UI was created for. */
  protected JList list;

  /**
   * The height of a single cell in the list. This field is used when the
   * fixedCellHeight property of the list is set. Otherwise this field is
   * set to <code>-1</code> and {@link #cellHeights} is used instead.
   */
  protected int cellHeight;

  /** The width of a single cell in the list. */
  protected int cellWidth;

  /** 
   * An array of varying heights of cells in the list, in cases where each
   * cell might have a different height. This field is used when the
   * <code>fixedCellHeight</code> property of the list is not set. Otherwise
   * this field is <code>null</code> and {@link #cellHeight} is used.
   */
  protected int[] cellHeights;

  /**
   * A bitmask that indicates which properties of the JList have changed.
   * When nonzero, indicates that the UI class is out of
   * date with respect to the underlying list, and must recalculate the
   * list layout before painting or performing size calculations.
   *
   * @see #modelChanged
   * @see #selectionModelChanged
   * @see #fontChanged
   * @see #fixedCellWidthChanged
   * @see #fixedCellHeightChanged
   * @see #prototypeCellValueChanged
   * @see #cellRendererChanged
   */
  protected int updateLayoutStateNeeded;

  /**
   * The {@link CellRendererPane} that is used for painting.
   */
  protected CellRendererPane rendererPane;
  
  /** The action bound to KeyStrokes. */
  ListAction action;

  /**
   * Calculate the height of a particular row. If there is a fixed {@link
   * #cellHeight}, return it; otherwise return the specific row height
   * requested from the {@link #cellHeights} array. If the requested row
   * is invalid, return <code>-1</code>.
   *
   * @param row The row to get the height of
   *
   * @return The height, in pixels, of the specified row
   */
  protected int getRowHeight(int row)
  {
    int height;
    if (cellHeights == null)
      height = cellHeight;
    else
      {
        if (row < 0 || row >= cellHeights.length)
          height = -1;
        else
          height = cellHeights[row];
      }
    return height;
  }

  /**
   * Calculate the bounds of a particular cell, considering the upper left
   * corner of the list as the origin position <code>(0,0)</code>.
   *
   * @param l Ignored; calculates over <code>this.list</code>
   * @param index1 The first row to include in the bounds
   * @param index2 The last row to incude in the bounds
   *
   * @return A rectangle encompassing the range of rows between 
   * <code>index1</code> and <code>index2</code> inclusive, or null
   * such a rectangle couldn't be calculated for the given indexes.
   */
  public Rectangle getCellBounds(JList l, int index1, int index2)
  {
    maybeUpdateLayoutState();

    if (l != list || cellWidth == -1)
      return null;

    int minIndex = Math.min(index1, index2);
    int maxIndex = Math.max(index1, index2);
    Point loc = indexToLocation(list, minIndex);

    // When the layoutOrientation is VERTICAL, then the width == the list
    // width. Otherwise the cellWidth field is used.
    int width = cellWidth;
    if (l.getLayoutOrientation() == JList.VERTICAL)
      width = l.getWidth();

    Rectangle bounds = new Rectangle(loc.x, loc.y, width,
                                     getCellHeight(minIndex));
    for (int i = minIndex + 1; i <= maxIndex; i++)
      {
        Point hiLoc = indexToLocation(list, i);
        bounds = SwingUtilities.computeUnion(hiLoc.x, hiLoc.y, width,
                                             getCellHeight(i), bounds);
      }

    return bounds;
  }

  /**
   * Calculates the maximum cell height.
   *
   * @param index the index of the cell
   *
   * @return the maximum cell height
   */
  private int getCellHeight(int index)
  {
    int height = cellHeight;
    if (height <= 0)
      {
        if (list.getLayoutOrientation() == JList.VERTICAL)
          height = getRowHeight(index);
        else
          {
            for (int j = 0; j < cellHeights.length; j++)
              height = Math.max(height, cellHeights[j]);
          }
      }
    return height;
  }

  /**
   * Calculate the Y coordinate of the upper edge of a particular row,
   * considering the Y coordinate <code>0</code> to occur at the top of the
   * list.
   *
   * @param row The row to calculate the Y coordinate of
   *
   * @return The Y coordinate of the specified row, or <code>-1</code> if
   * the specified row number is invalid
   */
  protected int convertRowToY(int row)
  {
    int y = 0;
    for (int i = 0; i < row; ++i)
      {
        int h = getRowHeight(i);
        if (h == -1)
          return -1;
        y += h;
      }
    return y;
  }

  /**
   * Calculate the row number containing a particular Y coordinate,
   * considering the Y coodrinate <code>0</code> to occur at the top of the
   * list.
   *
   * @param y0 The Y coordinate to calculate the row number for
   *
   * @return The row number containing the specified Y value, or <code>-1</code>
   *         if the list model is empty
   *
   * @specnote This method is specified to return -1 for an invalid Y
   *           coordinate. However, some simple tests show that the behaviour
   *           is to return the index of the last list element for an Y
   *           coordinate that lies outside of the list bounds (even for
   *           negative indices). <code>-1</code>
   *           is only returned if the list model is empty.
   */
  protected int convertYToRow(int y0)
  {
    if (list.getModel().getSize() == 0)
      return -1;

    // When y0 < 0, then the JDK returns the maximum row index of the list. So
    // do we.
    if (y0 < 0)
      return list.getModel().getSize() - 1;

    // Update the layout if necessary.
    maybeUpdateLayoutState();

    int index = list.getModel().getSize() - 1;

    // If a fixed cell height is set, then we can work more efficient.
    if (cellHeight > 0)
      index = Math.min(y0 / cellHeight, index);
    // If we have no fixed cell height, we must add up each cell height up
    // to y0.
    else
      {
        int h = 0;
        for (int row = 0; row < cellHeights.length; ++row)
          {
            h += cellHeights[row];
            if (y0 < h)
              {
                index = row;
                break;
              }
          }
      }
    return index;
  }

  /**
   * Recomputes the {@link #cellHeights}, {@link #cellHeight}, and {@link
   * #cellWidth} properties by examining the variouis properties of the
   * {@link JList}.
   */
  protected void updateLayoutState()
  {
    int nrows = list.getModel().getSize();
    cellHeight = -1;
    cellWidth = -1;
    if (cellHeights == null || cellHeights.length != nrows)
      cellHeights = new int[nrows];
    ListCellRenderer rend = list.getCellRenderer();
    // Update the cellHeight(s) fields.
    int fixedCellHeight = list.getFixedCellHeight();
    if (fixedCellHeight > 0)
      {
        cellHeight = fixedCellHeight;
        cellHeights = null;
      }
    else
      {
        cellHeight = -1;
        for (int i = 0; i < nrows; ++i)
          {
            Component flyweight =
              rend.getListCellRendererComponent(list,
                      list.getModel().getElementAt(i),
                      i, list.isSelectedIndex(i),
                      list.getSelectionModel().getAnchorSelectionIndex() == i);
            Dimension dim = flyweight.getPreferredSize();
            cellHeights[i] = dim.height;
          }
      }

    // Update the cellWidth field.
    int fixedCellWidth = list.getFixedCellWidth();
    if (fixedCellWidth > 0)
      cellWidth = fixedCellWidth;
    else
      {
        for (int i = 0; i < nrows; ++i)
          {
            Component flyweight =
              rend.getListCellRendererComponent(list,
                                                list.getModel().getElementAt(i),
                                                i, list.isSelectedIndex(i),
                                                list.getSelectionModel().getAnchorSelectionIndex() == i);
            Dimension dim = flyweight.getPreferredSize();
            cellWidth = Math.max(cellWidth, dim.width);
          }
      }
  }

  /**
   * Calls {@link #updateLayoutState} if {@link #updateLayoutStateNeeded}
   * is nonzero, then resets {@link #updateLayoutStateNeeded} to zero.
   */
  protected void maybeUpdateLayoutState()
  {
    if (updateLayoutStateNeeded != 0)
      {
        updateLayoutState();
        updateLayoutStateNeeded = 0;
      }
  }

  /**
   * Creates a new BasicListUI object.
   */
  public BasicListUI()
  {
    updateLayoutStateNeeded = 1;
    rendererPane = new CellRendererPane();
  }

  /**
   * Installs various default settings (mostly colors) from the {@link
   * UIDefaults} into the {@link JList}
   *
   * @see #uninstallDefaults
   */
  protected void installDefaults()
  {
    LookAndFeel.installColorsAndFont(list, "List.background",
                                     "List.foreground", "List.font");
    list.setSelectionForeground(UIManager.getColor("List.selectionForeground"));
    list.setSelectionBackground(UIManager.getColor("List.selectionBackground"));
    list.setOpaque(true);
  }

  /**
   * Resets to <code>null</code> those defaults which were installed in 
   * {@link #installDefaults}
   */
  protected void uninstallDefaults()
  {
    list.setForeground(null);
    list.setBackground(null);
    list.setSelectionForeground(null);
    list.setSelectionBackground(null);
  }

  /**
   * Attaches all the listeners we have in the UI class to the {@link
   * JList}, its model and its selection model.
   *
   * @see #uninstallListeners
   */
  protected void installListeners()
  {
    if (focusListener == null)
      focusListener = createFocusListener();
    list.addFocusListener(focusListener);
    if (listDataListener == null)
      listDataListener = createListDataListener();
    list.getModel().addListDataListener(listDataListener);
    if (listSelectionListener == null)
      listSelectionListener = createListSelectionListener();
    list.addListSelectionListener(listSelectionListener);
    if (mouseInputListener == null)
      mouseInputListener = createMouseInputListener();
    list.addMouseListener(mouseInputListener);
    list.addMouseMotionListener(mouseInputListener);
    if (propertyChangeListener == null)
      propertyChangeListener = createPropertyChangeListener();
    list.addPropertyChangeListener(propertyChangeListener);
  }

  /**
   * Detaches all the listeners we attached in {@link #installListeners}.
   */
  protected void uninstallListeners()
  {
    list.removeFocusListener(focusListener);
    list.getModel().removeListDataListener(listDataListener);
    list.removeListSelectionListener(listSelectionListener);
    list.removeMouseListener(mouseInputListener);
    list.removeMouseMotionListener(mouseInputListener);
    list.removePropertyChangeListener(propertyChangeListener);
  }
  
  /**
   * Installs keyboard actions for this UI in the {@link JList}.
   */
  protected void installKeyboardActions()
  {
    // Install UI InputMap.
    InputMap focusInputMap = (InputMap) UIManager.get("List.focusInputMap");
    SwingUtilities.replaceUIInputMap(list, JComponent.WHEN_FOCUSED,
                                     focusInputMap);

    // Install UI ActionMap.
    ActionMap am = (ActionMap) UIManager.get("List.actionMap");
    if (am == null)
      {
        // Create the actionMap once and store it in the current UIDefaults
        // for use in other components.
        am = new ActionMapUIResource();
        ListAction action;
        action = new ListAction("selectPreviousRow");
        am.put("selectPreviousRow", action);
        action = new ListAction("selectNextRow");
        am.put("selectNextRow", action);
        action = new ListAction("selectPreviousRowExtendSelection");
        am.put("selectPreviousRowExtendSelection", action);
        action = new ListAction("selectNextRowExtendSelection");
        am.put("selectNextRowExtendSelection", action);

        action = new ListAction("selectPreviousColumn");
        am.put("selectPreviousColumn", action);
        action = new ListAction("selectNextColumn");
        am.put("selectNextColumn", action);
        action = new ListAction("selectPreviousColumnExtendSelection");
        am.put("selectPreviousColumnExtendSelection", action);
        action = new ListAction("selectNextColumnExtendSelection");
        am.put("selectNextColumnExtendSelection", action);

        action = new ListAction("selectFirstRow");
        am.put("selectFirstRow", action);
        action = new ListAction("selectLastRow");
        am.put("selectLastRow", action);
        action = new ListAction("selectFirstRowExtendSelection");
        am.put("selectFirstRowExtendSelection", action);
        action = new ListAction("selectLastRowExtendSelection");
        am.put("selectLastRowExtendSelection", action);

        action = new ListAction("scrollUp");
        am.put("scrollUp", action);
        action = new ListAction("scrollUpExtendSelection");
        am.put("scrollUpExtendSelection", action);
        action = new ListAction("scrollDown");
        am.put("scrollDown", action);
        action = new ListAction("scrollDownExtendSelection");
        am.put("scrollDownExtendSelection", action);

        action = new ListAction("selectAll");
        am.put("selectAll", action);
        action = new ListAction("clearSelection");
        am.put("clearSelection", action);

        am.put("copy", TransferHandler.getCopyAction());
        am.put("cut", TransferHandler.getCutAction());
        am.put("paste", TransferHandler.getPasteAction());

        UIManager.put("List.actionMap", am);
      }

    SwingUtilities.replaceUIActionMap(list, am);
  }

  /**
   * Uninstalls keyboard actions for this UI in the {@link JList}.
   */
  protected void uninstallKeyboardActions()
  {
    // Uninstall the InputMap.
    InputMap im = SwingUtilities.getUIInputMap(list, JComponent.WHEN_FOCUSED);
    if (im instanceof UIResource)
      SwingUtilities.replaceUIInputMap(list, JComponent.WHEN_FOCUSED, null);

    // Uninstall the ActionMap.
    if (SwingUtilities.getUIActionMap(list) instanceof UIResource)
      SwingUtilities.replaceUIActionMap(list, null);
  }

  /**
   * Installs the various aspects of the UI in the {@link JList}. In
   * particular, calls {@link #installDefaults}, {@link #installListeners}
   * and {@link #installKeyboardActions}. Also saves a reference to the
   * provided component, cast to a {@link JList}.
   *
   * @param c The {@link JList} to install the UI into
   */
  public void installUI(final JComponent c)
  {
    super.installUI(c);
    list = (JList) c;
    installDefaults();
    installListeners();
    installKeyboardActions();
    maybeUpdateLayoutState();
  }

  /**
   * Uninstalls all the aspects of the UI which were installed in {@link
   * #installUI}. When finished uninstalling, drops the saved reference to
   * the {@link JList}.
   *
   * @param c Ignored; the UI is uninstalled from the {@link JList}
   * reference saved during the call to {@link #installUI}
   */
  public void uninstallUI(final JComponent c)
  {
    uninstallKeyboardActions();
    uninstallListeners();
    uninstallDefaults();
    list = null;
  }

  /**
   * Gets the size this list would prefer to assume. This is calculated by
   * calling {@link #getCellBounds} over the entire list.
   *
   * @param c Ignored; uses the saved {@link JList} reference 
   *
   * @return DOCUMENT ME!
   */
  public Dimension getPreferredSize(JComponent c)
  {
    maybeUpdateLayoutState();
    int size = list.getModel().getSize();
    int visibleRows = list.getVisibleRowCount();
    int layoutOrientation = list.getLayoutOrientation();

    int h;
    int w;
    int maxCellHeight = cellHeight;
    if (maxCellHeight <= 0)
      {
        for (int i = 0; i < cellHeights.length; i++)
          maxCellHeight = Math.max(maxCellHeight, cellHeights[i]);
      }
    if (layoutOrientation == JList.HORIZONTAL_WRAP)
      {
        if (visibleRows > 0)
          {
            // We cast to double here to force double divisions.
            double modelSize = size;
            int neededColumns = (int) Math.ceil(modelSize / visibleRows); 
            int adjustedRows = (int) Math.ceil(modelSize / neededColumns);
            h = maxCellHeight * adjustedRows;
            w = cellWidth * neededColumns;
          }
        else
          {
            int neededColumns = Math.min(1, list.getWidth() / cellWidth);
            h = size / neededColumns * maxCellHeight;
            w = neededColumns * cellWidth;
          }
      }
    else if (layoutOrientation == JList.VERTICAL_WRAP)
      {
        if (visibleRows > 0)
          h = visibleRows * maxCellHeight;
        else
          h = Math.max(list.getHeight(), maxCellHeight);
        int neededColumns = h / maxCellHeight;
        w = cellWidth * neededColumns;
      }
    else
      {
        if (list.getFixedCellWidth() > 0)
          w = list.getFixedCellWidth();
        else
          w = cellWidth;
        if (list.getFixedCellHeight() > 0)
          // FIXME: We need to add some cellVerticalMargins here, according
          // to the specs.
          h = list.getFixedCellHeight() * size;
        else
          h = maxCellHeight * size;
      }
    Insets insets = list.getInsets();
    Dimension retVal = new Dimension(w + insets.left + insets.right,
                                     h + insets.top + insets.bottom);
    return retVal;
  }

  /**
   * Paints a single cell in the list.
   *
   * @param g The graphics context to paint in
   * @param row The row number to paint
   * @param bounds The bounds of the cell to paint, assuming a coordinate
   * system beginning at <code>(0,0)</code> in the upper left corner of the
   * list
   * @param rend A cell renderer to paint with
   * @param data The data to provide to the cell renderer
   * @param sel A selection model to provide to the cell renderer
   * @param lead The lead selection index of the list
   */
  protected void paintCell(Graphics g, int row, Rectangle bounds,
                 ListCellRenderer rend, ListModel data,
                 ListSelectionModel sel, int lead)
  {
    boolean isSel = list.isSelectedIndex(row);
    boolean hasFocus = (list.getLeadSelectionIndex() == row) && BasicListUI.this.list.hasFocus();
    Component comp = rend.getListCellRendererComponent(list,
                                                       data.getElementAt(row),
                                                       row, isSel, hasFocus);
    rendererPane.paintComponent(g, comp, list, bounds);
  }

  /**
   * Paints the list by repeatedly calling {@link #paintCell} for each visible
   * cell in the list.
   *
   * @param g The graphics context to paint with
   * @param c Ignored; uses the saved {@link JList} reference 
   */
  public void paint(Graphics g, JComponent c)
  {
    int nrows = list.getModel().getSize();
    if (nrows == 0)
      return;

    maybeUpdateLayoutState();
    ListCellRenderer render = list.getCellRenderer();
    ListModel model = list.getModel();
    ListSelectionModel sel = list.getSelectionModel();
    int lead = sel.getLeadSelectionIndex();
    Rectangle clip = g.getClipBounds();

    int startIndex = locationToIndex(list, new Point(clip.x, clip.y));
    int endIndex = locationToIndex(list, new Point(clip.x + clip.width,
                                             clip.y + clip.height));
    
    for (int row = startIndex; row <= endIndex; ++row)
      {
        Rectangle bounds = getCellBounds(list, row, row);
        if (bounds != null && bounds.intersects(clip))
          paintCell(g, row, bounds, render, model, sel, lead);
      }
  }

  /**
   * Computes the index of a list cell given a point within the list. If the
   * location lies outside the bounds of the list, the greatest index in the
   * list model is returned.
   *
   * @param l the list which on which the computation is based on
   * @param location the coordinates
   *
   * @return the index of the list item that is located at the given
   *         coordinates or <code>-1</code> if the list model is empty
   */
  public int locationToIndex(JList l, Point location)
  {
    int layoutOrientation = list.getLayoutOrientation();
    int index = -1;
    switch (layoutOrientation)
      {
      case JList.VERTICAL:
        index = convertYToRow(location.y);
        break;
      case JList.HORIZONTAL_WRAP:
        // determine visible rows and cells per row
        int maxCellHeight = getCellHeight(0);
        int visibleRows = list.getHeight() / maxCellHeight;
        int cellsPerRow = -1;
        int numberOfItems = list.getModel().getSize();
        cellsPerRow = numberOfItems / visibleRows + 1;

        // determine index for the given location
        int cellsPerColumn = numberOfItems / cellsPerRow + 1;
        int gridX = Math.min(location.x / cellWidth, cellsPerRow - 1);
        int gridY = Math.min(location.y / maxCellHeight, cellsPerColumn);
        index = gridX + gridY * cellsPerRow;
        break;
      case JList.VERTICAL_WRAP:
        // determine visible rows and cells per column
        int maxCellHeight2 = getCellHeight(0);
        int visibleRows2 = list.getHeight() / maxCellHeight2;
        int numberOfItems2 = list.getModel().getSize();
        int cellsPerRow2 = numberOfItems2 / visibleRows2 + 1;

        int gridX2 = Math.min(location.x / cellWidth, cellsPerRow2 - 1);
        int gridY2 = Math.min(location.y / maxCellHeight2, visibleRows2);
        index = gridY2 + gridX2 * visibleRows2;
        break;
      }
    return index;
  }

  public Point indexToLocation(JList l, int index)
  {
    int layoutOrientation = list.getLayoutOrientation();
    Point loc = null;
    switch (layoutOrientation)
      {
      case JList.VERTICAL:
        loc = new Point(0, convertRowToY(index));
        break;
      case JList.HORIZONTAL_WRAP:
        // determine visible rows and cells per row
        int maxCellHeight = getCellHeight(0);
        int visibleRows = list.getHeight() / maxCellHeight;
        int numberOfCellsPerRow = -1;
        int numberOfItems = list.getModel().getSize();
        numberOfCellsPerRow = numberOfItems / visibleRows + 1;

        // compute coordinates inside the grid
        int gridX = index % numberOfCellsPerRow;
        int gridY = index / numberOfCellsPerRow;
        int locX = gridX * cellWidth;
        int locY;
        locY = gridY * maxCellHeight;
        loc = new Point(locX, locY);
        break;
      case JList.VERTICAL_WRAP:
        // determine visible rows and cells per column
        int maxCellHeight2 = getCellHeight(0);
        int visibleRows2 = list.getHeight() / maxCellHeight2;
        // compute coordinates inside the grid
        if (visibleRows2 > 0)
          {
            int gridY2 = index % visibleRows2;
            int gridX2 = index / visibleRows2;
            int locX2 = gridX2 * cellWidth;
            int locY2 = gridY2 * maxCellHeight2;
            loc = new Point(locX2, locY2);
          }
        else
          loc = new Point(0, convertRowToY(index));
        break;
      }
    return loc;
  }

  /**
   * Creates and returns the focus listener for this UI.
   *
   * @return the focus listener for this UI
   */
  protected FocusListener createFocusListener()
  {
    return new FocusHandler();
  }

  /**
   * Creates and returns the list data listener for this UI.
   *
   * @return the list data listener for this UI
   */
  protected ListDataListener createListDataListener()
  {
    return new ListDataHandler();
  }

  /**
   * Creates and returns the list selection listener for this UI.
   *
   * @return the list selection listener for this UI
   */
  protected ListSelectionListener createListSelectionListener()
  {
    return new ListSelectionHandler();
  }

  /**
   * Creates and returns the mouse input listener for this UI.
   *
   * @return the mouse input listener for this UI
   */
  protected MouseInputListener createMouseInputListener()
  {
    return new MouseInputHandler();
  }

  /**
   * Creates and returns the property change listener for this UI.
   *
   * @return the property change listener for this UI
   */
  protected PropertyChangeListener createPropertyChangeListener()
  {
    return new PropertyChangeHandler();
  }

  /**
   * Selects the next list item and force it to be visible.
   */
  protected void selectNextIndex()
  {
    int index = list.getSelectionModel().getLeadSelectionIndex();
    if (index < list.getModel().getSize() - 1)
      {
        index++;
        list.setSelectedIndex(index);
      }
    list.ensureIndexIsVisible(index);
  }

  /**
   * Selects the previous list item and force it to be visible.
   */
  protected void selectPreviousIndex()
  {
    int index = list.getSelectionModel().getLeadSelectionIndex();
    if (index > 0)
      {
        index--;
        list.setSelectedIndex(index);
      }
    list.ensureIndexIsVisible(index);
  }
}
