Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
SelectableAction |
|
| 2.066666666666667;2.067 | ||||
SelectableAction$1 |
|
| 2.066666666666667;2.067 |
1 | /* | |
2 | * Copyright (c) 2009, Swiss Federal Department of Defence Civil Protection and Sport | |
3 | * (http://www.vbs.admin.ch) | |
4 | * Copyright (c) 2009, Ergon Informatik AG (http://www.ergon.ch) | |
5 | * All rights reserved. | |
6 | * | |
7 | * Licensed under the Open Permis License which accompanies this distribution, | |
8 | * and is available at http://www.openpermis.org/BSDlicenceKent.txt | |
9 | */ | |
10 | package org.openpermis.editor.policy.gui; | |
11 | ||
12 | import java.awt.event.ActionEvent; | |
13 | import java.awt.event.ItemEvent; | |
14 | import java.awt.event.ItemListener; | |
15 | import java.beans.PropertyChangeEvent; | |
16 | import java.beans.PropertyChangeListener; | |
17 | ||
18 | import javax.swing.AbstractAction; | |
19 | import javax.swing.AbstractButton; | |
20 | import javax.swing.Action; | |
21 | import javax.swing.Icon; | |
22 | import javax.swing.JCheckBox; | |
23 | import javax.swing.JCheckBoxMenuItem; | |
24 | import javax.swing.JToggleButton; | |
25 | ||
26 | ||
27 | /** | |
28 | * Extended swing {@link Action} that provides selection support. | |
29 | * @note Selection support is built-in in JSE6, this class is for backward compatibility | |
30 | * of JSE5 only. | |
31 | * @since 0.1.0 | |
32 | */ | |
33 | public abstract class SelectableAction | |
34 | extends AbstractAction | |
35 | implements ItemListener | |
36 | { | |
37 | ||
38 | //---- Static | |
39 | ||
40 | /** | |
41 | * @since 0.1.0 | |
42 | */ | |
43 | private static final long serialVersionUID = -7232379579443222905L; | |
44 | ||
45 | /** | |
46 | * The property key used to indicate that an action is selected. | |
47 | * <p>The value of this property is of type {@link Boolean}.</p> | |
48 | * @since 0.1.0 | |
49 | */ | |
50 | private static final String SELECTED_KEY = "_selected"; | |
51 | ||
52 | /** | |
53 | * Configures the specified button for use with the given action. | |
54 | * <p>If the action is a selectable action then selection support will be added.</p> | |
55 | * @param <T> the type of button to configure. | |
56 | * @param button the button to configure. | |
57 | * @param action the action to configure to button from. | |
58 | * @return the button passed in for fluent style use. | |
59 | * @since 0.1.0 | |
60 | */ | |
61 | private static <T extends AbstractButton> T configure (final T button, Action action) { | |
62 | 0 | if (!(action instanceof SelectableAction)) { |
63 | 0 | return button; |
64 | } | |
65 | 0 | final SelectableAction selectableAction = (SelectableAction) action; |
66 | 0 | button.addItemListener(selectableAction); |
67 | 0 | selectableAction.addPropertyChangeListener( |
68 | new PropertyChangeListener() { | |
69 | 0 | public void propertyChange (PropertyChangeEvent event) { |
70 | 0 | if (selectableAction.isSelectionEvent(event)) { |
71 | 0 | if (button.getAction() != selectableAction) { |
72 | // Button has a new action, detach. | |
73 | 0 | selectableAction.removePropertyChangeListener(this); |
74 | 0 | return; |
75 | } | |
76 | 0 | final boolean selected = selectableAction.isSelected(); |
77 | 0 | if (button.isSelected() != selected) { |
78 | 0 | button.setSelected(selected); |
79 | } | |
80 | } | |
81 | 0 | } |
82 | } | |
83 | ); | |
84 | 0 | return button; |
85 | } | |
86 | ||
87 | /** | |
88 | * Creates a check box where properties are taken from the Action supplied. | |
89 | * <p>Also provides selection support if the action specified is a selectable action.</p> | |
90 | * @param action the action to create the check box. | |
91 | * @return the check box requested. | |
92 | * @since 0.1.0 | |
93 | */ | |
94 | public static JCheckBox createCheckBox (Action action) { | |
95 | 0 | return configure(new JCheckBox(action), action); |
96 | } | |
97 | ||
98 | /** | |
99 | * Creates a toggle button where properties are taken from the Action supplied. | |
100 | * <p>Also provides selection support if the action specified is a selectable action.</p> | |
101 | * @param action the action to create the toggle button. | |
102 | * @return the toggle button requested. | |
103 | * @since 0.1.0 | |
104 | */ | |
105 | public static JToggleButton createToggleButton (Action action) { | |
106 | 0 | return configure(new JToggleButton(action), action); |
107 | } | |
108 | ||
109 | /** | |
110 | * Creates a check box menu item where properties are taken from the Action supplied. | |
111 | * <p>Also provides selection support if the action specified is a selectable action.</p> | |
112 | * @param action the action to create the check box menu item. | |
113 | * @return the check box menu item requested. | |
114 | * @since 0.1.0 | |
115 | */ | |
116 | public static JCheckBoxMenuItem createCheckBoxMenuItem (Action action) { | |
117 | 0 | return configure(new JCheckBoxMenuItem(action), action); |
118 | } | |
119 | ||
120 | /** | |
121 | * Check if the specified action is selected. | |
122 | * <p>Only selectable actions can have the selected state, all others return {@code false}.</p> | |
123 | * @param action the action to check. | |
124 | * @return {@code true} if it is selected, {@code false} otherwise. | |
125 | * @since 0.1.0 | |
126 | */ | |
127 | public boolean isSelected (Action action) { | |
128 | 0 | if (action instanceof SelectableAction) { |
129 | 0 | return ((SelectableAction) action).isSelected(); |
130 | } | |
131 | 0 | return false; |
132 | } | |
133 | ||
134 | //---- Constructors | |
135 | ||
136 | /** | |
137 | * Defines an <code>Action</code> with the specified name and small icon. | |
138 | * @param name the description of the action. | |
139 | * @param icon the small icon of the action. | |
140 | * @since 0.1.0 | |
141 | */ | |
142 | public SelectableAction (String name, Icon icon) { | |
143 | 0 | super(name, icon); |
144 | 0 | } |
145 | ||
146 | //---- Methods | |
147 | ||
148 | /** | |
149 | * Convenience factory method to create a check box that is bound to this action. | |
150 | * @return the check box requested. | |
151 | * @since 0.1.0 | |
152 | */ | |
153 | public JCheckBox createCheckBox () { | |
154 | 0 | return createCheckBox(this); |
155 | } | |
156 | ||
157 | /** | |
158 | * Convenience factory method to create a toggle button that is bound to this action. | |
159 | * @return the toggle button requested. | |
160 | * @since 0.1.0 | |
161 | */ | |
162 | public JToggleButton createToggleButton () { | |
163 | 0 | return createToggleButton(this); |
164 | } | |
165 | ||
166 | /** | |
167 | * Convenience factory method to create a check box menu item that is bound to this action. | |
168 | * @return the check box menu item requested. | |
169 | * @since 0.1.0 | |
170 | */ | |
171 | public JCheckBoxMenuItem createCheckBoxMenuItem () { | |
172 | 0 | return createCheckBoxMenuItem(this); |
173 | } | |
174 | ||
175 | /** | |
176 | * Checks if the event is a selection change event fired by this action. | |
177 | * <p>Use {@link #isSelected()} to check the value or inspect the event values | |
178 | * which are of type {@link Boolean}.</p> | |
179 | * @param event the event to check, may be {@code null}. | |
180 | * @return {@code true} if the event is a selection change event on this action. | |
181 | * @since 0.1.0 | |
182 | */ | |
183 | public boolean isSelectionEvent (PropertyChangeEvent event) { | |
184 | 0 | if (event == null || event.getSource() != this) { |
185 | 0 | return false; |
186 | } | |
187 | 0 | return SELECTED_KEY.equals(event.getPropertyName()); |
188 | } | |
189 | ||
190 | /** | |
191 | * Check if the specified action is selected. | |
192 | * @return {@code true} if it is selected, {@code false} otherwise. | |
193 | * @since 0.1.0 | |
194 | */ | |
195 | public boolean isSelected () { | |
196 | 0 | return Boolean.TRUE.equals(getValue(SELECTED_KEY)); |
197 | } | |
198 | ||
199 | /** | |
200 | * Sets the selection state of this action. | |
201 | * @param selected the new selection state of this action. | |
202 | * @since 0.1.0 | |
203 | */ | |
204 | public void setSelected (boolean selected) { | |
205 | 0 | putValue(SELECTED_KEY, Boolean.valueOf(selected)); |
206 | 0 | } |
207 | ||
208 | //---- Action | |
209 | ||
210 | /** | |
211 | * @since 0.1.0 | |
212 | */ | |
213 | public abstract void actionPerformed (ActionEvent e); | |
214 | ||
215 | //---- ItemListener | |
216 | ||
217 | /** | |
218 | * Synchronizes the selection state of this action with the one of the button. | |
219 | * <p>If the button changes, the action will change as well.</p> | |
220 | * @param e the item state change event. | |
221 | * @since 0.1.0 | |
222 | */ | |
223 | public void itemStateChanged (ItemEvent e) { | |
224 | 0 | if (!(e.getItemSelectable() instanceof AbstractButton)) { |
225 | // Only use this item listener for buttons the action is attached to! | |
226 | 0 | return; |
227 | } | |
228 | 0 | final AbstractButton button = (AbstractButton) e.getItemSelectable(); |
229 | 0 | if (button.getAction() != this) { |
230 | // The action of the button has changed, we are no longer tracking | |
231 | // this button in this case. | |
232 | 0 | button.removeItemListener(this); |
233 | 0 | return; |
234 | } | |
235 | 0 | final boolean selected = e.getStateChange() == ItemEvent.SELECTED; |
236 | 0 | if (isSelected() != selected) { |
237 | 0 | setSelected(selected); |
238 | } | |
239 | 0 | } |
240 | ||
241 | } |