001 /*
002 * Copyright 2002-2007 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005 * use this file except in compliance with the License. You may obtain a copy of
006 * 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, WITHOUT
012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013 * License for the specific language governing permissions and limitations under
014 * the License.
015 */
016 package org.springframework.richclient.command;
017
018 import org.springframework.richclient.command.config.CommandFaceDescriptor;
019 import org.springframework.util.Assert;
020 import org.springframework.util.ObjectUtils;
021
022 import javax.swing.*;
023 import java.awt.event.ActionEvent;
024 import java.awt.event.ActionListener;
025 import java.util.*;
026
027 public abstract class ActionCommand extends AbstractCommand implements ActionCommandExecutor,
028 ParameterizableActionCommandExecutor
029 {
030 public static final String ACTION_COMMAND_PROPERTY = "actionCommand";
031
032 public static final String ACTION_COMMAND_PARAMETER_KEY = "actionCommand";
033
034 public static final String ACTION_EVENT_PARAMETER_KEY = "actionEvent";
035
036 public static final String MODIFIERS_PARAMETER_KEY = "modifiers";
037
038 private static final String ELLIPSES = "...";
039
040 private List<ActionCommandInterceptor> commandInterceptors;
041
042 private String actionCommand;
043
044 private SwingActionAdapter swingActionAdapter;
045
046 private Map<Object, Object> parameters = new HashMap<Object, Object>(6);
047
048 private boolean displaysInputDialog;
049
050 public ActionCommand()
051 {
052 super();
053 }
054
055 public ActionCommand(String commandId)
056 {
057 super(commandId);
058 }
059
060 public ActionCommand(String id, CommandFaceDescriptor face)
061 {
062 super(id, face);
063 }
064
065 public ActionCommand(String id, String encodedLabel)
066 {
067 super(id, encodedLabel);
068 }
069
070 public ActionCommand(String id, String encodedLabel, Icon icon, String caption)
071 {
072 super(id, encodedLabel, icon, caption);
073 }
074
075 public void addParameter(Object key, Object value)
076 {
077 parameters.put(key, value);
078 }
079
080 protected Object getParameter(Object key)
081 {
082 return parameters.get(key);
083 }
084
085 protected Map getParameters()
086 {
087 return Collections.unmodifiableMap(parameters);
088 }
089
090 protected Object getParameter(Object key, Object defaultValue)
091 {
092 Object value = parameters.get(key);
093 return value != null ? value : defaultValue;
094 }
095
096 public void addCommandInterceptor(ActionCommandInterceptor l)
097 {
098 if (commandInterceptors == null)
099 {
100 commandInterceptors = new ArrayList<ActionCommandInterceptor>(6);
101 }
102 commandInterceptors.add(l);
103 }
104
105 public void removeCommandInterceptor(ActionCommandInterceptor l)
106 {
107 Assert.notNull(commandInterceptors, "The command interceptors list has not yet been initialized");
108 commandInterceptors.remove(l);
109 }
110
111 protected void onButtonAttached(AbstractButton button)
112 {
113 super.onButtonAttached(button);
114 button.setActionCommand(actionCommand);
115 button.addActionListener(actionPerformedHandler);
116 if (displaysInputDialog)
117 {
118 if (button.getText() != null && !button.getText().endsWith(ELLIPSES))
119 {
120 button.setText(getText() + ELLIPSES);
121 }
122 }
123 }
124
125 ActionListener actionPerformedHandler = new ActionListener()
126 {
127 public void actionPerformed(ActionEvent e)
128 {
129 addParameter(ACTION_EVENT_PARAMETER_KEY, e);
130 addParameter(MODIFIERS_PARAMETER_KEY, e.getModifiers());
131 addParameter(ACTION_COMMAND_PARAMETER_KEY, ActionCommand.this);
132 execute();
133 }
134 };
135
136 protected int getModifiers()
137 {
138 return (Integer) getParameter(MODIFIERS_PARAMETER_KEY, 0);
139 }
140
141 public Action getActionAdapter()
142 {
143 if (swingActionAdapter == null)
144 {
145 this.swingActionAdapter = new SwingActionAdapter(this);
146 }
147 return swingActionAdapter;
148 }
149
150 public String getActionCommand()
151 {
152 return actionCommand;
153 }
154
155 public void setActionCommand(String newCommandName)
156 {
157 if (!ObjectUtils.nullSafeEquals(actionCommand, newCommandName))
158 {
159 String old = actionCommand;
160 actionCommand = newCommandName;
161 Iterator iter = buttonIterator();
162 while (iter.hasNext())
163 {
164 AbstractButton button = (AbstractButton) iter.next();
165 button.setActionCommand(actionCommand);
166 }
167 firePropertyChange(ACTION_COMMAND_PROPERTY, old, newCommandName);
168 }
169 }
170
171 public void setDefaultButtonIn(RootPaneContainer container)
172 {
173 JRootPane rootPane = container.getRootPane();
174 JButton button = (JButton) getButtonIn(rootPane);
175 if (button != null)
176 {
177 rootPane.setDefaultButton(button);
178 }
179 }
180
181 public void setDefaultButton()
182 {
183 Iterator it = buttonIterator();
184 while (it.hasNext())
185 {
186 Object o = it.next();
187 if (o instanceof JButton)
188 {
189 JButton button = (JButton) o;
190 JRootPane pane = SwingUtilities.getRootPane(button);
191 if (pane != null)
192 {
193 pane.setDefaultButton(button);
194 }
195 }
196 }
197 }
198
199 public void setDisplaysInputDialog(boolean displaysInputDialog)
200 {
201 this.displaysInputDialog = displaysInputDialog;
202 }
203
204 public boolean isDisplaysInputDialog()
205 {
206 return displaysInputDialog;
207 }
208
209 public final void execute(Map parameters)
210 {
211 this.parameters.putAll(parameters);
212 execute();
213 }
214
215 public final void execute()
216 {
217 if (onPreExecute())
218 {
219 doExecuteCommand();
220 onPostExecute();
221 }
222 parameters.clear();
223 }
224
225 protected final boolean onPreExecute()
226 {
227 if (commandInterceptors == null)
228 {
229 return true;
230 }
231 for (Object commandInterceptor : commandInterceptors)
232 {
233 ActionCommandInterceptor listener = (ActionCommandInterceptor) commandInterceptor;
234 if (!listener.preExecution(this))
235 {
236 return false;
237 }
238 }
239 return true;
240 }
241
242 protected abstract void doExecuteCommand();
243
244 protected final void onPostExecute()
245 {
246 if (commandInterceptors == null)
247 {
248 return;
249 }
250 for (Object commandInterceptor : commandInterceptors)
251 {
252 ActionCommandInterceptor interceptor = (ActionCommandInterceptor) commandInterceptor;
253 interceptor.postExecution(this);
254 }
255 }
256
257 /**
258 * Returns <code>true</code> if the shift key was down when invoking this
259 * <code>ActionCommand</code>.
260 *
261 * @return <code>true</code> if the shift key was down, <code>false</code>
262 * otherwise
263 */
264 protected boolean isShiftDown()
265 {
266 return (getModifiers() & ActionEvent.SHIFT_MASK) != 0;
267 }
268
269 /**
270 * Returns <code>true</code> if the control key was down when invoking this
271 * <code>ActionCommand</code>.
272 *
273 * @return <code>true</code> if the control key was down, <code>false</code>
274 * otherwise
275 */
276 protected boolean isControlDown()
277 {
278 return (getModifiers() & ActionEvent.CTRL_MASK) != 0;
279 }
280
281 /**
282 * Returns <code>true</code> if the meta key was down when invoking this
283 * <code>ActionCommand</code>.
284 *
285 * @return <code>true</code> if the meta key was down, <code>false</code>
286 * otherwise
287 */
288 protected boolean isMetaDown()
289 {
290 return (getModifiers() & ActionEvent.META_MASK) != 0;
291 }
292
293 /**
294 * Returns <code>true</code> if the alt key was down when invoking this
295 * <code>ActionCommand</code>.
296 *
297 * @return <code>true</code> if the alt key was down, <code>false</code>
298 * otherwise
299 */
300
301 protected boolean isAltDown()
302 {
303 return (getModifiers() & ActionEvent.ALT_MASK) != 0;
304 }
305
306 }