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    }