1295 lines · 44.1 KB · Java
RawDownload
/* * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.swing.plaf.basic; import javax.accessibility.AccessibleContext;import javax.swing.*;import javax.swing.border.Border;import javax.swing.border.LineBorder;import javax.swing.event.*;import java.awt.*;import java.awt.event.*;import java.beans.PropertyChangeListener;import java.beans.PropertyChangeEvent;import java.io.Serializable;  /** * This is a basic implementation of the <code>ComboPopup</code> interface. * * This class represents the ui for the popup portion of the combo box. * <p> * All event handling is handled by listener classes created with the * <code>createxxxListener()</code> methods and internal classes. * You can change the behavior of this class by overriding the * <code>createxxxListener()</code> methods and supplying your own * event listeners or subclassing from the ones supplied in this class. * <p> * <strong>Warning:</strong> * Serialized objects of this class will not be compatible with * future Swing releases. The current serialization support is * appropriate for short term storage or RMI between applications running * the same version of Swing.  As of 1.4, support for long term storage * of all JavaBeans<sup><font size="-2">TM</font></sup> * has been added to the <code>java.beans</code> package. * Please see {@link java.beans.XMLEncoder}. * * @author Tom Santos * @author Mark Davidson */public class BasicComboPopup extends JPopupMenu implements ComboPopup {    // An empty ListMode, this is used when the UI changes to allow    // the JList to be gc'ed.    private static class EmptyListModelClass implements ListModel,                                                        Serializable {        public int getSize() { return 0; }        public Object getElementAt(int index) { return null; }        public void addListDataListener(ListDataListener l) {}        public void removeListDataListener(ListDataListener l) {}    };     static final ListModel EmptyListModel = new EmptyListModelClass();     private static Border LIST_BORDER = new LineBorder(Color.BLACK, 1);     protected JComboBox                comboBox;    /**     * This protected field is implementation specific. Do not access directly     * or override. Use the accessor methods instead.     *     * @see #getList     * @see #createList     */    protected JList                    list;    /**     * This protected field is implementation specific. Do not access directly     * or override. Use the create method instead     *     * @see #createScroller     */    protected JScrollPane              scroller;     /**     * As of Java 2 platform v1.4 this previously undocumented field is no     * longer used.     */    protected boolean                  valueIsAdjusting = false;     // Listeners that are required by the ComboPopup interface     /**     * Implementation of all the listener classes.     */    private Handler handler;     /**     * This protected field is implementation specific. Do not access directly     * or override. Use the accessor or create methods instead.     *     * @see #getMouseMotionListener     * @see #createMouseMotionListener     */    protected MouseMotionListener      mouseMotionListener;    /**     * This protected field is implementation specific. Do not access directly     * or override. Use the accessor or create methods instead.     *     * @see #getMouseListener     * @see #createMouseListener     */    protected MouseListener            mouseListener;     /**     * This protected field is implementation specific. Do not access directly     * or override. Use the accessor or create methods instead.     *     * @see #getKeyListener     * @see #createKeyListener     */    protected KeyListener              keyListener;     /**     * This protected field is implementation specific. Do not access directly     * or override. Use the create method instead.     *     * @see #createListSelectionListener     */    protected ListSelectionListener    listSelectionListener;     // Listeners that are attached to the list    /**     * This protected field is implementation specific. Do not access directly     * or override. Use the create method instead.     *     * @see #createListMouseListener     */    protected MouseListener            listMouseListener;    /**     * This protected field is implementation specific. Do not access directly     * or override. Use the create method instead     *     * @see #createListMouseMotionListener     */    protected MouseMotionListener      listMouseMotionListener;     // Added to the combo box for bound properties    /**     * This protected field is implementation specific. Do not access directly     * or override. Use the create method instead     *     * @see #createPropertyChangeListener     */    protected PropertyChangeListener   propertyChangeListener;     // Added to the combo box model    /**     * This protected field is implementation specific. Do not access directly     * or override. Use the create method instead     *     * @see #createListDataListener     */    protected ListDataListener         listDataListener;     /**     * This protected field is implementation specific. Do not access directly     * or override. Use the create method instead     *     * @see #createItemListener     */    protected ItemListener             itemListener;     /**     * This protected field is implementation specific. Do not access directly     * or override.     */    protected Timer                    autoscrollTimer;    protected boolean                  hasEntered = false;    protected boolean                  isAutoScrolling = false;    protected int                      scrollDirection = SCROLL_UP;     protected static final int         SCROLL_UP = 0;    protected static final int         SCROLL_DOWN = 1;      //========================================    // begin ComboPopup method implementations    //     /**     * Implementation of ComboPopup.show().     */    public void show() {        comboBox.firePopupMenuWillBecomeVisible();        setListSelection(comboBox.getSelectedIndex());        Point location = getPopupLocation();        show( comboBox, location.x, location.y );    }      /**     * Implementation of ComboPopup.hide().     */    public void hide() {        MenuSelectionManager manager = MenuSelectionManager.defaultManager();        MenuElement [] selection = manager.getSelectedPath();        for ( int i = 0 ; i < selection.length ; i++ ) {            if ( selection[i] == this ) {                manager.clearSelectedPath();                break;            }        }        if (selection.length > 0) {            comboBox.repaint();        }    }     /**     * Implementation of ComboPopup.getList().     */    public JList getList() {        return list;    }     /**     * Implementation of ComboPopup.getMouseListener().     *     * @return a <code>MouseListener</code> or null     * @see ComboPopup#getMouseListener     */    public MouseListener getMouseListener() {        if (mouseListener == null) {            mouseListener = createMouseListener();        }        return mouseListener;    }     /**     * Implementation of ComboPopup.getMouseMotionListener().     *     * @return a <code>MouseMotionListener</code> or null     * @see ComboPopup#getMouseMotionListener     */    public MouseMotionListener getMouseMotionListener() {        if (mouseMotionListener == null) {            mouseMotionListener = createMouseMotionListener();        }        return mouseMotionListener;    }     /**     * Implementation of ComboPopup.getKeyListener().     *     * @return a <code>KeyListener</code> or null     * @see ComboPopup#getKeyListener     */    public KeyListener getKeyListener() {        if (keyListener == null) {            keyListener = createKeyListener();        }        return keyListener;    }     /**     * Called when the UI is uninstalling.  Since this popup isn't in the component     * tree, it won't get it's uninstallUI() called.  It removes the listeners that     * were added in addComboBoxListeners().     */    public void uninstallingUI() {        if (propertyChangeListener != null) {            comboBox.removePropertyChangeListener( propertyChangeListener );        }        if (itemListener != null) {            comboBox.removeItemListener( itemListener );        }        uninstallComboBoxModelListeners(comboBox.getModel());        uninstallKeyboardActions();        uninstallListListeners();        // We do this, otherwise the listener the ui installs on        // the model (the combobox model in this case) will keep a        // reference to the list, causing the list (and us) to never get gced.        list.setModel(EmptyListModel);    }     //    // end ComboPopup method implementations    //======================================     /**     * Removes the listeners from the combo box model     *     * @param model The combo box model to install listeners     * @see #installComboBoxModelListeners     */    protected void uninstallComboBoxModelListeners( ComboBoxModel model ) {        if (model != null && listDataListener != null) {            model.removeListDataListener(listDataListener);        }    }     protected void uninstallKeyboardActions() {        // XXX - shouldn't call this method//        comboBox.unregisterKeyboardAction( KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, 0 ) );    }       //===================================================================    // begin Initialization routines    //    public BasicComboPopup( JComboBox combo ) {        super();        setName("ComboPopup.popup");        comboBox = combo;         setLightWeightPopupEnabled( comboBox.isLightWeightPopupEnabled() );         // UI construction of the popup.        list = createList();        list.setName("ComboBox.list");        configureList();        scroller = createScroller();        scroller.setName("ComboBox.scrollPane");        configureScroller();        configurePopup();         installComboBoxListeners();        installKeyboardActions();    }     // Overriden PopupMenuListener notification methods to inform combo box    // PopupMenuListeners.     protected void firePopupMenuWillBecomeVisible() {        super.firePopupMenuWillBecomeVisible();        // comboBox.firePopupMenuWillBecomeVisible() is called from BasicComboPopup.show() method        // to let the user change the popup menu from the PopupMenuListener.popupMenuWillBecomeVisible()    }     protected void firePopupMenuWillBecomeInvisible() {        super.firePopupMenuWillBecomeInvisible();        comboBox.firePopupMenuWillBecomeInvisible();    }     protected void firePopupMenuCanceled() {        super.firePopupMenuCanceled();        comboBox.firePopupMenuCanceled();    }     /**     * Creates a listener     * that will watch for mouse-press and release events on the combo box.     *     * <strong>Warning:</strong>     * When overriding this method, make sure to maintain the existing     * behavior.     *     * @return a <code>MouseListener</code> which will be added to     * the combo box or null     */    protected MouseListener createMouseListener() {        return getHandler();    }     /**     * Creates the mouse motion listener which will be added to the combo     * box.     *     * <strong>Warning:</strong>     * When overriding this method, make sure to maintain the existing     * behavior.     *     * @return a <code>MouseMotionListener</code> which will be added to     *         the combo box or null     */    protected MouseMotionListener createMouseMotionListener() {        return getHandler();    }     /**     * Creates the key listener that will be added to the combo box. If     * this method returns null then it will not be added to the combo box.     *     * @return a <code>KeyListener</code> or null     */    protected KeyListener createKeyListener() {        return null;    }     /**     * Creates a list selection listener that watches for selection changes in     * the popup's list.  If this method returns null then it will not     * be added to the popup list.     *     * @return an instance of a <code>ListSelectionListener</code> or null     */    protected ListSelectionListener createListSelectionListener() {        return null;    }     /**     * Creates a list data listener which will be added to the     * <code>ComboBoxModel</code>. If this method returns null then     * it will not be added to the combo box model.     *     * @return an instance of a <code>ListDataListener</code> or null     */    protected ListDataListener createListDataListener() {        return null;    }     /**     * Creates a mouse listener that watches for mouse events in     * the popup's list. If this method returns null then it will     * not be added to the combo box.     *     * @return an instance of a <code>MouseListener</code> or null     */    protected MouseListener createListMouseListener() {        return getHandler();    }     /**     * Creates a mouse motion listener that watches for mouse motion     * events in the popup's list. If this method returns null then it will     * not be added to the combo box.     *     * @return an instance of a <code>MouseMotionListener</code> or null     */    protected MouseMotionListener createListMouseMotionListener() {        return getHandler();    }     /**     * Creates a <code>PropertyChangeListener</code> which will be added to     * the combo box. If this method returns null then it will not     * be added to the combo box.     *     * @return an instance of a <code>PropertyChangeListener</code> or null     */    protected PropertyChangeListener createPropertyChangeListener() {        return getHandler();    }     /**     * Creates an <code>ItemListener</code> which will be added to the     * combo box. If this method returns null then it will not     * be added to the combo box.     * <p>     * Subclasses may override this method to return instances of their own     * ItemEvent handlers.     *     * @return an instance of an <code>ItemListener</code> or null     */    protected ItemListener createItemListener() {        return getHandler();    }     private Handler getHandler() {        if (handler == null) {            handler = new Handler();        }        return handler;    }     /**     * Creates the JList used in the popup to display     * the items in the combo box model. This method is called when the UI class     * is created.     *     * @return a <code>JList</code> used to display the combo box items     */    protected JList createList() {        return new JList( comboBox.getModel() ) {            public void processMouseEvent(MouseEvent e)  {                if (BasicGraphicsUtils.isMenuShortcutKeyDown(e))  {                    // Fix for 4234053. Filter out the Control Key from the list.                    // ie., don't allow CTRL key deselection.                    Toolkit toolkit = Toolkit.getDefaultToolkit();                    e = new MouseEvent((Component)e.getSource(), e.getID(), e.getWhen(),                                       e.getModifiers() ^ toolkit.getMenuShortcutKeyMask(),                                       e.getX(), e.getY(),                                       e.getXOnScreen(), e.getYOnScreen(),                                       e.getClickCount(),                                       e.isPopupTrigger(),                                       MouseEvent.NOBUTTON);                }                super.processMouseEvent(e);            }

Lines 1–500 of 1295.