/* * 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. Load more
/* * 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); }