History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/swing/JComboBox.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/swing/JComboBox.java+2412−0
@@ -0,0 +1,2412 @@
1+/*
2+ * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+package javax.swing;
26+
27+import java.beans.PropertyChangeEvent;
28+import java.beans.PropertyChangeListener;
29+import java.beans.Transient;
30+import java.util.*;
31+
32+import java.awt.*;
33+import java.awt.event.*;
34+
35+import java.io.Serializable;
36+import java.io.ObjectOutputStream;
37+import java.io.IOException;
38+
39+import javax.swing.event.*;
40+import javax.swing.plaf.*;
41+
42+import javax.accessibility.*;
43+
44+/**
45+ * A component that combines a button or editable field and a drop-down list.
46+ * The user can select a value from the drop-down list, which appears at the
47+ * user's request. If you make the combo box editable, then the combo box
48+ * includes an editable field into which the user can type a value.
49+ * <p>
50+ * <strong>Warning:</strong> Swing is not thread safe. For more
51+ * information see <a
52+ * href="package-summary.html#threading">Swing's Threading
53+ * Policy</a>.
54+ * <p>
55+ * <strong>Warning:</strong>
56+ * Serialized objects of this class will not be compatible with
57+ * future Swing releases. The current serialization support is
58+ * appropriate for short term storage or RMI between applications running
59+ * the same version of Swing. As of 1.4, support for long term storage
60+ * of all JavaBeans<sup><font size="-2">TM</font></sup>
61+ * has been added to the <code>java.beans</code> package.
62+ * Please see {@link java.beans.XMLEncoder}.
63+ *
64+ * <p>
65+ * See <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/combobox.html">How to Use Combo Boxes</a>
66+ * in <a href="http://java.sun.com/Series/Tutorial/index.html"><em>The Java Tutorial</em></a>
67+ * for further information.
68+ * <p>
69+ * @see ComboBoxModel
70+ * @see DefaultComboBoxModel
71+ *
72+ * @param <E> the type of the elements of this combo box
73+ *
74+ * @beaninfo
75+ * attribute: isContainer false
76+ * description: A combination of a text field and a drop-down list.
77+ *
78+ * @author Arnaud Weber
79+ * @author Mark Davidson
80+ */
81+public class JComboBox<E> extends JComponent
82+implements ItemSelectable,ListDataListener,ActionListener, Accessible {
83+ /**
84+ * @see #getUIClassID
85+ * @see #readObject
86+ */
87+ private static final String uiClassID = "ComboBoxUI";
88+
89+ /**
90+ * This protected field is implementation specific. Do not access directly
91+ * or override. Use the accessor methods instead.
92+ *
93+ * @see #getModel
94+ * @see #setModel
95+ */
96+ protected ComboBoxModel<E> dataModel;
97+ /**
98+ * This protected field is implementation specific. Do not access directly
99+ * or override. Use the accessor methods instead.
100+ *
101+ * @see #getRenderer
102+ * @see #setRenderer
103+ */
104+ protected ListCellRenderer<? super E> renderer;
105+ /**
106+ * This protected field is implementation specific. Do not access directly
107+ * or override. Use the accessor methods instead.
108+ *
109+ * @see #getEditor
110+ * @see #setEditor
111+ */
112+ protected ComboBoxEditor editor;
113+ /**
114+ * This protected field is implementation specific. Do not access directly
115+ * or override. Use the accessor methods instead.
116+ *
117+ * @see #getMaximumRowCount
118+ * @see #setMaximumRowCount
119+ */
120+ protected int maximumRowCount = 8;
121+
122+ /**
123+ * This protected field is implementation specific. Do not access directly
124+ * or override. Use the accessor methods instead.
125+ *
126+ * @see #isEditable
127+ * @see #setEditable
128+ */
129+ protected boolean isEditable = false;
130+ /**
131+ * This protected field is implementation specific. Do not access directly
132+ * or override. Use the accessor methods instead.
133+ *
134+ * @see #setKeySelectionManager
135+ * @see #getKeySelectionManager
136+ */
137+ protected KeySelectionManager keySelectionManager = null;
138+ /**
139+ * This protected field is implementation specific. Do not access directly
140+ * or override. Use the accessor methods instead.
141+ *
142+ * @see #setActionCommand
143+ * @see #getActionCommand
144+ */
145+ protected String actionCommand = "comboBoxChanged";
146+ /**
147+ * This protected field is implementation specific. Do not access directly
148+ * or override. Use the accessor methods instead.
149+ *
150+ * @see #setLightWeightPopupEnabled
151+ * @see #isLightWeightPopupEnabled
152+ */
153+ protected boolean lightWeightPopupEnabled = JPopupMenu.getDefaultLightWeightPopupEnabled();
154+
155+ /**
156+ * This protected field is implementation specific. Do not access directly
157+ * or override.
158+ */
159+ protected Object selectedItemReminder = null;
160+
161+ private E prototypeDisplayValue;
162+
163+ // Flag to ensure that infinite loops do not occur with ActionEvents.
164+ private boolean firingActionEvent = false;
165+
166+ // Flag to ensure the we don't get multiple ActionEvents on item selection.
167+ private boolean selectingItem = false;
168+
169+ /**
170+ * Creates a <code>JComboBox</code> that takes its items from an
171+ * existing <code>ComboBoxModel</code>. Since the
172+ * <code>ComboBoxModel</code> is provided, a combo box created using
173+ * this constructor does not create a default combo box model and
174+ * may impact how the insert, remove and add methods behave.
175+ *
176+ * @param aModel the <code>ComboBoxModel</code> that provides the
177+ * displayed list of items
178+ * @see DefaultComboBoxModel
179+ */
180+ public JComboBox(ComboBoxModel<E> aModel) {
181+ super();
182+ setModel(aModel);
183+ init();
184+ }
185+
186+ /**
187+ * Creates a <code>JComboBox</code> that contains the elements
188+ * in the specified array. By default the first item in the array
189+ * (and therefore the data model) becomes selected.
190+ *
191+ * @param items an array of objects to insert into the combo box
192+ * @see DefaultComboBoxModel
193+ */
194+ public JComboBox(E[] items) {
195+ super();
196+ setModel(new DefaultComboBoxModel<E>(items));
197+ init();
198+ }
199+
200+ /**
201+ * Creates a <code>JComboBox</code> that contains the elements
202+ * in the specified Vector. By default the first item in the vector
203+ * (and therefore the data model) becomes selected.
204+ *
205+ * @param items an array of vectors to insert into the combo box
206+ * @see DefaultComboBoxModel
207+ */
208+ public JComboBox(Vector<E> items) {
209+ super();
210+ setModel(new DefaultComboBoxModel<E>(items));
211+ init();
212+ }
213+
214+ /**
215+ * Creates a <code>JComboBox</code> with a default data model.
216+ * The default data model is an empty list of objects.
217+ * Use <code>addItem</code> to add items. By default the first item
218+ * in the data model becomes selected.
219+ *
220+ * @see DefaultComboBoxModel
221+ */
222+ public JComboBox() {
223+ super();
224+ setModel(new DefaultComboBoxModel<E>());
225+ init();
226+ }
227+
228+ private void init() {
229+ installAncestorListener();
230+ setUIProperty("opaque",true);
231+ updateUI();
232+ }
233+
234+ protected void installAncestorListener() {
235+ addAncestorListener(new AncestorListener(){
236+ public void ancestorAdded(AncestorEvent event){ hidePopup();}
237+ public void ancestorRemoved(AncestorEvent event){ hidePopup();}
238+ public void ancestorMoved(AncestorEvent event){
239+ if (event.getSource() != JComboBox.this)
240+ hidePopup();
241+ }});
242+ }
243+
244+ /**
245+ * Sets the L&F object that renders this component.
246+ *
247+ * @param ui the <code>ComboBoxUI</code> L&F object
248+ * @see UIDefaults#getUI
249+ *
250+ * @beaninfo
251+ * bound: true
252+ * hidden: true
253+ * attribute: visualUpdate true
254+ * description: The UI object that implements the Component's LookAndFeel.
255+ */
256+ public void setUI(ComboBoxUI ui) {
257+ super.setUI(ui);
258+ }
259+
260+ /**
261+ * Resets the UI property to a value from the current look and feel.
262+ *
263+ * @see JComponent#updateUI
264+ */
265+ public void updateUI() {
266+ setUI((ComboBoxUI)UIManager.getUI(this));
267+
268+ ListCellRenderer<? super E> renderer = getRenderer();
269+ if (renderer instanceof Component) {
270+ SwingUtilities.updateComponentTreeUI((Component)renderer);
271+ }
272+ }
273+
274+
275+ /**
276+ * Returns the name of the L&F class that renders this component.
277+ *
278+ * @return the string "ComboBoxUI"
279+ * @see JComponent#getUIClassID
280+ * @see UIDefaults#getUI
281+ */
282+ public String getUIClassID() {
283+ return uiClassID;
284+ }
285+
286+
287+ /**
288+ * Returns the L&F object that renders this component.
289+ *
290+ * @return the ComboBoxUI object that renders this component
291+ */
292+ public ComboBoxUI getUI() {
293+ return(ComboBoxUI)ui;
294+ }
295+
296+ /**
297+ * Sets the data model that the <code>JComboBox</code> uses to obtain
298+ * the list of items.
299+ *
300+ * @param aModel the <code>ComboBoxModel</code> that provides the
301+ * displayed list of items
302+ *
303+ * @beaninfo
304+ * bound: true
305+ * description: Model that the combo box uses to get data to display.
306+ */
307+ public void setModel(ComboBoxModel<E> aModel) {
308+ ComboBoxModel<E> oldModel = dataModel;
309+ if (oldModel != null) {
310+ oldModel.removeListDataListener(this);
311+ }
312+ dataModel = aModel;
313+ dataModel.addListDataListener(this);
314+
315+ // set the current selected item.
316+ selectedItemReminder = dataModel.getSelectedItem();
317+
318+ firePropertyChange( "model", oldModel, dataModel);
319+ }
320+
321+ /**
322+ * Returns the data model currently used by the <code>JComboBox</code>.
323+ *
324+ * @return the <code>ComboBoxModel</code> that provides the displayed
325+ * list of items
326+ */
327+ public ComboBoxModel<E> getModel() {
328+ return dataModel;
329+ }
330+
331+ /*
332+ * Properties
333+ */
334+
335+ /**
336+ * Sets the <code>lightWeightPopupEnabled</code> property, which
337+ * provides a hint as to whether or not a lightweight
338+ * <code>Component</code> should be used to contain the
339+ * <code>JComboBox</code>, versus a heavyweight
340+ * <code>Component</code> such as a <code>Panel</code>
341+ * or a <code>Window</code>. The decision of lightweight
342+ * versus heavyweight is ultimately up to the
343+ * <code>JComboBox</code>. Lightweight windows are more
344+ * efficient than heavyweight windows, but lightweight
345+ * and heavyweight components do not mix well in a GUI.
346+ * If your application mixes lightweight and heavyweight
347+ * components, you should disable lightweight popups.
348+ * The default value for the <code>lightWeightPopupEnabled</code>
349+ * property is <code>true</code>, unless otherwise specified
350+ * by the look and feel. Some look and feels always use
351+ * heavyweight popups, no matter what the value of this property.
352+ * <p>
353+ * See the article <a href="http://java.sun.com/products/jfc/tsc/articles/mixing/index.html">Mixing Heavy and Light Components</a>
354+ * on <a href="http://java.sun.com/products/jfc/tsc">
355+ * <em>The Swing Connection</em></a>
356+ * This method fires a property changed event.
357+ *
358+ * @param aFlag if <code>true</code>, lightweight popups are desired
359+ *
360+ * @beaninfo
361+ * bound: true
362+ * expert: true
363+ * description: Set to <code>false</code> to require heavyweight popups.
364+ */
365+ public void setLightWeightPopupEnabled(boolean aFlag) {
366+ boolean oldFlag = lightWeightPopupEnabled;
367+ lightWeightPopupEnabled = aFlag;
368+ firePropertyChange("lightWeightPopupEnabled", oldFlag, lightWeightPopupEnabled);
369+ }
370+
371+ /**
372+ * Gets the value of the <code>lightWeightPopupEnabled</code>
373+ * property.
374+ *
375+ * @return the value of the <code>lightWeightPopupEnabled</code>
376+ * property
377+ * @see #setLightWeightPopupEnabled
378+ */
379+ public boolean isLightWeightPopupEnabled() {
380+ return lightWeightPopupEnabled;
381+ }
382+
383+ /**
384+ * Determines whether the <code>JComboBox</code> field is editable.
385+ * An editable <code>JComboBox</code> allows the user to type into the
386+ * field or selected an item from the list to initialize the field,
387+ * after which it can be edited. (The editing affects only the field,
388+ * the list item remains intact.) A non editable <code>JComboBox</code>
389+ * displays the selected item in the field,
390+ * but the selection cannot be modified.
391+ *
392+ * @param aFlag a boolean value, where true indicates that the
393+ * field is editable
394+ *
395+ * @beaninfo
396+ * bound: true
397+ * preferred: true
398+ * description: If true, the user can type a new value in the combo box.
399+ */
400+ public void setEditable(boolean aFlag) {
401+ boolean oldFlag = isEditable;
402+ isEditable = aFlag;
403+ firePropertyChange( "editable", oldFlag, isEditable );
404+ }
405+
406+ /**
407+ * Returns true if the <code>JComboBox</code> is editable.
408+ * By default, a combo box is not editable.
409+ *
410+ * @return true if the <code>JComboBox</code> is editable, else false
411+ */
412+ public boolean isEditable() {
413+ return isEditable;
414+ }
415+
416+ /**
417+ * Sets the maximum number of rows the <code>JComboBox</code> displays.
418+ * If the number of objects in the model is greater than count,
419+ * the combo box uses a scrollbar.
420+ *
421+ * @param count an integer specifying the maximum number of items to
422+ * display in the list before using a scrollbar
423+ * @beaninfo
424+ * bound: true
425+ * preferred: true
426+ * description: The maximum number of rows the popup should have
427+ */
428+ public void setMaximumRowCount(int count) {
429+ int oldCount = maximumRowCount;
430+ maximumRowCount = count;
431+ firePropertyChange( "maximumRowCount", oldCount, maximumRowCount );
432+ }
433+
434+ /**
435+ * Returns the maximum number of items the combo box can display
436+ * without a scrollbar
437+ *
438+ * @return an integer specifying the maximum number of items that are
439+ * displayed in the list before using a scrollbar
440+ */
441+ public int getMaximumRowCount() {
442+ return maximumRowCount;
443+ }
444+
445+ /**
446+ * Sets the renderer that paints the list items and the item selected from the list in
447+ * the JComboBox field. The renderer is used if the JComboBox is not
448+ * editable. If it is editable, the editor is used to render and edit
449+ * the selected item.
450+ * <p>
451+ * The default renderer displays a string or an icon.
452+ * Other renderers can handle graphic images and composite items.
453+ * <p>
454+ * To display the selected item,
455+ * <code>aRenderer.getListCellRendererComponent</code>
456+ * is called, passing the list object and an index of -1.
457+ *
458+ * @param aRenderer the <code>ListCellRenderer</code> that
459+ * displays the selected item
460+ * @see #setEditor
461+ * @beaninfo
462+ * bound: true
463+ * expert: true
464+ * description: The renderer that paints the item selected in the list.
465+ */
466+ public void setRenderer(ListCellRenderer<? super E> aRenderer) {
467+ ListCellRenderer<? super E> oldRenderer = renderer;
468+ renderer = aRenderer;
469+ firePropertyChange( "renderer", oldRenderer, renderer );
470+ invalidate();
471+ }
472+
473+ /**
474+ * Returns the renderer used to display the selected item in the
475+ * <code>JComboBox</code> field.
476+ *
477+ * @return the <code>ListCellRenderer</code> that displays
478+ * the selected item.
479+ */
480+ public ListCellRenderer<? super E> getRenderer() {
481+ return renderer;
482+ }
483+
484+ /**
485+ * Sets the editor used to paint and edit the selected item in the
486+ * <code>JComboBox</code> field. The editor is used only if the
487+ * receiving <code>JComboBox</code> is editable. If not editable,
488+ * the combo box uses the renderer to paint the selected item.
489+ *
490+ * @param anEditor the <code>ComboBoxEditor</code> that
491+ * displays the selected item
492+ * @see #setRenderer
493+ * @beaninfo
494+ * bound: true
495+ * expert: true
496+ * description: The editor that combo box uses to edit the current value
497+ */
498+ public void setEditor(ComboBoxEditor anEditor) {
499+ ComboBoxEditor oldEditor = editor;
500+
501+ if ( editor != null ) {
502+ editor.removeActionListener(this);
503+ }
504+ editor = anEditor;
505+ if ( editor != null ) {
506+ editor.addActionListener(this);
507+ }
508+ firePropertyChange( "editor", oldEditor, editor );
509+ }
510+
511+ /**
512+ * Returns the editor used to paint and edit the selected item in the
513+ * <code>JComboBox</code> field.
514+ *
515+ * @return the <code>ComboBoxEditor</code> that displays the selected item
516+ */
517+ public ComboBoxEditor getEditor() {
518+ return editor;
519+ }
520+
521+ //
522+ // Selection
523+ //
524+
525+ /**
526+ * Sets the selected item in the combo box display area to the object in
527+ * the argument.
528+ * If <code>anObject</code> is in the list, the display area shows
529+ * <code>anObject</code> selected.
530+ * <p>
531+ * If <code>anObject</code> is <i>not</i> in the list and the combo box is
532+ * uneditable, it will not change the current selection. For editable
533+ * combo boxes, the selection will change to <code>anObject</code>.
534+ * <p>
535+ * If this constitutes a change in the selected item,
536+ * <code>ItemListener</code>s added to the combo box will be notified with
537+ * one or two <code>ItemEvent</code>s.
538+ * If there is a current selected item, an <code>ItemEvent</code> will be
539+ * fired and the state change will be <code>ItemEvent.DESELECTED</code>.
540+ * If <code>anObject</code> is in the list and is not currently selected
541+ * then an <code>ItemEvent</code> will be fired and the state change will
542+ * be <code>ItemEvent.SELECTED</code>.
543+ * <p>
544+ * <code>ActionListener</code>s added to the combo box will be notified
545+ * with an <code>ActionEvent</code> when this method is called.
546+ *
547+ * @param anObject the list object to select; use <code>null</code> to
548+ clear the selection
549+ * @beaninfo
550+ * preferred: true
551+ * description: Sets the selected item in the JComboBox.
552+ */
553+ public void setSelectedItem(Object anObject) {
554+ Object oldSelection = selectedItemReminder;
555+ Object objectToSelect = anObject;
556+ if (oldSelection == null || !oldSelection.equals(anObject)) {
557+
558+ if (anObject != null && !isEditable()) {
559+ // For non editable combo boxes, an invalid selection
560+ // will be rejected.
561+ boolean found = false;
562+ for (int i = 0; i < dataModel.getSize(); i++) {
563+ E element = dataModel.getElementAt(i);
564+ if (anObject.equals(element)) {
565+ found = true;
566+ objectToSelect = element;
567+ break;
568+ }
569+ }
570+ if (!found) {
571+ return;
572+ }
573+ }
574+
575+ // Must toggle the state of this flag since this method
576+ // call may result in ListDataEvents being fired.
577+ selectingItem = true;
578+ dataModel.setSelectedItem(objectToSelect);
579+ selectingItem = false;
580+
581+ if (selectedItemReminder != dataModel.getSelectedItem()) {
582+ // in case a users implementation of ComboBoxModel
583+ // doesn't fire a ListDataEvent when the selection
584+ // changes.
585+ selectedItemChanged();
586+ }
587+ }
588+ fireActionEvent();
589+ }
590+
591+ /**
592+ * Returns the current selected item.
593+ * <p>
594+ * If the combo box is editable, then this value may not have been added
595+ * to the combo box with <code>addItem</code>, <code>insertItemAt</code>
596+ * or the data constructors.
597+ *
598+ * @return the current selected Object
599+ * @see #setSelectedItem
600+ */
601+ public Object getSelectedItem() {
602+ return dataModel.getSelectedItem();
603+ }
604+
605+ /**
606+ * Selects the item at index <code>anIndex</code>.
607+ *
608+ * @param anIndex an integer specifying the list item to select,
609+ * where 0 specifies the first item in the list and -1 indicates no selection
610+ * @exception IllegalArgumentException if <code>anIndex</code> < -1 or
611+ * <code>anIndex</code> is greater than or equal to size
612+ * @beaninfo
613+ * preferred: true
614+ * description: The item at index is selected.
615+ */
616+ public void setSelectedIndex(int anIndex) {
617+ int size = dataModel.getSize();
618+
619+ if ( anIndex == -1 ) {
620+ setSelectedItem( null );
621+ } else if ( anIndex < -1 || anIndex >= size ) {
622+ throw new IllegalArgumentException("setSelectedIndex: " + anIndex + " out of bounds");
623+ } else {
624+ setSelectedItem(dataModel.getElementAt(anIndex));
625+ }
626+ }
627+
628+ /**
629+ * Returns the first item in the list that matches the given item.
630+ * The result is not always defined if the <code>JComboBox</code>
631+ * allows selected items that are not in the list.
632+ * Returns -1 if there is no selected item or if the user specified
633+ * an item which is not in the list.
634+
635+ * @return an integer specifying the currently selected list item,
636+ * where 0 specifies
637+ * the first item in the list;
638+ * or -1 if no item is selected or if
639+ * the currently selected item is not in the list
640+ */
641+ @Transient
642+ public int getSelectedIndex() {
643+ Object sObject = dataModel.getSelectedItem();
644+ int i,c;
645+ E obj;
646+
647+ for ( i=0,c=dataModel.getSize();i<c;i++ ) {
648+ obj = dataModel.getElementAt(i);
649+ if ( obj != null && obj.equals(sObject) )
650+ return i;
651+ }
652+ return -1;
653+ }
654+
655+ /**
656+ * Returns the "prototypical display" value - an Object used
657+ * for the calculation of the display height and width.
658+ *
659+ * @return the value of the <code>prototypeDisplayValue</code> property
660+ * @see #setPrototypeDisplayValue
661+ * @since 1.4
662+ */
663+ public E getPrototypeDisplayValue() {
664+ return prototypeDisplayValue;
665+ }
666+
667+ /**
668+ * Sets the prototype display value used to calculate the size of the display
669+ * for the UI portion.
670+ * <p>
671+ * If a prototype display value is specified, the preferred size of
672+ * the combo box is calculated by configuring the renderer with the
673+ * prototype display value and obtaining its preferred size. Specifying
674+ * the preferred display value is often useful when the combo box will be
675+ * displaying large amounts of data. If no prototype display value has
676+ * been specified, the renderer must be configured for each value from
677+ * the model and its preferred size obtained, which can be
678+ * relatively expensive.
679+ *
680+ * @param prototypeDisplayValue
681+ * @see #getPrototypeDisplayValue
682+ * @since 1.4
683+ * @beaninfo
684+ * bound: true
685+ * attribute: visualUpdate true
686+ * description: The display prototype value, used to compute display width and height.
687+ */
688+ public void setPrototypeDisplayValue(E prototypeDisplayValue) {
689+ Object oldValue = this.prototypeDisplayValue;
690+ this.prototypeDisplayValue = prototypeDisplayValue;
691+ firePropertyChange("prototypeDisplayValue", oldValue, prototypeDisplayValue);
692+ }
693+
694+ /**
695+ * Adds an item to the item list.
696+ * This method works only if the <code>JComboBox</code> uses a
697+ * mutable data model.
698+ * <p>
699+ * <strong>Warning:</strong>
700+ * Focus and keyboard navigation problems may arise if you add duplicate
701+ * String objects. A workaround is to add new objects instead of String
702+ * objects and make sure that the toString() method is defined.
703+ * For example:
704+ * <pre>
705+ * comboBox.addItem(makeObj("Item 1"));
706+ * comboBox.addItem(makeObj("Item 1"));
707+ * ...
708+ * private Object makeObj(final String item) {
709+ * return new Object() { public String toString() { return item; } };
710+ * }
711+ * </pre>
712+ *
713+ * @param item the item to add to the list
714+ * @see MutableComboBoxModel
715+ */
716+ public void addItem(E item) {
717+ checkMutableComboBoxModel();
718+ ((MutableComboBoxModel<E>)dataModel).addElement(item);
719+ }
720+
721+ /**
722+ * Inserts an item into the item list at a given index.
723+ * This method works only if the <code>JComboBox</code> uses a
724+ * mutable data model.
725+ *
726+ * @param item the item to add to the list
727+ * @param index an integer specifying the position at which
728+ * to add the item
729+ * @see MutableComboBoxModel
730+ */
731+ public void insertItemAt(E item, int index) {
732+ checkMutableComboBoxModel();
733+ ((MutableComboBoxModel<E>)dataModel).insertElementAt(item,index);
734+ }
735+
736+ /**
737+ * Removes an item from the item list.
738+ * This method works only if the <code>JComboBox</code> uses a
739+ * mutable data model.
740+ *
741+ * @param anObject the object to remove from the item list
742+ * @see MutableComboBoxModel
743+ */
744+ public void removeItem(Object anObject) {
745+ checkMutableComboBoxModel();
746+ ((MutableComboBoxModel)dataModel).removeElement(anObject);
747+ }
748+
749+ /**
750+ * Removes the item at <code>anIndex</code>
751+ * This method works only if the <code>JComboBox</code> uses a
752+ * mutable data model.
753+ *
754+ * @param anIndex an int specifying the index of the item to remove,
755+ * where 0
756+ * indicates the first item in the list
757+ * @see MutableComboBoxModel
758+ */
759+ public void removeItemAt(int anIndex) {
760+ checkMutableComboBoxModel();
761+ ((MutableComboBoxModel<E>)dataModel).removeElementAt( anIndex );
762+ }
763+
764+ /**
765+ * Removes all items from the item list.
766+ */
767+ public void removeAllItems() {
768+ checkMutableComboBoxModel();
769+ MutableComboBoxModel<E> model = (MutableComboBoxModel<E>)dataModel;
770+ int size = model.getSize();
771+
772+ if ( model instanceof DefaultComboBoxModel ) {
773+ ((DefaultComboBoxModel)model).removeAllElements();
774+ }
775+ else {
776+ for ( int i = 0; i < size; ++i ) {
777+ E element = model.getElementAt( 0 );
778+ model.removeElement( element );
779+ }
780+ }
781+ selectedItemReminder = null;
782+ if (isEditable()) {
783+ editor.setItem(null);
784+ }
785+ }
786+
787+ /**
788+ * Checks that the <code>dataModel</code> is an instance of
789+ * <code>MutableComboBoxModel</code>. If not, it throws an exception.
790+ * @exception RuntimeException if <code>dataModel</code> is not an
791+ * instance of <code>MutableComboBoxModel</code>.
792+ */
793+ void checkMutableComboBoxModel() {
794+ if ( !(dataModel instanceof MutableComboBoxModel) )
795+ throw new RuntimeException("Cannot use this method with a non-Mutable data model.");
796+ }
797+
798+ /**
799+ * Causes the combo box to display its popup window.
800+ * @see #setPopupVisible
801+ */
802+ public void showPopup() {
803+ setPopupVisible(true);
804+ }
805+
806+ /**
807+ * Causes the combo box to close its popup window.
808+ * @see #setPopupVisible
809+ */
810+ public void hidePopup() {
811+ setPopupVisible(false);
812+ }
813+
814+ /**
815+ * Sets the visibility of the popup.
816+ */
817+ public void setPopupVisible(boolean v) {
818+ getUI().setPopupVisible(this, v);
819+ }
820+
821+ /**
822+ * Determines the visibility of the popup.
823+ *
824+ * @return true if the popup is visible, otherwise returns false
825+ */
826+ public boolean isPopupVisible() {
827+ return getUI().isPopupVisible(this);
828+ }
829+
830+ /** Selection **/
831+
832+ /**
833+ * Adds an <code>ItemListener</code>.
834+ * <p>
835+ * <code>aListener</code> will receive one or two <code>ItemEvent</code>s when
836+ * the selected item changes.
837+ *
838+ * @param aListener the <code>ItemListener</code> that is to be notified
839+ * @see #setSelectedItem
840+ */
841+ public void addItemListener(ItemListener aListener) {
842+ listenerList.add(ItemListener.class,aListener);
843+ }
844+
845+ /** Removes an <code>ItemListener</code>.
846+ *
847+ * @param aListener the <code>ItemListener</code> to remove
848+ */
849+ public void removeItemListener(ItemListener aListener) {
850+ listenerList.remove(ItemListener.class,aListener);
851+ }
852+
853+ /**
854+ * Returns an array of all the <code>ItemListener</code>s added
855+ * to this JComboBox with addItemListener().
856+ *
857+ * @return all of the <code>ItemListener</code>s added or an empty
858+ * array if no listeners have been added
859+ * @since 1.4
860+ */
861+ public ItemListener[] getItemListeners() {
862+ return listenerList.getListeners(ItemListener.class);
863+ }
864+
865+ /**
866+ * Adds an <code>ActionListener</code>.
867+ * <p>
868+ * The <code>ActionListener</code> will receive an <code>ActionEvent</code>
869+ * when a selection has been made. If the combo box is editable, then
870+ * an <code>ActionEvent</code> will be fired when editing has stopped.
871+ *
872+ * @param l the <code>ActionListener</code> that is to be notified
873+ * @see #setSelectedItem
874+ */
875+ public void addActionListener(ActionListener l) {
876+ listenerList.add(ActionListener.class,l);
877+ }
878+
879+ /** Removes an <code>ActionListener</code>.
880+ *
881+ * @param l the <code>ActionListener</code> to remove
882+ */
883+ public void removeActionListener(ActionListener l) {
884+ if ((l != null) && (getAction() == l)) {
885+ setAction(null);
886+ } else {
887+ listenerList.remove(ActionListener.class, l);
888+ }
889+ }
890+
891+ /**
892+ * Returns an array of all the <code>ActionListener</code>s added
893+ * to this JComboBox with addActionListener().
894+ *
895+ * @return all of the <code>ActionListener</code>s added or an empty
896+ * array if no listeners have been added
897+ * @since 1.4
898+ */
899+ public ActionListener[] getActionListeners() {
900+ return listenerList.getListeners(ActionListener.class);
901+ }
902+
903+ /**
904+ * Adds a <code>PopupMenu</code> listener which will listen to notification
905+ * messages from the popup portion of the combo box.
906+ * <p>
907+ * For all standard look and feels shipped with Java, the popup list
908+ * portion of combo box is implemented as a <code>JPopupMenu</code>.
909+ * A custom look and feel may not implement it this way and will
910+ * therefore not receive the notification.
911+ *
912+ * @param l the <code>PopupMenuListener</code> to add
913+ * @since 1.4
914+ */
915+ public void addPopupMenuListener(PopupMenuListener l) {
916+ listenerList.add(PopupMenuListener.class,l);
917+ }
918+
919+ /**
920+ * Removes a <code>PopupMenuListener</code>.
921+ *
922+ * @param l the <code>PopupMenuListener</code> to remove
923+ * @see #addPopupMenuListener
924+ * @since 1.4
925+ */
926+ public void removePopupMenuListener(PopupMenuListener l) {
927+ listenerList.remove(PopupMenuListener.class,l);
928+ }
929+
930+ /**
931+ * Returns an array of all the <code>PopupMenuListener</code>s added
932+ * to this JComboBox with addPopupMenuListener().
933+ *
934+ * @return all of the <code>PopupMenuListener</code>s added or an empty
935+ * array if no listeners have been added
936+ * @since 1.4
937+ */
938+ public PopupMenuListener[] getPopupMenuListeners() {
939+ return listenerList.getListeners(PopupMenuListener.class);
940+ }
941+
942+ /**
943+ * Notifies <code>PopupMenuListener</code>s that the popup portion of the
944+ * combo box will become visible.
945+ * <p>
946+ * This method is public but should not be called by anything other than
947+ * the UI delegate.
948+ * @see #addPopupMenuListener
949+ * @since 1.4
950+ */
951+ public void firePopupMenuWillBecomeVisible() {
952+ Object[] listeners = listenerList.getListenerList();
953+ PopupMenuEvent e=null;
954+ for (int i = listeners.length-2; i>=0; i-=2) {
955+ if (listeners[i]==PopupMenuListener.class) {
956+ if (e == null)
957+ e = new PopupMenuEvent(this);
958+ ((PopupMenuListener)listeners[i+1]).popupMenuWillBecomeVisible(e);
959+ }
960+ }
961+ }
962+
963+ /**
964+ * Notifies <code>PopupMenuListener</code>s that the popup portion of the
965+ * combo box has become invisible.
966+ * <p>
967+ * This method is public but should not be called by anything other than
968+ * the UI delegate.
969+ * @see #addPopupMenuListener
970+ * @since 1.4
971+ */
972+ public void firePopupMenuWillBecomeInvisible() {
973+ Object[] listeners = listenerList.getListenerList();
974+ PopupMenuEvent e=null;
975+ for (int i = listeners.length-2; i>=0; i-=2) {
976+ if (listeners[i]==PopupMenuListener.class) {
977+ if (e == null)
978+ e = new PopupMenuEvent(this);
979+ ((PopupMenuListener)listeners[i+1]).popupMenuWillBecomeInvisible(e);
980+ }
981+ }
982+ }
983+
984+ /**
985+ * Notifies <code>PopupMenuListener</code>s that the popup portion of the
986+ * combo box has been canceled.
987+ * <p>
988+ * This method is public but should not be called by anything other than
989+ * the UI delegate.
990+ * @see #addPopupMenuListener
991+ * @since 1.4
992+ */
993+ public void firePopupMenuCanceled() {
994+ Object[] listeners = listenerList.getListenerList();
995+ PopupMenuEvent e=null;
996+ for (int i = listeners.length-2; i>=0; i-=2) {
997+ if (listeners[i]==PopupMenuListener.class) {
998+ if (e == null)
999+ e = new PopupMenuEvent(this);
1000+ ((PopupMenuListener)listeners[i+1]).popupMenuCanceled(e);
1001+ }
1002+ }
1003+ }
1004+
1005+ /**
1006+ * Sets the action command that should be included in the event
1007+ * sent to action listeners.
1008+ *
1009+ * @param aCommand a string containing the "command" that is sent
1010+ * to action listeners; the same listener can then
1011+ * do different things depending on the command it
1012+ * receives
1013+ */
1014+ public void setActionCommand(String aCommand) {
1015+ actionCommand = aCommand;
1016+ }
1017+
1018+ /**
1019+ * Returns the action command that is included in the event sent to
1020+ * action listeners.
1021+ *
1022+ * @return the string containing the "command" that is sent
1023+ * to action listeners.
1024+ */
1025+ public String getActionCommand() {
1026+ return actionCommand;
1027+ }
1028+
1029+ private Action action;
1030+ private PropertyChangeListener actionPropertyChangeListener;
1031+
1032+ /**
1033+ * Sets the <code>Action</code> for the <code>ActionEvent</code> source.
1034+ * The new <code>Action</code> replaces any previously set
1035+ * <code>Action</code> but does not affect <code>ActionListeners</code>
1036+ * independently added with <code>addActionListener</code>.
1037+ * If the <code>Action</code> is already a registered
1038+ * <code>ActionListener</code> for the <code>ActionEvent</code> source,
1039+ * it is not re-registered.
1040+ * <p>
1041+ * Setting the <code>Action</code> results in immediately changing
1042+ * all the properties described in <a href="Action.html#buttonActions">
1043+ * Swing Components Supporting <code>Action</code></a>.
1044+ * Subsequently, the combobox's properties are automatically updated
1045+ * as the <code>Action</code>'s properties change.
1046+ * <p>
1047+ * This method uses three other methods to set
1048+ * and help track the <code>Action</code>'s property values.
1049+ * It uses the <code>configurePropertiesFromAction</code> method
1050+ * to immediately change the combobox's properties.
1051+ * To track changes in the <code>Action</code>'s property values,
1052+ * this method registers the <code>PropertyChangeListener</code>
1053+ * returned by <code>createActionPropertyChangeListener</code>. The
1054+ * default {@code PropertyChangeListener} invokes the
1055+ * {@code actionPropertyChanged} method when a property in the
1056+ * {@code Action} changes.
1057+ *
1058+ * @param a the <code>Action</code> for the <code>JComboBox</code>,
1059+ * or <code>null</code>.
1060+ * @since 1.3
1061+ * @see Action
1062+ * @see #getAction
1063+ * @see #configurePropertiesFromAction
1064+ * @see #createActionPropertyChangeListener
1065+ * @see #actionPropertyChanged
1066+ * @beaninfo
1067+ * bound: true
1068+ * attribute: visualUpdate true
1069+ * description: the Action instance connected with this ActionEvent source
1070+ */
1071+ public void setAction(Action a) {
1072+ Action oldValue = getAction();
1073+ if (action==null || !action.equals(a)) {
1074+ action = a;
1075+ if (oldValue!=null) {
1076+ removeActionListener(oldValue);
1077+ oldValue.removePropertyChangeListener(actionPropertyChangeListener);
1078+ actionPropertyChangeListener = null;
1079+ }
1080+ configurePropertiesFromAction(action);
1081+ if (action!=null) {
1082+ // Don't add if it is already a listener
1083+ if (!isListener(ActionListener.class, action)) {
1084+ addActionListener(action);
1085+ }
1086+ // Reverse linkage:
1087+ actionPropertyChangeListener = createActionPropertyChangeListener(action);
1088+ action.addPropertyChangeListener(actionPropertyChangeListener);
1089+ }
1090+ firePropertyChange("action", oldValue, action);
1091+ }
1092+ }
1093+
1094+ private boolean isListener(Class c, ActionListener a) {
1095+ boolean isListener = false;
1096+ Object[] listeners = listenerList.getListenerList();
1097+ for (int i = listeners.length-2; i>=0; i-=2) {
1098+ if (listeners[i]==c && listeners[i+1]==a) {
1099+ isListener=true;
1100+ }
1101+ }
1102+ return isListener;
1103+ }
1104+
1105+ /**
1106+ * Returns the currently set <code>Action</code> for this
1107+ * <code>ActionEvent</code> source, or <code>null</code> if no
1108+ * <code>Action</code> is set.
1109+ *
1110+ * @return the <code>Action</code> for this <code>ActionEvent</code>
1111+ * source; or <code>null</code>
1112+ * @since 1.3
1113+ * @see Action
1114+ * @see #setAction
1115+ */
1116+ public Action getAction() {
1117+ return action;
1118+ }
1119+
1120+ /**
1121+ * Sets the properties on this combobox to match those in the specified
1122+ * <code>Action</code>. Refer to <a href="Action.html#buttonActions">
1123+ * Swing Components Supporting <code>Action</code></a> for more
1124+ * details as to which properties this sets.
1125+ *
1126+ * @param a the <code>Action</code> from which to get the properties,
1127+ * or <code>null</code>
1128+ * @since 1.3
1129+ * @see Action
1130+ * @see #setAction
1131+ */
1132+ protected void configurePropertiesFromAction(Action a) {
1133+ AbstractAction.setEnabledFromAction(this, a);
1134+ AbstractAction.setToolTipTextFromAction(this, a);
1135+ setActionCommandFromAction(a);
1136+ }
1137+
1138+ /**
1139+ * Creates and returns a <code>PropertyChangeListener</code> that is
1140+ * responsible for listening for changes from the specified
1141+ * <code>Action</code> and updating the appropriate properties.
1142+ * <p>
1143+ * <b>Warning:</b> If you subclass this do not create an anonymous
1144+ * inner class. If you do the lifetime of the combobox will be tied to
1145+ * that of the <code>Action</code>.
1146+ *
1147+ * @param a the combobox's action
1148+ * @since 1.3
1149+ * @see Action
1150+ * @see #setAction
1151+ */
1152+ protected PropertyChangeListener createActionPropertyChangeListener(Action a) {
1153+ return new ComboBoxActionPropertyChangeListener(this, a);
1154+ }
1155+
1156+ /**
1157+ * Updates the combobox's state in response to property changes in
1158+ * associated action. This method is invoked from the
1159+ * {@code PropertyChangeListener} returned from
1160+ * {@code createActionPropertyChangeListener}. Subclasses do not normally
1161+ * need to invoke this. Subclasses that support additional {@code Action}
1162+ * properties should override this and
1163+ * {@code configurePropertiesFromAction}.
1164+ * <p>
1165+ * Refer to the table at <a href="Action.html#buttonActions">
1166+ * Swing Components Supporting <code>Action</code></a> for a list of
1167+ * the properties this method sets.
1168+ *
1169+ * @param action the <code>Action</code> associated with this combobox
1170+ * @param propertyName the name of the property that changed
1171+ * @since 1.6
1172+ * @see Action
1173+ * @see #configurePropertiesFromAction
1174+ */
1175+ protected void actionPropertyChanged(Action action, String propertyName) {
1176+ if (propertyName == Action.ACTION_COMMAND_KEY) {
1177+ setActionCommandFromAction(action);
1178+ } else if (propertyName == "enabled") {
1179+ AbstractAction.setEnabledFromAction(this, action);
1180+ } else if (Action.SHORT_DESCRIPTION == propertyName) {
1181+ AbstractAction.setToolTipTextFromAction(this, action);
1182+ }
1183+ }
1184+
1185+ private void setActionCommandFromAction(Action a) {
1186+ setActionCommand((a != null) ?
1187+ (String)a.getValue(Action.ACTION_COMMAND_KEY) :
1188+ null);
1189+ }
1190+
1191+
1192+ private static class ComboBoxActionPropertyChangeListener
1193+ extends ActionPropertyChangeListener<JComboBox<?>> {
1194+ ComboBoxActionPropertyChangeListener(JComboBox<?> b, Action a) {
1195+ super(b, a);
1196+ }
1197+ protected void actionPropertyChanged(JComboBox<?> cb,
1198+ Action action,
1199+ PropertyChangeEvent e) {
1200+ if (AbstractAction.shouldReconfigure(e)) {
1201+ cb.configurePropertiesFromAction(action);
1202+ } else {
1203+ cb.actionPropertyChanged(action, e.getPropertyName());
1204+ }
1205+ }
1206+ }
1207+
1208+ /**
1209+ * Notifies all listeners that have registered interest for
1210+ * notification on this event type.
1211+ * @param e the event of interest
1212+ *
1213+ * @see EventListenerList
1214+ */
1215+ protected void fireItemStateChanged(ItemEvent e) {
1216+ // Guaranteed to return a non-null array
1217+ Object[] listeners = listenerList.getListenerList();
1218+ // Process the listeners last to first, notifying
1219+ // those that are interested in this event
1220+ for ( int i = listeners.length-2; i>=0; i-=2 ) {
1221+ if ( listeners[i]==ItemListener.class ) {
1222+ // Lazily create the event:
1223+ // if (changeEvent == null)
1224+ // changeEvent = new ChangeEvent(this);
1225+ ((ItemListener)listeners[i+1]).itemStateChanged(e);
1226+ }
1227+ }
1228+ }
1229+
1230+ /**
1231+ * Notifies all listeners that have registered interest for
1232+ * notification on this event type.
1233+ *
1234+ * @see EventListenerList
1235+ */
1236+ protected void fireActionEvent() {
1237+ if (!firingActionEvent) {
1238+ // Set flag to ensure that an infinite loop is not created
1239+ firingActionEvent = true;
1240+ ActionEvent e = null;
1241+ // Guaranteed to return a non-null array
1242+ Object[] listeners = listenerList.getListenerList();
1243+ long mostRecentEventTime = EventQueue.getMostRecentEventTime();
1244+ int modifiers = 0;
1245+ AWTEvent currentEvent = EventQueue.getCurrentEvent();
1246+ if (currentEvent instanceof InputEvent) {
1247+ modifiers = ((InputEvent)currentEvent).getModifiers();
1248+ } else if (currentEvent instanceof ActionEvent) {
1249+ modifiers = ((ActionEvent)currentEvent).getModifiers();
1250+ }
1251+ // Process the listeners last to first, notifying
1252+ // those that are interested in this event
1253+ for ( int i = listeners.length-2; i>=0; i-=2 ) {
1254+ if ( listeners[i]==ActionListener.class ) {
1255+ // Lazily create the event:
1256+ if ( e == null )
1257+ e = new ActionEvent(this,ActionEvent.ACTION_PERFORMED,
1258+ getActionCommand(),
1259+ mostRecentEventTime, modifiers);
1260+ ((ActionListener)listeners[i+1]).actionPerformed(e);
1261+ }
1262+ }
1263+ firingActionEvent = false;
1264+ }
1265+ }
1266+
1267+ /**
1268+ * This protected method is implementation specific. Do not access directly
1269+ * or override.
1270+ */
1271+ protected void selectedItemChanged() {
1272+ if (selectedItemReminder != null ) {
1273+ fireItemStateChanged(new ItemEvent(this,ItemEvent.ITEM_STATE_CHANGED,
1274+ selectedItemReminder,
1275+ ItemEvent.DESELECTED));
1276+ }
1277+
1278+ // set the new selected item.
1279+ selectedItemReminder = dataModel.getSelectedItem();
1280+
1281+ if (selectedItemReminder != null ) {
1282+ fireItemStateChanged(new ItemEvent(this,ItemEvent.ITEM_STATE_CHANGED,
1283+ selectedItemReminder,
1284+ ItemEvent.SELECTED));
1285+ }
1286+ }
1287+
1288+ /**
1289+ * Returns an array containing the selected item.
1290+ * This method is implemented for compatibility with
1291+ * <code>ItemSelectable</code>.
1292+ *
1293+ * @return an array of <code>Objects</code> containing one
1294+ * element -- the selected item
1295+ */
1296+ public Object[] getSelectedObjects() {
1297+ Object selectedObject = getSelectedItem();
1298+ if ( selectedObject == null )
1299+ return new Object[0];
1300+ else {
1301+ Object result[] = new Object[1];
1302+ result[0] = selectedObject;
1303+ return result;
1304+ }
1305+ }
1306+
1307+ /**
1308+ * This method is public as an implementation side effect.
1309+ * do not call or override.
1310+ */
1311+ public void actionPerformed(ActionEvent e) {
1312+ Object newItem = getEditor().getItem();
1313+ setPopupVisible(false);
1314+ getModel().setSelectedItem(newItem);
1315+ String oldCommand = getActionCommand();
1316+ setActionCommand("comboBoxEdited");
1317+ fireActionEvent();
1318+ setActionCommand(oldCommand);
1319+ }
1320+
1321+ /**
1322+ * This method is public as an implementation side effect.
1323+ * do not call or override.
1324+ */
1325+ public void contentsChanged(ListDataEvent e) {
1326+ Object oldSelection = selectedItemReminder;
1327+ Object newSelection = dataModel.getSelectedItem();
1328+ if (oldSelection == null || !oldSelection.equals(newSelection)) {
1329+ selectedItemChanged();
1330+ if (!selectingItem) {
1331+ fireActionEvent();
1332+ }
1333+ }
1334+ }
1335+
1336+ /**
1337+ * This method is public as an implementation side effect.
1338+ * do not call or override.
1339+ */
1340+ public void intervalAdded(ListDataEvent e) {
1341+ if (selectedItemReminder != dataModel.getSelectedItem()) {
1342+ selectedItemChanged();
1343+ }
1344+ }
1345+
1346+ /**
1347+ * This method is public as an implementation side effect.
1348+ * do not call or override.
1349+ */
1350+ public void intervalRemoved(ListDataEvent e) {
1351+ contentsChanged(e);
1352+ }
1353+
1354+ /**
1355+ * Selects the list item that corresponds to the specified keyboard
1356+ * character and returns true, if there is an item corresponding
1357+ * to that character. Otherwise, returns false.
1358+ *
1359+ * @param keyChar a char, typically this is a keyboard key
1360+ * typed by the user
1361+ */
1362+ public boolean selectWithKeyChar(char keyChar) {
1363+ int index;
1364+
1365+ if ( keySelectionManager == null )
1366+ keySelectionManager = createDefaultKeySelectionManager();
1367+
1368+ index = keySelectionManager.selectionForKey(keyChar,getModel());
1369+ if ( index != -1 ) {
1370+ setSelectedIndex(index);
1371+ return true;
1372+ }
1373+ else
1374+ return false;
1375+ }
1376+
1377+ /**
1378+ * Enables the combo box so that items can be selected. When the
1379+ * combo box is disabled, items cannot be selected and values
1380+ * cannot be typed into its field (if it is editable).
1381+ *
1382+ * @param b a boolean value, where true enables the component and
1383+ * false disables it
1384+ * @beaninfo
1385+ * bound: true
1386+ * preferred: true
1387+ * description: Whether the combo box is enabled.
1388+ */
1389+ public void setEnabled(boolean b) {
1390+ super.setEnabled(b);
1391+ firePropertyChange( "enabled", !isEnabled(), isEnabled() );
1392+ }
1393+
1394+ /**
1395+ * Initializes the editor with the specified item.
1396+ *
1397+ * @param anEditor the <code>ComboBoxEditor</code> that displays
1398+ * the list item in the
1399+ * combo box field and allows it to be edited
1400+ * @param anItem the object to display and edit in the field
1401+ */
1402+ public void configureEditor(ComboBoxEditor anEditor, Object anItem) {
1403+ anEditor.setItem(anItem);
1404+ }
1405+
1406+ /**
1407+ * Handles <code>KeyEvent</code>s, looking for the Tab key.
1408+ * If the Tab key is found, the popup window is closed.
1409+ *
1410+ * @param e the <code>KeyEvent</code> containing the keyboard
1411+ * key that was pressed
1412+ */
1413+ public void processKeyEvent(KeyEvent e) {
1414+ if ( e.getKeyCode() == KeyEvent.VK_TAB ) {
1415+ hidePopup();
1416+ }
1417+ super.processKeyEvent(e);
1418+ }
1419+
1420+ /**
1421+ * Sets the object that translates a keyboard character into a list
1422+ * selection. Typically, the first selection with a matching first
1423+ * character becomes the selected item.
1424+ *
1425+ * @beaninfo
1426+ * expert: true
1427+ * description: The objects that changes the selection when a key is pressed.
1428+ */
1429+ public void setKeySelectionManager(KeySelectionManager aManager) {
1430+ keySelectionManager = aManager;
1431+ }
1432+
1433+ /**
1434+ * Returns the list's key-selection manager.
1435+ *
1436+ * @return the <code>KeySelectionManager</code> currently in use
1437+ */
1438+ public KeySelectionManager getKeySelectionManager() {
1439+ return keySelectionManager;
1440+ }
1441+
1442+ /* Accessing the model */
1443+ /**
1444+ * Returns the number of items in the list.
1445+ *
1446+ * @return an integer equal to the number of items in the list
1447+ */
1448+ public int getItemCount() {
1449+ return dataModel.getSize();
1450+ }
1451+
1452+ /**
1453+ * Returns the list item at the specified index. If <code>index</code>
1454+ * is out of range (less than zero or greater than or equal to size)
1455+ * it will return <code>null</code>.
1456+ *
1457+ * @param index an integer indicating the list position, where the first
1458+ * item starts at zero
1459+ * @return the item at that list position; or
1460+ * <code>null</code> if out of range
1461+ */
1462+ public E getItemAt(int index) {
1463+ return dataModel.getElementAt(index);
1464+ }
1465+
1466+ /**
1467+ * Returns an instance of the default key-selection manager.
1468+ *
1469+ * @return the <code>KeySelectionManager</code> currently used by the list
1470+ * @see #setKeySelectionManager
1471+ */
1472+ protected KeySelectionManager createDefaultKeySelectionManager() {
1473+ return new DefaultKeySelectionManager();
1474+ }
1475+
1476+
1477+ /**
1478+ * The interface that defines a <code>KeySelectionManager</code>.
1479+ * To qualify as a <code>KeySelectionManager</code>,
1480+ * the class needs to implement the method
1481+ * that identifies the list index given a character and the
1482+ * combo box data model.
1483+ */
1484+ public interface KeySelectionManager {
1485+ /** Given <code>aKey</code> and the model, returns the row
1486+ * that should become selected. Return -1 if no match was
1487+ * found.
1488+ *
1489+ * @param aKey a char value, usually indicating a keyboard key that
1490+ * was pressed
1491+ * @param aModel a ComboBoxModel -- the component's data model, containing
1492+ * the list of selectable items
1493+ * @return an int equal to the selected row, where 0 is the
1494+ * first item and -1 is none.
1495+ */
1496+ int selectionForKey(char aKey,ComboBoxModel aModel);
1497+ }
1498+
1499+ class DefaultKeySelectionManager implements KeySelectionManager, Serializable {
1500+ public int selectionForKey(char aKey,ComboBoxModel aModel) {
1501+ int i,c;
1502+ int currentSelection = -1;
1503+ Object selectedItem = aModel.getSelectedItem();
1504+ String v;
1505+ String pattern;
1506+
1507+ if ( selectedItem != null ) {
1508+ for ( i=0,c=aModel.getSize();i<c;i++ ) {
1509+ if ( selectedItem == aModel.getElementAt(i) ) {
1510+ currentSelection = i;
1511+ break;
1512+ }
1513+ }
1514+ }
1515+
1516+ pattern = ("" + aKey).toLowerCase();
1517+ aKey = pattern.charAt(0);
1518+
1519+ for ( i = ++currentSelection, c = aModel.getSize() ; i < c ; i++ ) {
1520+ Object elem = aModel.getElementAt(i);
1521+ if (elem != null && elem.toString() != null) {
1522+ v = elem.toString().toLowerCase();
1523+ if ( v.length() > 0 && v.charAt(0) == aKey )
1524+ return i;
1525+ }
1526+ }
1527+
1528+ for ( i = 0 ; i < currentSelection ; i ++ ) {
1529+ Object elem = aModel.getElementAt(i);
1530+ if (elem != null && elem.toString() != null) {
1531+ v = elem.toString().toLowerCase();
1532+ if ( v.length() > 0 && v.charAt(0) == aKey )
1533+ return i;
1534+ }
1535+ }
1536+ return -1;
1537+ }
1538+ }
1539+
1540+
1541+ /**
1542+ * See <code>readObject</code> and <code>writeObject</code> in
1543+ * <code>JComponent</code> for more
1544+ * information about serialization in Swing.
1545+ */
1546+ private void writeObject(ObjectOutputStream s) throws IOException {
1547+ s.defaultWriteObject();
1548+ if (getUIClassID().equals(uiClassID)) {
1549+ byte count = JComponent.getWriteObjCounter(this);
1550+ JComponent.setWriteObjCounter(this, --count);
1551+ if (count == 0 && ui != null) {
1552+ ui.installUI(this);
1553+ }
1554+ }
1555+ }
1556+
1557+
1558+ /**
1559+ * Returns a string representation of this <code>JComboBox</code>.
1560+ * This method is intended to be used only for debugging purposes,
1561+ * and the content and format of the returned string may vary between
1562+ * implementations. The returned string may be empty but may not
1563+ * be <code>null</code>.
1564+ *
1565+ * @return a string representation of this <code>JComboBox</code>
1566+ */
1567+ protected String paramString() {
1568+ String selectedItemReminderString = (selectedItemReminder != null ?
1569+ selectedItemReminder.toString() :
1570+ "");
1571+ String isEditableString = (isEditable ? "true" : "false");
1572+ String lightWeightPopupEnabledString = (lightWeightPopupEnabled ?
1573+ "true" : "false");
1574+
1575+ return super.paramString() +
1576+ ",isEditable=" + isEditableString +
1577+ ",lightWeightPopupEnabled=" + lightWeightPopupEnabledString +
1578+ ",maximumRowCount=" + maximumRowCount +
1579+ ",selectedItemReminder=" + selectedItemReminderString;
1580+ }
1581+
1582+
1583+///////////////////
1584+// Accessibility support
1585+///////////////////
1586+
1587+ /**
1588+ * Gets the AccessibleContext associated with this JComboBox.
1589+ * For combo boxes, the AccessibleContext takes the form of an
1590+ * AccessibleJComboBox.
1591+ * A new AccessibleJComboBox instance is created if necessary.
1592+ *
1593+ * @return an AccessibleJComboBox that serves as the
1594+ * AccessibleContext of this JComboBox
1595+ */
1596+ public AccessibleContext getAccessibleContext() {
1597+ if ( accessibleContext == null ) {
1598+ accessibleContext = new AccessibleJComboBox();
1599+ }
1600+ return accessibleContext;
1601+ }
1602+
1603+ /**
1604+ * This class implements accessibility support for the
1605+ * <code>JComboBox</code> class. It provides an implementation of the
1606+ * Java Accessibility API appropriate to Combo Box user-interface elements.
1607+ * <p>
1608+ * <strong>Warning:</strong>
1609+ * Serialized objects of this class will not be compatible with
1610+ * future Swing releases. The current serialization support is
1611+ * appropriate for short term storage or RMI between applications running
1612+ * the same version of Swing. As of 1.4, support for long term storage
1613+ * of all JavaBeans<sup><font size="-2">TM</font></sup>
1614+ * has been added to the <code>java.beans</code> package.
1615+ * Please see {@link java.beans.XMLEncoder}.
1616+ */
1617+ protected class AccessibleJComboBox extends AccessibleJComponent
1618+ implements AccessibleAction, AccessibleSelection {
1619+
1620+
1621+ private JList popupList; // combo box popup list
1622+ private Accessible previousSelectedAccessible = null;
1623+
1624+ /**
1625+ * Returns an AccessibleJComboBox instance
1626+ * @since 1.4
1627+ */
1628+ public AccessibleJComboBox() {
1629+ // set the combo box editor's accessible name and description
1630+ JComboBox.this.addPropertyChangeListener(new AccessibleJComboBoxPropertyChangeListener());
1631+ setEditorNameAndDescription();
1632+
1633+ // Get the popup list
1634+ Accessible a = getUI().getAccessibleChild(JComboBox.this, 0);
1635+ if (a instanceof javax.swing.plaf.basic.ComboPopup) {
1636+ // Listen for changes to the popup menu selection.
1637+ popupList = ((javax.swing.plaf.basic.ComboPopup)a).getList();
1638+ popupList.addListSelectionListener(
1639+ new AccessibleJComboBoxListSelectionListener());
1640+ }
1641+ // Listen for popup menu show/hide events
1642+ JComboBox.this.addPopupMenuListener(
1643+ new AccessibleJComboBoxPopupMenuListener());
1644+ }
1645+
1646+ /*
1647+ * JComboBox PropertyChangeListener
1648+ */
1649+ private class AccessibleJComboBoxPropertyChangeListener
1650+ implements PropertyChangeListener {
1651+
1652+ public void propertyChange(PropertyChangeEvent e) {
1653+ if (e.getPropertyName() == "editor") {
1654+ // set the combo box editor's accessible name
1655+ // and description
1656+ setEditorNameAndDescription();
1657+ }
1658+ }
1659+ }
1660+
1661+ /*
1662+ * Sets the combo box editor's accessible name and descripton
1663+ */
1664+ private void setEditorNameAndDescription() {
1665+ ComboBoxEditor editor = JComboBox.this.getEditor();
1666+ if (editor != null) {
1667+ Component comp = editor.getEditorComponent();
1668+ if (comp instanceof Accessible) {
1669+ AccessibleContext ac = comp.getAccessibleContext();
1670+ if (ac != null) { // may be null
1671+ ac.setAccessibleName(getAccessibleName());
1672+ ac.setAccessibleDescription(getAccessibleDescription());
1673+ }
1674+ }
1675+ }
1676+ }
1677+
1678+ /*
1679+ * Listener for combo box popup menu
1680+ * TIGER - 4669379 4894434
1681+ */
1682+ private class AccessibleJComboBoxPopupMenuListener
1683+ implements PopupMenuListener {
1684+
1685+ /**
1686+ * This method is called before the popup menu becomes visible
1687+ */
1688+ public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
1689+ // save the initial selection
1690+ if (popupList == null) {
1691+ return;
1692+ }
1693+ int selectedIndex = popupList.getSelectedIndex();
1694+ if (selectedIndex < 0) {
1695+ return;
1696+ }
1697+ previousSelectedAccessible =
1698+ popupList.getAccessibleContext().getAccessibleChild(selectedIndex);
1699+ }
1700+
1701+ /**
1702+ * This method is called before the popup menu becomes invisible
1703+ * Note that a JPopupMenu can become invisible any time
1704+ */
1705+ public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
1706+ // ignore
1707+ }
1708+
1709+ /**
1710+ * This method is called when the popup menu is canceled
1711+ */
1712+ public void popupMenuCanceled(PopupMenuEvent e) {
1713+ // ignore
1714+ }
1715+ }
1716+
1717+ /*
1718+ * Handles changes to the popup list selection.
1719+ * TIGER - 4669379 4894434 4933143
1720+ */
1721+ private class AccessibleJComboBoxListSelectionListener
1722+ implements ListSelectionListener {
1723+
1724+ public void valueChanged(ListSelectionEvent e) {
1725+ if (popupList == null) {
1726+ return;
1727+ }
1728+
1729+ // Get the selected popup list item.
1730+ int selectedIndex = popupList.getSelectedIndex();
1731+ if (selectedIndex < 0) {
1732+ return;
1733+ }
1734+ Accessible selectedAccessible =
1735+ popupList.getAccessibleContext().getAccessibleChild(selectedIndex);
1736+ if (selectedAccessible == null) {
1737+ return;
1738+ }
1739+
1740+ // Fire a FOCUSED lost PropertyChangeEvent for the
1741+ // previously selected list item.
1742+ PropertyChangeEvent pce;
1743+
1744+ if (previousSelectedAccessible != null) {
1745+ pce = new PropertyChangeEvent(previousSelectedAccessible,
1746+ AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
1747+ AccessibleState.FOCUSED, null);
1748+ firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
1749+ null, pce);
1750+ }
1751+ // Fire a FOCUSED gained PropertyChangeEvent for the
1752+ // currently selected list item.
1753+ pce = new PropertyChangeEvent(selectedAccessible,
1754+ AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
1755+ null, AccessibleState.FOCUSED);
1756+ firePropertyChange(AccessibleContext.ACCESSIBLE_STATE_PROPERTY,
1757+ null, pce);
1758+
1759+ // Fire the ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY event
1760+ // for the combo box.
1761+ firePropertyChange(AccessibleContext.ACCESSIBLE_ACTIVE_DESCENDANT_PROPERTY,
1762+ previousSelectedAccessible, selectedAccessible);
1763+
1764+ // Save the previous selection.
1765+ previousSelectedAccessible = selectedAccessible;
1766+ }
1767+ }
1768+
1769+
1770+ /**
1771+ * Returns the number of accessible children in the object. If all
1772+ * of the children of this object implement Accessible, than this
1773+ * method should return the number of children of this object.
1774+ *
1775+ * @return the number of accessible children in the object.
1776+ */
1777+ public int getAccessibleChildrenCount() {
1778+ // Always delegate to the UI if it exists
1779+ if (ui != null) {
1780+ return ui.getAccessibleChildrenCount(JComboBox.this);
1781+ } else {
1782+ return super.getAccessibleChildrenCount();
1783+ }
1784+ }
1785+
1786+ /**
1787+ * Returns the nth Accessible child of the object.
1788+ * The child at index zero represents the popup.
1789+ * If the combo box is editable, the child at index one
1790+ * represents the editor.
1791+ *
1792+ * @param i zero-based index of child
1793+ * @return the nth Accessible child of the object
1794+ */
1795+ public Accessible getAccessibleChild(int i) {
1796+ // Always delegate to the UI if it exists
1797+ if (ui != null) {
1798+ return ui.getAccessibleChild(JComboBox.this, i);
1799+ } else {
1800+ return super.getAccessibleChild(i);
1801+ }
1802+ }
1803+
1804+ /**
1805+ * Get the role of this object.
1806+ *
1807+ * @return an instance of AccessibleRole describing the role of the
1808+ * object
1809+ * @see AccessibleRole
1810+ */
1811+ public AccessibleRole getAccessibleRole() {
1812+ return AccessibleRole.COMBO_BOX;
1813+ }
1814+
1815+ /**
1816+ * Gets the state set of this object. The AccessibleStateSet of
1817+ * an object is composed of a set of unique AccessibleStates.
1818+ * A change in the AccessibleStateSet of an object will cause a
1819+ * PropertyChangeEvent to be fired for the ACCESSIBLE_STATE_PROPERTY
1820+ * property.
1821+ *
1822+ * @return an instance of AccessibleStateSet containing the
1823+ * current state set of the object
1824+ * @see AccessibleStateSet
1825+ * @see AccessibleState
1826+ * @see #addPropertyChangeListener
1827+ *
1828+ */
1829+ public AccessibleStateSet getAccessibleStateSet() {
1830+ // TIGER - 4489748
1831+ AccessibleStateSet ass = super.getAccessibleStateSet();
1832+ if (ass == null) {
1833+ ass = new AccessibleStateSet();
1834+ }
1835+ if (JComboBox.this.isPopupVisible()) {
1836+ ass.add(AccessibleState.EXPANDED);
1837+ } else {
1838+ ass.add(AccessibleState.COLLAPSED);
1839+ }
1840+ return ass;
1841+ }
1842+
1843+ /**
1844+ * Get the AccessibleAction associated with this object. In the
1845+ * implementation of the Java Accessibility API for this class,
1846+ * return this object, which is responsible for implementing the
1847+ * AccessibleAction interface on behalf of itself.
1848+ *
1849+ * @return this object
1850+ */
1851+ public AccessibleAction getAccessibleAction() {
1852+ return this;
1853+ }
1854+
1855+ /**
1856+ * Return a description of the specified action of the object.
1857+ *
1858+ * @param i zero-based index of the actions
1859+ */
1860+ public String getAccessibleActionDescription(int i) {
1861+ if (i == 0) {
1862+ return UIManager.getString("ComboBox.togglePopupText");
1863+ }
1864+ else {
1865+ return null;
1866+ }
1867+ }
1868+
1869+ /**
1870+ * Returns the number of Actions available in this object. The
1871+ * default behavior of a combo box is to have one action.
1872+ *
1873+ * @return 1, the number of Actions in this object
1874+ */
1875+ public int getAccessibleActionCount() {
1876+ return 1;
1877+ }
1878+
1879+ /**
1880+ * Perform the specified Action on the object
1881+ *
1882+ * @param i zero-based index of actions
1883+ * @return true if the the action was performed; else false.
1884+ */
1885+ public boolean doAccessibleAction(int i) {
1886+ if (i == 0) {
1887+ setPopupVisible(!isPopupVisible());
1888+ return true;
1889+ }
1890+ else {
1891+ return false;
1892+ }
1893+ }
1894+
1895+
1896+ /**
1897+ * Get the AccessibleSelection associated with this object. In the
1898+ * implementation of the Java Accessibility API for this class,
1899+ * return this object, which is responsible for implementing the
1900+ * AccessibleSelection interface on behalf of itself.
1901+ *
1902+ * @return this object
1903+ */
1904+ public AccessibleSelection getAccessibleSelection() {
1905+ return this;
1906+ }
1907+
1908+ /**
1909+ * Returns the number of Accessible children currently selected.
1910+ * If no children are selected, the return value will be 0.
1911+ *
1912+ * @return the number of items currently selected.
1913+ * @since 1.3
1914+ */
1915+ public int getAccessibleSelectionCount() {
1916+ Object o = JComboBox.this.getSelectedItem();
1917+ if (o != null) {
1918+ return 1;
1919+ } else {
1920+ return 0;
1921+ }
1922+ }
1923+
1924+ /**
1925+ * Returns an Accessible representing the specified selected child
1926+ * in the popup. If there isn't a selection, or there are
1927+ * fewer children selected than the integer passed in, the return
1928+ * value will be null.
1929+ * <p>Note that the index represents the i-th selected child, which
1930+ * is different from the i-th child.
1931+ *
1932+ * @param i the zero-based index of selected children
1933+ * @return the i-th selected child
1934+ * @see #getAccessibleSelectionCount
1935+ * @since 1.3
1936+ */
1937+ public Accessible getAccessibleSelection(int i) {
1938+ // Get the popup
1939+ Accessible a =
1940+ JComboBox.this.getUI().getAccessibleChild(JComboBox.this, 0);
1941+ if (a != null &&
1942+ a instanceof javax.swing.plaf.basic.ComboPopup) {
1943+
1944+ // get the popup list
1945+ JList list = ((javax.swing.plaf.basic.ComboPopup)a).getList();
1946+
1947+ // return the i-th selection in the popup list
1948+ AccessibleContext ac = list.getAccessibleContext();
1949+ if (ac != null) {
1950+ AccessibleSelection as = ac.getAccessibleSelection();
1951+ if (as != null) {
1952+ return as.getAccessibleSelection(i);
1953+ }
1954+ }
1955+ }
1956+ return null;
1957+ }
1958+
1959+ /**
1960+ * Determines if the current child of this object is selected.
1961+ *
1962+ * @return true if the current child of this object is selected;
1963+ * else false
1964+ * @param i the zero-based index of the child in this Accessible
1965+ * object.
1966+ * @see AccessibleContext#getAccessibleChild
1967+ * @since 1.3
1968+ */
1969+ public boolean isAccessibleChildSelected(int i) {
1970+ return JComboBox.this.getSelectedIndex() == i;
1971+ }
1972+
1973+ /**
1974+ * Adds the specified Accessible child of the object to the object's
1975+ * selection. If the object supports multiple selections,
1976+ * the specified child is added to any existing selection, otherwise
1977+ * it replaces any existing selection in the object. If the
1978+ * specified child is already selected, this method has no effect.
1979+ *
1980+ * @param i the zero-based index of the child
1981+ * @see AccessibleContext#getAccessibleChild
1982+ * @since 1.3
1983+ */
1984+ public void addAccessibleSelection(int i) {
1985+ // TIGER - 4856195
1986+ clearAccessibleSelection();
1987+ JComboBox.this.setSelectedIndex(i);
1988+ }
1989+
1990+ /**
1991+ * Removes the specified child of the object from the object's
1992+ * selection. If the specified item isn't currently selected, this
1993+ * method has no effect.
1994+ *
1995+ * @param i the zero-based index of the child
1996+ * @see AccessibleContext#getAccessibleChild
1997+ * @since 1.3
1998+ */
1999+ public void removeAccessibleSelection(int i) {
2000+ if (JComboBox.this.getSelectedIndex() == i) {
2001+ clearAccessibleSelection();
2002+ }
2003+ }
2004+
2005+ /**
2006+ * Clears the selection in the object, so that no children in the
2007+ * object are selected.
2008+ * @since 1.3
2009+ */
2010+ public void clearAccessibleSelection() {
2011+ JComboBox.this.setSelectedIndex(-1);
2012+ }
2013+
2014+ /**
2015+ * Causes every child of the object to be selected
2016+ * if the object supports multiple selections.
2017+ * @since 1.3
2018+ */
2019+ public void selectAllAccessibleSelection() {
2020+ // do nothing since multiple selection is not supported
2021+ }
2022+
2023+// public Accessible getAccessibleAt(Point p) {
2024+// Accessible a = getAccessibleChild(1);
2025+// if ( a != null ) {
2026+// return a; // the editor
2027+// }
2028+// else {
2029+// return getAccessibleChild(0); // the list
2030+// }
2031+// }
2032+ private EditorAccessibleContext editorAccessibleContext = null;
2033+
2034+ private class AccessibleEditor implements Accessible {
2035+ public AccessibleContext getAccessibleContext() {
2036+ if (editorAccessibleContext == null) {
2037+ Component c = JComboBox.this.getEditor().getEditorComponent();
2038+ if (c instanceof Accessible) {
2039+ editorAccessibleContext =
2040+ new EditorAccessibleContext((Accessible)c);
2041+ }
2042+ }
2043+ return editorAccessibleContext;
2044+ }
2045+ }
2046+
2047+ /*
2048+ * Wrapper class for the AccessibleContext implemented by the
2049+ * combo box editor. Delegates all method calls except
2050+ * getAccessibleIndexInParent to the editor. The
2051+ * getAccessibleIndexInParent method returns the selected
2052+ * index in the combo box.
2053+ */
2054+ private class EditorAccessibleContext extends AccessibleContext {
2055+
2056+ private AccessibleContext ac;
2057+
2058+ private EditorAccessibleContext() {
2059+ }
2060+
2061+ /*
2062+ * @param a the AccessibleContext implemented by the
2063+ * combo box editor
2064+ */
2065+ EditorAccessibleContext(Accessible a) {
2066+ this.ac = a.getAccessibleContext();
2067+ }
2068+
2069+ /**
2070+ * Gets the accessibleName property of this object. The accessibleName
2071+ * property of an object is a localized String that designates the purpose
2072+ * of the object. For example, the accessibleName property of a label
2073+ * or button might be the text of the label or button itself. In the
2074+ * case of an object that doesn't display its name, the accessibleName
2075+ * should still be set. For example, in the case of a text field used
2076+ * to enter the name of a city, the accessibleName for the en_US locale
2077+ * could be 'city.'
2078+ *
2079+ * @return the localized name of the object; null if this
2080+ * object does not have a name
2081+ *
2082+ * @see #setAccessibleName
2083+ */
2084+ public String getAccessibleName() {
2085+ return ac.getAccessibleName();
2086+ }
2087+
2088+ /**
2089+ * Sets the localized accessible name of this object. Changing the
2090+ * name will cause a PropertyChangeEvent to be fired for the
2091+ * ACCESSIBLE_NAME_PROPERTY property.
2092+ *
2093+ * @param s the new localized name of the object.
2094+ *
2095+ * @see #getAccessibleName
2096+ * @see #addPropertyChangeListener
2097+ *
2098+ * @beaninfo
2099+ * preferred: true
2100+ * description: Sets the accessible name for the component.
2101+ */
2102+ public void setAccessibleName(String s) {
2103+ ac.setAccessibleName(s);
2104+ }
2105+
2106+ /**
2107+ * Gets the accessibleDescription property of this object. The
2108+ * accessibleDescription property of this object is a short localized
2109+ * phrase describing the purpose of the object. For example, in the
2110+ * case of a 'Cancel' button, the accessibleDescription could be
2111+ * 'Ignore changes and close dialog box.'
2112+ *
2113+ * @return the localized description of the object; null if
2114+ * this object does not have a description
2115+ *
2116+ * @see #setAccessibleDescription
2117+ */
2118+ public String getAccessibleDescription() {
2119+ return ac.getAccessibleDescription();
2120+ }
2121+
2122+ /**
2123+ * Sets the accessible description of this object. Changing the
2124+ * name will cause a PropertyChangeEvent to be fired for the
2125+ * ACCESSIBLE_DESCRIPTION_PROPERTY property.
2126+ *
2127+ * @param s the new localized description of the object
2128+ *
2129+ * @see #setAccessibleName
2130+ * @see #addPropertyChangeListener
2131+ *
2132+ * @beaninfo
2133+ * preferred: true
2134+ * description: Sets the accessible description for the component.
2135+ */
2136+ public void setAccessibleDescription(String s) {
2137+ ac.setAccessibleDescription(s);
2138+ }
2139+
2140+ /**
2141+ * Gets the role of this object. The role of the object is the generic
2142+ * purpose or use of the class of this object. For example, the role
2143+ * of a push button is AccessibleRole.PUSH_BUTTON. The roles in
2144+ * AccessibleRole are provided so component developers can pick from
2145+ * a set of predefined roles. This enables assistive technologies to
2146+ * provide a consistent interface to various tweaked subclasses of
2147+ * components (e.g., use AccessibleRole.PUSH_BUTTON for all components
2148+ * that act like a push button) as well as distinguish between sublasses
2149+ * that behave differently (e.g., AccessibleRole.CHECK_BOX for check boxes
2150+ * and AccessibleRole.RADIO_BUTTON for radio buttons).
2151+ * <p>Note that the AccessibleRole class is also extensible, so
2152+ * custom component developers can define their own AccessibleRole's
2153+ * if the set of predefined roles is inadequate.
2154+ *
2155+ * @return an instance of AccessibleRole describing the role of the object
2156+ * @see AccessibleRole
2157+ */
2158+ public AccessibleRole getAccessibleRole() {
2159+ return ac.getAccessibleRole();
2160+ }
2161+
2162+ /**
2163+ * Gets the state set of this object. The AccessibleStateSet of an object
2164+ * is composed of a set of unique AccessibleStates. A change in the
2165+ * AccessibleStateSet of an object will cause a PropertyChangeEvent to
2166+ * be fired for the ACCESSIBLE_STATE_PROPERTY property.
2167+ *
2168+ * @return an instance of AccessibleStateSet containing the
2169+ * current state set of the object
2170+ * @see AccessibleStateSet
2171+ * @see AccessibleState
2172+ * @see #addPropertyChangeListener
2173+ */
2174+ public AccessibleStateSet getAccessibleStateSet() {
2175+ return ac.getAccessibleStateSet();
2176+ }
2177+
2178+ /**
2179+ * Gets the Accessible parent of this object.
2180+ *
2181+ * @return the Accessible parent of this object; null if this
2182+ * object does not have an Accessible parent
2183+ */
2184+ public Accessible getAccessibleParent() {
2185+ return ac.getAccessibleParent();
2186+ }
2187+
2188+ /**
2189+ * Sets the Accessible parent of this object. This is meant to be used
2190+ * only in the situations where the actual component's parent should
2191+ * not be treated as the component's accessible parent and is a method
2192+ * that should only be called by the parent of the accessible child.
2193+ *
2194+ * @param a - Accessible to be set as the parent
2195+ */
2196+ public void setAccessibleParent(Accessible a) {
2197+ ac.setAccessibleParent(a);
2198+ }
2199+
2200+ /**
2201+ * Gets the 0-based index of this object in its accessible parent.
2202+ *
2203+ * @return the 0-based index of this object in its parent; -1 if this
2204+ * object does not have an accessible parent.
2205+ *
2206+ * @see #getAccessibleParent
2207+ * @see #getAccessibleChildrenCount
2208+ * @see #getAccessibleChild
2209+ */
2210+ public int getAccessibleIndexInParent() {
2211+ return JComboBox.this.getSelectedIndex();
2212+ }
2213+
2214+ /**
2215+ * Returns the number of accessible children of the object.
2216+ *
2217+ * @return the number of accessible children of the object.
2218+ */
2219+ public int getAccessibleChildrenCount() {
2220+ return ac.getAccessibleChildrenCount();
2221+ }
2222+
2223+ /**
2224+ * Returns the specified Accessible child of the object. The Accessible
2225+ * children of an Accessible object are zero-based, so the first child
2226+ * of an Accessible child is at index 0, the second child is at index 1,
2227+ * and so on.
2228+ *
2229+ * @param i zero-based index of child
2230+ * @return the Accessible child of the object
2231+ * @see #getAccessibleChildrenCount
2232+ */
2233+ public Accessible getAccessibleChild(int i) {
2234+ return ac.getAccessibleChild(i);
2235+ }
2236+
2237+ /**
2238+ * Gets the locale of the component. If the component does not have a
2239+ * locale, then the locale of its parent is returned.
2240+ *
2241+ * @return this component's locale. If this component does not have
2242+ * a locale, the locale of its parent is returned.
2243+ *
2244+ * @exception IllegalComponentStateException
2245+ * If the Component does not have its own locale and has not yet been
2246+ * added to a containment hierarchy such that the locale can be
2247+ * determined from the containing parent.
2248+ */
2249+ public Locale getLocale() throws IllegalComponentStateException {
2250+ return ac.getLocale();
2251+ }
2252+
2253+ /**
2254+ * Adds a PropertyChangeListener to the listener list.
2255+ * The listener is registered for all Accessible properties and will
2256+ * be called when those properties change.
2257+ *
2258+ * @see #ACCESSIBLE_NAME_PROPERTY
2259+ * @see #ACCESSIBLE_DESCRIPTION_PROPERTY
2260+ * @see #ACCESSIBLE_STATE_PROPERTY
2261+ * @see #ACCESSIBLE_VALUE_PROPERTY
2262+ * @see #ACCESSIBLE_SELECTION_PROPERTY
2263+ * @see #ACCESSIBLE_TEXT_PROPERTY
2264+ * @see #ACCESSIBLE_VISIBLE_DATA_PROPERTY
2265+ *
2266+ * @param listener The PropertyChangeListener to be added
2267+ */
2268+ public void addPropertyChangeListener(PropertyChangeListener listener) {
2269+ ac.addPropertyChangeListener(listener);
2270+ }
2271+
2272+ /**
2273+ * Removes a PropertyChangeListener from the listener list.
2274+ * This removes a PropertyChangeListener that was registered
2275+ * for all properties.
2276+ *
2277+ * @param listener The PropertyChangeListener to be removed
2278+ */
2279+ public void removePropertyChangeListener(PropertyChangeListener listener) {
2280+ ac.removePropertyChangeListener(listener);
2281+ }
2282+
2283+ /**
2284+ * Gets the AccessibleAction associated with this object that supports
2285+ * one or more actions.
2286+ *
2287+ * @return AccessibleAction if supported by object; else return null
2288+ * @see AccessibleAction
2289+ */
2290+ public AccessibleAction getAccessibleAction() {
2291+ return ac.getAccessibleAction();
2292+ }
2293+
2294+ /**
2295+ * Gets the AccessibleComponent associated with this object that has a
2296+ * graphical representation.
2297+ *
2298+ * @return AccessibleComponent if supported by object; else return null
2299+ * @see AccessibleComponent
2300+ */
2301+ public AccessibleComponent getAccessibleComponent() {
2302+ return ac.getAccessibleComponent();
2303+ }
2304+
2305+ /**
2306+ * Gets the AccessibleSelection associated with this object which allows its
2307+ * Accessible children to be selected.
2308+ *
2309+ * @return AccessibleSelection if supported by object; else return null
2310+ * @see AccessibleSelection
2311+ */
2312+ public AccessibleSelection getAccessibleSelection() {
2313+ return ac.getAccessibleSelection();
2314+ }
2315+
2316+ /**
2317+ * Gets the AccessibleText associated with this object presenting
2318+ * text on the display.
2319+ *
2320+ * @return AccessibleText if supported by object; else return null
2321+ * @see AccessibleText
2322+ */
2323+ public AccessibleText getAccessibleText() {
2324+ return ac.getAccessibleText();
2325+ }
2326+
2327+ /**
2328+ * Gets the AccessibleEditableText associated with this object
2329+ * presenting editable text on the display.
2330+ *
2331+ * @return AccessibleEditableText if supported by object; else return null
2332+ * @see AccessibleEditableText
2333+ */
2334+ public AccessibleEditableText getAccessibleEditableText() {
2335+ return ac.getAccessibleEditableText();
2336+ }
2337+
2338+ /**
2339+ * Gets the AccessibleValue associated with this object that supports a
2340+ * Numerical value.
2341+ *
2342+ * @return AccessibleValue if supported by object; else return null
2343+ * @see AccessibleValue
2344+ */
2345+ public AccessibleValue getAccessibleValue() {
2346+ return ac.getAccessibleValue();
2347+ }
2348+
2349+ /**
2350+ * Gets the AccessibleIcons associated with an object that has
2351+ * one or more associated icons
2352+ *
2353+ * @return an array of AccessibleIcon if supported by object;
2354+ * otherwise return null
2355+ * @see AccessibleIcon
2356+ */
2357+ public AccessibleIcon [] getAccessibleIcon() {
2358+ return ac.getAccessibleIcon();
2359+ }
2360+
2361+ /**
2362+ * Gets the AccessibleRelationSet associated with an object
2363+ *
2364+ * @return an AccessibleRelationSet if supported by object;
2365+ * otherwise return null
2366+ * @see AccessibleRelationSet
2367+ */
2368+ public AccessibleRelationSet getAccessibleRelationSet() {
2369+ return ac.getAccessibleRelationSet();
2370+ }
2371+
2372+ /**
2373+ * Gets the AccessibleTable associated with an object
2374+ *
2375+ * @return an AccessibleTable if supported by object;
2376+ * otherwise return null
2377+ * @see AccessibleTable
2378+ */
2379+ public AccessibleTable getAccessibleTable() {
2380+ return ac.getAccessibleTable();
2381+ }
2382+
2383+ /**
2384+ * Support for reporting bound property changes. If oldValue and
2385+ * newValue are not equal and the PropertyChangeEvent listener list
2386+ * is not empty, then fire a PropertyChange event to each listener.
2387+ * In general, this is for use by the Accessible objects themselves
2388+ * and should not be called by an application program.
2389+ * @param propertyName The programmatic name of the property that
2390+ * was changed.
2391+ * @param oldValue The old value of the property.
2392+ * @param newValue The new value of the property.
2393+ * @see java.beans.PropertyChangeSupport
2394+ * @see #addPropertyChangeListener
2395+ * @see #removePropertyChangeListener
2396+ * @see #ACCESSIBLE_NAME_PROPERTY
2397+ * @see #ACCESSIBLE_DESCRIPTION_PROPERTY
2398+ * @see #ACCESSIBLE_STATE_PROPERTY
2399+ * @see #ACCESSIBLE_VALUE_PROPERTY
2400+ * @see #ACCESSIBLE_SELECTION_PROPERTY
2401+ * @see #ACCESSIBLE_TEXT_PROPERTY
2402+ * @see #ACCESSIBLE_VISIBLE_DATA_PROPERTY
2403+ */
2404+ public void firePropertyChange(String propertyName,
2405+ Object oldValue,
2406+ Object newValue) {
2407+ ac.firePropertyChange(propertyName, oldValue, newValue);
2408+ }
2409+ }
2410+
2411+ } // innerclass AccessibleJComboBox
2412+}