blob: c29829d777d3a7c1e28cea169ebe889e13645c2c [file] [log] [blame]
/* BasicComboPopup.java --
Copyright (C) 2004, 2005 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath 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 for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
package javax.swing.plaf.basic;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.BorderFactory;
import javax.swing.ComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JList;
import javax.swing.JPopupMenu;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.MenuSelectionManager;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
/**
* UI Delegate for ComboPopup
*
* @author Olga Rodimina
*/
public class BasicComboPopup extends JPopupMenu implements ComboPopup
{
/* Timer for autoscrolling */
protected Timer autoscrollTimer;
/** ComboBox associated with this popup */
protected JComboBox comboBox;
/** FIXME: Need to document */
protected boolean hasEntered;
/**
* Indicates whether the scroll bar located in popup menu with comboBox's
* list of items is currently autoscrolling. This happens when mouse event
* originated in the combo box and is dragged outside of its bounds
*/
protected boolean isAutoScrolling;
/** ItemListener listening to the selection changes in the combo box */
protected ItemListener itemListener;
/** This listener is not used */
protected KeyListener keyListener;
/** JList which is used to display item is the combo box */
protected JList list;
/** This listener is not used */
protected ListDataListener listDataListener;
/**
* MouseListener listening to mouse events occuring in the combo box's
* list.
*/
protected MouseListener listMouseListener;
/**
* MouseMotionListener listening to mouse motion events occuring in the
* combo box's list
*/
protected MouseMotionListener listMouseMotionListener;
/** This listener is not used */
protected ListSelectionListener listSelectionListener;
/** MouseListener listening to mouse events occuring in the combo box */
protected MouseListener mouseListener;
/**
* MouseMotionListener listening to mouse motion events occuring in the
* combo box
*/
protected MouseMotionListener mouseMotionListener;
/**
* PropertyChangeListener listening to changes occuring in the bound
* properties of the combo box
*/
protected PropertyChangeListener propertyChangeListener;
/** direction for scrolling down list of combo box's items */
protected static final int SCROLL_DOWN = 1;
/** direction for scrolling up list of combo box's items */
protected static final int SCROLL_UP = 0;
/** Indicates auto scrolling direction */
protected int scrollDirection;
/** JScrollPane that contains list portion of the combo box */
protected JScrollPane scroller;
/** This field is not used */
protected boolean valueIsAdjusting;
/**
* Creates a new BasicComboPopup object.
*
* @param comboBox the combo box with which this popup should be associated
*/
public BasicComboPopup(JComboBox comboBox)
{
this.comboBox = comboBox;
mouseListener = createMouseListener();
mouseMotionListener = createMouseMotionListener();
keyListener = createKeyListener();
list = createList();
configureList();
scroller = createScroller();
configureScroller();
configurePopup();
installComboBoxListeners();
installKeyboardActions();
}
/**
* This method displays drow down list of combo box items on the screen.
*/
public void show()
{
Dimension size = comboBox.getSize();
size.height = getPopupHeightForRowCount(comboBox.getMaximumRowCount());
Insets i = getInsets();
size.width -= i.left + i.right;
Rectangle bounds = computePopupBounds(0, comboBox.getBounds().height,
size.width, size.height);
scroller.setMaximumSize(bounds.getSize());
scroller.setPreferredSize(bounds.getSize());
scroller.setMinimumSize(bounds.getSize());
list.invalidate();
syncListSelection();
list.ensureIndexIsVisible(list.getSelectedIndex());
setLightWeightPopupEnabled(comboBox.isLightWeightPopupEnabled());
show(comboBox, bounds.x, bounds.y);
}
/**
* This method hides drop down list of items
*/
public void hide()
{
MenuSelectionManager menuSelectionManager =
MenuSelectionManager.defaultManager();
javax.swing.MenuElement[] menuElements =
menuSelectionManager.getSelectedPath();
for (int i = 0; i < menuElements.length; i++)
{
if (menuElements[i] == this)
{
menuSelectionManager.clearSelectedPath();
break;
}
}
comboBox.repaint();
}
/**
* Return list cointaining JComboBox's items
*
* @return list cointaining JComboBox's items
*/
public JList getList()
{
return list;
}
/**
* Returns MouseListener that is listening to mouse events occuring in the
* combo box.
*
* @return MouseListener
*/
public MouseListener getMouseListener()
{
return mouseListener;
}
/**
* Returns MouseMotionListener that is listening to mouse motion events
* occuring in the combo box.
*
* @return MouseMotionListener
*/
public MouseMotionListener getMouseMotionListener()
{
return mouseMotionListener;
}
/**
* Returns KeyListener listening to key events occuring in the combo box.
* This method returns null because KeyHandler is not longer used.
*
* @return KeyListener
*/
public KeyListener getKeyListener()
{
return keyListener;
}
/**
* This method uninstalls the UI for the given JComponent.
*/
public void uninstallingUI()
{
uninstallComboBoxModelListeners(comboBox.getModel());
uninstallListeners();
uninstallKeyboardActions();
}
/**
* This method uninstalls listeners that were listening to changes occuring
* in the comb box's data model
*
* @param model data model for the combo box from which to uninstall
* listeners
*/
protected void uninstallComboBoxModelListeners(ComboBoxModel model)
{
model.removeListDataListener(listDataListener);
}
/**
* This method uninstalls keyboard actions installed by the UI.
*/
protected void uninstallKeyboardActions()
{
// Nothing to do here.
}
/**
* This method fires PopupMenuEvent indicating that combo box's popup list
* of items will become visible
*/
protected void firePopupMenuWillBecomeVisible()
{
PopupMenuListener[] ll = comboBox.getPopupMenuListeners();
for (int i = 0; i < ll.length; i++)
ll[i].popupMenuWillBecomeVisible(new PopupMenuEvent(comboBox));
}
/**
* This method fires PopupMenuEvent indicating that combo box's popup list
* of items will become invisible.
*/
protected void firePopupMenuWillBecomeInvisible()
{
PopupMenuListener[] ll = comboBox.getPopupMenuListeners();
for (int i = 0; i < ll.length; i++)
ll[i].popupMenuWillBecomeInvisible(new PopupMenuEvent(comboBox));
}
/**
* This method fires PopupMenuEvent indicating that combo box's popup list
* of items was closed without selection.
*/
protected void firePopupMenuCanceled()
{
PopupMenuListener[] ll = comboBox.getPopupMenuListeners();
for (int i = 0; i < ll.length; i++)
ll[i].popupMenuCanceled(new PopupMenuEvent(comboBox));
}
/**
* Creates MouseListener to listen to mouse events occuring in the combo
* box. Note that this listener doesn't listen to mouse events occuring in
* the popup portion of the combo box, it only listens to main combo box
* part.
*
* @return new MouseMotionListener that listens to mouse events occuring in
* the combo box
*/
protected MouseListener createMouseListener()
{
return new InvocationMouseHandler();
}
/**
* Create Mouse listener that listens to mouse dragging events occuring in
* the combo box. This listener is responsible for changing the selection
* in the combo box list to the component over which mouse is being
* currently dragged
*
* @return new MouseMotionListener that listens to mouse dragging events
* occuring in the combo box
*/
protected MouseMotionListener createMouseMotionListener()
{
return new InvocationMouseMotionHandler();
}
/**
* KeyListener created in this method is not used anymore.
*
* @return KeyListener that does nothing
*/
protected KeyListener createKeyListener()
{
return new InvocationKeyHandler();
}
/**
* ListSelectionListener created in this method is not used anymore
*
* @return ListSelectionListener that does nothing
*/
protected ListSelectionListener createListSelectionListener()
{
return new ListSelectionHandler();
}
/**
* Creates ListDataListener. This method returns null, because
* ListDataHandler class is obsolete and is no longer used.
*
* @return null
*/
protected ListDataListener createListDataListener()
{
return null;
}
/**
* This method creates ListMouseListener to listen to mouse events occuring
* in the combo box's item list.
*
* @return MouseListener to listen to mouse events occuring in the combo
* box's items list.
*/
protected MouseListener createListMouseListener()
{
return new ListMouseHandler();
}
/**
* Creates ListMouseMotionlistener to listen to mouse motion events occuring
* in the combo box's list. This listener is responsible for highlighting
* items in the list when mouse is moved over them.
*
* @return MouseMotionListener that handles mouse motion events occuring in
* the list of the combo box.
*/
protected MouseMotionListener createListMouseMotionListener()
{
return new ListMouseMotionHandler();
}
/**
* Creates PropertyChangeListener to handle changes in the JComboBox's bound
* properties.
*
* @return PropertyChangeListener to handle changes in the JComboBox's bound
* properties.
*/
protected PropertyChangeListener createPropertyChangeListener()
{
return new PropertyChangeHandler();
}
/**
* Creates new ItemListener that will listen to ItemEvents occuring in the
* combo box.
*
* @return ItemListener to listen to ItemEvents occuring in the combo box.
*/
protected ItemListener createItemListener()
{
return new ItemHandler();
}
/**
* Creates JList that will be used to display items in the combo box.
*
* @return JList that will be used to display items in the combo box.
*/
protected JList createList()
{
JList l = new JList(comboBox.getModel());
return l;
}
/**
* This method configures the list of comboBox's items by setting default
* properties and installing listeners.
*/
protected void configureList()
{
list.setFont(comboBox.getFont());
list.setForeground(comboBox.getForeground());
list.setBackground(comboBox.getBackground());
Color sfg = UIManager.getColor("ComboBox.selectionForeground");
list.setSelectionForeground(sfg);
Color sbg = UIManager.getColor("ComboBox.selectionBackground");
list.setSelectionBackground(sbg);
list.setBorder(null);
list.setCellRenderer(comboBox.getRenderer());
list.setFocusable(false);
syncListSelection();
list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
installListListeners();
}
/**
* This method installs list listeners.
*/
protected void installListListeners()
{
// mouse listener listening to mouse events occuring in the
// combo box's list of items.
listMouseListener = createListMouseListener();
list.addMouseListener(listMouseListener);
// mouse listener listening to mouse motion events occuring in the
// combo box's list of items
listMouseMotionListener = createListMouseMotionListener();
list.addMouseMotionListener(listMouseMotionListener);
listSelectionListener = createListSelectionListener();
list.addListSelectionListener(listSelectionListener);
}
/**
* This method creates scroll pane that will contain the list of comboBox's
* items inside of it.
*
* @return JScrollPane
*/
protected JScrollPane createScroller()
{
return new JScrollPane(list, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
}
/**
* This method configures scroll pane to contain list of comboBox's items
*/
protected void configureScroller()
{
scroller.setBorder(null);
scroller.setFocusable(false);
scroller.getVerticalScrollBar().setFocusable(false);
}
/**
* This method configures popup menu that will be used to display Scrollpane
* with list of items inside of it.
*/
protected void configurePopup()
{
setBorderPainted(true);
setBorder(BorderFactory.createLineBorder(Color.BLACK));
setOpaque(false);
add(scroller);
setFocusable(false);
}
/*
* This method installs listeners that will listen to changes occuring
* in the combo box.
*/
protected void installComboBoxListeners()
{
// item listener listenening to selection events in the combo box
itemListener = createItemListener();
comboBox.addItemListener(itemListener);
propertyChangeListener = createPropertyChangeListener();
comboBox.addPropertyChangeListener(propertyChangeListener);
installComboBoxModelListeners(comboBox.getModel());
}
/**
* This method installs listeners that will listen to changes occuring in
* the comb box's data model
*
* @param model data model for the combo box for which to install listeners
*/
protected void installComboBoxModelListeners(ComboBoxModel model)
{
// list data listener to listen for ListDataEvents in combo box.
// This listener is now obsolete and nothing is done here
listDataListener = createListDataListener();
comboBox.getModel().addListDataListener(listDataListener);
}
/**
* Installs the keyboard actions.
*/
protected void installKeyboardActions()
{
// Nothing to do here
}
/**
* This method always returns false to indicate that items in the combo box
* list are not focus traversable.
*
* @return false
*/
public boolean isFocusTraversable()
{
return false;
}
/**
* This method start scrolling combo box's list of items either up or down
* depending on the specified 'direction'
*
* @param direction of the scrolling.
*/
protected void startAutoScrolling(int direction)
{
// FIXME: add timer
isAutoScrolling = true;
if (direction == SCROLL_UP)
autoScrollUp();
else
autoScrollDown();
}
/**
* This method stops scrolling the combo box's list of items
*/
protected void stopAutoScrolling()
{
// FIXME: add timer
isAutoScrolling = false;
}
/**
* This method scrolls up list of combo box's items up and highlights that
* just became visible.
*/
protected void autoScrollUp()
{
// scroll up the scroll bar to make the item above visible
JScrollBar scrollbar = scroller.getVerticalScrollBar();
int scrollToNext = list.getScrollableUnitIncrement(super.getBounds(),
SwingConstants.VERTICAL,
SCROLL_UP);
scrollbar.setValue(scrollbar.getValue() - scrollToNext);
// If we haven't reached the begging of the combo box's list of items,
// then highlight next element above currently highlighted element
if (list.getSelectedIndex() != 0)
list.setSelectedIndex(list.getSelectedIndex() - 1);
}
/**
* This method scrolls down list of combo box's and highlights item in the
* list that just became visible.
*/
protected void autoScrollDown()
{
// scroll scrollbar down to make next item visible
JScrollBar scrollbar = scroller.getVerticalScrollBar();
int scrollToNext = list.getScrollableUnitIncrement(super.getBounds(),
SwingConstants.VERTICAL,
SCROLL_DOWN);
scrollbar.setValue(scrollbar.getValue() + scrollToNext);
// If we haven't reached the end of the combo box's list of items
// then highlight next element below currently highlighted element
if (list.getSelectedIndex() + 1 != comboBox.getItemCount())
list.setSelectedIndex(list.getSelectedIndex() + 1);
}
/**
* This method helps to delegate focus to the right component in the
* JComboBox. If the comboBox is editable then focus is sent to
* ComboBoxEditor, otherwise it is delegated to JComboBox.
*
* @param e MouseEvent
*/
protected void delegateFocus(MouseEvent e)
{
if (comboBox.isEditable())
comboBox.getEditor().getEditorComponent().requestFocus();
else
comboBox.requestFocus();
}
/**
* This method displays combo box popup if the popup is not currently shown
* on the screen and hides it if it is currently visible
*/
protected void togglePopup()
{
if (isVisible())
hide();
else
show();
}
/**
* DOCUMENT ME!
*
* @param e DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
protected MouseEvent convertMouseEvent(MouseEvent e)
{
Point point = SwingUtilities.convertPoint((Component) e.getSource(),
e.getPoint(), list);
MouseEvent newEvent = new MouseEvent((Component) e.getSource(),
e.getID(), e.getWhen(),
e.getModifiers(), point.x, point.y,
e.getModifiers(),
e.isPopupTrigger());
return newEvent;
}
/**
* Returns required height of the popup such that number of items visible in
* it are equal to the maximum row count. By default
* comboBox.maximumRowCount=8
*
* @param maxRowCount number of maximum visible rows in the combo box's
* popup list of items
*
* @return height of the popup required to fit number of items equal to
* JComboBox.maximumRowCount.
*/
protected int getPopupHeightForRowCount(int maxRowCount)
{
int totalHeight = 0;
ListCellRenderer rend = list.getCellRenderer();
if (comboBox.getItemCount() < maxRowCount)
maxRowCount = comboBox.getItemCount();
for (int i = 0; i < maxRowCount; i++)
{
Component comp = rend.getListCellRendererComponent(list,
comboBox.getModel()
.getElementAt(i),
-1, false, false);
Dimension dim = comp.getPreferredSize();
totalHeight += dim.height;
}
return totalHeight == 0 ? 100 : totalHeight;
}
/**
* DOCUMENT ME!
*
* @param px DOCUMENT ME!
* @param py DOCUMENT ME!
* @param pw DOCUMENT ME!
* @param ph DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
protected Rectangle computePopupBounds(int px, int py, int pw, int ph)
{
return new Rectangle(px, py, pw, ph);
}
/**
* This method changes the selection in the list to the item over which the
* mouse is currently located.
*
* @param anEvent MouseEvent
* @param shouldScroll DOCUMENT ME!
*/
protected void updateListBoxSelectionForEvent(MouseEvent anEvent,
boolean shouldScroll)
{
Point point = anEvent.getPoint();
if (list != null)
{
int index = list.locationToIndex(point);
if (index == -1)
{
if (point.y < 0)
index = 0;
else
index = comboBox.getModel().getSize() - 1;
}
if (list.getSelectedIndex() != index)
{
list.setSelectedIndex(index);
if (shouldScroll)
list.ensureIndexIsVisible(index);
}
}
}
/**
* InvocationMouseHandler is a listener that listens to mouse events
* occuring in the combo box. Note that this listener doesn't listen to
* mouse events occuring in the popup portion of the combo box, it only
* listens to main combo box part(area that displays selected item). This
* listener is responsible for showing and hiding popup portion of the
* combo box.
*/
protected class InvocationMouseHandler extends MouseAdapter
{
/**
* Creates a new InvocationMouseHandler object.
*/
protected InvocationMouseHandler()
{
// Nothing to do here.
}
/**
* This method is invoked whenever mouse is being pressed over the main
* part of the combo box. This method will show popup if the popup is
* not shown on the screen right now, and it will hide popup otherwise.
*
* @param e MouseEvent that should be handled
*/
public void mousePressed(MouseEvent e)
{
if (SwingUtilities.isLeftMouseButton(e) && comboBox.isEnabled())
{
delegateFocus(e);
togglePopup();
}
}
/**
* This method is invoked whenever mouse event was originated in the combo
* box and released either in the combBox list of items or in the combo
* box itself.
*
* @param e MouseEvent that should be handled
*/
public void mouseReleased(MouseEvent e)
{
Component component = (Component) e.getSource();
Dimension size = component.getSize();
Rectangle bounds = new Rectangle(0, 0, size.width - 1, size.height - 1);
// If mouse was released inside the bounds of combo box then do nothing,
// Otherwise if mouse was released inside the list of combo box items
// then change selection and close popup
if (! bounds.contains(e.getPoint()))
{
MouseEvent convEvent = convertMouseEvent(e);
Point point = convEvent.getPoint();
Rectangle visRect = new Rectangle();
list.computeVisibleRect(visRect);
if (visRect.contains(point))
{
updateListBoxSelectionForEvent(convEvent, false);
comboBox.setSelectedIndex(list.getSelectedIndex());
}
hide();
}
hasEntered = false;
stopAutoScrolling();
}
}
/**
* InvocationMouseMotionListener is a mouse listener that listens to mouse
* dragging events occuring in the combo box.
*/
protected class InvocationMouseMotionHandler extends MouseMotionAdapter
{
/**
* Creates a new InvocationMouseMotionHandler object.
*/
protected InvocationMouseMotionHandler()
{
// Nothing to do here.
}
/**
* This method is responsible for highlighting item in the drop down list
* over which the mouse is currently being dragged.
*/
public void mouseDragged(MouseEvent e)
{
if (isVisible())
{
MouseEvent convEvent = convertMouseEvent(e);
Rectangle visRect = new Rectangle();
list.computeVisibleRect(visRect);
if (convEvent.getPoint().y >= visRect.y
&& (convEvent.getPoint().y <= visRect.y + visRect.height - 1))
{
hasEntered = true;
if (isAutoScrolling)
stopAutoScrolling();
Point point = convEvent.getPoint();
if (visRect.contains(point))
{
valueIsAdjusting = true;
updateListBoxSelectionForEvent(convEvent, false);
valueIsAdjusting = false;
}
}
else if (hasEntered)
{
int dir = convEvent.getPoint().y < visRect.y ? SCROLL_UP
: SCROLL_DOWN;
if (isAutoScrolling && scrollDirection != dir)
{
stopAutoScrolling();
startAutoScrolling(dir);
}
else if (!isAutoScrolling)
startAutoScrolling(dir);
}
else if (e.getPoint().y < 0)
{
hasEntered = true;
startAutoScrolling(SCROLL_UP);
}
}
}
}
/**
* ItemHandler is an item listener that listens to selection events occuring
* in the combo box. FIXME: should specify here what it does when item is
* selected or deselected in the combo box list.
*/
protected class ItemHandler extends Object implements ItemListener
{
/**
* Creates a new ItemHandler object.
*/
protected ItemHandler()
{
// Nothing to do here.
}
/**
* This method responds to the selection events occuring in the combo box.
*
* @param e ItemEvent specifying the combo box's selection
*/
public void itemStateChanged(ItemEvent e)
{
if (e.getStateChange() == ItemEvent.SELECTED && ! valueIsAdjusting)
{
valueIsAdjusting = true;
syncListSelection();
valueIsAdjusting = false;
list.ensureIndexIsVisible(comboBox.getSelectedIndex());
}
}
}
/**
* ListMouseHandler is a listener that listens to mouse events occuring in
* the combo box's list of items. This class is responsible for hiding
* popup portion of the combo box if the mouse is released inside the combo
* box's list.
*/
protected class ListMouseHandler extends MouseAdapter
{
protected ListMouseHandler()
{
// Nothing to do here.
}
public void mousePressed(MouseEvent e)
{
// Nothing to do here.
}
public void mouseReleased(MouseEvent anEvent)
{
comboBox.setSelectedIndex(list.getSelectedIndex());
hide();
}
}
/**
* ListMouseMotionHandler listens to mouse motion events occuring in the
* combo box's list. This class is responsible for highlighting items in
* the list when mouse is moved over them
*/
protected class ListMouseMotionHandler extends MouseMotionAdapter
{
protected ListMouseMotionHandler()
{
// Nothing to do here.
}
public void mouseMoved(MouseEvent anEvent)
{
Point point = anEvent.getPoint();
Rectangle visRect = new Rectangle();
list.computeVisibleRect(visRect);
if (visRect.contains(point))
{
valueIsAdjusting = true;
updateListBoxSelectionForEvent(anEvent, false);
valueIsAdjusting = false;
}
}
}
/**
* This class listens to changes occuring in the bound properties of the
* combo box
*/
protected class PropertyChangeHandler extends Object
implements PropertyChangeListener
{
protected PropertyChangeHandler()
{
// Nothing to do here.
}
public void propertyChange(PropertyChangeEvent e)
{
if (e.getPropertyName().equals("renderer"))
{
list.setCellRenderer(comboBox.getRenderer());
if (isVisible())
hide();
}
if (e.getPropertyName().equals("model"))
{
ComboBoxModel oldModel = (ComboBoxModel) e.getOldValue();
uninstallComboBoxModelListeners(oldModel);
ComboBoxModel newModel = (ComboBoxModel) e.getNewValue();
list.setModel(newModel);
installComboBoxModelListeners(newModel);
if (comboBox.getItemCount() > 0)
comboBox.setSelectedIndex(0);
if (isVisible())
hide();
}
}
}
// ------ private helper methods --------------------
/**
* This method uninstalls listeners installed by the UI
*/
private void uninstallListeners()
{
uninstallComboBoxListeners();
uninstallComboBoxModelListeners(comboBox.getModel());
}
/**
* This method uninstalls Listeners registered with combo boxes list of
* items
*/
private void uninstallListListeners()
{
list.removeMouseListener(listMouseListener);
listMouseListener = null;
list.removeMouseMotionListener(listMouseMotionListener);
listMouseMotionListener = null;
}
/**
* This method uninstalls listeners listening to combo box associated with
* this popup menu
*/
private void uninstallComboBoxListeners()
{
comboBox.removeItemListener(itemListener);
itemListener = null;
comboBox.removePropertyChangeListener(propertyChangeListener);
propertyChangeListener = null;
}
void syncListSelection()
{
int index = comboBox.getSelectedIndex();
if (index == -1)
list.clearSelection();
else
list.setSelectedIndex(index);
}
// --------------------------------------------------------------------
// The following classes are here only for backwards API compatibility
// They aren't used.
// --------------------------------------------------------------------
/**
* This class is not used any more.
*/
public class ListDataHandler extends Object implements ListDataListener
{
public ListDataHandler()
{
// Nothing to do here.
}
public void contentsChanged(ListDataEvent e)
{
// Nothing to do here.
}
public void intervalAdded(ListDataEvent e)
{
// Nothing to do here.
}
public void intervalRemoved(ListDataEvent e)
{
// Nothing to do here.
}
}
/**
* This class is not used anymore
*/
protected class ListSelectionHandler extends Object
implements ListSelectionListener
{
protected ListSelectionHandler()
{
// Nothing to do here.
}
public void valueChanged(ListSelectionEvent e)
{
// Nothing to do here.
}
}
/**
* This class is not used anymore
*/
public class InvocationKeyHandler extends KeyAdapter
{
public InvocationKeyHandler()
{
// Nothing to do here.
}
public void keyReleased(KeyEvent e)
{
// Nothing to do here.
}
}
}