JDK-4104452 : Proper keyboard navigation must be verified on JRadioButton for Windows LAF
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.1.6,1.2.0,1.3.0,5.0
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS:
    generic,solaris_2.4,solaris_2.6,windows_nt,windows_xp generic,solaris_2.4,solaris_2.6,windows_nt,windows_xp
  • CPU: generic,unknown,x86,sparc
  • Submitted: 1998-01-16
  • Updated: 2005-07-20
  • Resolved: 2005-07-19
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Description
The following navigation, activation and selection keyboard bindings on JRadioButton need verification for proper operation and key binding sequences. 

JRadioButton 
	Navigate in -	Tab
	Navigate out -	Tab, Shift+Tab (reverses direction) 
	Navigate within -	Arrow keys 
	Toggle on/off-	Spacebar 

        Note: Navigating to a radio button selects it, and deselects
              others in the group. Spacebar is a no-op with this
              implementation. It is implemented this way in Cafe's
              Visual Page editor and Pronto email. (eric)

        

Comments
SUGGESTED FIX ========
28-09-2004

SUGGESTED FIX Name: keR10081 Date: 09/03/2001 ------- WindowsLookAndFeel.java ------- *** /tmp/sccs.sQaqBb Mon Sep 3 12:04:40 2001 --- WindowsLookAndFeel.java Mon Sep 3 11:54:27 2001 *************** *** 491,496 **** --- 491,506 ---- "Button.showMnemonics", showMnemonics, "Button.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "TAB", "tabOut", + "shift TAB", "tabBackOut", + "UP", "focusPreviousInButtonGroup", + "LEFT", "focusPreviousInButtonGroup", + "KP_UP", "focusPreviousInButtonGroup", + "KP_LEFT", "focusPreviousInButtonGroup", + "DOWN", "focusNextInButtonGroup", + "RIGHT", "focusNextInButtonGroup", + "KP_DOWN", "focusNextInButtonGroup", + "KP_RIGHT", "focusNextInButtonGroup", "SPACE", "pressed", "released SPACE", "released" }), *************** *** 506,511 **** --- 516,531 ---- "CheckBox.focus", black, "CheckBox.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "TAB", "tabOut", + "shift TAB", "tabBackOut", + "UP", "focusPreviousInButtonGroup", + "LEFT", "focusPreviousInButtonGroup", + "KP_UP", "focusPreviousInButtonGroup", + "KP_LEFT", "focusPreviousInButtonGroup", + "DOWN", "focusNextInButtonGroup", + "RIGHT", "focusNextInButtonGroup", + "KP_DOWN", "focusNextInButtonGroup", + "KP_RIGHT", "focusNextInButtonGroup", "SPACE", "pressed", "released SPACE", "released" }), *************** *** 780,785 **** --- 800,815 ---- "RadioButton.focus", black, "RadioButton.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "TAB", "tabOut", + "shift TAB", "tabBackOut", + "UP", "focusPreviousInButtonGroup", + "LEFT", "focusPreviousInButtonGroup", + "KP_UP", "focusPreviousInButtonGroup", + "KP_LEFT", "focusPreviousInButtonGroup", + "DOWN", "focusNextInButtonGroup", + "RIGHT", "focusNextInButtonGroup", + "KP_DOWN", "focusNextInButtonGroup", + "KP_RIGHT", "focusNextInButtonGroup", "SPACE", "pressed", "released SPACE", "released" }), *************** *** 1140,1145 **** --- 1170,1185 ---- "ToggleButton.textShiftOffset", new Integer(1), "ToggleButton.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "TAB", "tabOut", + "shift TAB", "tabBackOut", + "UP", "focusPreviousInButtonGroup", + "LEFT", "focusPreviousInButtonGroup", + "KP_UP", "focusPreviousInButtonGroup", + "KP_LEFT", "focusPreviousInButtonGroup", + "DOWN", "focusNextInButtonGroup", + "RIGHT", "focusNextInButtonGroup", + "KP_DOWN", "focusNextInButtonGroup", + "KP_RIGHT", "focusNextInButtonGroup", "SPACE", "pressed", "released SPACE", "released" }), ------- BasicLookAndFeel.java ------- *** /tmp/sccs._1aOqj Mon Sep 3 12:13:08 2001 --- BasicLookAndFeel.java Mon Sep 3 11:47:29 2001 *************** *** 530,535 **** --- 530,545 ---- "Button.textIconGap", four, "Button.textShiftOffset", zero, "Button.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "TAB", "tabOut", + "shift TAB", "tabBackOut", + "UP", "focusPreviousInButtonGroup", + "LEFT", "focusPreviousInButtonGroup", + "KP_UP", "focusPreviousInButtonGroup", + "KP_LEFT", "focusPreviousInButtonGroup", + "DOWN", "focusNextInButtonGroup", + "RIGHT", "focusNextInButtonGroup", + "KP_DOWN", "focusNextInButtonGroup", + "KP_RIGHT", "focusNextInButtonGroup", "SPACE", "pressed", "released SPACE", "released", "ENTER", "pressed", *************** *** 549,554 **** --- 559,574 ---- "ToggleButton.textShiftOffset", zero, "ToggleButton.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "TAB", "tabOut", + "shift TAB", "tabBackOut", + "UP", "focusPreviousInButtonGroup", + "LEFT", "focusPreviousInButtonGroup", + "KP_UP", "focusPreviousInButtonGroup", + "KP_LEFT", "focusPreviousInButtonGroup", + "DOWN", "focusNextInButtonGroup", + "RIGHT", "focusNextInButtonGroup", + "KP_DOWN", "focusNextInButtonGroup", + "KP_RIGHT", "focusNextInButtonGroup", "SPACE", "pressed", "released SPACE", "released" }), *************** *** 567,572 **** --- 587,602 ---- "RadioButton.icon", radioButtonIcon, "RadioButton.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "TAB", "tabOut", + "shift TAB", "tabBackOut", + "UP", "focusPreviousInButtonGroup", + "LEFT", "focusPreviousInButtonGroup", + "KP_UP", "focusPreviousInButtonGroup", + "KP_LEFT", "focusPreviousInButtonGroup", + "DOWN", "focusNextInButtonGroup", + "RIGHT", "focusNextInButtonGroup", + "KP_DOWN", "focusNextInButtonGroup", + "KP_RIGHT", "focusNextInButtonGroup", "SPACE", "pressed", "released SPACE", "released", "RETURN", "pressed" *************** *** 582,587 **** --- 612,627 ---- "CheckBox.icon", checkBoxIcon, "CheckBox.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "TAB", "tabOut", + "shift TAB", "tabBackOut", + "UP", "focusPreviousInButtonGroup", + "LEFT", "focusPreviousInButtonGroup", + "KP_UP", "focusPreviousInButtonGroup", + "KP_LEFT", "focusPreviousInButtonGroup", + "DOWN", "focusNextInButtonGroup", + "RIGHT", "focusNextInButtonGroup", + "KP_DOWN", "focusNextInButtonGroup", + "KP_RIGHT", "focusNextInButtonGroup", "SPACE", "pressed", "released SPACE", "released" }), ------- BasicButtonUI.java ------- *** /tmp/sccs.f6a4yj Mon Sep 3 12:13:50 2001 --- BasicButtonUI.java Mon Sep 3 11:25:17 2001 *************** *** 17,22 **** --- 17,23 ---- import javax.swing.border.*; import java.awt.*; import java.awt.event.*; + import java.util.*; import javax.swing.plaf.ButtonUI; import javax.swing.plaf.UIResource; import javax.swing.plaf.ComponentUI; *************** *** 87,93 **** defaults_initialized = true; } ! // set the following defaults on the button if (b.isContentAreaFilled()) { b.setOpaque(true); } else { --- 88,97 ---- defaults_initialized = true; } ! Set tempSet = new TreeSet(); ! b.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,tempSet); ! b.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,tempSet); ! // set the following defaults on the button if (b.isContentAreaFilled()) { b.setOpaque(true); } else { ------- BasicButtonListener.java ------- *** /tmp/sccs.e6aqKj Mon Sep 3 12:15:03 2001 --- BasicButtonListener.java Thu Aug 30 14:43:42 2001 *************** *** 123,128 **** --- 123,132 ---- retValue.put("pressed", new PressedAction((AbstractButton)c)); retValue.put("released", new ReleasedAction((AbstractButton)c)); + retValue.put("focusNextInButtonGroup",new FocusNextInButtonGroupAction()); + retValue.put("focusPreviousInButtonGroup",new FocusPreviousInButtonGroupAction()); + retValue.put("tabOut",new TabOutAction()); + retValue.put("tabBackOut",new TabBackOutAction()); return retValue; } *************** *** 326,330 **** --- 330,387 ---- } } + static class FocusNextInButtonGroupAction extends AbstractAction { + public void actionPerformed(ActionEvent e){ + AbstractButton b = (AbstractButton)e.getSource(); + Container rootAncestor = b.getFocusCycleRootAncestor(); + FocusTraversalPolicy policy = rootAncestor.getFocusTraversalPolicy(); + Component toFocus = policy.getComponentAfter(rootAncestor,b); + if (((DefaultButtonModel)b.getModel()).getGroup() != null) + if ((toFocus instanceof AbstractButton) && (((DefaultButtonModel)b.getModel()).getGroup() == ((DefaultButtonModel)((AbstractButton)toFocus).getModel()).getGroup())) toFocus.requestFocus(); + else{ + toFocus = SwingUtilities.findFocusOwner(b); + while ((policy.getComponentBefore(rootAncestor,toFocus) instanceof AbstractButton) && (((DefaultButtonModel)b.getModel()).getGroup() == ((DefaultButtonModel)((AbstractButton)policy.getComponentBefore(rootAncestor,toFocus)).getModel()).getGroup())) toFocus = policy.getComponentBefore(rootAncestor,toFocus); + toFocus.requestFocus(); + } + } + } + + static class FocusPreviousInButtonGroupAction extends AbstractAction { + public void actionPerformed(ActionEvent e){ + AbstractButton b = (AbstractButton)e.getSource(); + Container rootAncestor = b.getFocusCycleRootAncestor(); + FocusTraversalPolicy policy = rootAncestor.getFocusTraversalPolicy(); + Component toFocus = policy.getComponentBefore(rootAncestor,b); + if (((DefaultButtonModel)b.getModel()).getGroup() != null) + if ((toFocus instanceof AbstractButton) && (((DefaultButtonModel)b.getModel()).getGroup() == ((DefaultButtonModel)((AbstractButton)toFocus).getModel()).getGroup())) toFocus.requestFocus(); + else{ + toFocus = SwingUtilities.findFocusOwner(b); + while ((policy.getComponentAfter(rootAncestor,toFocus) instanceof AbstractButton) && (((DefaultButtonModel)b.getModel()).getGroup() == ((DefaultButtonModel)((AbstractButton)policy.getComponentAfter(rootAncestor,toFocus)).getModel()).getGroup())) toFocus = policy.getComponentAfter(rootAncestor,toFocus); + toFocus.requestFocus(); + } + } + } + + static class TabOutAction extends AbstractAction { + public void actionPerformed(ActionEvent e){ + AbstractButton b = (AbstractButton)e.getSource(); + Container rootAncestor = b.getFocusCycleRootAncestor(); + FocusTraversalPolicy policy = rootAncestor.getFocusTraversalPolicy(); + Component toFocus = policy.getComponentAfter(rootAncestor,b); + while ((toFocus instanceof AbstractButton) && (((DefaultButtonModel)b.getModel()).getGroup() != null) && (((DefaultButtonModel)b.getModel()).getGroup() == ((DefaultButtonModel)((AbstractButton)toFocus).getModel()).getGroup())) toFocus = policy.getComponentAfter(rootAncestor,toFocus); + toFocus.requestFocus(); + } + } + + static class TabBackOutAction extends AbstractAction { + public void actionPerformed(ActionEvent e){ + AbstractButton b = (AbstractButton)e.getSource(); + Container rootAncestor = b.getFocusCycleRootAncestor(); + FocusTraversalPolicy policy = rootAncestor.getFocusTraversalPolicy(); + Component toFocus = policy.getComponentBefore(rootAncestor,b); + while ((toFocus instanceof AbstractButton) && (((DefaultButtonModel)b.getModel()).getGroup() != null) && (((DefaultButtonModel)b.getModel()).getGroup() == ((DefaultButtonModel)((AbstractButton)toFocus).getModel()).getGroup())) toFocus = policy.getComponentBefore(rootAncestor,toFocus); + toFocus.requestFocus(); + } + } } ------- MetalLookAndFeel.java ------- *** /tmp/sccs.WRa4Kj Mon Sep 3 12:17:22 2001 --- MetalLookAndFeel.java Mon Sep 3 11:52:52 2001 *************** *** 482,487 **** --- 482,497 ---- "getControlTextFont"), "Button.focus", getFocusColor(), "Button.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "TAB", "tabOut", + "shift TAB", "tabBackOut", + "UP", "focusPreviousInButtonGroup", + "LEFT", "focusPreviousInButtonGroup", + "KP_UP", "focusPreviousInButtonGroup", + "KP_LEFT", "focusPreviousInButtonGroup", + "DOWN", "focusNextInButtonGroup", + "RIGHT", "focusNextInButtonGroup", + "KP_DOWN", "focusNextInButtonGroup", + "KP_RIGHT", "focusNextInButtonGroup", "SPACE", "pressed", "released SPACE", "released" }), *************** *** 497,502 **** --- 507,522 ---- "CheckBox.icon", new UIDefaults.ProxyLazyValue("javax.swing.plaf.metal.MetalIconFactory", "getCheckBoxIcon"), "CheckBox.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "TAB", "tabOut", + "shift TAB", "tabBackOut", + "UP", "focusPreviousInButtonGroup", + "LEFT", "focusPreviousInButtonGroup", + "KP_UP", "focusPreviousInButtonGroup", + "KP_LEFT", "focusPreviousInButtonGroup", + "DOWN", "focusNextInButtonGroup", + "RIGHT", "focusNextInButtonGroup", + "KP_DOWN", "focusNextInButtonGroup", + "KP_RIGHT", "focusNextInButtonGroup", "SPACE", "pressed", "released SPACE", "released" }), *************** *** 512,517 **** --- 532,547 ---- "RadioButton.focus", getFocusColor(), "RadioButton.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "TAB", "tabOut", + "shift TAB", "tabBackOut", + "UP", "focusPreviousInButtonGroup", + "LEFT", "focusPreviousInButtonGroup", + "KP_UP", "focusPreviousInButtonGroup", + "KP_LEFT", "focusPreviousInButtonGroup", + "DOWN", "focusNextInButtonGroup", + "RIGHT", "focusNextInButtonGroup", + "KP_DOWN", "focusNextInButtonGroup", + "KP_RIGHT", "focusNextInButtonGroup", "SPACE", "pressed", "released SPACE", "released" }), *************** *** 531,536 **** --- 561,576 ---- "getControlTextFont"), "ToggleButton.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "TAB", "tabOut", + "shift TAB", "tabBackOut", + "UP", "focusPreviousInButtonGroup", + "LEFT", "focusPreviousInButtonGroup", + "KP_UP", "focusPreviousInButtonGroup", + "KP_LEFT", "focusPreviousInButtonGroup", + "DOWN", "focusNextInButtonGroup", + "RIGHT", "focusNextInButtonGroup", + "KP_DOWN", "focusNextInButtonGroup", + "KP_RIGHT", "focusNextInButtonGroup", "SPACE", "pressed", "released SPACE", "released" }), ==============================================================
28-09-2004

EVALUATION Navigate in - Tab: Works on Windows L&F on Windows NT & Windows 95. Navigate out - Tab, Shift+Tab: Works on Windows L&F on Windows NT & Windows 95. Navigate within - Arrow keys: DOES NOT WORK on Windows L&F on Windows NT & Windows 95. Toggle on/off - Spacebar: Works on Windows L&F on Windows NT & Windows 95. SUMMARY: We need to add arrow key functionality. nancy.schorr@eng 1998-03-18 Name: keR10081 Date: 09/03/2001 See suggested fix for necessary diffs. Since there was no alike bug on Motif LAF, there's no diffs for MotifLookAndFeel.java, but it would be obvious in case of necessity. ###@###.### ====================================================================== Name: ibR10256 Date: 10/10/2003 According to the LF specifications, the arrow keys functionality should be added to Windows and Motif, and not to Metal. But I think it can be added to Metal as well. ###@###.### 2003-10-10 ====================================================================== ###@###.###, I've just closed another bug as a duplicate of this one. It requests the same thing for the GTK L&F. I beleive I have a pending review from you on this one. I'll attempt to get to it ASAP. I'm guessing we'll need to do some minor adjustments to work out the subtle differences between the platforms. ###@###.### 2004-03-09
09-03-2004