-
Bug
-
Resolution: Fixed
-
P3
-
6u10
-
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.
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.