/* JList.java --
   Copyright (C) 2002, 2003, 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;

import java.awt.Color;
import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Locale;
import java.util.Vector;

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleComponent;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleSelection;
import javax.accessibility.AccessibleState;
import javax.accessibility.AccessibleStateSet;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.plaf.ListUI;
import javax.swing.text.Position;

/**
 * <p>This class is a facade over three separate objects: {@link
 * javax.swing.ListModel}, {@link javax.swing.ListSelectionModel} and
 * {@link javax.swing.plaf.ListUI}. The facade represents a unified "list"
 * concept, with independently replacable (possibly client-provided) models
 * for its contents and its current selection. In addition, each element in
 * the list is rendered via a strategy class {@link
 * javax.swing.ListCellRenderer}.</p>
 *
 * <p>Lists have many properties, some of which are stored in this class
 * while others are delegated to the list's model or selection. The
 * following properties are available:</p>
 *
 * <table>
 * <tr><th>Property                       </th><th>Stored in</th><th>Bound?</th></tr>
 * <tr><td>accessibleContext              </td><td>list     </td><td>no    </td></tr>
 * <tr><td>anchorSelectionIndex           </td><td>selection</td><td>no    </td></tr>
 * <tr><td>cellRenderer                   </td><td>list     </td><td>yes   </td></tr>
 * <tr><td>dragEnabled                    </td><td>list     </td><td>no    </td></tr>
 * <tr><td>firstVisibleIndex              </td><td>list     </td><td>no    </td></tr>
 * <tr><td>fixedCellHeight                </td><td>list     </td><td>yes   </td></tr>
 * <tr><td>fixedCellWidth                 </td><td>list     </td><td>yes   </td></tr>
 * <tr><td>lastVisibleIndex               </td><td>list     </td><td>no    </td></tr>
 * <tr><td>layoutOrientation              </td><td>list     </td><td>yes   </td></tr>
 * <tr><td>leadSelectionIndex             </td><td>selection</td><td>no    </td></tr>
 * <tr><td>maxSelectionIndex              </td><td>selection</td><td>no    </td></tr>
 * <tr><td>minSelectionIndex              </td><td>selection</td><td>no    </td></tr>
 * <tr><td>model                          </td><td>list     </td><td>yes   </td></tr>
 * <tr><td>opaque                         </td><td>list     </td><td>no    </td></tr>
 * <tr><td>preferredScrollableViewportSize</td><td>list     </td><td>no    </td></tr>
 * <tr><td>prototypeCellValue             </td><td>list     </td><td>yes   </td></tr>
 * <tr><td>scrollableTracksViewportHeight </td><td>list     </td><td>no    </td></tr>
 * <tr><td>scrollableTracksViewportWidth  </td><td>list     </td><td>no    </td></tr>
 * <tr><td>selectedIndex                  </td><td>selection</td><td>no    </td></tr>
 * <tr><td>selectedIndices                </td><td>selection</td><td>no    </td></tr>
 * <tr><td>selectedValue                  </td><td>model    </td><td>no    </td></tr>
 * <tr><td>selectedValues                 </td><td>model    </td><td>no    </td></tr>
 * <tr><td>selectionBackground            </td><td>list     </td><td>yes   </td></tr>
 * <tr><td>selectionEmpty                 </td><td>selection</td><td>no    </td></tr>
 * <tr><td>selectionForeground            </td><td>list     </td><td>yes   </td></tr>
 * <tr><td>selectionMode                  </td><td>selection</td><td>no    </td></tr>
 * <tr><td>selectionModel                 </td><td>list     </td><td>yes   </td></tr>
 * <tr><td>UI                             </td><td>list     </td><td>yes   </td></tr>
 * <tr><td>UIClassID                      </td><td>list     </td><td>no    </td></tr>
 * <tr><td>valueIsAdjusting               </td><td>list     </td><td>no    </td></tr>
 * <tr><td>visibleRowCount                </td><td>list     </td><td>no    </td></tr>
 * </table> 
 *
 * @author Graydon Hoare (graydon@redhat.com)
 */

public class JList extends JComponent implements Accessible, Scrollable
{

  /**
   * Provides accessibility support for <code>JList</code>.
   */
  protected class AccessibleJList extends AccessibleJComponent
    implements AccessibleSelection, PropertyChangeListener,
               ListSelectionListener, ListDataListener
  {

    /**
     * Provides accessibility support for list elements in <code>JList</code>s.
     */
    protected class AccessibleJListChild extends AccessibleContext
      implements Accessible, AccessibleComponent
    {

      /**
       * The parent list.
       */
      JList parent;

      /**
       * The index in the list for that child.
       */
      int listIndex;

      /**
       * The cursor for this list child.
       */
      // TODO: Testcases show that this class somehow stores state about the
      // cursor. I cannot make up though how that could affect
      // the actual list.
      Cursor cursor = Cursor.getDefaultCursor();

      /**
       * Creates a new instance of <code>AccessibleJListChild</code>.
       *
       * @param list the list of which this is an accessible child
       * @param index the list index for this child
       */
      public AccessibleJListChild(JList list, int index)
      {
        parent = list;
        listIndex = index;
      }

      /**
       * Returns the accessible context of this object. Returns
       * <code>this</code> since <code>AccessibleJListChild</code>s are their
       * own accessible contexts.
       *
       * @return the accessible context of this object, <code>this</code>
       */
      public AccessibleContext getAccessibleContext()
      {
        return this;
      }

      /**
       * Returns the background color for this list child. This returns the
       * background of the <code>JList</code> itself since the background
       * cannot be set on list children individually
       *
       * @return the background color for this list child
       */
      public Color getBackground()
      {
        return parent.getBackground();
      }

      /**
       * Calling this method has no effect, since the background color cannot be
       * set on list children individually.
       *
       * @param color not used here.
       */
      public void setBackground(Color color)
      {
        // Calling this method has no effect, since the background color cannot
        // be set on list children individually.
      }

      /**
       * Returns the foreground color for this list child. This returns the
       * background of the <code>JList</code> itself since the foreground
       * cannot be set on list children individually.
       *
       * @return the background color for this list child
       */
      public Color getForeground()
      {
        return parent.getForeground();
      }

      /**
       * Calling this method has no effect, since the foreground color cannot be
       * set on list children individually.
       *
       * @param color not used here.
       */
      public void setForeground(Color color)
      {
        // Calling this method has no effect, since the foreground color cannot
        // be set on list children individually.
      }

      /**
       * Returns the cursor for this list child.
       *
       * @return the cursor for this list child
       */
      public Cursor getCursor()
      {
        // TODO: Testcases show that this method returns the cursor that has
        // been set by setCursor. I cannot make up though how that could affect
        // the actual list.
        return cursor;
      }

      /**
       * Sets the cursor for this list child.
       */
      public void setCursor(Cursor cursor)
      {
        this.cursor = cursor;
        // TODO: Testcases show that this method returns the cursor that has
        // been set by setCursor. I cannot make up though how that could affect
        // the actual list.
      }

      /**
       * Returns the font of the <code>JList</code> since it is not possible to
       * set fonts for list children individually.
       *
       * @return the font of the <code>JList</code>
       */
      public Font getFont()
      {
        return parent.getFont();
      }

      /**
       * Does nothing since it is not possible to set the font on list children
       * individually.
       *
       * @param font not used here
       */
      public void setFont(Font font)
      {
        // Does nothing since it is not possible to set the font on list
        // children individually.
      }

      /**
       * Returns the font metrics for the specified font. This method forwards
       * to the parent <code>JList</code>. 
       *
       * @param font the font for which the font metrics is queried
       *
       * @return the font metrics for the specified font
       */
      public FontMetrics getFontMetrics(Font font)
      {
        return parent.getFontMetrics(font);
      }

      /**
       * Returns <code>true</code> if the parent <code>JList</code> is enabled,
       * <code>false</code> otherwise. The list children cannot have an enabled
       * flag set individually.
       *
       * @return <code>true</code> if the parent <code>JList</code> is enabled,
       *         <code>false</code> otherwise
       */
      public boolean isEnabled()
      {
        return parent.isEnabled();
      }

      /**
       * Does nothing since the enabled flag cannot be set for list children
       * individually.
       *
       * @param b not used here
       */
      public void setEnabled(boolean b)
      {
        // Does nothing since the enabled flag cannot be set for list children
        // individually.
      }

      /**
       * Returns <code>true</code> if this list child is visible,
       * <code>false</code> otherwise. The value of this property depends
       * on {@link JList#getFirstVisibleIndex()} and
       * {@link JList#getLastVisibleIndex()}.
       *
       * @return <code>true</code> if this list child is visible,
       *         <code>false</code> otherwise
       */
      public boolean isVisible()
      {
        return listIndex >= parent.getFirstVisibleIndex()
               && listIndex <= parent.getLastVisibleIndex();
      }

      /**
       * The value of the visible property cannot be modified, so this method
       * does nothing.
       *
       * @param b not used here
       */
      public void setVisible(boolean b)
      {
        // The value of the visible property cannot be modified, so this method
        // does nothing.
      }

      /**
       * Returns <code>true</code> if this list child is currently showing on
       * screen and <code>false</code> otherwise. The list child is showing if
       * it is visible and if it's parent JList is currently showing.
       *
       * @return <code>true</code> if this list child is currently showing on
       *         screen and <code>false</code> otherwise
       */
      public boolean isShowing()
      {
        return isVisible() && parent.isShowing();
      }

      /**
       * Returns <code>true</code> if this list child covers the screen location
       * <code>point</code> (relative to the <code>JList</code> coordinate
       * system, <code>false</code> otherwise.
       *
       * @return <code>true</code> if this list child covers the screen location
       *         <code>point</code> , <code>false</code> otherwise
       */
      public boolean contains(Point point)
      {
        return getBounds().contains(point);
      }

      /**
       * Returns the absolute screen location of this list child.
       *
       * @return the absolute screen location of this list child
       */
      public Point getLocationOnScreen()
      {
        Point loc = getLocation();
        SwingUtilities.convertPointToScreen(loc, parent);
        return loc;
      }

      /**
       * Returns the screen location of this list child relative to it's parent.
       *
       * @return the location of this list child relative to it's parent
       *
       * @see JList#indexToLocation(int)
       */
      public Point getLocation()
      {
        return parent.indexToLocation(listIndex);
      }

      /**
       * Does nothing since the screen location cannot be set on list children
       * explictitly.
       *
       * @param point not used here
       */
      public void setLocation(Point point)
      {
        // Does nothing since the screen location cannot be set on list children
        // explictitly.
      }

      /**
       * Returns the bounds of this list child.
       *
       * @return the bounds of this list child
       *
       * @see JList#getCellBounds(int, int)
       */
      public Rectangle getBounds()
      {
        return parent.getCellBounds(listIndex, listIndex);
      }

      /**
       * Does nothing since the bounds cannot be set on list children
       * individually.
       *
       * @param rectangle not used here
       */
      public void setBounds(Rectangle rectangle)
      {
        // Does nothing since the bounds cannot be set on list children
        // individually.
      }

      /**
       * Returns the size of this list child.
       *
       * @return the size of this list child
       */
      public Dimension getSize()
      {
        Rectangle b = getBounds();
        return b.getSize();
      }

      /**
       * Does nothing since the size cannot be set on list children
       * individually.
       *
       * @param dimension not used here
       */
      public void setSize(Dimension dimension)
      {
        // Does nothing since the size cannot be set on list children
        // individually.
      }

      /**
       * Returns <code>null</code> because list children do not have children
       * themselves
       *
       * @return <code>null</code>
       */
      public Accessible getAccessibleAt(Point point)
      {
        return null;
      }

      /**
       * Returns <code>true</code> since list children are focus traversable.
       *
       * @return true
       */
      public boolean isFocusTraversable()
      {
        // TODO: Is this 100% ok?
        return true;
      }

      /**
       * Requests focus on the parent list. List children cannot request focus
       * individually.
       */
      public void requestFocus()
      {
        // TODO: Is this 100% ok?
        parent.requestFocus();
      }

      /**
       * Adds a focus listener to the parent list. List children do not have
       * their own focus management.
       *
       * @param listener the focus listener to add
       */
      public void addFocusListener(FocusListener listener)
      {
        // TODO: Is this 100% ok?
        parent.addFocusListener(listener);
      }

      /**
       * Removes a focus listener from the parent list. List children do not
       * have their own focus management.
       *
       * @param listener the focus listener to remove
       */
      public void removeFocusListener(FocusListener listener)
      {
        // TODO: Is this 100%
        parent.removeFocusListener(listener);
      }

      /**
       * Returns the accessible role of this list item, which is
       * {@link AccessibleRole#LABEL}.
       *
       * @return {@link AccessibleRole#LABEL}
       */
      public AccessibleRole getAccessibleRole()
      {
        return AccessibleRole.LABEL;
      }

      /**
       * Returns the accessible state set of this list item.
       *
       * @return the accessible state set of this list item
       */
      public AccessibleStateSet getAccessibleStateSet()
      {
        AccessibleStateSet states = new AccessibleStateSet();
        if (isVisible())
          states.add(AccessibleState.VISIBLE);
        if (isShowing())
          states.add(AccessibleState.SHOWING);
        if (isFocusTraversable())
          states.add(AccessibleState.FOCUSABLE);
        // TODO: How should the active state be handled? The API docs
        // suggest that this state is set on the activated list child,
        // that is the one that is drawn with a box. However, I don't know how
        // to implement this.

        // TODO: We set the selectable state here because list children are
        // selectable. Is there a way to disable single children?
        if (parent.isEnabled())
          states.add(AccessibleState.SELECTABLE);
 
        if (parent.isSelectedIndex(listIndex))
          states.add(AccessibleState.SELECTED);

        // TODO: Handle more states here?
        return states;
      }

      /**
       * Returns the index of this list child within it's parent list.
       *
       * @return the index of this list child within it's parent list
       */
      public int getAccessibleIndexInParent()
      {
        return listIndex;
      }

      /**
       * Returns <code>0</code> since list children don't have children
       * themselves.
       *
       * @return <code>0</code>
       */
      public int getAccessibleChildrenCount()
      {
        return 0;
      }

      /**
       * Returns <code>null</code> since list children don't have children
       * themselves.
       *
       * @return <code>null</code>
       */
      public Accessible getAccessibleChild(int i)
      {
        return null;
      }

      /**
       * Returns the locale of this component. This call is forwarded to the
       * parent list since list children don't have a separate locale setting.
       *
       * @return the locale of this component
       */
      public Locale getLocale()
      {
        return parent.getLocale();
      }

      /**
       * This method does
       * nothing, list children are transient accessible objects which means
       * that they don't fire property change events.
       *
       * @param l not used here
       */
      public void addPropertyChangeListener(PropertyChangeListener l)
      {
        // Do nothing here.
      }

      /**
       * This method does
       * nothing, list children are transient accessible objects which means
       * that they don't fire property change events.
       *
       * @param l not used here
       */
      public void removePropertyChangeListener(PropertyChangeListener l)
      {
        // Do nothing here.
      }
      
      // TODO: Implement the remaining methods of this class.
    }
    
    /**
     * Create a new AccessibleJList.
     */
    public AccessibleJList()
    {
      // Nothing to do here.
    }

    /**
     * Returns the number of selected accessible children.
     *
     * @return the number of selected accessible children
     */
    public int getAccessibleSelectionCount()
    {
      return getSelectedIndices().length;
    }

    /**
     * Returns the n-th selected accessible child.
     *
     * @param n the index of the selected child to return
     *
     * @return the n-th selected accessible child
     */
    public Accessible getAccessibleSelection(int n)
    {
      return new AccessibleJListChild(JList.this, getSelectedIndices()[n]);
    }

    /**
     * Returns <code>true</code> if the n-th child is selected,
     * <code>false</code> otherwise.
     *
     * @param n the index of the child of which the selected state is queried
     *
     * @return <code>true</code> if the n-th child is selected,
     *         <code>false</code> otherwise
     */
    public boolean isAccessibleChildSelected(int n)
    {
      return isSelectedIndex(n);
    }

    /**
     * Adds the accessible item with the specified index to the selected items.
     * If multiple selections are supported, the item is added to the selection,
     * otherwise the item replaces the current selection.
     *
     * @param i the index of the item to add to the selection
     */
    public void addAccessibleSelection(int i)
    {
      addSelectionInterval(i, i);
    }

    /**
     * Removes the accessible item with the specified index to the selection.
     *
     * @param i the index of the item to be removed from the selection
     */
    public void removeAccessibleSelection(int i)
    {
      removeSelectionInterval(i, i);
    }

    /**
     * Remove all selection items from the selection.
     */
    public void clearAccessibleSelection()
    {
      clearSelection();
    }

    /**
     * Selects all items if multiple selections are supported.
     * Otherwise do nothing.
     */
    public void selectAllAccessibleSelection()
    {
      addSelectionInterval(0, getModel().getSize());
    }

    /**
     * Receices notification when the list selection is changed. This method
     * fires two property change events, the first with
     * {@link AccessibleContext#ACCESSIBLE_VISIBLE_DATA_PROPERTY} and the second
     * with {@link AccessibleContext#ACCESSIBLE_SELECTION_PROPERTY}.
     *
     * @param event the list selection event
     */
    public void valueChanged(ListSelectionEvent event)
    {
      firePropertyChange(ACCESSIBLE_VISIBLE_DATA_PROPERTY, Boolean.FALSE,
                         Boolean.TRUE);
      firePropertyChange(ACCESSIBLE_SELECTION_PROPERTY, Boolean.FALSE,
                         Boolean.TRUE);
    }

    /**
     * Receives notification when items have changed in the
     * <code>JList</code>. This method fires a property change event with
     * {@link AccessibleContext#ACCESSIBLE_VISIBLE_DATA_PROPERTY}.
     *
     * @param event the list data event
     */
    public void contentsChanged(ListDataEvent event)
    {
      firePropertyChange(ACCESSIBLE_VISIBLE_DATA_PROPERTY, Boolean.FALSE,
                         Boolean.TRUE);
    }

    /**
     * Receives notification when items are inserted into the
     * <code>JList</code>. This method fires a property change event with
     * {@link AccessibleContext#ACCESSIBLE_VISIBLE_DATA_PROPERTY}.
     *
     * @param event the list data event
     */
    public void intervalAdded(ListDataEvent event)
    {
      firePropertyChange(ACCESSIBLE_VISIBLE_DATA_PROPERTY, Boolean.FALSE,
                         Boolean.TRUE);
    }

    /**
     * Receives notification when items are removed from the
     * <code>JList</code>. This method fires a property change event with
     * {@link AccessibleContext#ACCESSIBLE_VISIBLE_DATA_PROPERTY}.
     *
     * @param event the list data event
     */
    public void intervalRemoved(ListDataEvent event)
    {
      firePropertyChange(ACCESSIBLE_VISIBLE_DATA_PROPERTY, Boolean.FALSE,
                         Boolean.TRUE);
    }


    /**
     * Receives notification about changes of the <code>JList</code>'s
     * properties. This is used to re-register this object as listener to
     * the data model and selection model when the data model or selection model
     * changes.
     *
     * @param e the property change event
     */
    public void propertyChange(PropertyChangeEvent e)
    {
      String propertyName = e.getPropertyName();
      if (propertyName.equals("model"))
        {
          ListModel oldModel = (ListModel) e.getOldValue();
          oldModel.removeListDataListener(this);
          ListModel newModel = (ListModel) e.getNewValue();
          newModel.addListDataListener(this);
        }
      else if (propertyName.equals("selectionModel"))
        {
          ListSelectionModel oldModel = (ListSelectionModel) e.getOldValue();
          oldModel.removeListSelectionListener(this);
          ListSelectionModel newModel = (ListSelectionModel) e.getNewValue();
          oldModel.addListSelectionListener(this);
        }
    }

    /**
     * Return the state set of the <code>JList</code>.
     *
     * @return the state set of the <code>JList</code>
     */
    public AccessibleStateSet getAccessibleStateSet()
    {
      // TODO: Figure out if there is possibly more state that must be
      // handled here.
      AccessibleStateSet s = super.getAccessibleStateSet();
      if (getSelectionMode() != ListSelectionModel.SINGLE_SELECTION)
        s.add(AccessibleState.MULTISELECTABLE);
      return s;
    }

    /**
     * Returns the accessible role for <code>JList</code>,
     * {@link AccessibleRole#LIST}.
     *
     * @return the accessible role for <code>JList</code>
     */
    public AccessibleRole getAccessibleRole()
    {
      return AccessibleRole.LIST;
    }

    /**
     * Returns the accessible child at the visual location <code>p</code>
     * (relative to the upper left corner of the <code>JList</code>). If there
     * is no child at that location, this returns <code>null</code>.
     *
     * @param p the screen location for which to return the accessible child
     *
     * @return the accessible child at the specified location, or
     *         <code>null</code> if there is no child at that location
     */
    public Accessible getAccessibleAt(Point p)
    {
      int childIndex = locationToIndex(p);
      return getAccessibleChild(childIndex);
    }

    /**
     * Returns the number of accessible children in the <code>JList</code>.
     *
     * @return the number of accessible children in the <code>JList</code>
     */
    public int getAccessibleChildrenCount()
    {
      return getModel().getSize();
    }

    /**
     * Returns the n-th accessible child of this <code>JList</code>. This will
     * be an instance of {@link AccessibleJListChild}. If there is no child
     * at that index, <code>null</code> is returned.
     *
     * @param n the index of the child to return
     *
     * @return the n-th accessible child of this <code>JList</code>
     */
    public Accessible getAccessibleChild(int n)
    {
      if (getModel().getSize() <= n)
        return null;
      return new AccessibleJListChild(JList.this, n);
    }
  }

  private static final long serialVersionUID = 4406629526391098046L;

  /** 
   * Constant value used in "layoutOrientation" property. This value means
   * that cells are laid out in a single vertical column. This is the default. 
   */
  public static final int VERTICAL = 0;

  /** 
   * Constant value used in "layoutOrientation" property. This value means
   * that cells are laid out in multiple columns "newspaper style", filling
   * vertically first, then horizontally. 
   */
  public static final int VERTICAL_WRAP = 1;
  
  /** 
   * Constant value used in "layoutOrientation" property. This value means
   * that cells are laid out in multiple columns "newspaper style",
   * filling horizontally first, then vertically. 
   */
  public static final int HORIZONTAL_WRAP = 2;

  /**
   * This property indicates whether "drag and drop" functions are enabled
   * on the list.
   */
  boolean dragEnabled;

  /** This property provides a strategy for rendering cells in the list. */
  ListCellRenderer cellRenderer;

  /**
   * This property indicates an fixed width to assign to all cells in the
   * list. If its value is <code>-1</code>, no width has been
   * assigned. This value can be set explicitly, or implicitly by setting
   * the {@link #prototypeCellValue} property.
   */
  int fixedCellWidth;
  
  /**
   * This property indicates an fixed height to assign to all cells in the
   * list. If its value is <code>-1</code>, no height has been
   * assigned. This value can be set explicitly, or implicitly by setting
   * the {@link #prototypeCellValue} property.
   */
  int fixedCellHeight;

  /** 
   * This property holds the current layout orientation of the list, which
   * is one of the integer constants {@link #VERTICAL}, {@link
   * #VERTICAL_WRAP}, or {@link #HORIZONTAL_WRAP}. 
   */
  int layoutOrientation;
  
  /** This property holds the data elements displayed by the list. */
  ListModel model;

  /**
   * <p>This property holds a reference to a "prototype" data value --
   * typically a String -- which is used to calculate the {@link
   * #fixedCellWidth} and {@link #fixedCellHeight} properties, using the
   * {@link #cellRenderer} property to acquire a component to render the
   * prototype.</p>
   *
   * <p>It is important that you <em>not</em> set this value to a
   * component. It has to be a <em>data value</em> such as the objects you
   * would find in the list's model. Setting it to a component will have
   * undefined (and undesirable) affects. </p>
   */
  Object prototypeCellValue;

  /** 
   * This property specifies a foreground color for the selected cells in
   * the list. When {@link ListCellRenderer#getListCellRendererComponent}
   * is called with a selected cell object, the component returned will
   * have its "foreground" set to this color.
   */
  Color selectionBackground;

  /** 
   * This property specifies a background color for the selected cells in
   * the list. When {@link ListCellRenderer#getListCellRendererComponent}
   * is called with a selected cell object, the component returned will
   * have its "background" property set to this color.
   */
  Color selectionForeground;

  /** 
   * This property holds a description of which data elements in the {@link
   * #model} property should be considered "selected", when displaying and
   * interacting with the list.
   */
  ListSelectionModel selectionModel;

  /** 
   * This property indicates a <em>preference</em> for the number of rows
   * displayed in the list, and will scale the
   * {@link #getPreferredScrollableViewportSize} property accordingly. The actual
   * number of displayed rows, when the list is placed in a real {@link
   * JViewport} or other component, may be greater or less than this number.
   */
  int visibleRowCount;

  /**
   * Fire a {@link ListSelectionEvent} to all the registered 
   * ListSelectionListeners.
   * 
   * @param firstIndex  the lowest index covering the selection change.
   * @param lastIndex  the highest index covering the selection change.
   * @param isAdjusting  a flag indicating if this event is one in a series
   *     of events updating the selection.
   */
  protected void fireSelectionValueChanged(int firstIndex, int lastIndex, 
                                           boolean isAdjusting) 
  {
    ListSelectionEvent evt = new ListSelectionEvent(this, firstIndex, 
                                                    lastIndex, isAdjusting);
    ListSelectionListener listeners[] = getListSelectionListeners();
    for (int i = 0; i < listeners.length; ++i)
      {
        listeners[i].valueChanged(evt);
      }
  }

  /**
   * This private listener propagates {@link ListSelectionEvent} events
   * from the list's "selectionModel" property to the list's {@link
   * ListSelectionListener} listeners. It also listens to {@link
   * ListDataEvent} events from the list's {@link #model} property. If this
   * class receives either type of event, it triggers repainting of the
   * list.
   */
  private class ListListener 
    implements ListSelectionListener, ListDataListener
  {
    // ListDataListener events
    public void contentsChanged(ListDataEvent event)
    {
      JList.this.revalidate();
      JList.this.repaint();
    }
    public void intervalAdded(ListDataEvent event)
    {
      JList.this.revalidate();
      JList.this.repaint();
    }
    public void intervalRemoved(ListDataEvent event)
    {
      JList.this.revalidate();
      JList.this.repaint();
    }
    // ListSelectionListener events
    public void valueChanged(ListSelectionEvent event)
    {
      JList.this.fireSelectionValueChanged(event.getFirstIndex(),
                                           event.getLastIndex(),
                                           event.getValueIsAdjusting());
      JList.this.repaint();
    }
  }

  /** 
   * Shared ListListener instance, subscribed to both the current {@link
   * #model} and {@link #selectionModel} properties of the list.
   */
  ListListener listListener;


  /**
   * Creates a new <code>JList</code> object.
   */
  public JList()
  {
    init(new DefaultListModel());
  }

  /**
   * Creates a new <code>JList</code> object.
   *
   * @param items  the initial list items.
   */
  public JList(Object[] items)
  {
    init(createListModel(items));
  }

  /**
   * Creates a new <code>JList</code> object.
   *
   * @param items  the initial list items.
   */
  public JList(Vector items)
  {
    init(createListModel(items));
  }

  /**
   * Creates a new <code>JList</code> object.
   *
   * @param model  a model containing the list items (<code>null</code> not
   *     permitted).
   *     
   * @throws IllegalArgumentException if <code>model</code> is 
   *     <code>null</code>.
   */
  public JList(ListModel model)
  {
    init(model);
  }

  /**
   * Initializes the list.
   *
   * @param m  the list model (<code>null</code> not permitted).
   */
  private void init(ListModel m)
  {
    if (m == null)
      throw new IllegalArgumentException("Null model not permitted.");
    dragEnabled = false;
    fixedCellHeight = -1;
    fixedCellWidth = -1;
    layoutOrientation = VERTICAL;
    opaque = true;
    visibleRowCount = 8;

    cellRenderer = new DefaultListCellRenderer();
    listListener = new ListListener();

    model = m;
    if (model != null)
      model.addListDataListener(listListener);

    selectionModel = createSelectionModel();
    if (selectionModel != null)
      {
        selectionModel.addListSelectionListener(listListener);
        selectionModel.setSelectionMode
                              (ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
      }
    setLayout(null);
    
    updateUI();
  }

  /**
   * Creates the default <code>ListSelectionModel</code>.
   *
   * @return the <code>ListSelectionModel</code>
   */
  protected ListSelectionModel createSelectionModel()
  {
    return new DefaultListSelectionModel();
  }
  
  /**
   * Gets the value of the {@link #fixedCellHeight} property. This property
   * may be <code>-1</code> to indicate that no cell height has been
   * set. This property is also set implicitly when the
   * {@link #prototypeCellValue} property is set.
   *
   * @return The current value of the property 
   * 
   * @see #fixedCellHeight
   * @see #setFixedCellHeight
   * @see #setPrototypeCellValue
   */
  public int getFixedCellHeight()
  {
    return fixedCellHeight;
  }

  /**
   * Sets the value of the {@link #fixedCellHeight} property. This property
   * may be <code>-1</code> to indicate that no cell height has been
   * set. This property is also set implicitly when the {@link
   * #prototypeCellValue} property is set, but setting it explicitly
   * overrides the height computed from {@link #prototypeCellValue}.
   *
   * @param h  the height.
   * 
   * @see #getFixedCellHeight
   * @see #getPrototypeCellValue
   */
  public void setFixedCellHeight(int h)
  {
    if (fixedCellHeight == h)
      return;

    int old = fixedCellHeight;
    fixedCellHeight = h;
    firePropertyChange("fixedCellHeight", old, h);
  }


  /**
   * Gets the value of the {@link #fixedCellWidth} property. This property
   * may be <code>-1</code> to indicate that no cell width has been
   * set. This property is also set implicitly when the {@link
   * #prototypeCellValue} property is set.
   *
   * @return The current value of the property 
   * 
   * @see #setFixedCellWidth
   * @see #setPrototypeCellValue
   */
  public int getFixedCellWidth()
  {
    return fixedCellWidth;
  }

  /**
   * Sets the value of the {@link #fixedCellWidth} property. This property
   * may be <code>-1</code> to indicate that no cell width has been
   * set. This property is also set implicitly when the {@link
   * #prototypeCellValue} property is set, but setting it explicitly
   * overrides the width computed from {@link #prototypeCellValue}.
   *
   * @param w  the width.
   * 
   * @see #getFixedCellHeight
   * @see #getPrototypeCellValue
   */
  public void setFixedCellWidth(int w)
  {
    if (fixedCellWidth == w)
      return;
    
    int old = fixedCellWidth;
    fixedCellWidth = w;
    firePropertyChange("fixedCellWidth", old, w);
  }

  /** 
   * Gets the value of the {@link #visibleRowCount} property.  The default 
   * value is 8.
   *
   * @return the current value of the property.
   * 
   * @see #setVisibleRowCount(int)
   */
  public int getVisibleRowCount()
  {
    return visibleRowCount;
  }

  /**
   * Sets the value of the {@link #visibleRowCount} property. 
   *
   * @param vc The new property value
   * 
   * @see #getVisibleRowCount()
   */
  public void setVisibleRowCount(int vc)
  {
    if (visibleRowCount != vc)
      {
        int oldValue = visibleRowCount;
        visibleRowCount = Math.max(vc, 0);
        firePropertyChange("visibleRowCount", oldValue, vc);
        revalidate();
        repaint();
      }
  }

  /**
   * Adds a {@link ListSelectionListener} to the listener list for this
   * list. The listener will be called back with a {@link
   * ListSelectionEvent} any time the list's {@link #selectionModel}
   * property changes. The source of such events will be the JList,
   * not the selection model.
   *
   * @param listener The new listener to add
   */
  public void addListSelectionListener(ListSelectionListener listener)
  {
    listenerList.add (ListSelectionListener.class, listener);
  }

  /**
   * Removes a {@link ListSelectionListener} from the listener list for
   * this list. The listener will no longer be called when the list's
   * {@link #selectionModel} changes.
   *
   * @param listener The listener to remove
   */
  public void removeListSelectionListener(ListSelectionListener listener)
  {
    listenerList.remove(ListSelectionListener.class, listener);
  }

  /**
   * Returns an array of all ListSelectionListeners subscribed to this
   * list. 
   *
   * @return The current subscribed listeners
   *
   * @since 1.4
   */
  public ListSelectionListener[] getListSelectionListeners()
  {
    return (ListSelectionListener[]) getListeners(ListSelectionListener.class);
  }

  /**
   * Returns the selection mode for the list (one of: 
   * {@link ListSelectionModel#SINGLE_SELECTION}, 
   * {@link ListSelectionModel#SINGLE_INTERVAL_SELECTION} and 
   * {@link ListSelectionModel#MULTIPLE_INTERVAL_SELECTION}).
   * 
   * @return The selection mode.
   * 
   * @see #setSelectionMode(int)
   */
  public int getSelectionMode()
  {
    return selectionModel.getSelectionMode();
  }
  
  /**
   * Sets the list's "selectionMode" property, which simply mirrors the
   * same property on the list's {@link #selectionModel} property. This
   * property should be one of the integer constants
   * <code>SINGLE_SELECTION</code>, <code>SINGLE_INTERVAL_SELECTION</code>,
   * or <code>MULTIPLE_INTERVAL_SELECTION</code> from the {@link
   * ListSelectionModel} interface.
   *
   * @param a The new selection mode
   */
  public void setSelectionMode(int a)
  {
    selectionModel.setSelectionMode(a);
  }

  /**
   * Adds the interval <code>[a,a]</code> to the set of selections managed
   * by this list's {@link #selectionModel} property. Depending on the
   * selection mode, this may cause existing selections to become invalid,
   * or may simply expand the set of selections. 
   *
   * @param a A number in the half-open range <code>[0, x)</code> where
   * <code>x = getModel.getSize()</code>, indicating the index of an
   * element in the list to select. When &lt; 0 the selection is cleared.
   *
   * @see #setSelectionMode
   * @see #selectionModel
   */
  public void setSelectedIndex(int a)
  {
    if (a < 0)
      selectionModel.clearSelection();
    else
      selectionModel.setSelectionInterval(a, a);
  }

  /**
   * For each element <code>a[i]</code> of the provided array
   * <code>a</code>, calls {@link #setSelectedIndex} on <code>a[i]</code>.
   *
   * @param a  an array of selected indices (<code>null</code> not permitted).
   * 
   * @throws NullPointerException if <code>a</code> is <code>null</code>.
   * @see #setSelectionMode
   * @see #selectionModel
   */
  public void setSelectedIndices(int [] a)
  {
    for (int i = 0; i < a.length; ++i)
      setSelectedIndex(a[i]);
  }

  /**
   * Returns the minimum index of an element in the list which is currently
   * selected.
   *
   * @return A number in the half-open range <code>[0, x)</code> where
   * <code>x = getModel.getSize()</code>, indicating the minimum index of
   * an element in the list for which the element is selected, or
   * <code>-1</code> if no elements are selected
   */
  public int getSelectedIndex()
  {
    return selectionModel.getMinSelectionIndex();
  }

  /**
   * Returns <code>true</code> if the model's selection is empty, otherwise
   * <code>false</code>. 
   *
   * @return The return value of {@link ListSelectionModel#isSelectionEmpty}
   */
  public boolean isSelectionEmpty()
  {
    return selectionModel.isSelectionEmpty();
  }

  /**
   * Returns the list index of the upper left or upper right corner of the
   * visible rectangle of this list, depending on the {@link
   * Component#getComponentOrientation} property.
   *
   * @return The index of the first visible list cell, or <code>-1</code>
   * if none is visible.
   */
  public int getFirstVisibleIndex()
  {
    ComponentOrientation or = getComponentOrientation();
    Rectangle r = getVisibleRect();
    if (or == ComponentOrientation.RIGHT_TO_LEFT)
      r.translate((int) r.getWidth() - 1, 0);
    return getUI().locationToIndex(this, r.getLocation());      
  }


  /**
   * Returns index of the cell to which specified location is closest to. If
   * the location is outside the bounds of the list, then the greatest index
   * in the list model is returned. If the list model is empty, then
   * <code>-1</code> is returned.
   *
   * @param location for which to look for in the list
   * 
   * @return index of the cell to which specified location is closest to.
   */
   public int locationToIndex(Point location)
   {
     return getUI().locationToIndex(this, location);      
   }

  /**
   * Returns location of the cell located at the specified index in the list.
   * @param index of the cell for which location will be determined
   * 
   * @return location of the cell located at the specified index in the list.
   */
   public Point indexToLocation(int index)
   {
     return getUI().indexToLocation(this, index);
   }

  /**
   * Returns the list index of the lower right or lower left corner of the
   * visible rectangle of this list, depending on the {@link
   * Component#getComponentOrientation} property.
   *
   * @return The index of the last visible list cell, or <code>-1</code>
   * if none is visible.
   */
  public int getLastVisibleIndex()
  {
    ComponentOrientation or = getComponentOrientation();
    Rectangle r = getVisibleRect();
    r.translate(0, (int) r.getHeight() - 1);
    if (or == ComponentOrientation.LEFT_TO_RIGHT)
      r.translate((int) r.getWidth() - 1, 0);
    if (getUI().locationToIndex(this, r.getLocation()) == -1
        && indexToLocation(getModel().getSize() - 1).y < r.y)
      return getModel().getSize() - 1;
    return getUI().locationToIndex(this, r.getLocation());
  }

  /**
   * Returns the indices of values in the {@link #model} property which are
   * selected.
   *
   * @return An array of model indices, each of which is selected according
   *         to the {@link #getSelectedValues} property
   */
  public int[] getSelectedIndices()
  {
    int lo, hi, n, i, j;
    if (selectionModel.isSelectionEmpty())
      return new int[0];
    lo = selectionModel.getMinSelectionIndex();
    hi = selectionModel.getMaxSelectionIndex();
    n = 0;
    for (i = lo; i <= hi; ++i)
      if (selectionModel.isSelectedIndex(i))
        n++;
    int [] v = new int[n];
    j = 0;
    for (i = lo; i <= hi; ++i)
      if (selectionModel.isSelectedIndex(i))
        v[j++] = i;
    return v;
  }

  /**
   * Indicates whether the list element at a given index value is
   * currently selected.
   *
   * @param a The index to check 
   * @return <code>true</code> if <code>a</code> is the index of a selected
   * list element
   */
  public boolean isSelectedIndex(int a)
  {
    return selectionModel.isSelectedIndex(a);
  }

  /**
   * Returns the first value in the list's {@link #model} property which is
   * selected, according to the list's {@link #selectionModel} property.
   * This is equivalent to calling
   * <code>getModel()getElementAt(getSelectedIndex())</code>, with a check
   * for the special index value of <code>-1</code> which returns null
   * <code>null</code>.
   *
   * @return The first selected element, or <code>null</code> if no element
   * is selected.
   *
   * @see #getSelectedValues
   */
  public Object getSelectedValue()
  {
    int index = getSelectedIndex();
    if (index == -1)
      return null;
    return getModel().getElementAt(index);
  }

  /**
   * Returns all the values in the list's {@link #model} property which are
   * selected, according to the list's {@link #selectionModel} property.
   * 
   * @return An array containing all the selected values
   * @see #setSelectedValue
   */
  public Object[] getSelectedValues()
  {
    int[] idx = getSelectedIndices();
    Object[] v = new Object[idx.length];
    for (int i = 0; i < idx.length; ++i)
      v[i] = getModel().getElementAt(idx[i]);
    return v;
  }

  /**
   * Gets the value of the {@link #selectionBackground} property.
   *
   * @return The current value of the property
   */
  public Color getSelectionBackground()
  {
    return selectionBackground;
  }

  /**
   * Sets the value of the {@link #selectionBackground} property.
   *
   * @param c The new value of the property
   */
  public void setSelectionBackground(Color c)
  {
    if (selectionBackground == c)
      return;

    Color old = selectionBackground;
    selectionBackground = c;
    firePropertyChange("selectionBackground", old, c);
    repaint();
  }

  /**
   * Gets the value of the {@link #selectionForeground} property.
   *
   * @return The current value of the property
   */
  public Color getSelectionForeground()
  {
    return selectionForeground;
  }
  
  /**
   * Sets the value of the {@link #selectionForeground} property.
   *
   * @param c The new value of the property
   */
  public void setSelectionForeground(Color c)
  {
    if (selectionForeground == c)
      return;

    Color old = selectionForeground;
    selectionForeground = c;
    firePropertyChange("selectionForeground", old, c);
  }

  /**
   * Sets the selection to cover only the specified value, if it
   * exists in the model. 
   *
   * @param obj The object to select
   * @param scroll Whether to scroll the list to make the newly selected
   * value visible
   *
   * @see #ensureIndexIsVisible
   */

  public void setSelectedValue(Object obj, boolean scroll)
  {
    for (int i = 0; i < model.getSize(); ++i)
      {
        if (model.getElementAt(i).equals(obj))
          {
            setSelectedIndex(i);
            if (scroll)
              ensureIndexIsVisible(i);
            break;
          }
      }
  }

  /**
   * Scrolls this list to make the specified cell visible. This
   * only works if the list is contained within a viewport.
   *
   * @param i The list index to make visible
   *
   * @see JComponent#scrollRectToVisible
   */
  public void ensureIndexIsVisible(int i)
  {
    Rectangle r = getUI().getCellBounds(this, i, i);
    if (r != null)
      scrollRectToVisible(r);
  }

  /**
   * Sets the {@link #model} property of the list to a new anonymous
   * {@link AbstractListModel} subclass which accesses the provided Object
   * array directly.
   *
   * @param listData The object array to build a new list model on
   * @see #setModel
   */
  public void setListData(Object[] listData)
  {
    setModel(createListModel(listData));
  }

  /**
   * Returns a {@link ListModel} backed by the specified array.
   * 
   * @param items  the list items (don't use <code>null</code>).
   * 
   * @return A list model containing the specified items.
   */
  private ListModel createListModel(final Object[] items)
  {
    return new AbstractListModel()
      {
        public int getSize()
        {
          return items.length;
        }
        public Object getElementAt(int i)
        {
          return items[i];
        }
      };
  }
  
  /**
   * Returns a {@link ListModel} backed by the specified vector.
   * 
   * @param items  the list items (don't use <code>null</code>).
   * 
   * @return A list model containing the specified items.
   */
  private ListModel createListModel(final Vector items)
  {
    return new AbstractListModel()
      {
        public int getSize()
        {
          return items.size();
        }
        public Object getElementAt(int i)
        {
          return items.get(i);
        }
      };
  }

  /**
   * Sets the {@link #model} property of the list to a new anonymous {@link
   * AbstractListModel} subclass which accesses the provided vector
   * directly.
   *
   * @param listData The object array to build a new list model on
   * @see #setModel
   */
  public void setListData(Vector listData)
  {
    setModel(createListModel(listData));
  }

  /**
   * Gets the value of the {@link #cellRenderer} property. 
   *
   * @return The current value of the property
   */
  public ListCellRenderer getCellRenderer()
  {
    return cellRenderer;
  }

  /**
   * Sets the value of the {@link #getCellRenderer} property.
   *
   * @param renderer The new property value
   */
  public void setCellRenderer(ListCellRenderer renderer)
  {
    if (cellRenderer == renderer)
      return;
    
    ListCellRenderer old = cellRenderer;
    cellRenderer = renderer;
    firePropertyChange("cellRenderer", old, renderer);
    revalidate();
    repaint();
  }

  /**
   * Gets the value of the {@link #model} property. 
   *
   * @return The current value of the property
   */
  public ListModel getModel()
  {
    return model;
  }

  /**
   * Sets the value of the {@link #model} property. The list's {@link
   * #listListener} is unsubscribed from the existing model, if it exists,
   * and re-subscribed to the new model.
   *
   * @param model  the new model (<code>null</code> not permitted).
   * 
   * @throws IllegalArgumentException if <code>model</code> is 
   *         <code>null</code>.
   */
  public void setModel(ListModel model)
  {
    if (model == null) 
      throw new IllegalArgumentException("Null 'model' argument.");
    if (this.model == model)
      return;
    
    if (this.model != null)
      this.model.removeListDataListener(listListener);
    
    ListModel old = this.model;
    this.model = model;
    
    if (this.model != null)
      this.model.addListDataListener(listListener);
    
    firePropertyChange("model", old, model);
    revalidate();
    repaint();
  }

  /**
   * Returns the selection model for the {@link JList} component.  Note that
   * this class contains a range of convenience methods for configuring the
   * selection model:<br>
   * <ul>
   *   <li>{@link #clearSelection()};</li>
   *   <li>{@link #setSelectionMode(int)};</li>
   *   <li>{@link #addSelectionInterval(int, int)};</li>
   *   <li>{@link #setSelectedIndex(int)};</li>
   *   <li>{@link #setSelectedIndices(int[])};</li>
   *   <li>{@link #setSelectionInterval(int, int)}.</li>
   * </ul>
   * 
   * @return The selection model.
   */
  public ListSelectionModel getSelectionModel()
  {
    return selectionModel;
  }

  /**
   * Sets the value of the {@link #selectionModel} property. The list's
   * {@link #listListener} is unsubscribed from the existing selection
   * model, if it exists, and re-subscribed to the new selection model.
   *
   * @param model The new property value
   */
  public void setSelectionModel(ListSelectionModel model)
  {
    if (selectionModel == model)
      return;
    
    if (selectionModel != null)
      selectionModel.removeListSelectionListener(listListener);
    
    ListSelectionModel old = selectionModel;
    selectionModel = model;
    
    if (selectionModel != null)
      selectionModel.addListSelectionListener(listListener);
    
    firePropertyChange("selectionModel", old, model);
    revalidate();
    repaint();
  }

  /**
   * Gets the value of the UI property.
   *
   * @return The current property value
   */
  public ListUI getUI()
  {
    return (ListUI) ui;
  }

  /**
   * Sets the value of the UI property.
   *
   * @param ui The new property value
   */
  public void setUI(ListUI ui)
  {
    super.setUI(ui);
  }

  /**
   * Calls {@link #setUI} with the {@link ListUI} subclass
   * returned from calling {@link UIManager#getUI}.
   */
  public void updateUI()
  {
    setUI((ListUI) UIManager.getUI(this));
  }

  /**
   * Return the class identifier for the list's UI property.  This should
   * be the constant string <code>"ListUI"</code>, and map to an
   * appropriate UI class in the {@link UIManager}.
   *
   * @return The class identifier
   */
  public String getUIClassID()
  {
    return "ListUI";
  }


  /**
   * Returns the current value of the {@link #prototypeCellValue}
   * property. This property holds a reference to a "prototype" data value
   * -- typically a String -- which is used to calculate the {@link
   * #fixedCellWidth} and {@link #fixedCellHeight} properties, using the
   * {@link #cellRenderer} property to acquire a component to render the
   * prototype.
   *
   * @return The current prototype cell value
   * @see #setPrototypeCellValue
   */
  public Object getPrototypeCellValue()
  {
    return prototypeCellValue;
  }

  /**
   * <p>Set the {@link #prototypeCellValue} property. This property holds a
   * reference to a "prototype" data value -- typically a String -- which
   * is used to calculate the {@link #fixedCellWidth} and {@link
   * #fixedCellHeight} properties, using the {@link #cellRenderer} property
   * to acquire a component to render the prototype.</p>
   *
   * <p>It is important that you <em>not</em> set this value to a
   * component. It has to be a <em>data value</em> such as the objects you
   * would find in the list's model. Setting it to a component will have
   * undefined (and undesirable) affects. </p>
   *
   * @param obj The new prototype cell value
   * @see #getPrototypeCellValue
   */
  public void setPrototypeCellValue(Object obj)
  {
    if (prototypeCellValue == obj)
      return;

    Object old = prototypeCellValue;
    Component comp = getCellRenderer()
      .getListCellRendererComponent(this, obj, 0, false, false); 
    Dimension d = comp.getPreferredSize();
    fixedCellWidth = d.width;
    fixedCellHeight = d.height;
    prototypeCellValue = obj;
    firePropertyChange("prototypeCellValue", old, obj);
  }

  public AccessibleContext getAccessibleContext()
  {
    return new AccessibleJList();
  }

  /**
   * Returns a size indicating how much space this list would like to
   * consume, when contained in a scrollable viewport. This is part of the
   * {@link Scrollable} interface, which interacts with {@link
   * ScrollPaneLayout} and {@link JViewport} to define scrollable objects.
   *
   * @return The preferred size
   */
  public Dimension getPreferredScrollableViewportSize()
  {
    //If the layout orientation is not VERTICAL, then this will 
    //return the value from getPreferredSize. The current ListUI is 
    //expected to override getPreferredSize to return an appropriate value.
    if (getLayoutOrientation() != VERTICAL)
      return getPreferredSize();        

    int size = getModel().getSize();
    
    // Trivial case: if fixedCellWidth and fixedCellHeight were set 
    // just use them
    if (fixedCellHeight != -1 && fixedCellWidth != -1)
      return new Dimension(fixedCellWidth, size * fixedCellHeight);
        
    // If the model is empty we use 16 * the number of visible rows
    // for the height and either fixedCellWidth (if set) or 256
    // for the width
    if (size == 0)
      {
        if (fixedCellWidth == -1)
          return new Dimension(256, 16 * getVisibleRowCount());
        else
          return new Dimension(fixedCellWidth, 16 * getVisibleRowCount());
      }

    // Calculate the width: if fixedCellWidth was set use that, otherwise
    // use the preferredWidth
    int prefWidth;
    if (fixedCellWidth != -1)
      prefWidth = fixedCellWidth;
    else
      prefWidth = getPreferredSize().width;

    // Calculate the height: if fixedCellHeight was set use that, otherwise
    // use the height of the first row multiplied by the number of visible
    // rows
    int prefHeight;
    if (fixedCellHeight != -1)
      prefHeight = fixedCellHeight;
    else
      prefHeight = getVisibleRowCount() * getCellBounds(0, 0).height;

    return new Dimension (prefWidth, prefHeight);
  }

  /**
   * <p>Return the number of pixels the list must scroll in order to move a
   * "unit" of the list into the provided visible rectangle. When the
   * provided direction is positive, the call describes a "downwards"
   * scroll, which will be exposing a cell at a <em>greater</em> index in
   * the list than those elements currently showing. Then the provided
   * direction is negative, the call describes an "upwards" scroll, which
   * will be exposing a cell at a <em>lesser</em> index in the list than
   * those elements currently showing.</p>
   *
   * <p>If the provided orientation is <code>HORIZONTAL</code>, the above
   * comments refer to "rightwards" for positive direction, and "leftwards"
   * for negative.</p>
   * 
   *
   * @param visibleRect The rectangle to scroll an element into
   * @param orientation One of the numeric consants <code>VERTICAL</code>
   * or <code>HORIZONTAL</code>
   * @param direction An integer indicating the scroll direction: positive means
   * forwards (down, right), negative means backwards (up, left)
   *
   * @return The scrollable unit increment, in pixels
   */
  public int getScrollableUnitIncrement(Rectangle visibleRect,
                                        int orientation, int direction)
  {
    ListUI lui = this.getUI();
    if (orientation == SwingConstants.VERTICAL)
      {
        if (direction > 0)
          {
            // Scrolling down
            Point bottomLeft = new Point(visibleRect.x,
                                         visibleRect.y + visibleRect.height);
            int curIdx = lui.locationToIndex(this, bottomLeft);
            Rectangle curBounds = lui.getCellBounds(this, curIdx, curIdx);
            if (curBounds.y + curBounds.height == bottomLeft.y)
              {
                // we are at the exact bottom of the current cell, so we 
                // are being asked to scroll to the end of the next one
                if (curIdx + 1 < model.getSize())
                  {
                    // there *is* a next item in the list
                    Rectangle nxtBounds = lui.getCellBounds(this, curIdx + 1, curIdx + 1);
                    return nxtBounds.height;
                  }
                else
                  {
                    // no next item, no advance possible
                    return 0;
                  }
              }
            else
              {
                // we are part way through an existing cell, so we are being
                // asked to scroll to the bottom of it
                return (curBounds.y + curBounds.height) - bottomLeft.y;
              }		      
          }
        else
          {
            // scrolling up
            Point topLeft = new Point(visibleRect.x, visibleRect.y);
            int curIdx = lui.locationToIndex(this, topLeft);
            Rectangle curBounds = lui.getCellBounds(this, curIdx, curIdx);
            if (curBounds.y == topLeft.y)
              {
                // we are at the exact top of the current cell, so we 
                // are being asked to scroll to the top of the previous one
                if (curIdx > 0)
                  {
                    // there *is* a previous item in the list
                    Rectangle nxtBounds = lui.getCellBounds(this, curIdx - 1, curIdx - 1);
                    return -nxtBounds.height;
                  }
                else
                  {
                    // no previous item, no advance possible
                    return 0;
                  }
              }
            else
              {
                // we are part way through an existing cell, so we are being
                // asked to scroll to the top of it
                return curBounds.y - topLeft.y;
              }		      
          }
      }

    // FIXME: handle horizontal scrolling (also wrapping?)
    return 1;
  }

  /**
   * <p>Return the number of pixels the list must scroll in order to move a
   * "block" of the list into the provided visible rectangle. When the
   * provided direction is positive, the call describes a "downwards"
   * scroll, which will be exposing a cell at a <em>greater</em> index in
   * the list than those elements currently showing. Then the provided
   * direction is negative, the call describes an "upwards" scroll, which
   * will be exposing a cell at a <em>lesser</em> index in the list than
   * those elements currently showing.</p>
   *
   * <p>If the provided orientation is <code>HORIZONTAL</code>, the above
   * comments refer to "rightwards" for positive direction, and "leftwards"
   * for negative.</p>
   * 
   *
   * @param visibleRect The rectangle to scroll an element into
   * @param orientation One of the numeric consants <code>VERTICAL</code>
   * or <code>HORIZONTAL</code>
   * @param direction An integer indicating the scroll direction: positive means
   * forwards (down, right), negative means backwards (up, left)
   *
   * @return The scrollable unit increment, in pixels
   */
  public int getScrollableBlockIncrement(Rectangle visibleRect,
                                         int orientation, int direction)
  {
      if (orientation == VERTICAL)
	  return visibleRect.height * direction;
      else
	  return visibleRect.width * direction;
  }

  /**
   * Gets the value of the <code>scrollableTracksViewportWidth</code> property.
   *
   * @return <code>true</code> if the viewport is larger (horizontally)
   * than the list and the list should be expanded to fit the viewport;
   * <code>false</code> if the viewport is smaller than the list and the
   * list should scroll (horizontally) within the viewport
   */
  public boolean getScrollableTracksViewportWidth()
  {
    Component parent = getParent();
    boolean retVal = false;
    if (parent instanceof JViewport)
      {
        JViewport viewport = (JViewport) parent;
        Dimension pref = getPreferredSize();
        if (viewport.getSize().width > pref.width)
          retVal = true;
        if ((getLayoutOrientation() == HORIZONTAL_WRAP)
            && (getVisibleRowCount() <= 0))
          retVal = true;
      }
    return retVal;
  }

  /**
   * Gets the value of the </code>scrollableTracksViewportWidth</code> property.
   *
   * @return <code>true</code> if the viewport is larger (vertically)
   * than the list and the list should be expanded to fit the viewport;
   * <code>false</code> if the viewport is smaller than the list and the
   * list should scroll (vertically) within the viewport
   */
  public boolean getScrollableTracksViewportHeight()
  {
    Component parent = getParent();
    boolean retVal = false;
    if (parent instanceof JViewport)
      {
        JViewport viewport = (JViewport) parent;
        Dimension pref = getPreferredSize();
        if (viewport.getSize().height > pref.height)
          retVal = true;
        if ((getLayoutOrientation() == VERTICAL_WRAP)
            && (getVisibleRowCount() <= 0))
          retVal = true;
      }
    return retVal;
  }

  /**
   * Returns the index of the anchor item in the current selection, or
   * <code>-1</code> if there is no anchor item.
   * 
   * @return The item index.
   */
  public int getAnchorSelectionIndex()
  {
    return selectionModel.getAnchorSelectionIndex();
  }

  /**
   * Returns the index of the lead item in the current selection, or
   * <code>-1</code> if there is no lead item.
   * 
   * @return The item index.
   */
  public int getLeadSelectionIndex()
  {
    return selectionModel.getLeadSelectionIndex();
  }

  /**
   * Returns the lowest item index in the current selection, or <code>-1</code>
   * if there is no selection.
   * 
   * @return The index.
   * 
   * @see #getMaxSelectionIndex()
   */
  public int getMinSelectionIndex()
  {
    return selectionModel.getMinSelectionIndex();
  }

  /**
   * Returns the highest item index in the current selection, or 
   * <code>-1</code> if there is no selection.
   * 
   * @return The index.
   * 
   * @see #getMinSelectionIndex()
   */
  public int getMaxSelectionIndex()
  {
    return selectionModel.getMaxSelectionIndex();
  }

  /**
   * Clears the current selection.
   */
  public void clearSelection()
  {
    selectionModel.clearSelection();
  }

  /**
   * Sets the current selection to the items in the specified range (inclusive).
   * Note that <code>anchor</code> can be less than, equal to, or greater than 
   * <code>lead</code>.
   * 
   * @param anchor  the index of the anchor item.
   * @param lead  the index of the anchor item.
   */
  public void setSelectionInterval(int anchor, int lead)
  {
    selectionModel.setSelectionInterval(anchor, lead);
  }

  /**
   * Adds the specified interval to the current selection.  Note that 
   * <code>anchor</code> can be less than, equal to, or greater than 
   * <code>lead</code>.
   * 
   * @param anchor  the index of the anchor item.
   * @param lead  the index of the lead item.
   */
  public void addSelectionInterval(int anchor, int lead)
  {
    selectionModel.addSelectionInterval(anchor, lead);
  }

  /**
   * Removes the specified interval from the current selection.  Note that 
   * <code>index0</code> can be less than, equal to, or greater than 
   * <code>index1</code>.
   * 
   * @param index0  an index for one end of the range.
   * @param index1  an index for the other end of the range.
   */
  public void removeSelectionInterval(int index0, int index1)
  {
    selectionModel.removeSelectionInterval(index0, index1);
  }

  /**
   * Returns the <code>valueIsAdjusting</code> flag from the list's selection
   * model.
   *
   * @return the value
   */
  public boolean getValueIsAdjusting()
  {
    return selectionModel.getValueIsAdjusting();
  }

  /**
   * Sets the <code>valueIsAdjusting</code> flag in the list's selection 
   * model.
   *
   * @param isAdjusting the new value
   */
  public void setValueIsAdjusting(boolean isAdjusting)
  {
    selectionModel.setValueIsAdjusting(isAdjusting);
  }

  /**
   * Return the value of the <code>dragEnabled</code> property.
   *
   * @return the value
   * 
   * @since 1.4
   */
  public boolean getDragEnabled()
  {
    return dragEnabled;
  }

  /**
   * Set the <code>dragEnabled</code> property.
   *
   * @param enabled new value
   * 
   * @since 1.4
   */
  public void setDragEnabled(boolean enabled)
  {
    dragEnabled = enabled;
  }

  /**
   * Returns the layout orientation, which will be one of {@link #VERTICAL}, 
   * {@link #VERTICAL_WRAP} and {@link #HORIZONTAL_WRAP}.  The default value
   * is {@link #VERTICAL}.
   *
   * @return the orientation.
   *
   * @see #setLayoutOrientation(int)
   * @since 1.4
   */
  public int getLayoutOrientation()
  {
    return layoutOrientation;
  }

  /**
   * Sets the layout orientation (this is a bound property with the name
   * 'layoutOrientation').  Valid orientations are {@link #VERTICAL}, 
   * {@link #VERTICAL_WRAP} and {@link #HORIZONTAL_WRAP}.
   *
   * @param orientation the orientation.
   *
   * @throws IllegalArgumentException if <code>orientation</code> is not one
   *     of the specified values.
   * @since 1.4
   * @see #getLayoutOrientation()
   */
  public void setLayoutOrientation(int orientation)
  {
    if (orientation < JList.VERTICAL || orientation > JList.HORIZONTAL_WRAP)
      throw new IllegalArgumentException();
    if (layoutOrientation == orientation)
      return;

    int old = layoutOrientation;
    layoutOrientation = orientation;
    firePropertyChange("layoutOrientation", old, orientation);
  }

  /**
   * Returns the bounds of the rectangle that encloses both list cells
   * with index0 and index1.
   *
   * @param index0 the index of the first cell
   * @param index1 the index of the second cell
   *
   * @return  the bounds of the rectangle that encloses both list cells
   *     with index0 and index1, <code>null</code> if one of the indices is
   *     not valid
   */
  public Rectangle getCellBounds(int index0, int index1)
  {
    ListUI ui = getUI();
    Rectangle bounds = null;
    if (ui != null)
      {
        bounds = ui.getCellBounds(this, index0, index1);
      }
    // When the UI is null, this method also returns null in the RI.
    return bounds;
  }

  /**
   * Returns the index of the next list element (beginning at 
   * <code>startIndex</code> and moving in the specified direction through the
   * list, looping around if necessary) that starts with <code>prefix</code>
   * (ignoring case).
   *
   * @param prefix the prefix to search for in the cell values
   * @param startIndex the index where to start searching from
   * @param direction the search direction, either {@link Position.Bias#Forward}
   *     or {@link Position.Bias#Backward} (<code>null</code> is interpreted
   *     as {@link Position.Bias#Backward}.
   *
   * @return the index of the found element or -1 if no such element has
   *     been found
   *
   * @throws IllegalArgumentException if prefix is <code>null</code> or
   *     startIndex is not valid
   *
   * @since 1.4
   */
  public int getNextMatch(String prefix, int startIndex, 
                          Position.Bias direction)
  {
    if (prefix == null)
      throw new IllegalArgumentException("The argument 'prefix' must not be"
                                         + " null.");
    if (startIndex < 0)
      throw new IllegalArgumentException("The argument 'startIndex' must not"
                                         + " be less than zero.");

    int size = model.getSize();
    if (startIndex >= model.getSize())
      throw new IllegalArgumentException("The argument 'startIndex' must not"
                                         + " be greater than the number of"
                                         + " elements in the ListModel.");

    int result = -1;
    int current = startIndex;
    int delta = -1;
    int itemCount = model.getSize();
    boolean finished = false;
    prefix = prefix.toUpperCase();
    
    if (direction == Position.Bias.Forward)
      delta = 1;
    while (!finished)
      {
        String itemStr = model.getElementAt(current).toString().toUpperCase();
        if (itemStr.startsWith(prefix))
          return current;
        current = (current + delta);
        if (current == -1)
          current += itemCount;
        else
          current = current % itemCount; 
        finished = current == startIndex;
      }
    return result;
  }
  
  /**
   * Returns a string describing the attributes for the <code>JList</code>
   * component, for use in debugging.  The return value is guaranteed to be 
   * non-<code>null</code>, but the format of the string may vary between
   * implementations.
   *
   * @return A string describing the attributes of the <code>JList</code>.
   */
  protected String paramString()
  {
    StringBuffer sb = new StringBuffer(super.paramString());
    sb.append(",fixedCellHeight=").append(getFixedCellHeight());
    sb.append(",fixedCellWidth=").append(getFixedCellWidth());
    sb.append(",selectionBackground=");
    if (getSelectionBackground() != null)
      sb.append(getSelectionBackground());
    sb.append(",selectionForeground=");
    if (getSelectionForeground() != null)
      sb.append(getSelectionForeground());
    sb.append(",visibleRowCount=").append(getVisibleRowCount());
    sb.append(",layoutOrientation=").append(getLayoutOrientation());
    return sb.toString();
  }
}
