Hi,
This patch implements the KeySelectionManager for JComboBox, as well as
fixing up the navigation keys and highlighting the combobox when it's in
focus.
Corresponding mauve test for the key actions has been committed. I
would appreciate any comments, or approval to commit.
Cheers,
Francis
2006-07-18 Francis Kung <[EMAIL PROTECTED]>
* javax/swing/JComboBox.java
(DefaultKeySelectionManager): Implemented.
(createDefaultKeySelectionManager): Implemented.
(getKeySelectionManager): Implemented.
(processKeyEvent): Removed duplicate code.
* javax/swing/JPopupMenu.java
(selectionModel): Changed visibility.
* javax/swing/plaf/basic/BasicComboBoxUI.java
(KeyHandler.keyPressed): Added navigation keys.
(configureEditor): Add key listener.
(installListeners): Install focus listener to combo box.
(isNavigationKey): Added enter, escape, and tab.
(selectPreviousPossibleValue): Added out of bounds check.
(unconfigureEditor): Remove key listener.
* javax/swing/plaf/metal/MetalComboBoxButton.java
(paintComponent): Highlight combo box when in focus.
Index: javax/swing/JComboBox.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/JComboBox.java,v
retrieving revision 1.32
diff -u -r1.32 JComboBox.java
--- javax/swing/JComboBox.java 1 Jun 2006 04:38:49 -0000 1.32
+++ javax/swing/JComboBox.java 18 Jul 2006 19:15:15 -0000
@@ -1028,7 +1028,8 @@
}
/**
- * This method hides combo box's popup whenever TAB key is pressed.
+ * This method is fired whenever a key is pressed with the combo box
+ * in focus
*
* @param e The KeyEvent indicating which key was pressed.
*/
@@ -1036,15 +1037,6 @@
{
if (e.getKeyCode() == KeyEvent.VK_TAB)
setPopupVisible(false);
- else if (keySelectionManager != null)
- {
- int i = keySelectionManager.selectionForKey(e.getKeyChar(),
- getModel());
- if (i >= 0)
- setSelectedIndex(i);
- else
- super.processKeyEvent(e);
- }
else
super.processKeyEvent(e);
}
@@ -1066,7 +1058,7 @@
*/
public KeySelectionManager getKeySelectionManager()
{
- return null;
+ return keySelectionManager;
}
/**
@@ -1098,7 +1090,7 @@
*/
protected KeySelectionManager createDefaultKeySelectionManager()
{
- return null;
+ return new DefaultKeySelectionManager();
}
/**
@@ -1471,4 +1463,34 @@
// Nothing to do here.
}
}
+
+ private class DefaultKeySelectionManager
+ implements KeySelectionManager
+ {
+
+ public int selectionForKey(char aKey, ComboBoxModel aModel)
+ {
+ int selectedIndex = getSelectedIndex();
+
+ // Start at currently selected item and iterate to end of list
+ for (int i = selectedIndex + 1; i < aModel.getSize(); i++)
+ {
+ String nextItem = aModel.getElementAt(i).toString();
+
+ if (nextItem.charAt(0) == aKey)
+ return i;
+ }
+
+ // Wrap to start of list if no match yet
+ for (int i = 0; i <= selectedIndex; i++)
+ {
+ String nextItem = aModel.getElementAt(i).toString();
+
+ if (nextItem.charAt(0) == aKey)
+ return i;
+ }
+
+ return - 1;
+ }
+ }
}
Index: javax/swing/JPopupMenu.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/JPopupMenu.java,v
retrieving revision 1.36
diff -u -r1.36 JPopupMenu.java
--- javax/swing/JPopupMenu.java 16 May 2006 17:43:50 -0000 1.36
+++ javax/swing/JPopupMenu.java 18 Jul 2006 19:15:15 -0000
@@ -120,7 +120,7 @@
private boolean lightWeightPopupEnabled;
/** SelectionModel that keeps track of menu selection. */
- private SingleSelectionModel selectionModel;
+ protected SingleSelectionModel selectionModel;
/* Popup that is used to display JPopupMenu */
private transient Popup popup;
Index: javax/swing/plaf/basic/BasicComboBoxUI.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java,v
retrieving revision 1.39
diff -u -r1.39 BasicComboBoxUI.java
--- javax/swing/plaf/basic/BasicComboBoxUI.java 15 Jun 2006 14:15:45 -0000 1.39
+++ javax/swing/plaf/basic/BasicComboBoxUI.java 18 Jul 2006 19:15:15 -0000
@@ -289,7 +289,7 @@
comboBox.addPropertyChangeListener(propertyChangeListener);
focusListener = createFocusListener();
- editor.addFocusListener(focusListener);
+ comboBox.addFocusListener(focusListener);
itemListener = createItemListener();
comboBox.addItemListener(itemListener);
@@ -543,7 +543,9 @@
{
editor.setFont(comboBox.getFont());
if (popupKeyListener != null)
- editor.addKeyListener(popupKeyListener);
+ editor.addKeyListener(popupKeyListener);
+ if (keyListener != null)
+ editor.addKeyListener(keyListener);
comboBox.configureEditor(comboBox.getEditor(),
comboBox.getSelectedItem());
}
@@ -555,6 +557,8 @@
{
if (popupKeyListener != null)
editor.removeKeyListener(popupKeyListener);
+ if (keyListener != null)
+ editor.removeKeyListener(keyListener);
}
/**
@@ -775,7 +779,9 @@
protected boolean isNavigationKey(int keyCode)
{
return keyCode == KeyEvent.VK_UP || keyCode == KeyEvent.VK_DOWN
- || keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_RIGHT;
+ || keyCode == KeyEvent.VK_LEFT || keyCode == KeyEvent.VK_RIGHT
+ || keyCode == KeyEvent.VK_ENTER || keyCode == KeyEvent.VK_ESCAPE
+ || keyCode == KeyEvent.VK_TAB;
}
/**
@@ -796,7 +802,7 @@
protected void selectPreviousPossibleValue()
{
int index = comboBox.getSelectedIndex();
- if (index != 0)
+ if (index > 0)
comboBox.setSelectedIndex(index - 1);
}
@@ -1201,11 +1207,29 @@
*/
public void keyPressed(KeyEvent e)
{
- if (! isNavigationKey(e.getKeyCode()) && comboBox.isEnabled()
- && comboBox.getModel().getSize() != 0)
+ if (comboBox.getModel().getSize() != 0 && comboBox.isEnabled())
{
- if (comboBox.selectWithKeyChar(e.getKeyChar()))
- e.consume();
+ if (! isNavigationKey(e.getKeyCode()))
+ {
+ if (! comboBox.isEditable())
+ if (comboBox.selectWithKeyChar(e.getKeyChar()))
+ e.consume();
+ }
+ else
+ {
+ if (e.getKeyCode() == KeyEvent.VK_UP && comboBox.isPopupVisible())
+ selectPreviousPossibleValue();
+ else if (e.getKeyCode() == KeyEvent.VK_DOWN)
+ {
+ if (comboBox.isPopupVisible())
+ selectNextPossibleValue();
+ else
+ comboBox.showPopup();
+ }
+ else if (e.getKeyCode() == KeyEvent.VK_ENTER
+ || e.getKeyCode() == KeyEvent.VK_ESCAPE)
+ popup.hide();
+ }
}
}
}
@@ -1370,5 +1394,4 @@
// FIXME: Need to handle changes in other bound properties.
}
}
-
}
Index: javax/swing/plaf/metal/MetalComboBoxButton.java
===================================================================
RCS file: /cvsroot/classpath/classpath/javax/swing/plaf/metal/MetalComboBoxButton.java,v
retrieving revision 1.11
diff -u -r1.11 MetalComboBoxButton.java
--- javax/swing/plaf/metal/MetalComboBoxButton.java 11 May 2006 17:05:55 -0000 1.11
+++ javax/swing/plaf/metal/MetalComboBoxButton.java 18 Jul 2006 19:15:15 -0000
@@ -259,7 +259,9 @@
Component comp = renderer.getListCellRendererComponent(listBox,
comboBox.getSelectedItem(), -1, false, false);
comp.setFont(rendererPane.getFont());
- if (model.isArmed() && model.isPressed())
+
+ if ((model.isArmed() && model.isPressed())
+ || (comboBox.isFocusOwner() && !comboBox.isPopupVisible()))
{
if (isOpaque())
{