/* 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 gnu.java.lang.CPStringBuilder;

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();
    CPStringBuilder sb = new CPStringBuilder();
    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;
    }
  }
}
