Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6342307

Accelerators trigger menuitems that are on disabled menus

    XMLWordPrintable

    Details

    • Subcomponent:
    • Resolved In Build:
      b74
    • CPU:
      generic, x86
    • OS:
      generic, windows_2000

      Description

      FULL PRODUCT VERSION :
      java version "1.5.0_05"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_05-b05)
      Java HotSpot(TM) Client VM (build 1.5.0_05-b05, mixed mode, sharing)

      ADDITIONAL OS VERSION INFORMATION :
      Windows 2000

      A DESCRIPTION OF THE PROBLEM :
      If a menuitem is on a menu that is itself disabled, the accelerator for the menuitem will still trigger the action.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Use source code below.

      Type 'a' in frame.

      Action corresponding to menuitem will trigger.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The action should not trigger, since the menu is disabled.

      Note that the action will also trigger if the menu is not visible.
      ACTUAL -
      Action triggered.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import javax.swing.*;
      import java.awt.event.ActionEvent;

      public class MenuTest {
          public static void test() {
              JFrame f = new JFrame();
              f.show();
              f.setSize(300, 300);

              JMenuBar mb = new JMenuBar();
              f.setJMenuBar(mb);

              JMenu m = new JMenu("m");
              mb.add(m);

              JMenu m1 = new JMenu("submenu");
              m.add(m1);

              JMenuItem m2 = new JMenuItem(new testAction());
              m1.setEnabled(false);
              m1.add(m2);

              f.validate();
          }

          public static void main(String[] args) {
              test();
          }

          private static class testAction extends AbstractAction {

              public testAction() {
                  super("Test&Menu");
                  putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke('a'));
              }

              public void actionPerformed(ActionEvent e) {
                  System.out.println("hi");
              }
          }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Extend MJMenuItem and override processKeyBinding.

      Walk up the tree from the menuitem. If something is encountered that is not visible or not enabled, do not process the keybinding.

          protected boolean processKeyBinding(KeyStroke ks, KeyEvent e,
      int condition, boolean pressed) {
              
              InputMap map = getInputMap(condition);
      ActionMap am = getActionMap();
              // Check first if this component has an action mapped to keyevent in order
              // to avoid recursive isInDisabledParent call unless absolutely needed.
              if(map != null && am != null && isEnabled()) {
                  Object binding = map.get(ks);
                  Action action = (binding == null) ? null : am.get(binding);
                  if (action != null) {
                      boolean disabled = isInDisabledParent(this);
                      if (disabled){
                          return false;
                      }
                      else{
                          return super.processKeyBinding(ks, e, condition, pressed);
                      }
                  }
              }
              return super.processKeyBinding(ks, e, condition, pressed);
          }
          
          private static boolean isInDisabledParent(JComponent comp){
              if (comp instanceof JPopupMenu){ // special case because getParent returns null
                  if (!(((JPopupMenu)comp).getInvoker() instanceof JMenuItem) &&
                      !(((JPopupMenu)comp).getInvoker() instanceof JPopupMenu)){
                      return false;
                  }
                  else
                      return isInDisabledParent((JComponent)((JPopupMenu)comp).getInvoker());
              }
              else if (comp == null){
                  return false;
              }
              else if (!comp.isVisible() || !comp.isEnabled()){
                  return true;
              }
              else{
                  if (!(comp.getParent() instanceof JMenuItem) &&
                      !(comp.getParent() instanceof JPopupMenu)){
                      return false;
                  }
                  else
                      return isInDisabledParent((JComponent)comp.getParent());
              }
          }

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              draskinsunw Daniel Raskin (Inactive)
              Reporter:
              gmanwanisunw Girish Manwani (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: