FileDocCategorySizeDatePackage
BasicComboPopup.javaAPI DocJava SE 6 API42924Tue Jun 10 00:26:46 BST 2008javax.swing.plaf.basic

BasicComboPopup

public class BasicComboPopup extends JPopupMenu implements ComboPopup
This is a basic implementation of the ComboPopup interface. This class represents the ui for the popup portion of the combo box.

All event handling is handled by listener classes created with the createxxxListener() methods and internal classes. You can change the behavior of this class by overriding the createxxxListener() methods and supplying your own event listeners or subclassing from the ones supplied in this class.

Warning: 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 JavaBeansTM has been added to the java.beans package. Please see {@link java.beans.XMLEncoder}.

version
1.84 08/03/06
author
Tom Santos
author
Mark Davidson

Fields Summary
static final ListModel
EmptyListModel
private static Border
LIST_BORDER
protected JComboBox
comboBox
protected JList
list
This protected field is implementation specific. Do not access directly or override. Use the accessor methods instead.
protected JScrollPane
scroller
This protected field is implementation specific. Do not access directly or override. Use the create method instead
protected boolean
valueIsAdjusting
As of Java 2 platform v1.4 this previously undocumented field is no longer used.
private Handler
handler
Implementation of all the listener classes.
protected MouseMotionListener
mouseMotionListener
This protected field is implementation specific. Do not access directly or override. Use the accessor or create methods instead.
protected MouseListener
mouseListener
This protected field is implementation specific. Do not access directly or override. Use the accessor or create methods instead.
protected KeyListener
keyListener
This protected field is implementation specific. Do not access directly or override. Use the accessor or create methods instead.
protected ListSelectionListener
listSelectionListener
This protected field is implementation specific. Do not access directly or override. Use the create method instead.
protected MouseListener
listMouseListener
This protected field is implementation specific. Do not access directly or override. Use the create method instead.
protected MouseMotionListener
listMouseMotionListener
This protected field is implementation specific. Do not access directly or override. Use the create method instead
protected PropertyChangeListener
propertyChangeListener
This protected field is implementation specific. Do not access directly or override. Use the create method instead
protected ListDataListener
listDataListener
This protected field is implementation specific. Do not access directly or override. Use the create method instead
protected ItemListener
itemListener
This protected field is implementation specific. Do not access directly or override. Use the create method instead
protected Timer
autoscrollTimer
This protected field is implementation specific. Do not access directly or override.
protected boolean
hasEntered
protected boolean
isAutoScrolling
protected int
scrollDirection
protected static final int
SCROLL_UP
protected static final int
SCROLL_DOWN
Constructors Summary
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();
    
Methods Summary
protected voidautoScrollDown()
This protected method is implementation specific and should be private. do not call or override.

        int index = list.getSelectedIndex();
        int lastItem = list.getModel().getSize() - 1;
        if ( index < lastItem ) {
            list.setSelectedIndex( index + 1 );
            list.ensureIndexIsVisible( index + 1 );
        }
    
protected voidautoScrollUp()
This protected method is implementation specific and should be private. do not call or override.

        int index = list.getSelectedIndex();
        if ( index > 0 ) {
            list.setSelectedIndex( index - 1 );
            list.ensureIndexIsVisible( index - 1 );
        }
    
protected java.awt.RectanglecomputePopupBounds(int px, int py, int pw, int ph)
Calculate the placement and size of the popup portion of the combo box based on the combo box location and the enclosing screen bounds. If no transformations are required, then the returned rectangle will have the same values as the parameters.

param
px starting x location
param
py starting y location
param
pw starting width
param
ph starting height
return
a rectangle which represents the placement and size of the popup

	Toolkit toolkit = Toolkit.getDefaultToolkit();
        Rectangle screenBounds;

	// Calculate the desktop dimensions relative to the combo box.
        GraphicsConfiguration gc = comboBox.getGraphicsConfiguration();
        Point p = new Point();
        SwingUtilities.convertPointFromScreen(p, comboBox);
        if (gc != null) {
	    Insets screenInsets = toolkit.getScreenInsets(gc);
            screenBounds = gc.getBounds();
	    screenBounds.width -= (screenInsets.left + screenInsets.right);
	    screenBounds.height -= (screenInsets.top + screenInsets.bottom);
            screenBounds.x += (p.x + screenInsets.left);
            screenBounds.y += (p.y + screenInsets.top);
        }
        else {
            screenBounds = new Rectangle(p, toolkit.getScreenSize());
        }

        Rectangle rect = new Rectangle(px,py,pw,ph);
        if (py+ph > screenBounds.y+screenBounds.height
	    && ph < screenBounds.height) {
	    rect.y = -rect.height;
	}
	return rect;
    
protected voidconfigureList()
Configures the list which is used to hold the combo box items in the popup. This method is called when the UI class is created.

see
#createList

        list.setFont( comboBox.getFont() );
        list.setForeground( comboBox.getForeground() );
        list.setBackground( comboBox.getBackground() );
        list.setSelectionForeground( UIManager.getColor( "ComboBox.selectionForeground" ) );
        list.setSelectionBackground( UIManager.getColor( "ComboBox.selectionBackground" ) );
        list.setBorder( null );
        list.setCellRenderer( comboBox.getRenderer() );
        list.setFocusable( false );
        list.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
        setListSelection( comboBox.getSelectedIndex() );
        installListListeners();
    
protected voidconfigurePopup()
Configures the popup portion of the combo box. This method is called when the UI class is created.

        setLayout( new BoxLayout( this, BoxLayout.Y_AXIS ) );
        setBorderPainted( true );
        setBorder(LIST_BORDER);
        setOpaque( false );
        add( scroller );
        setDoubleBuffered( true );
        setFocusable( false );
    
protected voidconfigureScroller()
Configures the scrollable portion which holds the list within the combo box popup. This method is called when the UI class is created.

        scroller.setFocusable( false );
        scroller.getVerticalScrollBar().setFocusable( false );
        scroller.setBorder( null );
    
protected java.awt.event.MouseEventconvertMouseEvent(java.awt.event.MouseEvent e)

        Point convertedPoint = SwingUtilities.convertPoint( (Component)e.getSource(),
                                                            e.getPoint(), list );
        MouseEvent newEvent = new MouseEvent( (Component)e.getSource(),
                                              e.getID(),
                                              e.getWhen(),
                                              e.getModifiers(),
                                              convertedPoint.x,
                                              convertedPoint.y,
                                              e.getXOnScreen(),
                                              e.getYOnScreen(),
                                              e.getClickCount(),
                                              e.isPopupTrigger(),
                                              MouseEvent.NOBUTTON );
        return newEvent;
    
protected java.awt.event.ItemListenercreateItemListener()
Creates an ItemListener which will be added to the combo box. If this method returns null then it will not be added to the combo box.

Subclasses may override this method to return instances of their own ItemEvent handlers.

return
an instance of an ItemListener or null

        return getHandler();
    
protected java.awt.event.KeyListenercreateKeyListener()
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 KeyListener or null

	return null;
    
protected javax.swing.JListcreateList()
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 JList used to display the combo box items

	return new JList( comboBox.getModel() ) {
            public void processMouseEvent(MouseEvent e)  {
                if (e.isControlDown())  {
                    // Fix for 4234053. Filter out the Control Key from the list. 
                    // ie., don't allow CTRL key deselection.
                    e = new MouseEvent((Component)e.getSource(), e.getID(), e.getWhen(), 
                                       e.getModifiers() ^ InputEvent.CTRL_MASK,
                                       e.getX(), e.getY(),
                                       e.getXOnScreen(), e.getYOnScreen(),
                                       e.getClickCount(),
                                       e.isPopupTrigger(),
                                       MouseEvent.NOBUTTON);
                }
                super.processMouseEvent(e);
            }
        };
    
protected javax.swing.event.ListDataListenercreateListDataListener()
Creates a list data listener which will be added to the ComboBoxModel. If this method returns null then it will not be added to the combo box model.

return
an instance of a ListDataListener or null

        return null;
    
protected java.awt.event.MouseListenercreateListMouseListener()
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 MouseListener or null

        return getHandler();
    
protected java.awt.event.MouseMotionListenercreateListMouseMotionListener()
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 MouseMotionListener or null

        return getHandler();
    
protected javax.swing.event.ListSelectionListenercreateListSelectionListener()
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 ListSelectionListener or null

        return null;
    
protected java.awt.event.MouseListenercreateMouseListener()
Creates a listener that will watch for mouse-press and release events on the combo box. Warning: When overriding this method, make sure to maintain the existing behavior.

return
a MouseListener which will be added to the combo box or null

        return getHandler();
    
protected java.awt.event.MouseMotionListenercreateMouseMotionListener()
Creates the mouse motion listener which will be added to the combo box. Warning: When overriding this method, make sure to maintain the existing behavior.

return
a MouseMotionListener which will be added to the combo box or null

        return getHandler();
    
protected java.beans.PropertyChangeListenercreatePropertyChangeListener()
Creates a PropertyChangeListener 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 PropertyChangeListener or null

        return getHandler();
    
protected javax.swing.JScrollPanecreateScroller()
Creates the scroll pane which houses the scrollable list.

        JScrollPane sp = new JScrollPane( list, 
				ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
				ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER );
        sp.setHorizontalScrollBar(null);
        return sp;
    
protected voiddelegateFocus(java.awt.event.MouseEvent e)
This is is a utility method that helps event handlers figure out where to send the focus when the popup is brought up. The standard implementation delegates the focus to the editor (if the combo box is editable) or to the JComboBox if it is not editable.

        if ( comboBox.isEditable() ) {
            Component comp = comboBox.getEditor().getEditorComponent();
            if ((!(comp instanceof JComponent)) || ((JComponent)comp).isRequestFocusEnabled()) {
                comp.requestFocus();
            }
        }
        else if (comboBox.isRequestFocusEnabled()) {
            comboBox.requestFocus();
        }
    
protected voidfirePopupMenuCanceled()

	super.firePopupMenuCanceled();
	comboBox.firePopupMenuCanceled();
    
protected voidfirePopupMenuWillBecomeInvisible()

	super.firePopupMenuWillBecomeInvisible();
	comboBox.firePopupMenuWillBecomeInvisible();
    
protected voidfirePopupMenuWillBecomeVisible()

	super.firePopupMenuWillBecomeVisible();
	comboBox.firePopupMenuWillBecomeVisible();
    
public javax.accessibility.AccessibleContextgetAccessibleContext()
Gets the AccessibleContext associated with this BasicComboPopup. The AccessibleContext will have its parent set to the ComboBox.

return
an AccessibleContext for the BasicComboPopup
since
1.5

        AccessibleContext context = super.getAccessibleContext();
        context.setAccessibleParent(comboBox);
        return context;
    
private javax.swing.plaf.basic.BasicComboPopup$HandlergetHandler()

        if (handler == null) {
            handler = new Handler();
        }
        return handler;
    
public java.awt.event.KeyListenergetKeyListener()
Implementation of ComboPopup.getKeyListener().

return
a KeyListener or null
see
ComboPopup#getKeyListener

	if (keyListener == null) {
	    keyListener = createKeyListener();
	}
	return keyListener;
    
public javax.swing.JListgetList()
Implementation of ComboPopup.getList().

        return list;
    
public java.awt.event.MouseListenergetMouseListener()
Implementation of ComboPopup.getMouseListener().

return
a MouseListener or null
see
ComboPopup#getMouseListener

	if (mouseListener == null) {
	    mouseListener = createMouseListener();
	}
        return mouseListener;
    
public java.awt.event.MouseMotionListenergetMouseMotionListener()
Implementation of ComboPopup.getMouseMotionListener().

return
a MouseMotionListener or null
see
ComboPopup#getMouseMotionListener

	if (mouseMotionListener == null) {
	    mouseMotionListener = createMouseMotionListener();
	}
        return mouseMotionListener;
    
protected intgetPopupHeightForRowCount(int maxRowCount)
Retrieves the height of the popup based on the current ListCellRenderer and the maximum row count.

	// Set the cached value of the minimum row count
        int minRowCount = Math.min( maxRowCount, comboBox.getItemCount() );
        int height = 0;
        ListCellRenderer renderer = list.getCellRenderer();
        Object value = null;

        for ( int i = 0; i < minRowCount; ++i ) {
            value = list.getModel().getElementAt( i );
            Component c = renderer.getListCellRendererComponent( list, value, i, false, false );
            height += c.getPreferredSize().height;
        }
        
        if (height == 0) {
            height = comboBox.getHeight();
        }
        
        Border border = scroller.getViewportBorder();
        if (border != null) {
            Insets insets = border.getBorderInsets(null);
            height += insets.top + insets.bottom;
        }
        
        border = scroller.getBorder();
        if (border != null) {
            Insets insets = border.getBorderInsets(null);
            height += insets.top + insets.bottom;
        }
        
        return height;
    
private java.awt.PointgetPopupLocation()
Calculates the upper left location of the Popup.

	Dimension popupSize = comboBox.getSize();
	Insets insets = getInsets();

	// reduce the width of the scrollpane by the insets so that the popup
	// is the same width as the combo box.
	popupSize.setSize(popupSize.width - (insets.right + insets.left), 
			  getPopupHeightForRowCount( comboBox.getMaximumRowCount()));
	Rectangle popupBounds = computePopupBounds( 0, comboBox.getBounds().height,
                                                    popupSize.width, popupSize.height);
	Dimension scrollSize = popupBounds.getSize();
	Point popupLocation = popupBounds.getLocation();
	    
	scroller.setMaximumSize( scrollSize );
	scroller.setPreferredSize( scrollSize );
	scroller.setMinimumSize( scrollSize );
	
	list.revalidate();

	return popupLocation;
    
public voidhide()
Implementation of ComboPopup.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();
        }
    
protected voidinstallComboBoxListeners()
This method adds the necessary listeners to the JComboBox.

        if ((propertyChangeListener = createPropertyChangeListener()) != null) {
	    comboBox.addPropertyChangeListener(propertyChangeListener);
	}
	if ((itemListener = createItemListener()) != null) {
	    comboBox.addItemListener(itemListener);
	}
	installComboBoxModelListeners(comboBox.getModel());
    
protected voidinstallComboBoxModelListeners(javax.swing.ComboBoxModel model)
Installs the listeners on the combo box model. Any listeners installed on the combo box model should be removed in uninstallComboBoxModelListeners.

param
model The combo box model to install listeners
see
#uninstallComboBoxModelListeners

	if (model != null && (listDataListener = createListDataListener()) != null) {
	    model.addListDataListener(listDataListener);
	}
    
protected voidinstallKeyboardActions()

        
        /* XXX - shouldn't call this method. take it out for testing.
        ActionListener action = new ActionListener() {
            public void actionPerformed(ActionEvent e){
            }
        };

        comboBox.registerKeyboardAction( action,
                                         KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, 0 ),
                                         JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ); */
        
    
protected voidinstallListListeners()
Adds the listeners to the list control.

        if ((listMouseListener = createListMouseListener()) != null) {
	    list.addMouseListener( listMouseListener );
	}
	if ((listMouseMotionListener = createListMouseMotionListener()) != null) {
	    list.addMouseMotionListener( listMouseMotionListener );
	}
	if ((listSelectionListener = createListSelectionListener()) != null) {
	    list.addListSelectionListener( listSelectionListener );
	}
    
public booleanisFocusTraversable()
Overridden to unconditionally return false.

        return false;
    
private voidsetListSelection(int selectedIndex)
Sets the list selection index to the selectedIndex. This method is used to synchronize the list selection with the combo box selection.

param
selectedIndex the index to set the list

        if ( selectedIndex == -1 ) {
            list.clearSelection();
        }
        else {
            list.setSelectedIndex( selectedIndex );
	    list.ensureIndexIsVisible( selectedIndex );
        }
    
public voidshow()
Implementation of ComboPopup.show().



    //========================================
    // begin ComboPopup method implementations
    //

            
       
	setListSelection(comboBox.getSelectedIndex());

	Point location = getPopupLocation();
        show( comboBox, location.x, location.y );
    
protected voidstartAutoScrolling(int direction)
This protected method is implementation specific and should be private. do not call or override.

        // XXX - should be a private method within InvocationMouseMotionHandler
        // if possible.
        if ( isAutoScrolling ) {
            autoscrollTimer.stop();
        }

        isAutoScrolling = true;

        if ( direction == SCROLL_UP ) {
            scrollDirection = SCROLL_UP;
            Point convertedPoint = SwingUtilities.convertPoint( scroller, new Point( 1, 1 ), list );
            int top = list.locationToIndex( convertedPoint );
            list.setSelectedIndex( top );

            autoscrollTimer = new Timer( 100, new AutoScrollActionHandler(
                                             SCROLL_UP) );
        }
        else if ( direction == SCROLL_DOWN ) {
            scrollDirection = SCROLL_DOWN;
            Dimension size = scroller.getSize();
            Point convertedPoint = SwingUtilities.convertPoint( scroller,
                                                                new Point( 1, (size.height - 1) - 2 ),
                                                                list );
            int bottom = list.locationToIndex( convertedPoint );
            list.setSelectedIndex( bottom );

            autoscrollTimer = new Timer(100, new AutoScrollActionHandler(
                                            SCROLL_DOWN));
        }
        autoscrollTimer.start();
    
protected voidstopAutoScrolling()
This protected method is implementation specific and should be private. do not call or override.

        isAutoScrolling = false;

        if ( autoscrollTimer != null ) {
            autoscrollTimer.stop();
            autoscrollTimer = null;
        }
    
protected voidtogglePopup()
Makes the popup visible if it is hidden and makes it hidden if it is visible.

        if ( isVisible() ) {
            hide();
        }
        else {
            show();
        }
    
protected voiduninstallComboBoxModelListeners(javax.swing.ComboBoxModel model)
Removes the listeners from the combo box model

param
model The combo box model to install listeners
see
#installComboBoxModelListeners

	if (model != null && listDataListener != null) {
	    model.removeListDataListener(listDataListener);
	}
    
protected voiduninstallKeyboardActions()

        // XXX - shouldn't call this method
//        comboBox.unregisterKeyboardAction( KeyStroke.getKeyStroke( KeyEvent.VK_ENTER, 0 ) );
    
voiduninstallListListeners()

	if (listMouseListener != null) {
	    list.removeMouseListener(listMouseListener);
	    listMouseListener = null;
	}
	if (listMouseMotionListener != null) {
	    list.removeMouseMotionListener(listMouseMotionListener);
	    listMouseMotionListener = null;
	}
	if (listSelectionListener != null) {
	    list.removeListSelectionListener(listSelectionListener);
	    listSelectionListener = null;
	}
        handler = null;
    
public voiduninstallingUI()
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().

	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);
    
protected voidupdateListBoxSelectionForEvent(java.awt.event.MouseEvent anEvent, boolean shouldScroll)
A utility method used by the event listeners. Given a mouse event, it changes the list selection to the list item below the mouse.

	// XXX - only seems to be called from this class. shouldScroll flag is
	// never true
        Point location = anEvent.getPoint();
        if ( list == null )
            return;
        int index = list.locationToIndex(location);
        if ( index == -1 ) {
            if ( location.y < 0 )
                index = 0;
            else
                index = comboBox.getModel().getSize() - 1;
        }
        if ( list.getSelectedIndex() != index ) {
            list.setSelectedIndex(index);
            if ( shouldScroll )
                list.ensureIndexIsVisible(index);
        }