brainfrz

Untitled

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