<Swing Dev> A proposal for a behavior change about mnemonic key

Sean Chou zhouyx at linux.vnet.ibm.com
Thu Apr 21 09:01:42 UTC 2011


Hi,

   I have a simple patch to demo the new behavior. With the patch, the focus
will go through the radiobuttons with mnemonic key Y when alt+y is pressed
instead of select the last.


The patch is as follows:

diff -r 554adcfb615e src/share/classes/javax/swing/KeyboardManager.java
--- a/src/share/classes/javax/swing/KeyboardManager.java	Wed Mar 16
15:01:07 2011 -0700
+++ b/src/share/classes/javax/swing/KeyboardManager.java	Thu Mar 17
14:57:14 2011 +0800
@@ -251,6 +251,93 @@
                  }
              } else if ( tmp instanceof Vector) { //more than one
comp registered for this
                  Vector v = (Vector)tmp;
+
+                 /* The below code is added to make sure the focus is
not always
+                    transferred to the last component in the vector
when
+                    more than one component have the same mnemonic
+                 */
+	              if ((e.getModifiers() & Event.ALT_MASK) == Event.ALT_MASK) {
+                      /* Mnemonic key should transfer the focus only,
do not select.
+                       * The following code works in this way:
+                       * 1. If only one component in the vector is
visible, fireBinding on it.
+                       * 2. If multi-components in the vector are
visible, move the focus to next component.
+                       *    2.1 If the next component is not a
JAbstractButton, fireBinding on it.
+                       *    2.2 If the next component is a JMenu,
which is a JAbstractButton, fireBinding
+                       *        on it to open the menu.
+                       *    2.3 If the next component is another
JAbstractButton like JRadioButton. Request
+                       *        focus on it instead of fireBinding.
To AVOID SELECTION & CLICK of the button.
+                       * 3. If the code is triggered by release
event, fireBinding on current focus component
+                       *    instead of move focus.
+                       * 4. Further consideration: there may be more
swing control like JMenu, or customized
+                       *    controls, which may break this behavior.
+                       */
+                      // This has alt as it's modifier so this could
be a mnemonic
+                      Component focusOwner =
KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
+                      {
+                      // If only one visible component, invoke it.
+                      int visibleComponentCounter = 0;
+                      int nextFocus = 0;
+                      for (int i =  0; i < v.size(); i++){
+                          JComponent c = (JComponent) v.elementAt(i);
+                          if (c.isShowing() && c.isEnabled()){
+                    	         visibleComponentCounter++ ;
+                    		      nextFocus = i;
+                    	     }
+                      }
+                      if (visibleComponentCounter == 1){
+                    	     JComponent tmpc = (JComponent)
v.elementAt(nextFocus);
+                    	     fireBinding(tmpc, ks, e, pressed);
+                          if (e.isConsumed())
+                        	  return true;
+                      }
+                      // If multi-components are visible, do not
select the button, just move the focus.
+                      for (int counter = v.size() - 1; counter >= 0;
counter--) {
+                          JComponent c = (JComponent) v.elementAt(counter);
+                          if (c.isShowing() && c.isEnabled()) {
+                              if ((c == focusOwner)
+                                       || (c instanceof JLabel &&
((JLabel) c).getLabelFor() == focusOwner)) {
+                                  if (e.getID() == KeyEvent.KEY_RELEASED){
+                                	     nextFocus = counter;
+                                	     break;
+                                  }
+                            	    nextFocus = (counter - 1 + v.size())
% v.size();
+                                  break;
+                              }
+                          }
+                      }
+                      for (; nextFocus >= 0; nextFocus--) {
+                          JComponent c = (JComponent) v.elementAt(nextFocus);
+                          if (c.isShowing() && c.isEnabled()) {
+                              break;
+                          }
+                      }
+                      if (nextFocus >= 0) {
+                          JComponent tmpc = (JComponent)
v.elementAt(nextFocus);
+                          // Next is the hack for this accessibility:
+                          // For general Buttons, do not press them,
but request focus only.
+                          // For special buttons like JMenu, needs press.
+                          // If it is not a button, let the component
handles by itself.
+                          if (!(tmpc instanceof javax.swing.AbstractButton)){
+                        	   fireBinding(tmpc, ks, e, pressed);
+                              if (e.isConsumed())
+                            	    return true;
+                          }
+                          if (tmpc instanceof JMenu ) {
+                              fireBinding(tmpc, ks, e, pressed);
+                              tmpc.requestFocusInWindow();
+                              if (e.isConsumed())
+                                  return true;
+                          } else {
+                              boolean result = tmpc.requestFocusInWindow();
+                              e.consume();
+                              return result;
+                          }
+                      }
+                      // If it is not handled here, default behavior
is selecting the last.
+                      }
+                 }
+
+
                  // There is no well defined order for WHEN_IN_FOCUSED_WINDOW
                  // bindings, but we give precedence to those bindings just
                  // added. This is done so that JMenus WHEN_IN_FOCUSED_WINDOW




2011/4/1 Sean Chou <zhouyx at linux.vnet.ibm.com>

> Hi all,
>
>    In daily use, we may encounter a problem of mnemonic key: there may be
> several
> controls want the same key to be set as mnemonic key. It is not common but
> it does exist.
>
>    Current openjdk implementation allows users to set a same mnemonic key
> for
> different controls; but during the execution, when the mnemonic key is
> pressed,
> the last control always gets the action. Users are not able to touch other
> controls with
> that mnemonic key. This may confuse them.
>
>    If all the controls with the same mnemonic key can be accessed through,
> for
> example, when the mnemonic key is pressed, the focus is moved to the last
> control,
> and when the mnemonic key is pressed again, the focus is moved to the
> second control
> with that mnemonic, it will give user the choice to select other controls.
>
>    Here is an example for the case:
>
> package test;
>
> import java.awt.BorderLayout;
> import java.awt.Container;
> import javax.swing.ButtonGroup;
> import javax.swing.JFrame;
> import javax.swing.JRadioButton;
>
> public class TestFocus extends JFrame {
> public TestFocus() {
>  Container pane = getContentPane();
> pane.setLayout(new BorderLayout());
> JRadioButton btn1,btn2,btn3;
>  btn1 = new JRadioButton("Yes");
> btn1.setMnemonic('Y');
>  btn2 = new JRadioButton("Yup");
> btn2.setMnemonic('Y');
> btn3 = new JRadioButton("No");
>  btn3.setMnemonic('N');
> btn3.setSelected(true);
> ButtonGroup group = new ButtonGroup();
>  group.add(btn1);
> group.add(btn2);
> group.add(btn3);
>  pane.add(btn1,BorderLayout.NORTH);
> pane.add(btn2,BorderLayout.CENTER);
> pane.add(btn3,BorderLayout.SOUTH);
>  setSize(200,200);
> setVisible(true);
> setDefaultCloseOperation(EXIT_ON_CLOSE);
>  }
>  public static void main(String[] args) {
>  new TestFocus();
> }
> }
>
>
>
>
> --
> Best Regards,
> Sean Chou
>
>


-- 
Best Regards,
Sean Chou
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/swing-dev/attachments/20110421/d1ea2aa0/attachment.html>


More information about the swing-dev mailing list