Source for javax.swing.JComboBox

   1: /* JComboBox.java --
   2:    Copyright (C) 2002, 2004, 2005, 2006,  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package javax.swing;
  40: 
  41: import gnu.java.lang.CPStringBuilder;
  42: 
  43: import java.awt.ItemSelectable;
  44: import java.awt.event.ActionEvent;
  45: import java.awt.event.ActionListener;
  46: import java.awt.event.ItemEvent;
  47: import java.awt.event.ItemListener;
  48: import java.awt.event.KeyEvent;
  49: import java.beans.PropertyChangeEvent;
  50: import java.beans.PropertyChangeListener;
  51: import java.util.Vector;
  52: 
  53: import javax.accessibility.Accessible;
  54: import javax.accessibility.AccessibleAction;
  55: import javax.accessibility.AccessibleContext;
  56: import javax.accessibility.AccessibleRole;
  57: import javax.accessibility.AccessibleSelection;
  58: import javax.swing.event.ListDataEvent;
  59: import javax.swing.event.ListDataListener;
  60: import javax.swing.event.PopupMenuEvent;
  61: import javax.swing.event.PopupMenuListener;
  62: import javax.swing.plaf.ComboBoxUI;
  63: import javax.swing.plaf.ComponentUI;
  64: import javax.swing.plaf.basic.ComboPopup;
  65: 
  66: /**
  67:  * A component that allows a user to select any item in its list and
  68:  * displays the selected item to the user. JComboBox also can show/hide a
  69:  * popup menu containing its list of item whenever the mouse is pressed
  70:  * over it.
  71:  *
  72:  * @author Andrew Selkirk
  73:  * @author Olga Rodimina
  74:  * @author Robert Schuster
  75:  */
  76: public class JComboBox extends JComponent implements ItemSelectable,
  77:                                                      ListDataListener,
  78:                                                      ActionListener,
  79:                                                      Accessible
  80: {
  81: 
  82:   private static final long serialVersionUID = 5654585963292734470L;
  83: 
  84:   /**
  85:    * Classes implementing this interface are
  86:    * responsible for matching key characters typed by the user with combo
  87:    * box's items.
  88:    */
  89:   public static interface KeySelectionManager
  90:   {
  91:     int selectionForKey(char aKey, ComboBoxModel aModel);
  92:   }
  93: 
  94:   /**
  95:    * Maximum number of rows that should be visible by default  in the
  96:    * JComboBox's popup
  97:    */
  98:   private static final int DEFAULT_MAXIMUM_ROW_COUNT = 8;
  99: 
 100:   /**
 101:    * Data model used by JComboBox to keep track of its list data and currently
 102:    * selected element in the list.
 103:    */
 104:   protected ComboBoxModel dataModel;
 105: 
 106:   /**
 107:    * Renderer renders(paints) every object in the combo box list in its
 108:    * associated list cell. This ListCellRenderer is used only when  this
 109:    * JComboBox is uneditable.
 110:    */
 111:   protected ListCellRenderer renderer;
 112: 
 113:   /**
 114:    * Editor that is responsible for editing an object in a combo box list.
 115:    */
 116:   protected ComboBoxEditor editor;
 117: 
 118:   /**
 119:    * Number of rows that will be visible in the JComboBox's popup.
 120:    */
 121:   protected int maximumRowCount;
 122: 
 123:   /**
 124:    * This field indicates if textfield of this JComboBox is editable or not.
 125:    */
 126:   protected boolean isEditable;
 127: 
 128:   /**
 129:    * This field is reference to the current selection of the combo box.
 130:    */
 131:   protected Object selectedItemReminder;
 132: 
 133:   /**
 134:    * keySelectionManager
 135:    */
 136:   protected KeySelectionManager keySelectionManager;
 137: 
 138:   /**
 139:    * This actionCommand is used in ActionEvent that is fired to JComboBox's
 140:    * ActionListeneres.
 141:    */
 142:   protected String actionCommand;
 143: 
 144:   /**
 145:    * This property indicates if heavyweight popup or lightweight popup will be
 146:    * used to diplay JComboBox's elements.
 147:    */
 148:   protected boolean lightWeightPopupEnabled;
 149: 
 150:   /**
 151:    * The action taken when new item is selected in the JComboBox
 152:    */
 153:   private Action action;
 154: 
 155:   /**
 156:    * since 1.4  If this field is set then comboBox's display area for the
 157:    * selected item  will be set by default to this value.
 158:    */
 159:   private Object prototypeDisplayValue;
 160: 
 161:   /**
 162:    * Constructs JComboBox object with specified data model for it.
 163:    * <p>Note that the JComboBox will not change the value that
 164:    * is preselected by your ComboBoxModel implementation.</p>
 165:    *
 166:    * @param model Data model that will be used by this JComboBox to keep track
 167:    *        of its list of items.
 168:    */
 169:   public JComboBox(ComboBoxModel model)
 170:   {
 171:     setEditable(false);
 172:     setEnabled(true);
 173:     setMaximumRowCount(DEFAULT_MAXIMUM_ROW_COUNT);
 174:     setModel(model);
 175:     setActionCommand("comboBoxChanged");
 176: 
 177:     lightWeightPopupEnabled = true;
 178:     isEditable = false;
 179: 
 180:     updateUI();
 181:   }
 182: 
 183:   /**
 184:    * Constructs JComboBox with specified list of items.
 185:    *
 186:    * @param itemArray array containing list of items for this JComboBox
 187:    */
 188:   public JComboBox(Object[] itemArray)
 189:   {
 190:     this(new DefaultComboBoxModel(itemArray));
 191: 
 192:     if (itemArray.length > 0)
 193:       setSelectedIndex(0);
 194:   }
 195: 
 196:   /**
 197:    * Constructs JComboBox object with specified list of items.
 198:    *
 199:    * @param itemVector vector containing list of items for this JComboBox.
 200:    */
 201:   public JComboBox(Vector<?> itemVector)
 202:   {
 203:     this(new DefaultComboBoxModel(itemVector));
 204: 
 205:     if (itemVector.size() > 0)
 206:       setSelectedIndex(0);
 207:   }
 208: 
 209:   /**
 210:    * Constructor. Creates new empty JComboBox. ComboBox's data model is set to
 211:    * DefaultComboBoxModel.
 212:    */
 213:   public JComboBox()
 214:   {
 215:     this(new DefaultComboBoxModel());
 216:   }
 217: 
 218:   /**
 219:    * This method returns true JComboBox is editable and false otherwise
 220:    *
 221:    * @return boolean true if JComboBox is editable and false otherwise
 222:    */
 223:   public boolean isEditable()
 224:   {
 225:     return isEditable;
 226:   }
 227: 
 228:   /*
 229:    * This method adds ancestor listener to this JComboBox.
 230:    */
 231:   protected void installAncestorListener()
 232:   {
 233:     /* FIXME: Need to implement.
 234:      *
 235:      * Need to add ancestor listener to this JComboBox. This listener
 236:      * should close combo box's popup list of items whenever it
 237:      * receives an AncestorEvent.
 238:      */
 239:   }
 240: 
 241:   /**
 242:    * Set the "UI" property of the combo box, which is a look and feel class
 243:    * responsible for handling comboBox's input events and painting it.
 244:    *
 245:    * @param ui The new "UI" property
 246:    */
 247:   public void setUI(ComboBoxUI ui)
 248:   {
 249:     super.setUI(ui);
 250:   }
 251: 
 252:   /**
 253:    * This method sets this comboBox's UI to the UIManager's default for the
 254:    * current look and feel.
 255:    */
 256:   public void updateUI()
 257:   {
 258:     setUI((ComboBoxUI) UIManager.getUI(this));
 259:   }
 260: 
 261:   /**
 262:    * This method returns the String identifier for the UI class to the used
 263:    * with the JComboBox.
 264:    *
 265:    * @return The String identifier for the UI class.
 266:    */
 267:   public String getUIClassID()
 268:   {
 269:     return "ComboBoxUI";
 270:   }
 271: 
 272:   /**
 273:    * This method returns the UI used to display the JComboBox.
 274:    *
 275:    * @return The UI used to display the JComboBox.
 276:    */
 277:   public ComboBoxUI getUI()
 278:   {
 279:     return (ComboBoxUI) ui;
 280:   }
 281: 
 282:   /**
 283:    * Set the data model for this JComboBox. This un-registers all  listeners
 284:    * associated with the current model, and re-registers them with the new
 285:    * model.
 286:    *
 287:    * @param newDataModel The new data model for this JComboBox
 288:    */
 289:   public void setModel(ComboBoxModel newDataModel)
 290:   {
 291:     // dataModel is null if it this method is called from inside the constructors.
 292:     if (dataModel != null)
 293:       {
 294:         // Prevents unneccessary updates.
 295:         if (dataModel == newDataModel)
 296:           return;
 297: 
 298:         // Removes itself (as DataListener) from the to-be-replaced model.
 299:         dataModel.removeListDataListener(this);
 300:       }
 301: 
 302:     /* Adds itself as a DataListener to the new model.
 303:      * It is intentioned that this operation will fail with a NullPointerException if the
 304:      * caller delivered a null argument.
 305:      */
 306:     newDataModel.addListDataListener(this);
 307: 
 308:     // Stores old data model for event notification.
 309:     ComboBoxModel oldDataModel = dataModel;
 310:     dataModel = newDataModel;
 311:     selectedItemReminder = newDataModel.getSelectedItem();
 312: 
 313:     // Notifies the listeners of the model change.
 314:     firePropertyChange("model", oldDataModel, dataModel);
 315:   }
 316: 
 317:   /**
 318:    * This method returns data model for this comboBox.
 319:    *
 320:    * @return ComboBoxModel containing items for this combo box.
 321:    */
 322:   public ComboBoxModel getModel()
 323:   {
 324:     return dataModel;
 325:   }
 326: 
 327:   /**
 328:    * This method sets JComboBox's popup to be either lightweight or
 329:    * heavyweight. If 'enabled' is true then lightweight popup is used and
 330:    * heavyweight otherwise. By default lightweight popup is used to display
 331:    * this JComboBox's elements.
 332:    *
 333:    * @param enabled indicates if lightweight popup or heavyweight popup should
 334:    *        be used to display JComboBox's elements.
 335:    */
 336:   public void setLightWeightPopupEnabled(boolean enabled)
 337:   {
 338:     lightWeightPopupEnabled = enabled;
 339:   }
 340: 
 341:   /**
 342:    * This method returns whether popup menu that is used to display list of
 343:    * combo box's item is lightWeight or not.
 344:    *
 345:    * @return boolean true if popup menu is lightweight and false otherwise.
 346:    */
 347:   public boolean isLightWeightPopupEnabled()
 348:   {
 349:     return lightWeightPopupEnabled;
 350:   }
 351: 
 352:   /**
 353:    * This method sets editability of the combo box. If combo box  is editable
 354:    * the user can choose component from the combo box list by typing
 355:    * component's name in the editor(JTextfield by default).  Otherwise if not
 356:    * editable, the user should use the list to choose   the component. This
 357:    * method fires PropertyChangeEvents to JComboBox's registered
 358:    * PropertyChangeListeners to indicate that 'editable' property of the
 359:    * JComboBox has changed.
 360:    *
 361:    * @param editable indicates if the JComboBox's textfield should be editable
 362:    *        or not.
 363:    */
 364:   public void setEditable(boolean editable)
 365:   {
 366:     if (isEditable != editable)
 367:       {
 368:         isEditable = editable;
 369:         firePropertyChange("editable", !isEditable, isEditable);
 370:       }
 371:   }
 372: 
 373:   /**
 374:    * Sets number of rows that should be visible in this JComboBox's popup. If
 375:    * this JComboBox's popup has more elements that maximum number or rows
 376:    * then popup will have a scroll pane to allow users to view other
 377:    * elements.
 378:    *
 379:    * @param rowCount number of rows that will be visible in JComboBox's popup.
 380:    */
 381:   public void setMaximumRowCount(int rowCount)
 382:   {
 383:     if (maximumRowCount != rowCount)
 384:       {
 385:         int oldMaximumRowCount = maximumRowCount;
 386:         maximumRowCount = rowCount;
 387:         firePropertyChange("maximumRowCount", oldMaximumRowCount,
 388:                            maximumRowCount);
 389:       }
 390:   }
 391: 
 392:   /**
 393:    * This method returns number of rows visible in the JComboBox's list of
 394:    * items.
 395:    *
 396:    * @return int maximun number of visible rows in the JComboBox's list.
 397:    */
 398:   public int getMaximumRowCount()
 399:   {
 400:     return maximumRowCount;
 401:   }
 402: 
 403:   /**
 404:    * This method sets cell renderer for this JComboBox that will be used to
 405:    * paint combo box's items. The Renderer should only be used only when
 406:    * JComboBox is not editable.  In the case when JComboBox is editable  the
 407:    * editor must be used.  This method also fires PropertyChangeEvent when
 408:    * cellRendered for this JComboBox has changed.
 409:    *
 410:    * @param aRenderer cell renderer that will be used by this JComboBox to
 411:    *        paint its elements.
 412:    */
 413:   public void setRenderer(ListCellRenderer aRenderer)
 414:   {
 415:     if (renderer != aRenderer)
 416:       {
 417:         ListCellRenderer oldRenderer = renderer;
 418:         renderer = aRenderer;
 419:         firePropertyChange("renderer", oldRenderer, renderer);
 420:       }
 421:   }
 422: 
 423:   /**
 424:    * This method returns renderer responsible for rendering selected item in
 425:    * the combo box
 426:    *
 427:    * @return ListCellRenderer
 428:    */
 429:   public ListCellRenderer getRenderer()
 430:   {
 431:     return renderer;
 432:   }
 433: 
 434:   /**
 435:    * Sets editor for this JComboBox
 436:    *
 437:    * @param newEditor ComboBoxEditor for this JComboBox. This method fires
 438:    *        PropertyChangeEvent when 'editor' property is changed.
 439:    */
 440:   public void setEditor(ComboBoxEditor newEditor)
 441:   {
 442:     if (editor == newEditor)
 443:       return;
 444: 
 445:     if (editor != null)
 446:       editor.removeActionListener(this);
 447: 
 448:     ComboBoxEditor oldEditor = editor;
 449:     editor = newEditor;
 450: 
 451:     if (editor != null)
 452:       editor.addActionListener(this);
 453: 
 454:     firePropertyChange("editor", oldEditor, editor);
 455:   }
 456: 
 457:   /**
 458:    * Returns editor component that is responsible for displaying/editing
 459:    * selected item in the combo box.
 460:    *
 461:    * @return ComboBoxEditor
 462:    */
 463:   public ComboBoxEditor getEditor()
 464:   {
 465:     return editor;
 466:   }
 467: 
 468:   /**
 469:    * Forces combo box to select given item
 470:    *
 471:    * @param item element in the combo box to select.
 472:    */
 473:   public void setSelectedItem(Object item)
 474:   {
 475:     dataModel.setSelectedItem(item);
 476:     fireActionEvent();
 477:   }
 478: 
 479:   /**
 480:    * Returns currently selected item in the combo box.
 481:    * The result may be <code>null</code> to indicate that nothing is
 482:    * currently selected.
 483:    *
 484:    * @return element that is currently selected in this combo box.
 485:    */
 486:   public Object getSelectedItem()
 487:   {
 488:     return dataModel.getSelectedItem();
 489:   }
 490: 
 491:   /**
 492:    * Forces JComboBox to select component located in the given index in the
 493:    * combo box.
 494:    * <p>If the index is below -1 or exceeds the upper bound an
 495:    * <code>IllegalArgumentException</code> is thrown.<p/>
 496:    * <p>If the index is -1 then no item gets selected.</p>
 497:    *
 498:    * @param index index specifying location of the component that  should be
 499:    *        selected.
 500:    */
 501:   public void setSelectedIndex(int index)
 502:   {
 503:         if (index < -1 || index >= dataModel.getSize())
 504:       // Fails because index is out of bounds.
 505:       throw new IllegalArgumentException("illegal index: " + index);
 506:     else
 507:        // Selects the item at the given index or clears the selection if the
 508:        // index value is -1.
 509:       setSelectedItem((index == -1) ? null : dataModel.getElementAt(index));
 510:   }
 511: 
 512:   /**
 513:    * Returns index of the item that is currently selected in the combo box. If
 514:    * no item is currently selected, then -1 is returned.
 515:    * <p>
 516:    * Note: For performance reasons you should minimize invocation of this
 517:    * method. If the data model is not an instance of
 518:    * <code>DefaultComboBoxModel</code> the complexity is O(n) where n is the
 519:    * number of elements in the combo box.
 520:    * </p>
 521:    *
 522:    * @return int Index specifying location of the currently selected item in the
 523:    *         combo box or -1 if nothing is selected in the combo box.
 524:    */
 525:   public int getSelectedIndex()
 526:   {
 527:     Object selectedItem = getSelectedItem();
 528: 
 529:     if (selectedItem != null)
 530:       {
 531:         if (dataModel instanceof DefaultComboBoxModel)
 532:           // Uses special method of DefaultComboBoxModel to retrieve the index.
 533:           return ((DefaultComboBoxModel) dataModel).getIndexOf(selectedItem);
 534:         else
 535:           {
 536:             // Iterates over all items to retrieve the index.
 537:             int size = dataModel.getSize();
 538: 
 539:             for (int i = 0; i < size; i++)
 540:               {
 541:                 Object o = dataModel.getElementAt(i);
 542: 
 543:                 // XXX: Is special handling of ComparableS neccessary?
 544:                 if ((selectedItem != null) ? selectedItem.equals(o) : o == null)
 545:                   return i;
 546:               }
 547:           }
 548:       }
 549: 
 550:     // returns that no item is currently selected
 551:     return -1;
 552:   }
 553: 
 554:   /**
 555:    * Returns an object that is used as the display value when calculating the
 556:    * preferred size for the combo box.  This value is, of course, never
 557:    * displayed anywhere.
 558:    *
 559:    * @return The prototype display value (possibly <code>null</code>).
 560:    *
 561:    * @since 1.4
 562:    * @see #setPrototypeDisplayValue(Object)
 563:    */
 564:   public Object getPrototypeDisplayValue()
 565:   {
 566:     return prototypeDisplayValue;
 567:   }
 568: 
 569:   /**
 570:    * Sets the object that is assumed to be the displayed item when calculating
 571:    * the preferred size for the combo box.  A {@link PropertyChangeEvent} (with
 572:    * the name <code>prototypeDisplayValue</code>) is sent to all registered
 573:    * listeners.
 574:    *
 575:    * @param value  the new value (<code>null</code> permitted).
 576:    *
 577:    * @since 1.4
 578:    * @see #getPrototypeDisplayValue()
 579:    */
 580:   public void setPrototypeDisplayValue(Object value)
 581:   {
 582:     Object oldValue = prototypeDisplayValue;
 583:     prototypeDisplayValue = value;
 584:     firePropertyChange("prototypeDisplayValue", oldValue, value);
 585:   }
 586: 
 587:   /**
 588:    * This method adds given element to this JComboBox.
 589:    * <p>A <code>RuntimeException</code> is thrown if the data model is not
 590:    * an instance of {@link MutableComboBoxModel}.</p>
 591:    *
 592:    * @param element element to add
 593:    */
 594:   public void addItem(Object element)
 595:   {
 596:         if (dataModel instanceof MutableComboBoxModel)
 597:       ((MutableComboBoxModel) dataModel).addElement(element);
 598:     else
 599:       throw new RuntimeException("Unable to add the item because the data "
 600:                                  + "model it is not an instance of "
 601:                                  + "MutableComboBoxModel.");
 602:   }
 603: 
 604:   /**
 605:    * Inserts given element at the specified index to this JComboBox.
 606:    * <p>A <code>RuntimeException</code> is thrown if the data model is not
 607:    * an instance of {@link MutableComboBoxModel}.</p>
 608:    *
 609:    * @param element element to insert
 610:    * @param index position where to insert the element
 611:    */
 612:   public void insertItemAt(Object element, int index)
 613:   {
 614:         if (dataModel instanceof MutableComboBoxModel)
 615:       ((MutableComboBoxModel) dataModel).insertElementAt(element, index);
 616:     else
 617:       throw new RuntimeException("Unable to insert the item because the data "
 618:                                  + "model it is not an instance of "
 619:                                  + "MutableComboBoxModel.");
 620:   }
 621: 
 622:   /**
 623:    * This method removes given element from this JComboBox.
 624:    * <p>A <code>RuntimeException</code> is thrown if the data model is not
 625:    * an instance of {@link MutableComboBoxModel}.</p>
 626:    *
 627:    * @param element element to remove
 628:    */
 629:   public void removeItem(Object element)
 630:   {
 631:         if (dataModel instanceof MutableComboBoxModel)
 632:       ((MutableComboBoxModel) dataModel).removeElement(element);
 633:     else
 634:       throw new RuntimeException("Unable to remove the item because the data "
 635:                                  + "model it is not an instance of "
 636:                                  + "MutableComboBoxModel.");
 637:   }
 638: 
 639:   /**
 640:    * This method remove element location in the specified index in the
 641:    * JComboBox.
 642:    * <p>A <code>RuntimeException</code> is thrown if the data model is not
 643:    * an instance of {@link MutableComboBoxModel}.</p>
 644:    *
 645:    * @param index index specifying position of the element to remove
 646:    */
 647:   public void removeItemAt(int index)
 648:   {
 649:     if (dataModel instanceof MutableComboBoxModel)
 650:       ((MutableComboBoxModel) dataModel).removeElementAt(index);
 651:     else
 652:       throw new RuntimeException("Unable to remove the item because the data "
 653:                                  + "model it is not an instance of "
 654:                                  + "MutableComboBoxModel.");
 655:   }
 656: 
 657:   /**
 658:    * This method removes all elements from this JComboBox.
 659:    * <p>
 660:    * A <code>RuntimeException</code> is thrown if the data model is not an
 661:    * instance of {@link MutableComboBoxModel}.
 662:    * </p>
 663:    */
 664:   public void removeAllItems()
 665:   {
 666:     if (dataModel instanceof DefaultComboBoxModel)
 667:       // Uses special method if we have a DefaultComboBoxModel.
 668:       ((DefaultComboBoxModel) dataModel).removeAllElements();
 669:     else if (dataModel instanceof MutableComboBoxModel)
 670:       {
 671:         // Iterates over all items and removes each.
 672:         MutableComboBoxModel mcbm = (MutableComboBoxModel) dataModel;
 673: 
 674:          // We intentionally remove the items backwards to support models which
 675:          // shift their content to the beginning (e.g. linked lists)
 676:         for (int i = mcbm.getSize() - 1; i >= 0; i--)
 677:           mcbm.removeElementAt(i);
 678:       }
 679:     else
 680:       throw new RuntimeException("Unable to remove the items because the data "
 681:                                  + "model it is not an instance of "
 682:                                  + "MutableComboBoxModel.");
 683:   }
 684: 
 685:   /**
 686:    * This method displays popup with list of combo box's items on the screen
 687:    */
 688:   public void showPopup()
 689:   {
 690:     setPopupVisible(true);
 691:   }
 692: 
 693:   /**
 694:    * This method hides popup containing list of combo box's items
 695:    */
 696:   public void hidePopup()
 697:   {
 698:     setPopupVisible(false);
 699:   }
 700: 
 701:   /**
 702:    * This method either displayes or hides the popup containing  list of combo
 703:    * box's items.
 704:    *
 705:    * @param visible show popup if 'visible' is true and hide it otherwise
 706:    */
 707:   public void setPopupVisible(boolean visible)
 708:   {
 709:     getUI().setPopupVisible(this, visible);
 710:   }
 711: 
 712:   /**
 713:    * Checks if popup is currently visible on the screen.
 714:    *
 715:    * @return boolean true if popup is visible and false otherwise
 716:    */
 717:   public boolean isPopupVisible()
 718:   {
 719:     return getUI().isPopupVisible(this);
 720:   }
 721: 
 722:   /**
 723:    * This method sets actionCommand to the specified string. ActionEvent fired
 724:    * to this JComboBox  registered ActionListeners will contain this
 725:    * actionCommand.
 726:    *
 727:    * @param aCommand new action command for the JComboBox's ActionEvent
 728:    */
 729:   public void setActionCommand(String aCommand)
 730:   {
 731:     actionCommand = aCommand;
 732:   }
 733: 
 734:   /**
 735:    * Returns actionCommand associated with the ActionEvent fired by the
 736:    * JComboBox to its registered ActionListeners.
 737:    *
 738:    * @return String actionCommand for the ActionEvent
 739:    */
 740:   public String getActionCommand()
 741:   {
 742:     return actionCommand;
 743:   }
 744: 
 745:   /**
 746:    * setAction
 747:    *
 748:    * @param a action to set
 749:    */
 750:   public void setAction(Action a)
 751:   {
 752:     Action old = action;
 753:     action = a;
 754:     configurePropertiesFromAction(action);
 755:     if (action != null)
 756:       // FIXME: remove from old action and add to new action
 757:       // PropertyChangeListener to listen to changes in the action
 758:       addActionListener(action);
 759:   }
 760: 
 761:   /**
 762:    * This method returns Action that is invoked when selected item is changed
 763:    * in the JComboBox.
 764:    *
 765:    * @return Action
 766:    */
 767:   public Action getAction()
 768:   {
 769:     return action;
 770:   }
 771: 
 772:   /**
 773:    * Configure properties of the JComboBox by reading properties of specified
 774:    * action. This method always sets the comboBox's "enabled" property to the
 775:    * value of the Action's "enabled" property.
 776:    *
 777:    * @param a An Action to configure the combo box from
 778:    */
 779:   protected void configurePropertiesFromAction(Action a)
 780:   {
 781:     if (a == null)
 782:       {
 783:         setEnabled(true);
 784:         setToolTipText(null);
 785:       }
 786:     else
 787:       {
 788:         setEnabled(a.isEnabled());
 789:         setToolTipText((String) (a.getValue(Action.SHORT_DESCRIPTION)));
 790:       }
 791:   }
 792: 
 793:   /**
 794:    * Creates PropertyChangeListener to listen for the changes in comboBox's
 795:    * action properties.
 796:    *
 797:    * @param action action to listen to for property changes
 798:    *
 799:    * @return a PropertyChangeListener that listens to changes in
 800:    *         action properties.
 801:    */
 802:   protected PropertyChangeListener createActionPropertyChangeListener(Action action)
 803:   {
 804:     return new PropertyChangeListener()
 805:       {
 806:         public void propertyChange(PropertyChangeEvent e)
 807:         {
 808:           Action act = (Action) (e.getSource());
 809:           configurePropertiesFromAction(act);
 810:         }
 811:       };
 812:   }
 813: 
 814:   /**
 815:    * This method fires ItemEvent to this JComboBox's registered ItemListeners.
 816:    * This method is invoked when currently selected item in this combo box
 817:    * has changed.
 818:    *
 819:    * @param e the ItemEvent describing the change in the combo box's
 820:    *        selection.
 821:    */
 822:   protected void fireItemStateChanged(ItemEvent e)
 823:   {
 824:     ItemListener[] ll = getItemListeners();
 825: 
 826:     for (int i = 0; i < ll.length; i++)
 827:       ll[i].itemStateChanged(e);
 828:   }
 829: 
 830:   /**
 831:    * This method fires ActionEvent to this JComboBox's registered
 832:    * ActionListeners. This method is invoked when user explicitly changes
 833:    * currently selected item.
 834:    */
 835:   protected void fireActionEvent()
 836:   {
 837:     ActionListener[] ll = getActionListeners();
 838: 
 839:     for (int i = 0; i < ll.length; i++)
 840:       ll[i].actionPerformed(new ActionEvent(this,
 841:                                             ActionEvent.ACTION_PERFORMED,
 842:                                             actionCommand));
 843:   }
 844: 
 845:   /**
 846:    * Fires a popupMenuCanceled() event to all <code>PopupMenuListeners</code>.
 847:    *
 848:    * Note: This method is intended for use by plaf classes only.
 849:    */
 850:   public void firePopupMenuCanceled()
 851:   {
 852:     PopupMenuListener[] listeners = getPopupMenuListeners();
 853:     PopupMenuEvent e = new PopupMenuEvent(this);
 854:     for (int i = 0; i < listeners.length; i++)
 855:       listeners[i].popupMenuCanceled(e);
 856:   }
 857: 
 858:   /**
 859:    * Fires a popupMenuWillBecomeInvisible() event to all
 860:    * <code>PopupMenuListeners</code>.
 861:    *
 862:    * Note: This method is intended for use by plaf classes only.
 863:    */
 864:   public void firePopupMenuWillBecomeInvisible()
 865:   {
 866:     PopupMenuListener[] listeners = getPopupMenuListeners();
 867:     PopupMenuEvent e = new PopupMenuEvent(this);
 868:     for (int i = 0; i < listeners.length; i++)
 869:       listeners[i].popupMenuWillBecomeInvisible(e);
 870:   }
 871: 
 872:   /**
 873:    * Fires a popupMenuWillBecomeVisible() event to all
 874:    * <code>PopupMenuListeners</code>.
 875:    *
 876:    * Note: This method is intended for use by plaf classes only.
 877:    */
 878:   public void firePopupMenuWillBecomeVisible()
 879:   {
 880:     PopupMenuListener[] listeners = getPopupMenuListeners();
 881:     PopupMenuEvent e = new PopupMenuEvent(this);
 882:     for (int i = 0; i < listeners.length; i++)
 883:       listeners[i].popupMenuWillBecomeVisible(e);
 884:   }
 885: 
 886:   /**
 887:    * This method is invoked whenever selected item changes in the combo box's
 888:    * data model. It fires ItemEvent and ActionEvent to all registered
 889:    * ComboBox's ItemListeners and ActionListeners respectively, indicating
 890:    * the change.
 891:    */
 892:   protected void selectedItemChanged()
 893:   {
 894:     // Fire ItemEvent to indicated that previously selected item is now
 895:     // deselected
 896:     if (selectedItemReminder != null)
 897:       fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED,
 898:                                          selectedItemReminder,
 899:                                          ItemEvent.DESELECTED));
 900: 
 901:     // Fire ItemEvent to indicate that new item is selected
 902:     Object newSelection = getSelectedItem();
 903:     if (newSelection != null)
 904:       fireItemStateChanged(new ItemEvent(this, ItemEvent.ITEM_STATE_CHANGED,
 905:                                          newSelection, ItemEvent.SELECTED));
 906: 
 907:     // Fire Action Event to JComboBox's registered listeners
 908:     fireActionEvent();
 909: 
 910:     selectedItemReminder = newSelection;
 911:   }
 912: 
 913:   /**
 914:    * Returns Object array of size 1 containing currently selected element in
 915:    * the JComboBox.
 916:    *
 917:    * @return Object[] Object array of size 1 containing currently selected
 918:    *         element in the JComboBox.
 919:    */
 920:   public Object[] getSelectedObjects()
 921:   {
 922:     return new Object[] { getSelectedItem() };
 923:   }
 924: 
 925:   /**
 926:    * This method handles actionEvents fired by the ComboBoxEditor. It changes
 927:    * this JComboBox's selection to the new value currently in the editor and
 928:    * hides list of combo box items.
 929:    *
 930:    * @param e the ActionEvent
 931:    */
 932:   public void actionPerformed(ActionEvent e)
 933:   {
 934:     setSelectedItem(getEditor().getItem());
 935:     setPopupVisible(false);
 936:   }
 937: 
 938:   /**
 939:    * This method selects item in this combo box that matches specified
 940:    * specified keyChar and returns true if such item is found. Otherwise
 941:    * false is returned.
 942:    *
 943:    * @param keyChar character indicating which item in the combo box should be
 944:    *        selected.
 945:    *
 946:    * @return boolean true if item corresponding to the specified keyChar
 947:    *         exists in the combo box. Otherwise false is returned.
 948:    */
 949:   public boolean selectWithKeyChar(char keyChar)
 950:   {
 951:     if (keySelectionManager == null)
 952:       {
 953:         keySelectionManager = createDefaultKeySelectionManager();
 954:       }
 955: 
 956:     int index = keySelectionManager.selectionForKey(keyChar, getModel());
 957:     boolean retVal = false;
 958:     if (index >= 0)
 959:       {
 960:         setSelectedIndex(index);
 961:         retVal = true;
 962:       }
 963:     return retVal;
 964:   }
 965: 
 966:   /**
 967:    * The part of implementation of ListDataListener interface. This method is
 968:    * invoked when some items where added to the JComboBox's data model.
 969:    *
 970:    * @param event ListDataEvent describing the change
 971:    */
 972:   public void intervalAdded(ListDataEvent event)
 973:   {
 974:     // FIXME: Need to implement
 975:     repaint();
 976:   }
 977: 
 978:   /**
 979:    * The part of implementation of ListDataListener interface. This method is
 980:    * invoked when some items where removed from the JComboBox's data model.
 981:    *
 982:    * @param event ListDataEvent describing the change.
 983:    */
 984:   public void intervalRemoved(ListDataEvent event)
 985:   {
 986:     // FIXME: Need to implement
 987:     repaint();
 988:   }
 989: 
 990:   /**
 991:    * The part of implementation of ListDataListener interface. This method is
 992:    * invoked when contents of the JComboBox's  data model changed.
 993:    *
 994:    * @param event ListDataEvent describing the change
 995:    */
 996:   public void contentsChanged(ListDataEvent event)
 997:   {
 998:     // if first and last index of the given ListDataEvent are both -1,
 999:     // then it indicates that selected item in the combo box data model
1000:     // have changed.
1001:     if (event.getIndex0() == -1 && event.getIndex1() == -1)
1002:       selectedItemChanged();
1003:   }
1004: 
1005:   /**
1006:    * This method disables or enables JComboBox. If the JComboBox is enabled,
1007:    * then user is able to make item choice, otherwise if JComboBox is
1008:    * disabled then user is not able to make a selection.
1009:    *
1010:    * @param enabled if 'enabled' is true then enable JComboBox and disable it
1011:    */
1012:   public void setEnabled(boolean enabled)
1013:   {
1014:     boolean oldEnabled = super.isEnabled();
1015:     if (enabled != oldEnabled)
1016:       {
1017:         super.setEnabled(enabled);
1018:         firePropertyChange("enabled", oldEnabled, enabled);
1019:       }
1020:   }
1021: 
1022:   /**
1023:    * This method initializes specified ComboBoxEditor to display given item.
1024:    *
1025:    * @param anEditor ComboBoxEditor to initialize
1026:    * @param anItem Item that should displayed in the specified editor
1027:    */
1028:   public void configureEditor(ComboBoxEditor anEditor, Object anItem)
1029:   {
1030:     anEditor.setItem(anItem);
1031:   }
1032: 
1033:   /**
1034:    * This method is fired whenever a key is pressed with the combo box
1035:    * in focus
1036:    *
1037:    * @param e The KeyEvent indicating which key was pressed.
1038:    */
1039:   public void processKeyEvent(KeyEvent e)
1040:   {
1041:     if (e.getKeyCode() == KeyEvent.VK_TAB)
1042:       setPopupVisible(false);
1043:     else
1044:       super.processKeyEvent(e);
1045:   }
1046: 
1047:   /**
1048:    * setKeySelectionManager
1049:    *
1050:    * @param aManager
1051:    */
1052:   public void setKeySelectionManager(KeySelectionManager aManager)
1053:   {
1054:     keySelectionManager = aManager;
1055:   }
1056: 
1057:   /**
1058:    * getKeySelectionManager
1059:    *
1060:    * @return JComboBox.KeySelectionManager
1061:    */
1062:   public KeySelectionManager getKeySelectionManager()
1063:   {
1064:     return keySelectionManager;
1065:   }
1066: 
1067:   /**
1068:    * This method returns number of elements in this JComboBox
1069:    *
1070:    * @return int number of elements in this JComboBox
1071:    */
1072:   public int getItemCount()
1073:   {
1074:     return dataModel.getSize();
1075:   }
1076: 
1077:   /**
1078:    * Returns elements located in the combo box at the given index.
1079:    *
1080:    * @param index index specifying location of the component to  return.
1081:    *
1082:    * @return component in the combo box that is located in  the given index.
1083:    */
1084:   public Object getItemAt(int index)
1085:   {
1086:     return dataModel.getElementAt(index);
1087:   }
1088: 
1089:   /**
1090:    * createDefaultKeySelectionManager
1091:    *
1092:    * @return KeySelectionManager
1093:    */
1094:   protected KeySelectionManager createDefaultKeySelectionManager()
1095:   {
1096:     return new DefaultKeySelectionManager();
1097:   }
1098: 
1099:   /**
1100:    * Returns an implementation-dependent string describing the attributes of
1101:    * this <code>JComboBox</code>.
1102:    *
1103:    * @return A string describing the attributes of this <code>JComboBox</code>
1104:    *         (never <code>null</code>).
1105:    */
1106:   protected String paramString()
1107:   {
1108:     String superParamStr = super.paramString();
1109:     CPStringBuilder sb = new CPStringBuilder();
1110:     sb.append(",isEditable=").append(isEditable());
1111:     sb.append(",lightWeightPopupEnabled=").append(isLightWeightPopupEnabled());
1112:     sb.append(",maximumRowCount=").append(getMaximumRowCount());
1113: 
1114:     sb.append(",selectedItemReminder=");
1115:     if (selectedItemReminder != null)
1116:       sb.append(selectedItemReminder);
1117:     return superParamStr + sb.toString();
1118:   }
1119: 
1120:   /**
1121:    * Returns the object that provides accessibility features for this
1122:    * <code>JComboBox</code> component.
1123:    *
1124:    * @return The accessible context (an instance of
1125:    *         {@link AccessibleJComboBox}).
1126:    */
1127:   public AccessibleContext getAccessibleContext()
1128:   {
1129:     if (accessibleContext == null)
1130:       accessibleContext = new AccessibleJComboBox();
1131: 
1132:     return accessibleContext;
1133:   }
1134: 
1135:   /**
1136:    * This methods adds specified ActionListener to this JComboBox.
1137:    *
1138:    * @param listener to add
1139:    */
1140:   public void addActionListener(ActionListener listener)
1141:   {
1142:     listenerList.add(ActionListener.class, listener);
1143:   }
1144: 
1145:   /**
1146:    * This method removes specified ActionListener from this JComboBox.
1147:    *
1148:    * @param listener ActionListener
1149:    */
1150:   public void removeActionListener(ActionListener listener)
1151:   {
1152:     listenerList.remove(ActionListener.class, listener);
1153:   }
1154: 
1155:   /**
1156:    * This method returns array of ActionListeners that are registered with
1157:    * this JComboBox.
1158:    *
1159:    * @since 1.4
1160:    */
1161:   public ActionListener[] getActionListeners()
1162:   {
1163:     return (ActionListener[]) getListeners(ActionListener.class);
1164:   }
1165: 
1166:   /**
1167:    * This method registers given ItemListener with this JComboBox
1168:    *
1169:    * @param listener to remove
1170:    */
1171:   public void addItemListener(ItemListener listener)
1172:   {
1173:     listenerList.add(ItemListener.class, listener);
1174:   }
1175: 
1176:   /**
1177:    * This method unregisters given ItemListener from this JComboBox
1178:    *
1179:    * @param listener to remove
1180:    */
1181:   public void removeItemListener(ItemListener listener)
1182:   {
1183:     listenerList.remove(ItemListener.class, listener);
1184:   }
1185: 
1186:   /**
1187:    * This method returns array of ItemListeners that are registered with this
1188:    * JComboBox.
1189:    *
1190:    * @since 1.4
1191:    */
1192:   public ItemListener[] getItemListeners()
1193:   {
1194:     return (ItemListener[]) getListeners(ItemListener.class);
1195:   }
1196: 
1197:   /**
1198:    * Adds PopupMenuListener to combo box to listen to the events fired by the
1199:    * combo box's popup menu containing its list of items
1200:    *
1201:    * @param listener to add
1202:    */
1203:   public void addPopupMenuListener(PopupMenuListener listener)
1204:   {
1205:     listenerList.add(PopupMenuListener.class, listener);
1206:   }
1207: 
1208:   /**
1209:    * Removes PopupMenuListener to combo box to listen to the events fired by
1210:    * the combo box's popup menu containing its list of items
1211:    *
1212:    * @param listener to add
1213:    */
1214:   public void removePopupMenuListener(PopupMenuListener listener)
1215:   {
1216:     listenerList.remove(PopupMenuListener.class, listener);
1217:   }
1218: 
1219:   /**
1220:    * Returns array of PopupMenuListeners that are registered with  combo box.
1221:    */
1222:   public PopupMenuListener[] getPopupMenuListeners()
1223:   {
1224:     return (PopupMenuListener[]) getListeners(PopupMenuListener.class);
1225:   }
1226: 
1227:   /**
1228:    * Accessibility support for <code>JComboBox</code>.
1229:    */
1230:   protected class AccessibleJComboBox extends AccessibleJComponent
1231:     implements AccessibleAction, AccessibleSelection
1232:   {
1233:     private static final long serialVersionUID = 8217828307256675666L;
1234: 
1235:     /**
1236:      * @specnote This constructor was protected in 1.4, but made public
1237:      * in 1.5.
1238:      */
1239:     public AccessibleJComboBox()
1240:     {
1241:       // Nothing to do here.
1242:     }
1243: 
1244:     /**
1245:      * Returns the number of accessible children of this object. The
1246:      * implementation of AccessibleJComboBox delegates this call to the UI
1247:      * of the associated JComboBox.
1248:      *
1249:      * @return the number of accessible children of this object
1250:      *
1251:      * @see ComponentUI#getAccessibleChildrenCount(JComponent)
1252:      */
1253:     public int getAccessibleChildrenCount()
1254:     {
1255:       ComponentUI ui = getUI();
1256:       int count;
1257:       if (ui != null)
1258:         count = ui.getAccessibleChildrenCount(JComboBox.this);
1259:       else
1260:         count = super.getAccessibleChildrenCount();
1261:       return count;
1262:     }
1263: 
1264:     /**
1265:      * Returns the number of accessible children of this object. The
1266:      * implementation of AccessibleJComboBox delegates this call to the UI
1267:      * of the associated JComboBox.
1268:      *
1269:      * @param index the index of the accessible child to fetch
1270:      *
1271:      * @return the number of accessible children of this object
1272:      *
1273:      * @see ComponentUI#getAccessibleChild(JComponent, int)
1274:      */
1275:     public Accessible getAccessibleChild(int index)
1276:     {
1277:       ComponentUI ui = getUI();
1278:       Accessible child = null;
1279:       if (ui != null)
1280:         child = ui.getAccessibleChild(JComboBox.this, index);
1281:       else
1282:         child = super.getAccessibleChild(index);
1283:       return child;
1284:     }
1285: 
1286:     /**
1287:      * Returns the AccessibleSelection object associated with this object.
1288:      * AccessibleJComboBoxes handle their selection themselves, so this
1289:      * always returns <code>this</code>.
1290:      *
1291:      * @return the AccessibleSelection object associated with this object
1292:      */
1293:     public AccessibleSelection getAccessibleSelection()
1294:     {
1295:       return this;
1296:     }
1297: 
1298:     /**
1299:      * Returns the accessible selection from this AccssibleJComboBox.
1300:      *
1301:      * @param index the index of the selected child to fetch
1302:      *
1303:      * @return the accessible selection from this AccssibleJComboBox
1304:      */
1305:     public Accessible getAccessibleSelection(int index)
1306:     {
1307:       // Get hold of the actual popup.
1308:       Accessible popup = getUI().getAccessibleChild(JComboBox.this, 0);
1309:       Accessible selected = null;
1310:       if (popup != null && popup instanceof ComboPopup)
1311:         {
1312:           ComboPopup cPopup = (ComboPopup) popup;
1313:           // Query the list for the currently selected child.
1314:           JList l = cPopup.getList();
1315:           AccessibleContext listCtx = l.getAccessibleContext();
1316:           if (listCtx != null)
1317:             {
1318:               AccessibleSelection s = listCtx.getAccessibleSelection();
1319:               if (s != null)
1320:                 {
1321:                   selected = s.getAccessibleSelection(index);
1322:                 }
1323:             }
1324:         }
1325:       return selected;
1326:     }
1327: 
1328:     /**
1329:      * Returns <code>true</code> if the accessible child with the specified
1330:      * <code>index</code> is selected, <code>false</code> otherwise.
1331:      *
1332:      * @param index the index of the accessible child
1333:      *
1334:      * @return <code>true</code> if the accessible child with the specified
1335:      *         <code>index</code> is selected, <code>false</code> otherwise
1336:      */
1337:     public boolean isAccessibleChildSelected(int index)
1338:     {
1339:       return getSelectedIndex() == index;
1340:     }
1341: 
1342:     /**
1343:      * Returns the accessible role for the <code>JComboBox</code> component.
1344:      *
1345:      * @return {@link AccessibleRole#COMBO_BOX}.
1346:      */
1347:     public AccessibleRole getAccessibleRole()
1348:     {
1349:       return AccessibleRole.COMBO_BOX;
1350:     }
1351: 
1352:     /**
1353:      * Returns the accessible action associated to this accessible object.
1354:      * AccessibleJComboBox implements its own AccessibleAction, so this
1355:      * method returns <code>this</code>.
1356:      *
1357:      * @return the accessible action associated to this accessible object
1358:      */
1359:     public AccessibleAction getAccessibleAction()
1360:     {
1361:       return this;
1362:     }
1363: 
1364:     /**
1365:      * Returns the description of the specified action. AccessibleJComboBox
1366:      * implements 1 action (toggle the popup menu) and thus returns
1367:      * <code>UIManager.getString("ComboBox.togglePopupText")</code>
1368:      *
1369:      * @param actionIndex the index of the action for which to return the
1370:      *        description
1371:      *
1372:      * @return the description of the specified action
1373:      */
1374:     public String getAccessibleActionDescription(int actionIndex)
1375:     {
1376:       return UIManager.getString("ComboBox.togglePopupText");
1377:     }
1378: 
1379:     /**
1380:      * Returns the number of accessible actions that can be performed by
1381:      * this object. AccessibleJComboBox implement s one accessible action
1382:      * (toggle the popup menu), so this method always returns <code>1</code>.
1383:      *
1384:      * @return the number of accessible actions that can be performed by
1385:      *         this object
1386:      */
1387:     public int getAccessibleActionCount()
1388:     {
1389:       return 1;
1390:     }
1391: 
1392:     /**
1393:      * Performs the accessible action with the specified index.
1394:      * AccessibleJComboBox has 1 accessible action
1395:      * (<code>actionIndex == 0</code>), which is to toggle the
1396:      * popup menu. All other action indices have no effect and return
1397:      * <code<>false</code>.
1398:      *
1399:      * @param actionIndex the index of the action to perform
1400:      *
1401:      * @return <code>true</code> if the action has been performed,
1402:      *         <code>false</code> otherwise
1403:      */
1404:     public boolean doAccessibleAction(int actionIndex)
1405:     {
1406:       boolean actionPerformed = false;
1407:       if (actionIndex == 0)
1408:         {
1409:           setPopupVisible(! isPopupVisible());
1410:           actionPerformed = true;
1411:         }
1412:       return actionPerformed;
1413:     }
1414: 
1415:     /**
1416:      * Returns the number of selected accessible children of this object. This
1417:      * returns <code>1</code> if the combobox has a selected entry,
1418:      * <code>0</code> otherwise.
1419:      *
1420:      * @return the number of selected accessible children of this object
1421:      */
1422:     public int getAccessibleSelectionCount()
1423:     {
1424:       Object sel = getSelectedItem();
1425:       int count = 0;
1426:       if (sel != null)
1427:         count = 1;
1428:       return count;
1429:     }
1430: 
1431:     /**
1432:      * Sets the current selection to the specified <code>index</code>.
1433:      *
1434:      * @param index the index to set as selection
1435:      */
1436:     public void addAccessibleSelection(int index)
1437:     {
1438:       setSelectedIndex(index);
1439:     }
1440: 
1441:     /**
1442:      * Removes the specified index from the current selection.
1443:      *
1444:      * @param index the index to remove from the selection
1445:      */
1446:     public void removeAccessibleSelection(int index)
1447:     {
1448:       if (getSelectedIndex() == index)
1449:         clearAccessibleSelection();
1450:     }
1451: 
1452:     /**
1453:      * Clears the current selection.
1454:      */
1455:     public void clearAccessibleSelection()
1456:     {
1457:       setSelectedIndex(-1);
1458:     }
1459: 
1460:     /**
1461:      * Multiple selection is not supported by AccessibleJComboBox, so this
1462:      * does nothing.
1463:      */
1464:     public void selectAllAccessibleSelection()
1465:     {
1466:       // Nothing to do here.
1467:     }
1468:   }
1469: 
1470:   private class DefaultKeySelectionManager
1471:       implements KeySelectionManager
1472:   {
1473: 
1474:     public int selectionForKey(char aKey, ComboBoxModel aModel)
1475:     {
1476:       int selectedIndex = getSelectedIndex();
1477: 
1478:       // Start at currently selected item and iterate to end of list
1479:       for (int i = selectedIndex + 1; i < aModel.getSize(); i++)
1480:         {
1481:           String nextItem = aModel.getElementAt(i).toString();
1482: 
1483:           if (nextItem.charAt(0) == aKey)
1484:             return i;
1485:         }
1486: 
1487:       // Wrap to start of list if no match yet
1488:       for (int i = 0; i <= selectedIndex; i++)
1489:         {
1490:           String nextItem = aModel.getElementAt(i).toString();
1491: 
1492:           if (nextItem.charAt(0) == aKey)
1493:             return i;
1494:         }
1495: 
1496:       return - 1;
1497:     }
1498:   }
1499: }