001 /*
002 * Copyright 2008-2015 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package griffon.swing.support;
017
018 import griffon.core.CallableWithArgs;
019 import griffon.core.RunnableWithArgs;
020
021 import javax.annotation.Nonnull;
022 import javax.annotation.Nullable;
023 import javax.swing.AbstractAction;
024 import javax.swing.Action;
025 import javax.swing.Icon;
026 import javax.swing.KeyStroke;
027 import java.awt.event.ActionEvent;
028
029 import static griffon.util.GriffonNameUtils.isBlank;
030 import static java.util.Objects.requireNonNull;
031
032 /**
033 * An action implementation that relies on a closure to handle events.
034 *
035 * @author Andres Almiray
036 * @since 2.0.0
037 */
038 public class SwingAction extends AbstractAction {
039 private static final long serialVersionUID = 4493562556110760713L;
040 private static final String ERROR_CALLABLE_NULL = "Argument 'callable' must not be null";
041 private static final String ERROR_RUNNABLE_NULL = "Argument 'runnable' must not be null";
042 private RunnableWithArgs runnable;
043
044 @Deprecated
045 public SwingAction(final @Nonnull CallableWithArgs<?> callable) {
046 requireNonNull(callable, ERROR_CALLABLE_NULL);
047 this.runnable = new RunnableWithArgs() {
048 @Override
049 public void run(@Nullable Object... args) {
050 callable.call(args);
051 }
052 };
053 }
054
055 public SwingAction(@Nonnull RunnableWithArgs runnable) {
056 this.runnable = requireNonNull(runnable, ERROR_RUNNABLE_NULL);
057 }
058
059 @Nonnull
060 public static ActionBuilder action() {
061 return new ActionBuilder();
062 }
063
064 @Nonnull
065 public static ActionBuilder action(@Nullable Action action) {
066 return new ActionBuilder(action);
067 }
068
069 @Nonnull
070 public static ActionBuilder action(@Nullable String name) {
071 return new ActionBuilder().withName(name);
072 }
073
074 public final void actionPerformed(ActionEvent evt) {
075 runnable.run(evt);
076 }
077
078 /**
079 * A builder for actions.
080 *
081 * @author Andres Almiray
082 * @since 2.0.0
083 */
084 public static class ActionBuilder {
085 private String name;
086 private int mnemonic;
087 private KeyStroke accelerator;
088 private String shortDescription;
089 private String longDescription;
090 private String command;
091 private Icon smallIcon;
092 private Icon largeIcon;
093 private RunnableWithArgs runnable;
094 private boolean enabled = true;
095 private boolean selected = false;
096
097 private Action action;
098 private boolean mnemonicSet = false;
099 private boolean enabledSet = false;
100 private boolean selectedSet = false;
101
102 public ActionBuilder() {
103 this(null);
104 }
105
106 @Nonnull
107 public ActionBuilder(@Nullable Action action) {
108 this.action = action;
109 }
110
111 @Nonnull
112 public ActionBuilder withName(@Nullable String name) {
113 this.name = name;
114 return this;
115 }
116
117 @Nonnull
118 public ActionBuilder withShortDescription(@Nullable String shortDescription) {
119 this.shortDescription = shortDescription;
120 return this;
121 }
122
123 @Nonnull
124 public ActionBuilder withLongDescription(@Nullable String longDescription) {
125 this.longDescription = longDescription;
126 return this;
127 }
128
129 @Nonnull
130 public ActionBuilder withCommand(@Nullable String command) {
131 this.command = command;
132 return this;
133 }
134
135 @Nonnull
136 public ActionBuilder withMnemonic(@Nullable String mnemonic) {
137 if (!isBlank(mnemonic)) {
138 this.mnemonic = KeyStroke.getKeyStroke(mnemonic).getKeyCode();
139 }
140 mnemonicSet = true;
141 return this;
142 }
143
144 @Nonnull
145 public ActionBuilder withMnemonic(int mnemonic) {
146 this.mnemonic = mnemonic;
147 mnemonicSet = true;
148 return this;
149 }
150
151 @Nonnull
152 public ActionBuilder withAccelerator(@Nullable String accelerator) {
153 if (!isBlank(accelerator)) {
154 this.accelerator = KeyStroke.getKeyStroke(accelerator);
155 }
156 return this;
157 }
158
159 @Nonnull
160 public ActionBuilder withAccelerator(@Nullable KeyStroke accelerator) {
161 this.accelerator = accelerator;
162 return this;
163 }
164
165 @Nonnull
166 public ActionBuilder withSmallIcon(@Nullable Icon smallIcon) {
167 this.smallIcon = smallIcon;
168 return this;
169 }
170
171 @Nonnull
172 public ActionBuilder withLargeIcon(@Nullable Icon largeIcon) {
173 this.largeIcon = largeIcon;
174 return this;
175 }
176
177 @Nonnull
178 @Deprecated
179 public ActionBuilder withRunnable(final @Nullable CallableWithArgs<?> callable) {
180 requireNonNull(callable, ERROR_CALLABLE_NULL);
181 this.runnable = new RunnableWithArgs() {
182 @Override
183 public void run(@Nullable Object... args) {
184 callable.call(args);
185 }
186 };
187 return this;
188 }
189
190 @Nonnull
191 public ActionBuilder withRunnable(@Nullable RunnableWithArgs runnable) {
192 this.runnable = runnable;
193 return this;
194 }
195
196 @Nonnull
197 public ActionBuilder withEnabled(boolean enabled) {
198 this.enabled = enabled;
199 this.enabledSet = true;
200 return this;
201 }
202
203 @Nonnull
204 public ActionBuilder withSelected(boolean selected) {
205 this.selected = selected;
206 this.enabledSet = true;
207 return this;
208 }
209
210 @Nonnull
211 public Action build() {
212 if (runnable == null && action == null) {
213 throw new IllegalArgumentException("Either runnable, callable, or action must have a value.");
214 }
215 if (action == null) {
216 action = new SwingAction(runnable);
217 }
218 if (!isBlank(command)) {
219 action.putValue(Action.ACTION_COMMAND_KEY, command);
220 }
221 if (!isBlank(name)) {
222 action.putValue(Action.NAME, name);
223 }
224 if (mnemonicSet) {
225 action.putValue(Action.MNEMONIC_KEY, mnemonic);
226 }
227 if (accelerator != null) {
228 action.putValue(Action.ACCELERATOR_KEY, accelerator);
229 }
230 if (largeIcon != null) {
231 action.putValue(Action.LARGE_ICON_KEY, largeIcon);
232 }
233 if (smallIcon != null) {
234 action.putValue(Action.SMALL_ICON, smallIcon);
235 }
236 if (!isBlank(longDescription)) {
237 action.putValue(Action.LONG_DESCRIPTION, longDescription);
238 }
239 if (!isBlank(shortDescription)) {
240 action.putValue(Action.SHORT_DESCRIPTION, shortDescription);
241 }
242 if (enabledSet) {
243 action.setEnabled(enabled);
244 }
245 if (selectedSet) {
246 action.putValue(Action.SELECTED_KEY, selected);
247 }
248 return action;
249 }
250 }
251 }
|