1 | // License: GPL. For details, see LICENSE file.
|
---|
2 | package org.openstreetmap.josm.actions;
|
---|
3 |
|
---|
4 | import java.awt.event.ActionEvent;
|
---|
5 | import java.util.HashSet;
|
---|
6 | import java.util.Set;
|
---|
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.Main;
|
---|
16 | import org.openstreetmap.josm.tools.ImageProvider;
|
---|
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 |
|
---|
25 | private final transient Set<ButtonModel> buttonModels = new HashSet<>();
|
---|
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 | */
|
---|
42 | public ToggleAction(String name, ImageProvider icon, String tooltip, Shortcut shortcut, boolean registerInToolbar,
|
---|
43 | String toolbarId, boolean installAdapters) {
|
---|
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 {
|
---|
81 | Main.warn(getClass().getName() + " does not define a boolean for SELECTED_KEY but " + selected +
|
---|
82 | ". You should report it to JOSM developers.");
|
---|
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.
|
---|
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.
|
---|
121 | * This method needs to be called especially if the action is associated with a keyboard shortcut to ensure correct selected state.
|
---|
122 | * @see <a href="https://weblogs.java.net/blog/zixle/archive/2005/11/changes_to_acti.html">Changes to Actions in 1.6</a>
|
---|
123 | * @see <a href="http://docs.oracle.com/javase/6/docs/api/javax/swing/Action.html">Interface Action</a>
|
---|
124 | */
|
---|
125 | protected final void toggleSelectedState(ActionEvent e) {
|
---|
126 | if (e == null || !(e.getSource() instanceof JToggleButton ||
|
---|
127 | e.getSource() instanceof JCheckBox ||
|
---|
128 | e.getSource() instanceof JRadioButton ||
|
---|
129 | e.getSource() instanceof JCheckBoxMenuItem ||
|
---|
130 | e.getSource() instanceof JRadioButtonMenuItem
|
---|
131 | )) {
|
---|
132 | setSelected(!isSelected());
|
---|
133 | }
|
---|
134 | }
|
---|
135 | }
|
---|