1972 lines · 69.3 KB · Java
RawDownload
/* * Copyright (c) 1997, 2011, 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 java.awt.*;import java.awt.event.*;import javax.swing.*;import javax.accessibility.*;import javax.swing.plaf.*;import javax.swing.text.*;import javax.swing.event.*;import java.beans.PropertyChangeListener;import java.beans.PropertyChangeEvent;import sun.awt.AppContext;import sun.swing.DefaultLookup;import sun.swing.UIAction; /** * Basic UI implementation for JComboBox. * <p> * The combo box is a compound component which means that it is an agregate of * many simpler components. This class creates and manages the listeners * on the combo box and the combo box model. These listeners update the user * interface in response to changes in the properties and state 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> * For adding specific actions, * overide <code>installKeyboardActions</code> to add actions in response to * KeyStroke bindings. See the article <a href="http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html">Keyboard Bindings in Swing</a> * at <a href="http://java.sun.com/products/jfc/tsc"><em>The Swing Connection</em></a>. * * @author Arnaud Weber * @author Tom Santos * @author Mark Davidson */public class BasicComboBoxUI extends ComboBoxUI {    protected JComboBox comboBox;    /**     * This protected field is implementation specific. Do not access directly     * or override.     */    protected boolean   hasFocus = false;     // Control the selection behavior of the JComboBox when it is used    // in the JTable DefaultCellEditor.    private boolean isTableCellEditor = false;    private static final String IS_TABLE_CELL_EDITOR = "JComboBox.isTableCellEditor";     // This list is for drawing the current item in the combo box.    protected JList   listBox;     // Used to render the currently selected item in the combo box.    // It doesn't have anything to do with the popup's rendering.    protected CellRendererPane currentValuePane = new CellRendererPane();     // The implementation of ComboPopup that is used to show the popup.    protected ComboPopup popup;     // The Component that the ComboBoxEditor uses for editing    protected Component editor;     // The arrow button that invokes the popup.    protected JButton   arrowButton;     // Listeners that are attached to the JComboBox    /**     * This protected field is implementation specific. Do not access directly     * or override. Override the listener construction method instead.     *     * @see #createKeyListener     */    protected KeyListener keyListener;    /**     * This protected field is implementation specific. Do not access directly     * or override. Override the listener construction method instead.     *     * @see #createFocusListener     */    protected FocusListener focusListener;    /**     * This protected field is implementation specific. Do not access directly     * or override. Override the listener construction method instead.     *     * @see #createPropertyChangeListener     */    protected PropertyChangeListener propertyChangeListener;     /**     * This protected field is implementation specific. Do not access directly     * or override. Override the listener construction method instead.     *     * @see #createItemListener     */    protected ItemListener itemListener;     // Listeners that the ComboPopup produces.    protected MouseListener popupMouseListener;    protected MouseMotionListener popupMouseMotionListener;    protected KeyListener popupKeyListener;     // This is used for knowing when to cache the minimum preferred size.    // If the data in the list changes, the cached value get marked for recalc.    // Added to the current JComboBox model    /**     * This protected field is implementation specific. Do not access directly     * or override. Override the listener construction method instead.     *     * @see #createListDataListener     */    protected ListDataListener listDataListener;     /**     * Implements all the Listeners needed by this class, all existing     * listeners redirect to it.     */    private Handler handler;     /**     * The time factor to treate the series of typed alphanumeric key     * as prefix for first letter navigation.     */    private long timeFactor = 1000L;     /**     * This is tricky, this variables is needed for DefaultKeySelectionManager     * to take into account time factor.     */    private long lastTime = 0L;    private long time = 0L;     /**     * The default key selection manager     */    JComboBox.KeySelectionManager keySelectionManager;     // Flag for recalculating the minimum preferred size.    protected boolean isMinimumSizeDirty = true;     // Cached minimum preferred size.    protected Dimension cachedMinimumSize = new Dimension( 0, 0 );     // Flag for calculating the display size    private boolean isDisplaySizeDirty = true;     // Cached the size that the display needs to render the largest item    private Dimension cachedDisplaySize = new Dimension( 0, 0 );     // Key used for lookup of the DefaultListCellRenderer in the AppContext.    private static final Object COMBO_UI_LIST_CELL_RENDERER_KEY =                        new StringBuffer("DefaultListCellRendererKey");     static final StringBuffer HIDE_POPUP_KEY                  = new StringBuffer("HidePopupKey");     /**     * Whether or not all cells have the same baseline.     */    private boolean sameBaseline;     /**     * Indicates whether or not the combo box button should be square.     * If square, then the width and height are equal, and are both set to     * the height of the combo minus appropriate insets.     *     * @since 1.7     */    protected boolean squareButton = true;     /**     * If specified, these insets act as padding around the cell renderer when     * laying out and painting the "selected" item in the combo box. These     * insets add to those specified by the cell renderer.     *     * @since 1.7     */    protected Insets padding;     // Used for calculating the default size.    private static ListCellRenderer getDefaultListCellRenderer() {        ListCellRenderer renderer = (ListCellRenderer)AppContext.                         getAppContext().get(COMBO_UI_LIST_CELL_RENDERER_KEY);         if (renderer == null) {            renderer = new DefaultListCellRenderer();            AppContext.getAppContext().put(COMBO_UI_LIST_CELL_RENDERER_KEY,                                           new DefaultListCellRenderer());        }        return renderer;    }     /**     * Populates ComboBox's actions.     */    static void loadActionMap(LazyActionMap map) {        map.put(new Actions(Actions.HIDE));        map.put(new Actions(Actions.PAGE_DOWN));        map.put(new Actions(Actions.PAGE_UP));        map.put(new Actions(Actions.HOME));        map.put(new Actions(Actions.END));        map.put(new Actions(Actions.DOWN));        map.put(new Actions(Actions.DOWN_2));        map.put(new Actions(Actions.TOGGLE));        map.put(new Actions(Actions.TOGGLE_2));        map.put(new Actions(Actions.UP));        map.put(new Actions(Actions.UP_2));        map.put(new Actions(Actions.ENTER));    }     //========================    // begin UI Initialization    //     public static ComponentUI createUI(JComponent c) {        return new BasicComboBoxUI();    }     @Override    public void installUI( JComponent c ) {        isMinimumSizeDirty = true;         comboBox = (JComboBox)c;        installDefaults();        popup = createPopup();        listBox = popup.getList();         // Is this combo box a cell editor?        Boolean inTable = (Boolean)c.getClientProperty(IS_TABLE_CELL_EDITOR );        if (inTable != null) {            isTableCellEditor = inTable.equals(Boolean.TRUE) ? true : false;        }         if ( comboBox.getRenderer() == null || comboBox.getRenderer() instanceof UIResource ) {            comboBox.setRenderer( createRenderer() );        }         if ( comboBox.getEditor() == null || comboBox.getEditor() instanceof UIResource ) {            comboBox.setEditor( createEditor() );        }         installListeners();        installComponents();         comboBox.setLayout( createLayoutManager() );         comboBox.setRequestFocusEnabled( true );         installKeyboardActions();         comboBox.putClientProperty("doNotCancelPopup", HIDE_POPUP_KEY);         if (keySelectionManager == null || keySelectionManager instanceof UIResource) {            keySelectionManager = new DefaultKeySelectionManager();        }        comboBox.setKeySelectionManager(keySelectionManager);    }     @Override    public void uninstallUI( JComponent c ) {        setPopupVisible( comboBox, false);        popup.uninstallingUI();         uninstallKeyboardActions();         comboBox.setLayout( null );         uninstallComponents();        uninstallListeners();        uninstallDefaults();         if ( comboBox.getRenderer() == null || comboBox.getRenderer() instanceof UIResource ) {            comboBox.setRenderer( null );        }         ComboBoxEditor comboBoxEditor = comboBox.getEditor();        if (comboBoxEditor instanceof UIResource ) {            if (comboBoxEditor.getEditorComponent().hasFocus()) {                // Leave focus in JComboBox.                comboBox.requestFocusInWindow();            }            comboBox.setEditor( null );        }         if (keySelectionManager instanceof UIResource) {            comboBox.setKeySelectionManager(null);        }         handler = null;        keyListener = null;        focusListener = null;        listDataListener = null;        propertyChangeListener = null;        popup = null;        listBox = null;        comboBox = null;    }     /**     * Installs the default colors, default font, default renderer, and default     * editor into the JComboBox.     */    protected void installDefaults() {        LookAndFeel.installColorsAndFont( comboBox,                                          "ComboBox.background",                                          "ComboBox.foreground",                                          "ComboBox.font" );        LookAndFeel.installBorder( comboBox, "ComboBox.border" );        LookAndFeel.installProperty( comboBox, "opaque", Boolean.TRUE);         Long l = (Long)UIManager.get("ComboBox.timeFactor");        timeFactor = l == null ? 1000L : l.longValue();         //NOTE: this needs to default to true if not specified        Boolean b = (Boolean)UIManager.get("ComboBox.squareButton");        squareButton = b == null ? true : b;         padding = UIManager.getInsets("ComboBox.padding");    }     /**     * Creates and installs listeners for the combo box and its model.     * This method is called when the UI is installed.     */    protected void installListeners() {        if ( (itemListener = createItemListener()) != null) {            comboBox.addItemListener( itemListener );        }        if ( (propertyChangeListener = createPropertyChangeListener()) != null ) {            comboBox.addPropertyChangeListener( propertyChangeListener );        }        if ( (keyListener = createKeyListener()) != null ) {            comboBox.addKeyListener( keyListener );        }        if ( (focusListener = createFocusListener()) != null ) {            comboBox.addFocusListener( focusListener );        }        if ((popupMouseListener = popup.getMouseListener()) != null) {            comboBox.addMouseListener( popupMouseListener );        }        if ((popupMouseMotionListener = popup.getMouseMotionListener()) != null) {            comboBox.addMouseMotionListener( popupMouseMotionListener );        }        if ((popupKeyListener = popup.getKeyListener()) != null) {            comboBox.addKeyListener(popupKeyListener);        }         if ( comboBox.getModel() != null ) {            if ( (listDataListener = createListDataListener()) != null ) {                comboBox.getModel().addListDataListener( listDataListener );            }        }    }     /**     * Uninstalls the default colors, default font, default renderer,     * and default editor from the combo box.     */    protected void uninstallDefaults() {        LookAndFeel.installColorsAndFont( comboBox,                                          "ComboBox.background",                                          "ComboBox.foreground",                                          "ComboBox.font" );        LookAndFeel.uninstallBorder( comboBox );    }     /**     * Removes the installed listeners from the combo box and its model.     * The number and types of listeners removed and in this method should be     * the same that was added in <code>installListeners</code>     */    protected void uninstallListeners() {        if ( keyListener != null ) {            comboBox.removeKeyListener( keyListener );        }        if ( itemListener != null) {            comboBox.removeItemListener( itemListener );        }        if ( propertyChangeListener != null ) {            comboBox.removePropertyChangeListener( propertyChangeListener );        }        if ( focusListener != null) {            comboBox.removeFocusListener( focusListener );        }        if ( popupMouseListener != null) {            comboBox.removeMouseListener( popupMouseListener );        }        if ( popupMouseMotionListener != null) {            comboBox.removeMouseMotionListener( popupMouseMotionListener );        }        if (popupKeyListener != null) {            comboBox.removeKeyListener(popupKeyListener);        }        if ( comboBox.getModel() != null ) {            if ( listDataListener != null ) {                comboBox.getModel().removeListDataListener( listDataListener );            }        }    }     /**     * Creates the popup portion of the combo box.     *     * @return an instance of <code>ComboPopup</code>     * @see ComboPopup     */    protected ComboPopup createPopup() {        return new BasicComboPopup( comboBox );    }     /**     * Creates a <code>KeyListener</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 <code>KeyListener</code> or null     */    protected KeyListener createKeyListener() {        return getHandler();    }     /**     * Creates a <code>FocusListener</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>FocusListener</code> or null     */    protected FocusListener createFocusListener() {        return getHandler();    }     /**     * 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 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 null;    }     /**     * 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 a layout manager for managing the components which make up the     * combo box.     *     * @return an instance of a layout manager     */    protected LayoutManager createLayoutManager() {

Lines 1–500 of 1972.