[7937] | 1 | // License: GPL. For details, see LICENSE file.
|
---|
| 2 | package org.openstreetmap.josm.actions;
|
---|
| 3 |
|
---|
| 4 | import java.awt.event.ActionEvent;
|
---|
[8390] | 5 | import java.util.HashSet;
|
---|
| 6 | import java.util.Set;
|
---|
[7937] | 7 |
|
---|
| 8 | import javax.swing.ButtonModel;
|
---|
| 9 | import javax.swing.JCheckBox;
|
---|
| 10 | import javax.swing.JCheckBoxMenuItem;
|
---|
| 11 | import javax.swing.JRadioButton;
|
---|
| 12 | import javax.swing.JRadioButtonMenuItem;
|
---|
| 13 | import javax.swing.JToggleButton;
|
---|
| 14 |
|
---|
| 15 | import org.openstreetmap.josm.tools.ImageProvider;
|
---|
[12620] | 16 | import org.openstreetmap.josm.tools.Logging;
|
---|
[7937] | 17 | import org.openstreetmap.josm.tools.Shortcut;
|
---|
| 18 |
|
---|
| 19 | /**
|
---|
| 20 | * Abtract class for Toggle Actions.
|
---|
| 21 | * @since 6220
|
---|
| 22 | */
|
---|
| 23 | public abstract class ToggleAction extends JosmAction {
|
---|
| 24 |
|
---|
[8390] | 25 | private final transient Set<ButtonModel> buttonModels = new HashSet<>();
|
---|
[7937] | 26 |
|
---|
| 27 | /**
|
---|
| 28 | * Constructs a {@code ToggleAction}.
|
---|
| 29 | *
|
---|
| 30 | * @param name the action's text as displayed on the menu (if it is added to a menu)
|
---|
| 31 | * @param icon the icon to use
|
---|
| 32 | * @param tooltip a longer description of the action that will be displayed in the tooltip. Please note
|
---|
| 33 | * that html is not supported for menu actions on some platforms.
|
---|
| 34 | * @param shortcut a ready-created shortcut object or null if you don't want a shortcut. But you always
|
---|
| 35 | * do want a shortcut, remember you can always register it with group=none, so you
|
---|
| 36 | * won't be assigned a shortcut unless the user configures one. If you pass null here,
|
---|
| 37 | * the user CANNOT configure a shortcut for your action.
|
---|
| 38 | * @param registerInToolbar register this action for the toolbar preferences?
|
---|
| 39 | * @param toolbarId identifier for the toolbar preferences. The iconName is used, if this parameter is null
|
---|
| 40 | * @param installAdapters false, if you don't want to install layer changed and selection changed adapters
|
---|
| 41 | */
|
---|
[8509] | 42 | public ToggleAction(String name, ImageProvider icon, String tooltip, Shortcut shortcut, boolean registerInToolbar,
|
---|
| 43 | String toolbarId, boolean installAdapters) {
|
---|
[7937] | 44 | super(name, icon, tooltip, shortcut, registerInToolbar, toolbarId, installAdapters);
|
---|
| 45 | // It is required to set the SELECTED_KEY to a non-null value in order to let Swing components update it
|
---|
| 46 | setSelected(false);
|
---|
| 47 | }
|
---|
| 48 |
|
---|
| 49 | /**
|
---|
| 50 | * Constructs a {@code ToggleAction}.
|
---|
| 51 | *
|
---|
| 52 | * @param name the action's text as displayed on the menu (if it is added to a menu)
|
---|
| 53 | * @param iconName the name of icon to use
|
---|
| 54 | * @param tooltip a longer description of the action that will be displayed in the tooltip. Please note
|
---|
| 55 | * that html is not supported for menu actions on some platforms.
|
---|
| 56 | * @param shortcut a ready-created shortcut object or null if you don't want a shortcut. But you always
|
---|
| 57 | * do want a shortcut, remember you can always register it with group=none, so you
|
---|
| 58 | * won't be assigned a shortcut unless the user configures one. If you pass null here,
|
---|
| 59 | * the user CANNOT configure a shortcut for your action.
|
---|
| 60 | * @param registerInToolbar register this action for the toolbar preferences?
|
---|
| 61 | */
|
---|
| 62 | public ToggleAction(String name, String iconName, String tooltip, Shortcut shortcut, boolean registerInToolbar) {
|
---|
| 63 | super(name, iconName, tooltip, shortcut, registerInToolbar);
|
---|
| 64 | // It is required to set the SELECTED_KEY to a non-null value in order to let Swing components update it
|
---|
| 65 | setSelected(false);
|
---|
| 66 | }
|
---|
| 67 |
|
---|
| 68 | protected final void setSelected(boolean selected) {
|
---|
| 69 | putValue(SELECTED_KEY, selected);
|
---|
| 70 | }
|
---|
| 71 |
|
---|
| 72 | /**
|
---|
| 73 | * Determines if this action is currently being selected.
|
---|
| 74 | * @return {@code true} if this action is currently being selected, {@code false} otherwise
|
---|
| 75 | */
|
---|
| 76 | public final boolean isSelected() {
|
---|
| 77 | Object selected = getValue(SELECTED_KEY);
|
---|
| 78 | if (selected instanceof Boolean) {
|
---|
| 79 | return (Boolean) selected;
|
---|
| 80 | } else {
|
---|
[12620] | 81 | Logging.warn(getClass().getName() + " does not define a boolean for SELECTED_KEY but " + selected +
|
---|
[8540] | 82 | ". You should report it to JOSM developers.");
|
---|
[7937] | 83 | return false;
|
---|
| 84 | }
|
---|
| 85 | }
|
---|
| 86 |
|
---|
| 87 | /**
|
---|
| 88 | * Adds a button model
|
---|
| 89 | * @param model The button model to add
|
---|
| 90 | */
|
---|
| 91 | public final void addButtonModel(ButtonModel model) {
|
---|
| 92 | if (model != null && !buttonModels.contains(model)) {
|
---|
| 93 | buttonModels.add(model);
|
---|
| 94 | model.setSelected(isSelected());
|
---|
| 95 | }
|
---|
| 96 | }
|
---|
| 97 |
|
---|
| 98 | /**
|
---|
| 99 | * Removes a button model
|
---|
| 100 | * @param model The button model to remove
|
---|
| 101 | */
|
---|
| 102 | public final void removeButtonModel(ButtonModel model) {
|
---|
| 103 | if (model != null && buttonModels.contains(model)) {
|
---|
| 104 | buttonModels.remove(model);
|
---|
| 105 | }
|
---|
| 106 | }
|
---|
| 107 |
|
---|
| 108 | protected void notifySelectedState() {
|
---|
| 109 | boolean selected = isSelected();
|
---|
| 110 | for (ButtonModel model: buttonModels) {
|
---|
| 111 | if (model.isSelected() != selected) {
|
---|
| 112 | model.setSelected(selected);
|
---|
| 113 | }
|
---|
| 114 | }
|
---|
| 115 | }
|
---|
| 116 |
|
---|
| 117 | /**
|
---|
| 118 | * Toggles the selcted action state, if needed according to the ActionEvent that trigerred the action.
|
---|
[8509] | 119 | * This method will do nothing if the action event comes from a Swing component supporting the SELECTED_KEY property because
|
---|
| 120 | * the component already set the selected state.
|
---|
[7937] | 121 | * This method needs to be called especially if the action is associated with a keyboard shortcut to ensure correct selected state.
|
---|
[8795] | 122 | * @param e ActionEvent that trigerred the action
|
---|
[7937] | 123 | * @see <a href="https://weblogs.java.net/blog/zixle/archive/2005/11/changes_to_acti.html">Changes to Actions in 1.6</a>
|
---|
| 124 | * @see <a href="http://docs.oracle.com/javase/6/docs/api/javax/swing/Action.html">Interface Action</a>
|
---|
| 125 | */
|
---|
| 126 | protected final void toggleSelectedState(ActionEvent e) {
|
---|
| 127 | if (e == null || !(e.getSource() instanceof JToggleButton ||
|
---|
| 128 | e.getSource() instanceof JCheckBox ||
|
---|
| 129 | e.getSource() instanceof JRadioButton ||
|
---|
| 130 | e.getSource() instanceof JCheckBoxMenuItem ||
|
---|
| 131 | e.getSource() instanceof JRadioButtonMenuItem
|
---|
| 132 | )) {
|
---|
| 133 | setSelected(!isSelected());
|
---|
| 134 | }
|
---|
| 135 | }
|
---|
| 136 | }
|
---|