Hi,

   Is there anybody interested in this feature? Or any other comments?

2011/4/21 Sean Chou <[email protected]>

> 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 <[email protected]>
>
>> 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
>
>


-- 
Best Regards,
Sean Chou

Reply via email to