summaryrefslogtreecommitdiff
path: root/libjava/classpath/javax/swing/JComboBox.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/javax/swing/JComboBox.java')
-rw-r--r--libjava/classpath/javax/swing/JComboBox.java1499
1 files changed, 1499 insertions, 0 deletions
diff --git a/libjava/classpath/javax/swing/JComboBox.java b/libjava/classpath/javax/swing/JComboBox.java
new file mode 100644
index 000000000..0d2be0c17
--- /dev/null
+++ b/libjava/classpath/javax/swing/JComboBox.java
@@ -0,0 +1,1499 @@
+/* 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;
+ }
+ }
+}