001 /*
002 * Copyright 2008-2014 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
020 import javax.annotation.Nonnull;
021 import javax.annotation.Nullable;
022 import javax.swing.AbstractAction;
023 import javax.swing.Action;
024 import javax.swing.Icon;
025 import javax.swing.KeyStroke;
026 import java.awt.event.ActionEvent;
027
028 import static griffon.util.GriffonNameUtils.isBlank;
029 import static java.util.Objects.requireNonNull;
030
031 /**
032 * An action implementation that relies on a closure to handle events.
033 *
034 * @author Andres Almiray
035 * @since 2.0.0
036 */
037 public class SwingAction extends AbstractAction {
038 private static final long serialVersionUID = 4598888514827528435L;
039 private static final String ERROR_CALLABLE_NULL = "Argument 'callable' must not be null";
040 private final CallableWithArgs<?> callable;
041
042 public SwingAction(@Nonnull CallableWithArgs<?> callable) {
043 this.callable = requireNonNull(callable, ERROR_CALLABLE_NULL);
044 }
045
046 public final void actionPerformed(ActionEvent evt) {
047 callable.call(evt);
048 }
049
050 @Nonnull
051 public static ActionBuilder action() {
052 return new ActionBuilder();
053 }
054
055 @Nonnull
056 public static ActionBuilder action(@Nullable Action action) {
057 return new ActionBuilder(action);
058 }
059
060 @Nonnull
061 public static ActionBuilder action(@Nullable String name) {
062 return new ActionBuilder().withName(name);
063 }
064
065 /**
066 * A builder for actions.
067 *
068 * @author Andres Almiray
069 * @since 2.0.0
070 */
071 public static class ActionBuilder {
072 private String name;
073 private int mnemonic;
074 private KeyStroke accelerator;
075 private String shortDescription;
076 private String longDescription;
077 private String command;
078 private Icon smallIcon;
079 private Icon largeIcon;
080 private CallableWithArgs<?> callable;
081 private boolean enabled = true;
082 private boolean selected = false;
083
084 private Action action;
085 private boolean mnemonicSet = false;
086 private boolean enabledSet = false;
087 private boolean selectedSet = false;
088
089 public ActionBuilder() {
090 this(null);
091 }
092
093 @Nonnull
094 public ActionBuilder(@Nullable Action action) {
095 this.action = action;
096 }
097
098 @Nonnull
099 public ActionBuilder withName(@Nullable String name) {
100 this.name = name;
101 return this;
102 }
103
104 @Nonnull
105 public ActionBuilder withShortDescription(@Nullable String shortDescription) {
106 this.shortDescription = shortDescription;
107 return this;
108 }
109
110 @Nonnull
111 public ActionBuilder withLongDescription(@Nullable String longDescription) {
112 this.longDescription = longDescription;
113 return this;
114 }
115
116 @Nonnull
117 public ActionBuilder withCommand(@Nullable String command) {
118 this.command = command;
119 return this;
120 }
121
122 @Nonnull
123 public ActionBuilder withMnemonic(@Nullable String mnemonic) {
124 if (!isBlank(mnemonic)) {
125 this.mnemonic = KeyStroke.getKeyStroke(mnemonic).getKeyCode();
126 }
127 mnemonicSet = true;
128 return this;
129 }
130
131 @Nonnull
132 public ActionBuilder withMnemonic(int mnemonic) {
133 this.mnemonic = mnemonic;
134 mnemonicSet = true;
135 return this;
136 }
137
138 @Nonnull
139 public ActionBuilder withAccelerator(@Nullable String accelerator) {
140 if (!isBlank(accelerator)) {
141 this.accelerator = KeyStroke.getKeyStroke(accelerator);
142 }
143 return this;
144 }
145
146 @Nonnull
147 public ActionBuilder withAccelerator(@Nullable KeyStroke accelerator) {
148 this.accelerator = accelerator;
149 return this;
150 }
151
152 @Nonnull
153 public ActionBuilder withSmallIcon(@Nullable Icon smallIcon) {
154 this.smallIcon = smallIcon;
155 return this;
156 }
157
158 @Nonnull
159 public ActionBuilder withLargeIcon(@Nullable Icon largeIcon) {
160 this.largeIcon = largeIcon;
161 return this;
162 }
163
164 @Nonnull
165 public ActionBuilder withRunnable(@Nullable CallableWithArgs<?> callable) {
166 this.callable = callable;
167 return this;
168 }
169
170 @Nonnull
171 public ActionBuilder withEnabled(boolean enabled) {
172 this.enabled = enabled;
173 this.enabledSet = true;
174 return this;
175 }
176
177 @Nonnull
178 public ActionBuilder withSelected(boolean selected) {
179 this.selected = selected;
180 this.enabledSet = true;
181 return this;
182 }
183
184 @Nonnull
185 public Action build() {
186 if (callable == null && action == null) {
187 throw new IllegalArgumentException("Either closure: or action: must have a value.");
188 }
189 if (action == null) {
190 action = new SwingAction(callable);
191 }
192 if (!isBlank(command)) {
193 action.putValue(Action.ACTION_COMMAND_KEY, command);
194 }
195 if (!isBlank(name)) {
196 action.putValue(Action.NAME, name);
197 }
198 if (mnemonicSet) {
199 action.putValue(Action.MNEMONIC_KEY, mnemonic);
200 }
201 if (accelerator != null) {
202 action.putValue(Action.ACCELERATOR_KEY, accelerator);
203 }
204 if (largeIcon != null) {
205 action.putValue(Action.LARGE_ICON_KEY, largeIcon);
206 }
207 if (smallIcon != null) {
208 action.putValue(Action.SMALL_ICON, smallIcon);
209 }
210 if (!isBlank(longDescription)) {
211 action.putValue(Action.LONG_DESCRIPTION, longDescription);
212 }
213 if (!isBlank(shortDescription)) {
214 action.putValue(Action.SHORT_DESCRIPTION, shortDescription);
215 }
216 if (enabledSet) {
217 action.setEnabled(enabled);
218 }
219 if (selectedSet) {
220 action.putValue(Action.SELECTED_KEY, selected);
221 }
222 return action;
223 }
224 }
225 }
|