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

Action.SELECTED_KEY not toggled when using key binding

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P3 P3
    • 21
    • 6u10
    • client-libs
    • b16
    • x86
    • windows_xp

      FULL PRODUCT VERSION :
      java version "1.6.0_12"
      Java(TM) SE Runtime Environment (build 1.6.0_12-b04)
      Java HotSpot(TM) Client VM (build 11.2-b01, mixed mode, sharing)

      A DESCRIPTION OF THE PROBLEM :
      The Action.SELECTED_KEY property is toggled between false <-> true when not null, when the action is assigned to toggle buttons / menu items.
      When pressing the accelerator for the action, I would expect this to happen as well.
      Possible fix is to toggled the property in SwingUtilities.notifyAction().

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      -Run attached test case
      -Press CTRL-Z to try to toggle the selected state of the action

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Action.SELECTED_KEY property toggled between false <-> true when not null
      ACTUAL -
      Action.SELECTED_KEY property is not changed

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.awt.BorderLayout;
      import java.awt.Dimension;
      import java.awt.EventQueue;
      import java.awt.event.ActionEvent;
      import java.awt.event.KeyEvent;
      import java.beans.PropertyChangeEvent;
      import java.beans.PropertyChangeListener;

      import javax.swing.*;

      public class TestSelectedKey {
          public static void main(String[] args) {
              EventQueue.invokeLater(new Runnable() {
                  public void run() {
                      createGUI();
                  }
              });
          }

          private static void createGUI() {
              final JLabel label = new JLabel("Toggle me actions 0");
              final JLabel selected = new JLabel("Toggle me selected: false");
              AbstractAction action = new AbstractAction("Toggle me") {
                  private int count = 0;
                  @Override
                  public void actionPerformed(ActionEvent e) {
                      label.setText("Toggle me actions " + (++count));
                  }
              };
              action.addPropertyChangeListener(new PropertyChangeListener() {
                  public void propertyChange(PropertyChangeEvent evt) {
                      if(Action.SELECTED_KEY.equals(evt.getPropertyName())) {
                          selected.setText("Toggle me selected: " + evt.getNewValue());
                      }
                  }
              });
              action.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_Z, KeyEvent.CTRL_DOWN_MASK));
              // need to set manually or won't be updated by Swing
              action.putValue(Action.SELECTED_KEY, Boolean.FALSE);

              Box labels = new Box(BoxLayout.PAGE_AXIS);
              labels.add(label);
              labels.add(selected);

              JToolBar toolBar = new JToolBar();
              toolBar.add(new JToggleButton(action));

              JPopupMenu popupMenu = new JPopupMenu();
              popupMenu.add(new JCheckBoxMenuItem(action));
              labels.setComponentPopupMenu(popupMenu);

              JFrame frame = new JFrame("Test Action.SELECTED_KEY");
              frame.getContentPane().add(toolBar, BorderLayout.PAGE_START);
              frame.getContentPane().add(labels, BorderLayout.CENTER);

              InputMap inputMap = frame.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
              ActionMap actionMap = frame.getRootPane().getActionMap();
              inputMap.put((KeyStroke) action.getValue(Action.ACCELERATOR_KEY), "toggleAction");
              actionMap.put("toggleAction", action);

              // workaround
              inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.CTRL_DOWN_MASK), "toggleActionWorkAround");
              actionMap.put("toggleActionWorkAround", new ToggleAction(action));

              frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
              frame.setPreferredSize(new Dimension(400, 200));
              frame.pack();
              frame.setLocationRelativeTo(null);
              frame.setVisible(true);
          }

          private static class ToggleAction implements Action {
              private final Action delegate;

              public ToggleAction(Action delegate) {
                  this.delegate = delegate;
                  assert delegate != null && delegate.getValue(SELECTED_KEY) != null;
              }

              public void actionPerformed(ActionEvent e) {
                  boolean selected = (Boolean) delegate.getValue(SELECTED_KEY);
                  delegate.putValue(SELECTED_KEY, !selected);
                  delegate.actionPerformed(e);
              }

              public void addPropertyChangeListener(
                      PropertyChangeListener listener) {
                  delegate.addPropertyChangeListener(listener);
              }

              public void putValue(String key, Object newValue) {
                  delegate.putValue(key, newValue);
              }

              public Object getValue(String key) {
                  return delegate.getValue(key);
              }

              public boolean isEnabled() {
                  return delegate.isEnabled();
              }

              public void removePropertyChangeListener(PropertyChangeListener listener) {
                  delegate.removePropertyChangeListener(listener);
              }

              public void setEnabled(boolean b) {
                  delegate.setEnabled(b);
              }
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Pass a delegating Action which toggles SELECTED_KEY in the actionPerformed() to the ActionMap. See test case, pressing CTRL-X will toggle the property correctly.

            psadhukhan Prasanta Sadhukhan
            ndcosta Nelson Dcosta (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: