/* List.java -- A listbox widget
   Copyright (C) 1999, 2002, 2004, 2006,  Free Software Foundation, Inc.

This file is part of GNU Classpath.

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

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

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

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

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


package java.awt;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.peer.ListPeer;
import java.util.EventListener;
import java.util.Vector;

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleSelection;
import javax.accessibility.AccessibleState;
import javax.accessibility.AccessibleStateSet;

/**
 * Class that implements a listbox widget
 *
 * @author Aaron M. Renn (arenn@urbanophile.com)
 */
public class List extends Component
  implements ItemSelectable, Accessible
{

  /**
   * The number used to generate the name returned by getName.
   */
  private static transient long next_list_number;

  // Serialization constant
  private static final long serialVersionUID = -3304312411574666869L;

  // FIXME: Need read/writeObject

  /**
    * @serial The items in the list.
    */
  private Vector items = new Vector();

  /**
   * @serial Indicates whether or not multiple items can be selected
   * simultaneously.
   */
  private boolean multipleMode;

  /**
   * @serial The number of rows in the list.  This is set on creation
   * only and cannot be modified.
   */
  private int rows;

  /**
   * @serial An array of the item indices that are selected.
   */
  private int[] selected;

  /**
   * @serial An index value used by <code>makeVisible()</code> and
   * <code>getVisibleIndex</code>.
   */
  private int visibleIndex = -1;

  // The list of ItemListeners for this object.
  private ItemListener item_listeners;

  // The list of ActionListeners for this object.
  private ActionListener action_listeners;

  /**
   * Initializes a new instance of <code>List</code> with no visible lines
   * and multi-select disabled.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   * @since 1.1
   */
  public List()
  {
    this(4, false);
  }

  /**
   * Initializes a new instance of <code>List</code> with the specified
   * number of visible lines and multi-select disabled.
   *
   * @param rows The number of visible rows in the list.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  public List(int rows)
  {
    this(rows, false);
  }

  /**
   * Initializes a new instance of <code>List</code> with the specified
   * number of lines and the specified multi-select setting.
   *
   * @param rows The number of visible rows in the list.
   * @param multipleMode <code>true</code> if multiple lines can be selected
   * simultaneously, <code>false</code> otherwise.
   *
   * @exception HeadlessException If GraphicsEnvironment.isHeadless() is true.
   */
  public List(int rows, boolean multipleMode)
  {
    if (rows == 0)
      this.rows = 4;
    else
      this.rows = rows;

    this.multipleMode = multipleMode;
    selected = new int[0];

    if (GraphicsEnvironment.isHeadless())
      throw new HeadlessException();

  }

  /**
   * Returns the number of items in this list.
   *
   * @return The number of items in this list.
   *
   * @since 1.1
   */
  public int getItemCount()
  {
    return countItems();
  }

  /**
   * Returns the number of items in this list.
   *
   * @return The number of items in this list.
   *
   * @deprecated This method is deprecated in favor of
   * <code>getItemCount()</code>
   */
  public int countItems()
  {
    return items.size();
  }

  /**
   * Returns the complete list of items.
   *
   * @return The complete list of items in the list.
   *
   * @since 1.1
   */
  public synchronized String[] getItems()
  {
    String[] l_items = new String[getItemCount()];

    items.copyInto(l_items);
    return(l_items);
  }

  /**
   * Returns the item at the specified index.
   *
   * @param index The index of the item to retrieve.
   *
   * @exception IndexOutOfBoundsException If the index value is not valid.
   */
  public String getItem(int index)
  {
    return((String) items.elementAt(index));
  }

  /**
   * Returns the number of visible rows in the list.
   *
   * @return The number of visible rows in the list.
   */
  public int getRows()
  {
    return(rows);
  }

  /**
   * Tests whether or not multi-select mode is enabled.
   *
   * @return <code>true</code> if multi-select mode is enabled,
   * <code>false</code> otherwise.
   *
   * @since 1.1
   */
  public boolean isMultipleMode()
  {
    return allowsMultipleSelections ();
  }

  /**
   * Tests whether or not multi-select mode is enabled.
   *
   * @return <code>true</code> if multi-select mode is enabled,
   * <code>false</code> otherwise.
   *
   * @deprecated This method is deprecated in favor of
   * <code>isMultipleMode()</code>.
   */
  public boolean allowsMultipleSelections()
  {
    return multipleMode;
  }

  /**
   * This method enables or disables multiple selection mode for this
   * list.
   *
   * @param multipleMode <code>true</code> to enable multiple mode,
   * <code>false</code> otherwise.
   *
   * @since 1.1
   */
  public void setMultipleMode(boolean multipleMode)
  {
    setMultipleSelections (multipleMode);
  }

  /**
   * This method enables or disables multiple selection mode for this
   * list.
   *
   * @param multipleMode <code>true</code> to enable multiple mode,
   * <code>false</code> otherwise.
   *
   * @deprecated
   */
  public void setMultipleSelections(boolean multipleMode)
  {
    this.multipleMode = multipleMode;

    ListPeer peer = (ListPeer) getPeer();
    if (peer != null)
      peer.setMultipleMode(multipleMode);

  }

  /**
   * Returns the minimum size of this component.
   *
   * @return The minimum size of this component.
   *
   * @since 1.1
   */
  public Dimension getMinimumSize()
  {
    return getMinimumSize(getRows());
  }

  /**
   * Returns the minimum size of this component.
   *
   * @return The minimum size of this component.
   *
   * @deprecated This method is deprecated in favor of
   * <code>getMinimumSize</code>.
   */
  public Dimension minimumSize()
  {
    return minimumSize(getRows());
  }

  /**
   * Returns the minimum size of this component assuming it had the specified
   * number of rows.
   *
   * @param rows The number of rows to size for.
   *
   * @return The minimum size of this component.
   *
   * @since 1.1
   */
  public Dimension getMinimumSize(int rows)
  {
    return minimumSize(rows);
  }

  /**
   * Returns the minimum size of this component assuming it had the specified
   * number of rows.
   *
   * @param rows The number of rows to size for.
   *
   * @return The minimum size of this component.
   *
   * @deprecated This method is deprecated in favor of
   * <code>getMinimumSize(int)</code>>
   */
  public Dimension minimumSize(int rows)
  {
    ListPeer peer = (ListPeer) getPeer();
    if (peer != null)
      return peer.minimumSize(rows);
    else
      return new Dimension(0, 0);
  }

  /**
   * Returns the preferred size of this component.
   *
   * @return The preferred size of this component.
   *
   * @since 1.1
   */
  public Dimension getPreferredSize()
  {
    return getPreferredSize(getRows());
  }

  /**
   * Returns the preferred size of this component.
   *
   * @return The preferred size of this component.
   *
   * @deprecated This method is deprecated in favor of
   * <code>getPreferredSize</code>.
   */
  public Dimension preferredSize()
  {
    return preferredSize(getRows());
  }

  /**
   * Returns the preferred size of this component assuming it had the specified
   * number of rows.
   *
   * @param rows The number of rows to size for.
   *
   * @return The preferred size of this component.
   *
   * @since 1.1
   */
  public Dimension getPreferredSize(int rows)
  {
    return preferredSize(rows);
  }

  /**
   * Returns the preferred size of this component assuming it had the specified
   * number of rows.
   *
   * @param rows The number of rows to size for.
   *
   * @return The preferred size of this component.
   *
   * @deprecated This method is deprecated in favor of
   * <code>getPreferredSize(int)</code>>
   */
  public Dimension preferredSize(int rows)
  {
    ListPeer peer = (ListPeer)getPeer();
    if (peer != null)
      return peer.preferredSize(rows);
    else
      return getSize();
  }

  /**
   * This method adds the specified item to the end of the list.
   *
   * @param item The item to add to the list.
   *
   * @since 1.1
   */
  public void add(String item)
  {
    add (item, -1);
  }

  /**
   * This method adds the specified item to the end of the list.
   *
   * @param item The item to add to the list.
   *
   * @deprecated Use add() instead.
   */
  public void addItem(String item)
  {
    addItem(item, -1);
  }

  /**
   * Adds the specified item to the specified location in the list.
   * If the desired index is -1 or greater than the number of rows
   * in the list, then the item is added to the end.
   *
   * @param item The item to add to the list.
   * @param index The location in the list to add the item, or -1 to add
   * to the end.
   *
   * @since 1.1
   */
  public void add(String item, int index)
  {
    addItem(item, index);
  }

  /**
   * Adds the specified item to the specified location in the list.
   * If the desired index is -1 or greater than the number of rows
   * in the list, then the item is added to the end.
   *
   * @param item The item to add to the list.
   * @param index The location in the list to add the item, or -1 to add
   * to the end.
   *
   * @deprecated Use add() instead.
   */
  public void addItem(String item, int index)
  {
    if (item == null)
      item = "";

    if (index < -1)
      index = -1;

    if ((index == -1) || (index >= items.size ()))
      items.addElement (item);
    else
      items.insertElementAt(item, index);

    ListPeer peer = (ListPeer) getPeer();
    if (peer != null)
      peer.add (item, index);
  }

  /**
   * Deletes the item at the specified index.
   *
   * @param index The index of the item to delete.
   *
   * @exception IllegalArgumentException If the index is not valid
   *
   * @deprecated
   */
  public void delItem(int index) throws IllegalArgumentException
  {
    boolean selected = false;
    if (isSelected(index))
      {
        selected = true;
        deselect(index);
      }

    items.removeElementAt (index);

    if (selected)
      select(index);

    ListPeer peer = (ListPeer) getPeer();
    if (peer != null)
      peer.delItems (index, index);
  }

  /**
   * Deletes the item at the specified index.
   *
   * @param index The index of the item to delete.
   *
   * @exception IllegalArgumentException If the index is not valid
   *
   * @since 1.1
   */
  public void remove(int index) throws IllegalArgumentException
  {
    delItem(index);
  }

  /**
   * Deletes all items in the specified index range.
   *
   * @param start The beginning index of the range to delete.
   * @param end The ending index of the range to delete.
   *
   * @exception IllegalArgumentException If the indexes are not valid
   *
   * @deprecated This method is deprecated for some unknown reason.
   */
  public synchronized void delItems(int start, int end)
    throws IllegalArgumentException
  {
    // We must run the loop in reverse direction.
    for (int i = end; i >= start; --i)
      items.removeElementAt (i);
    if (peer != null)
      {
        ListPeer l = (ListPeer) peer;
        l.delItems (start, end);
      }
  }

  /**
   * Deletes the first occurrence of the specified item from the list.
   *
   * @param item The item to delete.
   *
   * @exception IllegalArgumentException If the specified item does not exist.
   *
   * @since 1.1
   */
  public synchronized void remove(String item) throws IllegalArgumentException
  {
    int index = items.indexOf(item);
    if (index == -1)
      throw new IllegalArgumentException("List element to delete not found");

    remove(index);
  }

  /**
   * Deletes all of the items from the list.
   *
   * @since 1.1
   */
  public synchronized void removeAll()
  {
    clear();
  }

  /**
   * Deletes all of the items from the list.
   *
   * @deprecated This method is deprecated in favor of <code>removeAll()</code>.
   */
  public void clear()
  {
    items.clear();

    ListPeer peer = (ListPeer) getPeer();
    if (peer != null)
      peer.removeAll();

    selected = new int[0];
  }

  /**
   * Replaces the item at the specified index with the specified item.
   *
   * @param item The new item value.
   * @param index The index of the item to replace.
   *
   * @exception ArrayIndexOutOfBoundsException If the index is not valid.
   */
  public synchronized void replaceItem(String item, int index)
    throws ArrayIndexOutOfBoundsException
  {
    if ((index < 0) || (index >= items.size()))
      throw new ArrayIndexOutOfBoundsException("Bad list index: " + index);

    items.insertElementAt(item, index + 1);
    items.removeElementAt (index);

    if (peer != null)
      {
        ListPeer l = (ListPeer) peer;

        /* We add first and then remove so that the selected
           item remains the same */
        l.add (item, index + 1);
        l.delItems (index, index);
      }
  }

  /**
   * Returns the index of the currently selected item.  -1 will be returned
   * if there are no selected rows or if there are multiple selected rows.
   *
   * @return The index of the selected row.
   */
  public synchronized int getSelectedIndex()
  {
    if (peer != null)
      {
        ListPeer l = (ListPeer) peer;
        selected = l.getSelectedIndexes ();
      }

    if (selected == null || selected.length != 1)
      return -1;

    return selected[0];
  }

  /**
   * Returns an array containing the indexes of the rows that are
   * currently selected.
   *
   * @return A list of indexes of selected rows.
   */
  public synchronized int[] getSelectedIndexes()
  {
    if (peer != null)
      {
        ListPeer l = (ListPeer) peer;
        selected = l.getSelectedIndexes();
      }

    return selected;
  }

  /**
   * Returns the item that is currently selected, or <code>null</code> if there
   * is no item selected.  FIXME: What happens if multiple items selected?
   *
   * @return The selected item, or <code>null</code> if there is no
   * selected item.
   */
  public synchronized String getSelectedItem()
  {
    int index = getSelectedIndex();
    if (index == -1)
      return(null);

    return((String) items.elementAt(index));
  }

  /**
   * Returns the list of items that are currently selected in this list.
   *
   * @return The list of currently selected items.
   */
  public synchronized String[] getSelectedItems()
  {
    int[] indexes = getSelectedIndexes();
    if (indexes == null)
      return(new String[0]);

    String[] retvals = new String[indexes.length];
    if (retvals.length > 0)
      for (int i = 0 ; i < retvals.length; i++)
         retvals[i] = (String)items.elementAt(indexes[i]);

    return(retvals);
  }

  /**
   * Returns the list of items that are currently selected in this list as
   * an array of type <code>Object[]</code> instead of <code>String[]</code>.
   *
   * @return The list of currently selected items.
   */
  public synchronized Object[] getSelectedObjects()
  {
    int[] indexes = getSelectedIndexes();
    if (indexes == null)
      return(new Object[0]);

    Object[] retvals = new Object[indexes.length];
    if (retvals.length > 0)
      for (int i = 0 ; i < retvals.length; i++)
         retvals[i] = items.elementAt(indexes[i]);

    return(retvals);
  }

  /**
   * Tests whether or not the specified index is selected.
   *
   * @param index The index to test.
   *
   * @return <code>true</code> if the index is selected, <code>false</code>
   * otherwise.
   *
   * @since 1.1
   */
  public boolean isIndexSelected(int index)
  {
    return isSelected(index);
  }

  /**
   * Tests whether or not the specified index is selected.
   *
   * @param index The index to test.
   *
   * @return <code>true</code> if the index is selected, <code>false</code>
   * otherwise.
   *
   * @deprecated This method is deprecated in favor of
   * <code>isIndexSelected(int)</code>.
   */
  public boolean isSelected(int index)
  {
    int[] indexes = getSelectedIndexes();

    for (int i = 0; i < indexes.length; i++)
      if (indexes[i] == index)
        return true;

    return false;
  }

  /**
   * This method ensures that the item at the specified index is visible.
   *
   * @param index The index of the item to be made visible.
   */
  public synchronized void makeVisible(int index)
    throws IllegalArgumentException
  {
    visibleIndex = index;
    if (peer != null)
      {
        ListPeer l = (ListPeer) peer;
        l.makeVisible (index);
      }
  }

  /**
   * Returns the index of the last item that was made visible via the
   * <code>makeVisible()</code> method.
   *
   * @return The index of the last item made visible via the
   * <code>makeVisible()</code> method.
   */
  public int getVisibleIndex()
  {
    return visibleIndex;
  }

  /**
   * Makes the item at the specified index selected.
   *
   * @param index The index of the item to select.
   */
  public synchronized void select(int index)
  {
    ListPeer lp = (ListPeer) getPeer();
    if (lp != null)
      lp.select(index);

   if (selected != null)
     {
       boolean found = false;
       for (int i = 0; i < selected.length; i++)
         {
           if (selected[i] == index)
           found = true;
         }
       if (! found)
         {
           if (! isMultipleMode())
             {
               selected = new int[] { index };
               return;
             }
           int[] temp = new int[selected.length + 1];
           System.arraycopy(selected, 0, temp, 0, selected.length);
           temp[selected.length] = index;
           selected = temp;
         }
     }
   else
     {
       selected = new int[1];
       selected[0] = index;
     }
  }

  /**
   * Makes the item at the specified index not selected.
   *
   * @param index The index of the item to unselect.
   */
  public synchronized void deselect(int index)
  {
    if (isSelected(index))
      {
        ListPeer lp = (ListPeer)getPeer();
        if (lp != null)
          lp.deselect(index);

        int[] temp = new int[selected.length - 1];
        for (int i = 0; i < temp.length; i++)
          {
            if (selected[i] != index)
              temp[i] = selected[i];
            else
              {
                System.arraycopy(selected, i + 1, temp, i,
                                 selected.length - i - 1);
                break;
              }
          }
        selected = temp;
      }
  }

  /**
   * Notifies this object to create its native peer.
   */
  public void addNotify()
  {
    if (peer == null)
      peer = getToolkit ().createList(this);
    super.addNotify ();
  }

  /**
   * Notifies this object to destroy its native peer.
   */
  public void removeNotify()
  {
    super.removeNotify();
  }

  /**
   * Adds the specified <code>ActionListener</code> to the list of
   * registered listeners for this object.
   *
   * @param listener The listener to add.
   *
   * @since 1.1
   */
  public synchronized void addActionListener(ActionListener listener)
  {
    action_listeners = AWTEventMulticaster.add(action_listeners, listener);
  }

  /**
   * Removes the specified <code>ActionListener</code> from the list of
   * registers listeners for this object.
   *
   * @param listener The listener to remove.
   *
   * @since 1.1
   */
  public synchronized void removeActionListener(ActionListener listener)
  {
    action_listeners = AWTEventMulticaster.remove(action_listeners, listener);
  }

  /**
   * Adds the specified <code>ItemListener</code> to the list of
   * registered listeners for this object.
   *
   * @param listener The listener to add.
   *
   * @since 1.1
   */
  public synchronized void addItemListener(ItemListener listener)
  {
    item_listeners = AWTEventMulticaster.add(item_listeners, listener);
  }

  /**
   * Removes the specified <code>ItemListener</code> from the list of
   * registers listeners for this object.
   *
   * @param listener The listener to remove.
   *
   * @since 1.1
   */
  public synchronized void removeItemListener(ItemListener listener)
  {
    item_listeners = AWTEventMulticaster.remove(item_listeners, listener);
  }

  /**
   * Processes the specified event for this object.  If the event is an
   * instance of <code>ActionEvent</code> then the
   * <code>processActionEvent()</code> method is called.  Similarly, if the
   * even is an instance of <code>ItemEvent</code> then the
   * <code>processItemEvent()</code> method is called.  Otherwise the
   * superclass method is called to process this event.
   *
   * @param event The event to process.
   *
   * @since 1.1
   */
  protected void processEvent(AWTEvent event)
  {
    if (event instanceof ActionEvent)
      processActionEvent((ActionEvent)event);
    else if (event instanceof ItemEvent)
      processItemEvent((ItemEvent)event);
    else
      super.processEvent(event);
  }

  /**
   * This method processes the specified event by dispatching it to any
   * registered listeners.  Note that this method will only get called if
   * action events are enabled.  This will happen automatically if any
   * listeners are added, or it can be done "manually" by calling
   * the <code>enableEvents()</code> method.
   *
   * @param event The event to process.
   *
   * @since 1.1
   */
  protected void processActionEvent(ActionEvent event)
  {
    if (action_listeners != null)
      action_listeners.actionPerformed(event);
  }

  /**
   * This method processes the specified event by dispatching it to any
   * registered listeners.  Note that this method will only get called if
   * item events are enabled.  This will happen automatically if any
   * listeners are added, or it can be done "manually" by calling
   * the <code>enableEvents()</code> method.
   *
   * @param event The event to process.
   *
   * @since 1.1
   */
  protected void processItemEvent(ItemEvent event)
  {
    if (item_listeners != null)
      item_listeners.itemStateChanged(event);
  }

  void dispatchEventImpl(AWTEvent e)
  {
    if (e.id <= ItemEvent.ITEM_LAST
        && e.id >= ItemEvent.ITEM_FIRST
        && (item_listeners != null
        || (eventMask & AWTEvent.ITEM_EVENT_MASK) != 0))
      processEvent(e);
    else if (e.id <= ActionEvent.ACTION_LAST
           && e.id >= ActionEvent.ACTION_FIRST
           && (action_listeners != null
           || (eventMask & AWTEvent.ACTION_EVENT_MASK) != 0))
      processEvent(e);
    else
      super.dispatchEventImpl(e);
  }

  /**
   * Returns a debugging string for this object.
   *
   * @return A debugging string for this object.
   */
  protected String paramString()
  {
    return "multiple=" + multipleMode + ",rows=" + rows + super.paramString();
  }

  /**
   * Returns an array of all the objects currently registered as FooListeners
   * upon this <code>List</code>. FooListeners are registered using the
   * addFooListener method.
   *
   * @exception ClassCastException If listenerType doesn't specify a class or
   * interface that implements java.util.EventListener.
   *
   * @since 1.3
   */
  public <T extends EventListener> T[] getListeners (Class<T> listenerType)
  {
    if (listenerType == ActionListener.class)
      return AWTEventMulticaster.getListeners (action_listeners, listenerType);

    if (listenerType == ItemListener.class)
      return AWTEventMulticaster.getListeners (item_listeners, listenerType);

    return super.getListeners (listenerType);
  }

  /**
   * Returns all action listeners registered to this object.
   *
   * @since 1.4
   */
  public ActionListener[] getActionListeners ()
  {
    return (ActionListener[]) getListeners (ActionListener.class);
  }

  /**
   * Returns all action listeners registered to this object.
   *
   * @since 1.4
   */
  public ItemListener[] getItemListeners ()
  {
    return (ItemListener[]) getListeners (ItemListener.class);
  }

  // Accessibility internal class
  protected class AccessibleAWTList extends AccessibleAWTComponent
    implements AccessibleSelection, ItemListener, ActionListener
  {
    private static final long serialVersionUID = 7924617370136012829L;

    protected class AccessibleAWTListChild extends AccessibleAWTComponent
      implements Accessible
    {
      private static final long serialVersionUID = 4412022926028300317L;

      // Field names are fixed by serialization spec.
      private List parent;
      private int indexInParent;

      public AccessibleAWTListChild(List parent, int indexInParent)
      {
        this.parent = parent;
        this.indexInParent = indexInParent;
        if (parent == null)
          this.indexInParent = -1;
      }

      /* (non-Javadoc)
       * @see javax.accessibility.Accessible#getAccessibleContext()
       */
      public AccessibleContext getAccessibleContext()
      {
        return this;
      }

      public AccessibleRole getAccessibleRole()
      {
        return AccessibleRole.LIST_ITEM;
      }

      public AccessibleStateSet getAccessibleStateSet()
      {
        AccessibleStateSet states = super.getAccessibleStateSet();
        if (parent.isIndexSelected(indexInParent))
          states.add(AccessibleState.SELECTED);
        return states;
      }

      public int getAccessibleIndexInParent()
      {
        return indexInParent;
      }

    }

    public AccessibleAWTList()
    {
      addItemListener(this);
      addActionListener(this);
    }

    public AccessibleRole getAccessibleRole()
    {
      return AccessibleRole.LIST;
    }

    public AccessibleStateSet getAccessibleStateSet()
    {
      AccessibleStateSet states = super.getAccessibleStateSet();
      states.add(AccessibleState.SELECTABLE);
      if (isMultipleMode())
        states.add(AccessibleState.MULTISELECTABLE);
      return states;
    }

    public int getAccessibleChildrenCount()
    {
      return getItemCount();
    }

    public Accessible getAccessibleChild(int i)
    {
      if (i >= getItemCount())
        return null;
      return new AccessibleAWTListChild(List.this, i);
    }

    /* (non-Javadoc)
     * @see javax.accessibility.AccessibleSelection#getAccessibleSelectionCount()
     */
    public int getAccessibleSelectionCount()
    {
      return getSelectedIndexes().length;
    }

    /* (non-Javadoc)
     * @see javax.accessibility.AccessibleSelection#getAccessibleSelection()
     */
    public AccessibleSelection getAccessibleSelection()
    {
      return this;
    }

    /* (non-Javadoc)
     * @see javax.accessibility.AccessibleSelection#getAccessibleSelection(int)
     */
    public Accessible getAccessibleSelection(int i)
    {
      int[] items = getSelectedIndexes();
      if (i >= items.length)
        return null;
      return new AccessibleAWTListChild(List.this, items[i]);
    }

    /* (non-Javadoc)
     * @see javax.accessibility.AccessibleSelection#isAccessibleChildSelected(int)
     */
    public boolean isAccessibleChildSelected(int i)
    {
      return isIndexSelected(i);
    }

    /* (non-Javadoc)
     * @see javax.accessibility.AccessibleSelection#addAccessibleSelection(int)
     */
    public void addAccessibleSelection(int i)
    {
      select(i);
    }

    /* (non-Javadoc)
     * @see javax.accessibility.AccessibleSelection#removeAccessibleSelection(int)
     */
    public void removeAccessibleSelection(int i)
    {
      deselect(i);
    }

    /* (non-Javadoc)
     * @see javax.accessibility.AccessibleSelection#clearAccessibleSelection()
     */
    public void clearAccessibleSelection()
    {
      for (int i = 0; i < getItemCount(); i++)
        deselect(i);
    }

    /* (non-Javadoc)
     * @see javax.accessibility.AccessibleSelection#selectAllAccessibleSelection()
     */
    public void selectAllAccessibleSelection()
    {
      if (isMultipleMode())
        for (int i = 0; i < getItemCount(); i++)
          select(i);
    }

    /* (non-Javadoc)
     * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent)
     */
    public void itemStateChanged(ItemEvent event)
    {
    }

    /* (non-Javadoc)
     * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
     */
    public void actionPerformed(ActionEvent event)
    {
    }

  }

  /**
   * Gets the AccessibleContext associated with this <code>List</code>.
   * The context is created, if necessary.
   *
   * @return the associated context
   */
  public AccessibleContext getAccessibleContext()
  {
    /* Create the context if this is the first request */
    if (accessibleContext == null)
      accessibleContext = new AccessibleAWTList();
    return accessibleContext;
  }

  /**
   * Generate a unique name for this <code>List</code>.
   *
   * @return A unique name for this <code>List</code>.
   */
  String generateName()
  {
    return "list" + getUniqueLong();
  }

  private static synchronized long getUniqueLong()
  {
    return next_list_number++;
  }
} // class List
