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

This file is part of GNU Classpath.

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

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

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

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

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


package javax.swing;

import java.awt.ItemSelectable;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Vector;

import javax.accessibility.Accessible;
import javax.accessibility.AccessibleAction;
import javax.accessibility.AccessibleContext;
import javax.accessibility.AccessibleRole;
import javax.accessibility.AccessibleSelection;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.plaf.ComboBoxUI;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.basic.ComboPopup;

/**
 * A component that allows a user to select any item in its list and
 * displays the selected item to the user. JComboBox also can show/hide a
 * popup menu containing its list of item whenever the mouse is pressed
 * over it.
 *
 * @author Andrew Selkirk
 * @author Olga Rodimina
 * @author Robert Schuster
 */
public class JComboBox extends JComponent implements ItemSelectable,
                                                     ListDataListener,
                                                     ActionListener,
                                                     Accessible
{

  private static final long serialVersionUID = 5654585963292734470L;

  /**
   * Classes implementing this interface are
   * responsible for matching key characters typed by the user with combo
   * box's items.
   */
  public static interface KeySelectionManager
  {
    int selectionForKey(char aKey, ComboBoxModel aModel);
  }

  /**
   * Maximum number of rows that should be visible by default  in the
   * JComboBox's popup
   */
  private static final int DEFAULT_MAXIMUM_ROW_COUNT = 8;

  /**
   * Data model used by JComboBox to keep track of its list data and currently
   * selected element in the list.
   */
  protected ComboBoxModel dataModel;

  /**
   * Renderer renders(paints) every object in the combo box list in its
   * associated list cell. This ListCellRenderer is used only when  this
   * JComboBox is uneditable.
   */
  protected ListCellRenderer renderer;

  /**
   * Editor that is responsible for editing an object in a combo box list.
   */
  protected ComboBoxEditor editor;

  /**
   * Number of rows that will be visible in the JComboBox's popup.
   */
  protected int maximumRowCount;

  /**
   * This field indicates if textfield of this JComboBox is editable or not.
   */
  protected boolean isEditable;

  /**
   * This field is reference to the current selection of the combo box.
   */
  protected Object selectedItemReminder;

  /**
   * keySelectionManager
   */
  protected KeySelectionManager keySelectionManager;

  /**
   * This actionCommand is used in ActionEvent that is fired to JComboBox's
   * ActionListeneres.
   */
  protected String actionCommand;

  /**
   * This property indicates if heavyweight popup or lightweight popup will be
   * used to diplay JComboBox's elements.
   */
  protected boolean lightWeightPopupEnabled;

  /**
   * The action taken when new item is selected in the JComboBox
   */
  private Action action;

  /**
   * since 1.4  If this field is set then comboBox's display area for the
   * selected item  will be set by default to this value.
   */
  private Object prototypeDisplayValue;

  /**
   * Constructs JComboBox object with specified data model for it.
   * <p>Note that the JComboBox will not change the value that
   * is preselected by your ComboBoxModel implementation.</p>
   *
   * @param model Data model that will be used by this JComboBox to keep track
   *        of its list of items.
   */
  public JComboBox(ComboBoxModel model)
  {
    setEditable(false);
    setEnabled(true);
    setMaximumRowCount(DEFAULT_MAXIMUM_ROW_COUNT);
    setModel(model);
    setActionCommand("comboBoxChanged");

    lightWeightPopupEnabled = true;
    isEditable = false;

    updateUI();
  }

  /**
   * Constructs JComboBox with specified list of items.
   *
   * @param itemArray array containing list of items for this JComboBox
   */
  public JComboBox(Object[] itemArray)
  {
    this(new DefaultComboBoxModel(itemArray));
    
    if (itemArray.length > 0) 
      setSelectedIndex(0);
  }

  /**
   * Constructs JComboBox object with specified list of items.
   *
   * @param itemVector vector containing list of items for this JComboBox.
   */
  public JComboBox(Vector itemVector)
  {
    this(new DefaultComboBoxModel(itemVector));

    if (itemVector.size() > 0)
      setSelectedIndex(0);
  }

  /**
   * Constructor. Creates new empty JComboBox. ComboBox's data model is set to
   * DefaultComboBoxModel.
   */
  public JComboBox()
  {
    this(new DefaultComboBoxModel());
  }

  /**
   * This method returns true JComboBox is editable and false otherwise
   *
   * @return boolean true if JComboBox is editable and false otherwise
   */
  public boolean isEditable()
  {
    return isEditable;
  }

  /*
   * This method adds ancestor listener to this JComboBox.
   */
  protected void installAncestorListener()
  {
    /* FIXME: Need to implement.
     *
     * Need to add ancestor listener to this JComboBox. This listener
     * should close combo box's popup list of items whenever it
     * receives an AncestorEvent.
     */
  }

  /**
   * Set the "UI" property of the combo box, which is a look and feel class
   * responsible for handling comboBox's input events and painting it.
   *
   * @param ui The new "UI" property
   */
  public void setUI(ComboBoxUI ui)
  {
    super.setUI(ui);
  }

  /**
   * This method sets this comboBox's UI to the UIManager's default for the
   * current look and feel.
   */
  public void updateUI()
  {
    setUI((ComboBoxUI) UIManager.getUI(this));
  }

  /**
   * This method returns the String identifier for the UI class to the used
   * with the JComboBox.
   *
   * @return The String identifier for the UI class.
   */
  public String getUIClassID()
  {
    return "ComboBoxUI";
  }

  /**
   * This method returns the UI used to display the JComboBox.
   *
   * @return The UI used to display the JComboBox.
   */
  public ComboBoxUI getUI()
  {
    return (ComboBoxUI) ui;
  }

  /**
   * Set the data model for this JComboBox. This un-registers all  listeners
   * associated with the current model, and re-registers them with the new
   * model.
   *
   * @param newDataModel The new data model for this JComboBox
   */
  public void setModel(ComboBoxModel newDataModel)
  {
    // dataModel is null if it this method is called from inside the constructors.
    if (dataModel != null)
      {
        // Prevents unneccessary updates.
        if (dataModel == newDataModel)
          return;

        // Removes itself (as DataListener) from the to-be-replaced model.
        dataModel.removeListDataListener(this);
      }
    
    /* Adds itself as a DataListener to the new model.
     * It is intentioned that this operation will fail with a NullPointerException if the
     * caller delivered a null argument.
     */
    newDataModel.addListDataListener(this);

    // Stores old data model for event notification.
    ComboBoxModel oldDataModel = dataModel;
    dataModel = newDataModel;
    selectedItemReminder = newDataModel.getSelectedItem();
    
    // Notifies the listeners of the model change.
    firePropertyChange("model", oldDataModel, dataModel);
  }

  /**
   * This method returns data model for this comboBox.
   *
   * @return ComboBoxModel containing items for this combo box.
   */
  public ComboBoxModel getModel()
  {
    return dataModel;
  }

  /**
   * This method sets JComboBox's popup to be either lightweight or
   * heavyweight. If 'enabled' is true then lightweight popup is used and
   * heavyweight otherwise. By default lightweight popup is used to display
   * this JComboBox's elements.
   *
   * @param enabled indicates if lightweight popup or heavyweight popup should
   *        be used to display JComboBox's elements.
   */
  public void setLightWeightPopupEnabled(boolean enabled)
  {
    lightWeightPopupEnabled = enabled;
  }

  /**
   * This method returns whether popup menu that is used to display list of
   * combo box's item is lightWeight or not.
   *
   * @return boolean true if popup menu is lightweight and false otherwise.
   */
  public boolean isLightWeightPopupEnabled()
  {
    return lightWeightPopupEnabled;
  }

  /**
   * This method sets editability of the combo box. If combo box  is editable
   * the user can choose component from the combo box list by typing
   * component's name in the editor(JTextfield by default).  Otherwise if not
   * editable, the user should use the list to choose   the component. This
   * method fires PropertyChangeEvents to JComboBox's registered
   * PropertyChangeListeners to indicate that 'editable' property of the
   * JComboBox has changed.
   *
   * @param editable indicates if the JComboBox's textfield should be editable
   *        or not.
   */
  public void setEditable(boolean editable)
  {
    if (isEditable != editable)
      {
        isEditable = editable;
        firePropertyChange("editable", !isEditable, isEditable);
      }
  }

  /**
   * Sets number of rows that should be visible in this JComboBox's popup. If
   * this JComboBox's popup has more elements that maximum number or rows
   * then popup will have a scroll pane to allow users to view other
   * elements.
   *
   * @param rowCount number of rows that will be visible in JComboBox's popup.
   */
  public void setMaximumRowCount(int rowCount)
  {
    if (maximumRowCount != rowCount)
      {
        int oldMaximumRowCount = maximumRowCount;
        maximumRowCount = rowCount;
        firePropertyChange("maximumRowCount", oldMaximumRowCount,
                           maximumRowCount);
      }
  }

  /**
   * This method returns number of rows visible in the JComboBox's list of
   * items.
   *
   * @return int maximun number of visible rows in the JComboBox's list.
   */
  public int getMaximumRowCount()
  {
    return maximumRowCount;
  }

  /**
   * This method sets cell renderer for this JComboBox that will be used to
   * paint combo box's items. The Renderer should only be used only when
   * JComboBox is not editable.  In the case when JComboBox is editable  the
   * editor must be used.  This method also fires PropertyChangeEvent when
   * cellRendered for this JComboBox has changed.
   *
   * @param aRenderer cell renderer that will be used by this JComboBox to
   *        paint its elements.
   */
  public void setRenderer(ListCellRenderer aRenderer)
  {
    if (renderer != aRenderer)
      {
        ListCellRenderer oldRenderer = renderer;
        renderer = aRenderer;
        firePropertyChange("renderer", oldRenderer, renderer);
      }
  }

  /**
   * This method returns renderer responsible for rendering selected item in
   * the combo box
   *
   * @return ListCellRenderer
   */
  public ListCellRenderer getRenderer()
  {
    return renderer;
  }

  /**
   * Sets editor for this JComboBox
   *
   * @param newEditor ComboBoxEditor for this JComboBox. This method fires
   *        PropertyChangeEvent when 'editor' property is changed.
   */
  public void setEditor(ComboBoxEditor newEditor)
  {
    if (editor == newEditor)
      return;

    if (editor != null)
      editor.removeActionListener(this);

    ComboBoxEditor oldEditor = editor;
    editor = newEditor;

    if (editor != null)
      editor.addActionListener(this);

    firePropertyChange("editor", oldEditor, editor);
  }

  /**
   * Returns editor component that is responsible for displaying/editing
   * selected item in the combo box.
   *
   * @return ComboBoxEditor
   */
  public ComboBoxEditor getEditor()
  {
    return editor;
  }

  /**
   * Forces combo box to select given item
   *
   * @param item element in the combo box to select.
   */
  public void setSelectedItem(Object item)
  {
    dataModel.setSelectedItem(item);
    fireActionEvent();
  }

  /**
   * Returns currently selected item in the combo box.
   * The result may be <code>null</code> to indicate that nothing is
   * currently selected.
   *
   * @return element that is currently selected in this combo box.
   */
  public Object getSelectedItem()
  {
    return dataModel.getSelectedItem();
  }

  /**
   * Forces JComboBox to select component located in the given index in the
   * combo box.
   * <p>If the index is below -1 or exceeds the upper bound an
   * <code>IllegalArgumentException</code> is thrown.<p/>
   * <p>If the index is -1 then no item gets selected.</p>
   *
   * @param index index specifying location of the component that  should be
   *        selected.
   */
  public void setSelectedIndex(int index)
  {
  	if (index < -1 || index >= dataModel.getSize())
      // Fails because index is out of bounds.
      throw new IllegalArgumentException("illegal index: " + index);
    else
       // Selects the item at the given index or clears the selection if the
       // index value is -1.
      setSelectedItem((index == -1) ? null : dataModel.getElementAt(index));
  }

  /**
   * Returns index of the item that is currently selected in the combo box. If
   * no item is currently selected, then -1 is returned.
   * <p>
   * Note: For performance reasons you should minimize invocation of this
   * method. If the data model is not an instance of
   * <code>DefaultComboBoxModel</code> the complexity is O(n) where n is the
   * number of elements in the combo box.
   * </p>
   * 
   * @return int Index specifying location of the currently selected item in the
   *         combo box or -1 if nothing is selected in the combo box.
   */
  public int getSelectedIndex()
  {
    Object selectedItem = getSelectedItem();

    if (selectedItem != null)
      {
        if (dataModel instanceof DefaultComboBoxModel)
          // Uses special method of DefaultComboBoxModel to retrieve the index.
          return ((DefaultComboBoxModel) dataModel).getIndexOf(selectedItem);
        else
          {
            // Iterates over all items to retrieve the index.
            int size = dataModel.getSize();

            for (int i = 0; i < size; i++)
              {
                Object o = dataModel.getElementAt(i);

                // XXX: Is special handling of ComparableS neccessary?
                if ((selectedItem != null) ? selectedItem.equals(o) : o == null)
                  return i;
              }
          }
      }

    // returns that no item is currently selected
    return -1;
  }

  /**
   * Returns an object that is used as the display value when calculating the 
   * preferred size for the combo box.  This value is, of course, never 
   * displayed anywhere.
   * 
   * @return The prototype display value (possibly <code>null</code>).
   * 
   * @since 1.4
   * @see #setPrototypeDisplayValue(Object)
   */
  public Object getPrototypeDisplayValue()
  {
    return prototypeDisplayValue;
  }

  /**
   * Sets the object that is assumed to be the displayed item when calculating
   * the preferred size for the combo box.  A {@link PropertyChangeEvent} (with
   * the name <code>prototypeDisplayValue</code>) is sent to all registered 
   * listeners. 
   * 
   * @param value  the new value (<code>null</code> permitted).
   * 
   * @since 1.4
   * @see #getPrototypeDisplayValue()
   */
  public void setPrototypeDisplayValue(Object value)
  {
    Object oldValue = prototypeDisplayValue;
    prototypeDisplayValue = value;
    firePropertyChange("prototypeDisplayValue", oldValue, value);
  }

  /**
   * This method adds given element to this JComboBox.
   * <p>A <code>RuntimeException</code> is thrown if the data model is not
   * an instance of {@link MutableComboBoxModel}.</p>
   *
   * @param element element to add
   */
  public void addItem(Object element)
  {
  	if (dataModel instanceof MutableComboBoxModel)
      ((MutableComboBoxModel) dataModel).addElement(element);
    else
      throw new RuntimeException("Unable to add the item because the data "
                                 + "model it is not an instance of "
                                 + "MutableComboBoxModel.");
  }

  /**
   * Inserts given element at the specified index to this JComboBox.
   * <p>A <code>RuntimeException</code> is thrown if the data model is not
   * an instance of {@link MutableComboBoxModel}.</p>
   *
   * @param element element to insert
   * @param index position where to insert the element
   */
  public void insertItemAt(Object element, int index)
  {
	if (dataModel instanceof MutableComboBoxModel)
      ((MutableComboBoxModel) dataModel).insertElementAt(element, index);
    else
      throw new RuntimeException("Unable to insert the item because the data "
                                 + "model it is not an instance of "
                                 + "MutableComboBoxModel.");
  }

  /**
   * This method removes given element from this JComboBox.
   * <p>A <code>RuntimeException</code> is thrown if the data model is not
   * an instance of {@link MutableComboBoxModel}.</p>
   *
   * @param element element to remove
   */
  public void removeItem(Object element)
  {
	if (dataModel instanceof MutableComboBoxModel)
      ((MutableComboBoxModel) dataModel).removeElement(element);
    else
      throw new RuntimeException("Unable to remove the item because the data "
                                 + "model it is not an instance of "
                                 + "MutableComboBoxModel.");
  }

  /**
   * This method remove element location in the specified index in the
   * JComboBox.
   * <p>A <code>RuntimeException</code> is thrown if the data model is not
   * an instance of {@link MutableComboBoxModel}.</p>
   *
   * @param index index specifying position of the element to remove
   */
  public void removeItemAt(int index)
  {
    if (dataModel instanceof MutableComboBoxModel)
      ((MutableComboBoxModel) dataModel).removeElementAt(index);
    else
      throw new RuntimeException("Unable to remove the item because the data "
                                 + "model it is not an instance of "
                                 + "MutableComboBoxModel.");
  }

  /**
   * This method removes all elements from this JComboBox.
   * <p>
   * A <code>RuntimeException</code> is thrown if the data model is not an
   * instance of {@link MutableComboBoxModel}.
   * </p>
   */
  public void removeAllItems()
  {
    if (dataModel instanceof DefaultComboBoxModel)
      // Uses special method if we have a DefaultComboBoxModel.
      ((DefaultComboBoxModel) dataModel).removeAllElements();
    else if (dataModel instanceof MutableComboBoxModel)
      {
        // Iterates over all items and removes each.
        MutableComboBoxModel mcbm = (MutableComboBoxModel) dataModel;

         // We intentionally remove the items backwards to support models which
         // shift their content to the beginning (e.g. linked lists)
        for (int i = mcbm.getSize() - 1; i >= 0; i--)
          mcbm.removeElementAt(i);
      }
    else
      throw new RuntimeException("Unable to remove the items because the data "
                                 + "model it is not an instance of "
                                 + "MutableComboBoxModel.");
  }

  /**
   * This method displays popup with list of combo box's items on the screen
   */
  public void showPopup()
  {
    setPopupVisible(true);
  }

  /**
   * This method hides popup containing list of combo box's items
   */
  public void hidePopup()
  {
    setPopupVisible(false);
  }

  /**
   * This method either displayes or hides the popup containing  list of combo
   * box's items.
   *
   * @param visible show popup if 'visible' is true and hide it otherwise
   */
  public void setPopupVisible(boolean visible)
  {
    getUI().setPopupVisible(this, visible);
  }

  /**
   * Checks if popup is currently visible on the screen.
   *
   * @return boolean true if popup is visible and false otherwise
   */
  public boolean isPopupVisible()
  {
    return getUI().isPopupVisible(this);
  }

  /**
   * This method sets actionCommand to the specified string. ActionEvent fired
   * to this JComboBox  registered ActionListeners will contain this
   * actionCommand.
   *
   * @param aCommand new action command for the JComboBox's ActionEvent
   */
  public void setActionCommand(String aCommand)
  {
    actionCommand = aCommand;
  }

  /**
   * Returns actionCommand associated with the ActionEvent fired by the
   * JComboBox to its registered ActionListeners.
   *
   * @return String actionCommand for the ActionEvent
   */
  public String getActionCommand()
  {
    return actionCommand;
  }

  /**
   * setAction
   *
   * @param a action to set
   */
  public void setAction(Action a)
  {
    Action old = action;
    action = a;
    configurePropertiesFromAction(action);
    if (action != null)
      // FIXME: remove from old action and add to new action 
      // PropertyChangeListener to listen to changes in the action
      addActionListener(action);
  }

  /**
   * This method returns Action that is invoked when selected item is changed
   * in the JComboBox.
   *
   * @return Action
   */
  public Action getAction()
  {
    return action;
  }

  /**
   * Configure properties of the JComboBox by reading properties of specified
   * action. This method always sets the comboBox's "enabled" property to the
   * value of the Action's "enabled" property.
   *
   * @param a An Action to configure the combo box from
   */
  protected void configurePropertiesFromAction(Action a)
  {
    if (a == null)
      {
        setEnabled(true);
        setToolTipText(null);
      }
    else
      {
        setEnabled(a.isEnabled());
        setToolTipText((String) (a.getValue(Action.SHORT_DESCRIPTION)));
      }
  }

  /**
   * Creates PropertyChangeListener to listen for the changes in comboBox's
   * action properties.
   *
   * @param action action to listen to for property changes
   *
   * @return a PropertyChangeListener that listens to changes in
   *         action properties.
   */
  protected PropertyChangeListener createActionPropertyChangeListener(Action action)
  {
    return new PropertyChangeListener()
      {
        public void propertyChange(PropertyChangeEvent e)
        {
          Action act = (Action) (e.getSource());
          configurePropertiesFromAction(act);
        }
      };
  }

  /**
   * This method fires ItemEvent to this JComboBox's registered ItemListeners.
   * This method is invoked when currently selected item in this combo box
   * has changed.
   *
   * @param e the ItemEvent describing the change in the combo box's
   *        selection.
   */
  protected void fireItemStateChanged(ItemEvent e)
  {
    ItemListener[] ll = getItemListeners();

    for (int i = 0; i < ll.length; i++)
      ll[i].itemStateChanged(e);
  }

  /**
   * This method fires ActionEvent to this JComboBox's registered
   * ActionListeners. This method is invoked when user explicitly changes
   * currently selected item.
   */
  protected void fireActionEvent()
  {
    ActionListener[] ll = getActionListeners();

    for (int i = 0; i < ll.length; i++)
      ll[i].actionPerformed(new ActionEvent(this,
                                            ActionEvent.ACTION_PERFORMED,
                                            actionCommand));
  }

  /**
   * Fires a popupMenuCanceled() event to all <code>PopupMenuListeners</code>.
   *
   * Note: This method is intended for use by plaf classes only.
   */
  public void firePopupMenuCanceled()
  {
    PopupMenuListener[] listeners = getPopupMenuListeners();
    PopupMenuEvent e = new PopupMenuEvent(this);
    for (int i = 0; i < listeners.length; i++)
      listeners[i].popupMenuCanceled(e);
  }

  /**
   * Fires a popupMenuWillBecomeInvisible() event to all 
   * <code>PopupMenuListeners</code>.
   *
   * Note: This method is intended for use by plaf classes only.
   */
  public void firePopupMenuWillBecomeInvisible()
  {
    PopupMenuListener[] listeners = getPopupMenuListeners();
    PopupMenuEvent e = new PopupMenuEvent(this);
    for (int i = 0; i < listeners.length; i++)
      listeners[i].popupMenuWillBecomeInvisible(e);
  }

  /**
   * Fires a popupMenuWillBecomeVisible() event to all 
   * <code>PopupMenuListeners</code>.
   *
   * Note: This method is intended for use by plaf classes only.
   */
  public void firePopupMenuWillBecomeVisible()
  {
    PopupMenuListener[] listeners = getPopupMenuListeners();
    PopupMenuEvent e = new PopupMenuEvent(this);
    for (int i = 0; i < listeners.length; i++)
      listeners[i].popupMenuWillBecomeVisible(e);
  }

  /**
   * This method is invoked whenever selected item changes in the combo box's
   * data model. It fires ItemEvent and ActionEvent to all registered
   * ComboBox's ItemListeners and ActionListeners respectively, indicating
   * the change.
   */
  protected void selectedItemChanged()
  {
    // Fire ItemEvent to indicated that previously selected item is now
    // deselected        
    if (selectedItemReminder != null)
      fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED,
                                         selectedItemReminder,
                                         ItemEvent.DESELECTED));

    // Fire ItemEvent to indicate that new item is selected    
    Object newSelection = getSelectedItem();
    if (newSelection != null)
      fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED,
                                         newSelection, ItemEvent.SELECTED));

    // Fire Action Event to JComboBox's registered listeners					 				 
    fireActionEvent();

    selectedItemReminder = newSelection;
  }

  /**
   * Returns Object array of size 1 containing currently selected element in
   * the JComboBox.
   *
   * @return Object[] Object array of size 1 containing currently selected
   *         element in the JComboBox.
   */
  public Object[] getSelectedObjects()
  {
    return new Object[] { getSelectedItem() };
  }

  /**
   * This method handles actionEvents fired by the ComboBoxEditor. It changes
   * this JComboBox's selection to the new value currently in the editor and
   * hides list of combo box items.
   *
   * @param e the ActionEvent
   */
  public void actionPerformed(ActionEvent e)
  {
    setSelectedItem(getEditor().getItem());
    setPopupVisible(false);
  }

  /**
   * This method selects item in this combo box that matches specified
   * specified keyChar and returns true if such item is found. Otherwise
   * false is returned.
   *
   * @param keyChar character indicating which item in the combo box should be
   *        selected.
   *
   * @return boolean true if item corresponding to the specified keyChar
   *         exists in the combo box. Otherwise false is returned.
   */
  public boolean selectWithKeyChar(char keyChar)
  {
    if (keySelectionManager == null)
      {
        keySelectionManager = createDefaultKeySelectionManager();
      }

    int index = keySelectionManager.selectionForKey(keyChar, getModel());
    boolean retVal = false;
    if (index >= 0)
      {
        setSelectedIndex(index);
        retVal = true;
      }
    return retVal;
  }

  /**
   * The part of implementation of ListDataListener interface. This method is
   * invoked when some items where added to the JComboBox's data model.
   *
   * @param event ListDataEvent describing the change
   */
  public void intervalAdded(ListDataEvent event)
  {
    // FIXME: Need to implement
    repaint();
  }

  /**
   * The part of implementation of ListDataListener interface. This method is
   * invoked when some items where removed from the JComboBox's data model.
   *
   * @param event ListDataEvent describing the change.
   */
  public void intervalRemoved(ListDataEvent event)
  {
    // FIXME: Need to implement
    repaint();
  }

  /**
   * The part of implementation of ListDataListener interface. This method is
   * invoked when contents of the JComboBox's  data model changed.
   *
   * @param event ListDataEvent describing the change
   */
  public void contentsChanged(ListDataEvent event)
  {
    // if first and last index of the given ListDataEvent are both -1,
    // then it indicates that selected item in the combo box data model
    // have changed. 
    if (event.getIndex0() == -1 && event.getIndex1() == -1)
      selectedItemChanged();
  }

  /**
   * This method disables or enables JComboBox. If the JComboBox is enabled,
   * then user is able to make item choice, otherwise if JComboBox is
   * disabled then user is not able to make a selection.
   *
   * @param enabled if 'enabled' is true then enable JComboBox and disable it
   */
  public void setEnabled(boolean enabled)
  {
    boolean oldEnabled = super.isEnabled();
    if (enabled != oldEnabled)
      {
        super.setEnabled(enabled);
        firePropertyChange("enabled", oldEnabled, enabled);
      }
  }

  /**
   * This method initializes specified ComboBoxEditor to display given item.
   *
   * @param anEditor ComboBoxEditor to initialize
   * @param anItem Item that should displayed in the specified editor
   */
  public void configureEditor(ComboBoxEditor anEditor, Object anItem)
  {
    anEditor.setItem(anItem);
  }

  /**
   * This method is fired whenever a key is pressed with the combo box
   * in focus
   *
   * @param e The KeyEvent indicating which key was pressed.
   */
  public void processKeyEvent(KeyEvent e)
  {
    if (e.getKeyCode() == KeyEvent.VK_TAB)
      setPopupVisible(false);
    else
      super.processKeyEvent(e);
  }

  /**
   * setKeySelectionManager
   *
   * @param aManager
   */
  public void setKeySelectionManager(KeySelectionManager aManager)
  {
    keySelectionManager = aManager;
  }

  /**
   * getKeySelectionManager
   *
   * @return JComboBox.KeySelectionManager
   */
  public KeySelectionManager getKeySelectionManager()
  {
    return keySelectionManager;
  }

  /**
   * This method returns number of elements in this JComboBox
   *
   * @return int number of elements in this JComboBox
   */
  public int getItemCount()
  {
    return dataModel.getSize();
  }

  /**
   * Returns elements located in the combo box at the given index.
   *
   * @param index index specifying location of the component to  return.
   *
   * @return component in the combo box that is located in  the given index.
   */
  public Object getItemAt(int index)
  {
    return dataModel.getElementAt(index);
  }

  /**
   * createDefaultKeySelectionManager
   *
   * @return KeySelectionManager
   */
  protected KeySelectionManager createDefaultKeySelectionManager()
  {
    return new DefaultKeySelectionManager();
  }

  /**
   * Returns an implementation-dependent string describing the attributes of
   * this <code>JComboBox</code>.
   *
   * @return A string describing the attributes of this <code>JComboBox</code>
   *         (never <code>null</code>).
   */
  protected String paramString()
  {
    String superParamStr = super.paramString();
    StringBuffer sb = new StringBuffer();
    sb.append(",isEditable=").append(isEditable());
    sb.append(",lightWeightPopupEnabled=").append(isLightWeightPopupEnabled());
    sb.append(",maximumRowCount=").append(getMaximumRowCount());
    
    sb.append(",selectedItemReminder=");
    if (selectedItemReminder != null)
      sb.append(selectedItemReminder);
    return superParamStr + sb.toString();
  }

  /**
   * Returns the object that provides accessibility features for this
   * <code>JComboBox</code> component.
   *
   * @return The accessible context (an instance of 
   *         {@link AccessibleJComboBox}).
   */
  public AccessibleContext getAccessibleContext()
  {
    if (accessibleContext == null)
      accessibleContext = new AccessibleJComboBox();

    return accessibleContext;
  }

  /**
   * This methods adds specified ActionListener to this JComboBox.
   *
   * @param listener to add
   */
  public void addActionListener(ActionListener listener)
  {
    listenerList.add(ActionListener.class, listener);
  }

  /**
   * This method removes specified ActionListener from this JComboBox.
   *
   * @param listener ActionListener
   */
  public void removeActionListener(ActionListener listener)
  {
    listenerList.remove(ActionListener.class, listener);
  }

  /**
   * This method returns array of ActionListeners that are registered with
   * this JComboBox.
   *
   * @since 1.4
   */
  public ActionListener[] getActionListeners()
  {
    return (ActionListener[]) getListeners(ActionListener.class);
  }

  /**
   * This method registers given ItemListener with this JComboBox
   *
   * @param listener to remove
   */
  public void addItemListener(ItemListener listener)
  {
    listenerList.add(ItemListener.class, listener);
  }

  /**
   * This method unregisters given ItemListener from this JComboBox
   *
   * @param listener to remove
   */
  public void removeItemListener(ItemListener listener)
  {
    listenerList.remove(ItemListener.class, listener);
  }

  /**
   * This method returns array of ItemListeners that are registered with this
   * JComboBox.
   *
   * @since 1.4
   */
  public ItemListener[] getItemListeners()
  {
    return (ItemListener[]) getListeners(ItemListener.class);
  }

  /**
   * Adds PopupMenuListener to combo box to listen to the events fired by the
   * combo box's popup menu containing its list of items
   *
   * @param listener to add
   */
  public void addPopupMenuListener(PopupMenuListener listener)
  {
    listenerList.add(PopupMenuListener.class, listener);
  }

  /**
   * Removes PopupMenuListener to combo box to listen to the events fired by
   * the combo box's popup menu containing its list of items
   *
   * @param listener to add
   */
  public void removePopupMenuListener(PopupMenuListener listener)
  {
    listenerList.remove(PopupMenuListener.class, listener);
  }

  /**
   * Returns array of PopupMenuListeners that are registered with  combo box.
   */
  public PopupMenuListener[] getPopupMenuListeners()
  {
    return (PopupMenuListener[]) getListeners(PopupMenuListener.class);
  }

  /**
   * Accessibility support for <code>JComboBox</code>.
   */
  protected class AccessibleJComboBox extends AccessibleJComponent
    implements AccessibleAction, AccessibleSelection
  {
    private static final long serialVersionUID = 8217828307256675666L;

    /**
     * @specnote This constructor was protected in 1.4, but made public
     * in 1.5.
     */
    public AccessibleJComboBox()
    {
      // Nothing to do here.
    }

    /**
     * Returns the number of accessible children of this object. The
     * implementation of AccessibleJComboBox delegates this call to the UI
     * of the associated JComboBox.
     *
     * @return the number of accessible children of this object
     *
     * @see ComponentUI#getAccessibleChildrenCount(JComponent)
     */
    public int getAccessibleChildrenCount()
    {
      ComponentUI ui = getUI();
      int count;
      if (ui != null)
        count = ui.getAccessibleChildrenCount(JComboBox.this);
      else
        count = super.getAccessibleChildrenCount();
      return count;
    }

    /**
     * Returns the number of accessible children of this object. The
     * implementation of AccessibleJComboBox delegates this call to the UI
     * of the associated JComboBox.
     *
     * @param index the index of the accessible child to fetch
     *
     * @return the number of accessible children of this object
     *
     * @see ComponentUI#getAccessibleChild(JComponent, int)
     */
    public Accessible getAccessibleChild(int index)
    {
      ComponentUI ui = getUI();
      Accessible child = null;
      if (ui != null)
        child = ui.getAccessibleChild(JComboBox.this, index);
      else
        child = super.getAccessibleChild(index);
      return child;
    }

    /**
     * Returns the AccessibleSelection object associated with this object.
     * AccessibleJComboBoxes handle their selection themselves, so this
     * always returns <code>this</code>.
     *
     * @return the AccessibleSelection object associated with this object
     */
    public AccessibleSelection getAccessibleSelection()
    {
      return this;
    }

    /**
     * Returns the accessible selection from this AccssibleJComboBox.
     *
     * @param index the index of the selected child to fetch
     *
     * @return the accessible selection from this AccssibleJComboBox
     */
    public Accessible getAccessibleSelection(int index)
    {
      // Get hold of the actual popup.
      Accessible popup = getUI().getAccessibleChild(JComboBox.this, 0);
      Accessible selected = null;
      if (popup != null && popup instanceof ComboPopup)
        {
          ComboPopup cPopup = (ComboPopup) popup;
          // Query the list for the currently selected child.
          JList l = cPopup.getList();
          AccessibleContext listCtx = l.getAccessibleContext();
          if (listCtx != null)
            {
              AccessibleSelection s = listCtx.getAccessibleSelection();
              if (s != null)
                {
                  selected = s.getAccessibleSelection(index);
                }
            }
        }
      return selected;
    }

    /**
     * Returns <code>true</code> if the accessible child with the specified
     * <code>index</code> is selected, <code>false</code> otherwise.
     *
     * @param index the index of the accessible child
     *
     * @return <code>true</code> if the accessible child with the specified
     *         <code>index</code> is selected, <code>false</code> otherwise
     */
    public boolean isAccessibleChildSelected(int index)
    {
      return getSelectedIndex() == index;
    }

    /**
     * Returns the accessible role for the <code>JComboBox</code> component.
     *
     * @return {@link AccessibleRole#COMBO_BOX}.
     */
    public AccessibleRole getAccessibleRole()
    {
      return AccessibleRole.COMBO_BOX;
    }

    /**
     * Returns the accessible action associated to this accessible object.
     * AccessibleJComboBox implements its own AccessibleAction, so this
     * method returns <code>this</code>.
     *
     * @return the accessible action associated to this accessible object
     */
    public AccessibleAction getAccessibleAction()
    {
      return this;
    }

    /**
     * Returns the description of the specified action. AccessibleJComboBox
     * implements 1 action (toggle the popup menu) and thus returns
     * <code>UIManager.getString("ComboBox.togglePopupText")</code>
     *
     * @param actionIndex the index of the action for which to return the
     *        description
     *
     * @return the description of the specified action
     */
    public String getAccessibleActionDescription(int actionIndex)
    {
      return UIManager.getString("ComboBox.togglePopupText");
    }

    /**
     * Returns the number of accessible actions that can be performed by
     * this object. AccessibleJComboBox implement s one accessible action
     * (toggle the popup menu), so this method always returns <code>1</code>.
     *
     * @return the number of accessible actions that can be performed by
     *         this object
     */
    public int getAccessibleActionCount()
    {
      return 1;
    }

    /**
     * Performs the accessible action with the specified index.
     * AccessibleJComboBox has 1 accessible action
     * (<code>actionIndex == 0</code>), which is to toggle the
     * popup menu. All other action indices have no effect and return
     * <code<>false</code>.
     *
     * @param actionIndex the index of the action to perform
     *
     * @return <code>true</code> if the action has been performed,
     *         <code>false</code> otherwise
     */
    public boolean doAccessibleAction(int actionIndex)
    {
      boolean actionPerformed = false;
      if (actionIndex == 0)
        {
          setPopupVisible(! isPopupVisible());
          actionPerformed = true;
        }
      return actionPerformed;
    }

    /**
     * Returns the number of selected accessible children of this object. This
     * returns <code>1</code> if the combobox has a selected entry,
     * <code>0</code> otherwise.
     *
     * @return the number of selected accessible children of this object
     */
    public int getAccessibleSelectionCount()
    {
      Object sel = getSelectedItem();
      int count = 0;
      if (sel != null)
        count = 1;
      return count;
    }

    /**
     * Sets the current selection to the specified <code>index</code>.
     *
     * @param index the index to set as selection
     */
    public void addAccessibleSelection(int index)
    {
      setSelectedIndex(index);
    }

    /**
     * Removes the specified index from the current selection.
     *
     * @param index the index to remove from the selection
     */
    public void removeAccessibleSelection(int index)
    {
      if (getSelectedIndex() == index)
        clearAccessibleSelection();
    }

    /**
     * Clears the current selection.
     */
    public void clearAccessibleSelection()
    {
      setSelectedIndex(-1);
    }

    /**
     * Multiple selection is not supported by AccessibleJComboBox, so this
     * does nothing.
     */
    public void selectAllAccessibleSelection()
    {
      // Nothing to do here.
    }
  }
  
  private class DefaultKeySelectionManager
      implements KeySelectionManager
  {

    public int selectionForKey(char aKey, ComboBoxModel aModel)
    {
      int selectedIndex = getSelectedIndex();

      // Start at currently selected item and iterate to end of list
      for (int i = selectedIndex + 1; i < aModel.getSize(); i++)
        {
          String nextItem = aModel.getElementAt(i).toString();

          if (nextItem.charAt(0) == aKey)
            return i;
        }

      // Wrap to start of list if no match yet
      for (int i = 0; i <= selectedIndex; i++)
        {
          String nextItem = aModel.getElementAt(i).toString();

          if (nextItem.charAt(0) == aKey)
            return i;
        }

      return - 1;
    }
  }
}
