Hi,
Is there anybody interested in this feature? Or
any other comments?
2011/4/21 Sean Chou <[email protected]
<mailto:[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]
<mailto:[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