KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jdesktop > swing > actions > ActionManager


1 /*
2  * $Id: ActionManager.java,v 1.2 2004/09/17 23:24:57 davidson1 Exp $
3  *
4  * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
5  * Santa Clara, California 95054, U.S.A. All rights reserved.
6  */

7 package org.jdesktop.swing.actions;
8
9 import java.beans.PropertyChangeListener JavaDoc;
10
11 import java.io.PrintStream JavaDoc;
12
13 import java.util.HashMap JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.Map JavaDoc;
16 import java.util.Set JavaDoc;
17
18 import javax.swing.*;
19
20 /**
21  * The ActionManager manages sets of <code>javax.swing.Action</code>s for an
22  * application. There are convenience methods for getting and setting the state
23  * of the action.
24  * All of these elements have a unique id tag which is used by the ActionManager
25  * to reference the action. This id maps to the <code>Action.ACTION_COMMAND_KEY</code>
26  * on the Action.
27  * <p>
28  * The ActionManager may be used to conveniently register callback methods
29  * on BoundActions.
30  * <p>
31  * A typical use case of the ActionManager is:
32  * <p>
33  * <pre>
34  * ActionManager manager = ActionManager.getInstance();
35  *
36  * // load Actions
37  * manager.addAction(action);
38  *
39  * // Change the state of the action:
40  * manager.setEnabled("new-action", newState);
41  * </pre>
42  *
43  * The ActionManager also supports Actions that can have a selected state
44  * associated with them. These Actions are typically represented by a
45  * JCheckBox or similar widget. For such actions the registered method is
46  * invoked with an additional parameter indicating the selected state of
47  * the widget. For example, for the callback handler:
48  *<p>
49  * <pre>
50  * public class Handler {
51  * public void stateChanged(boolean newState);
52  * }
53  * </pre>
54  * The registration method would look similar:
55  * <pre>
56  * manager.registerCallback("select-action", new Handler(), "stateChanged");
57  * </pre>
58  *<p>
59  * The stateChanged method would be invoked as the selected state of
60  * the widget changed. Additionally if you need to change the selected
61  * state of the Action use the ActionManager method <code>setSelected</code>.
62  * <p>
63  * The <code>ActionContainerFactory</code> uses the managed Actions in the
64  * ActionManager to create
65  * user interface components. For example, to create a JMenu based on an
66  * action-list id:
67  * <pre>
68  * JMenu file = manager.getFactory().createMenu(list);
69  * </pre>
70  *
71  * @see ActionContainerFactory
72  * @see TargetableAction
73  * @see BoundAction
74  * @author Mark Davidson
75  */

76 public class ActionManager {
77
78     // Internal data structures which manage the actions.
79

80     // key: value of ID_ATTR, value instanceof AbstractAction
81
private Map JavaDoc actionMap;
82
83     // Container factory instance for this ActionManager
84
private ActionContainerFactory factory;
85
86     /**
87      * Shared instance of the singleton ActionManager.
88      */

89     private static ActionManager INSTANCE;
90
91     // To enable debugging:
92
// Pass -Ddebug=true to the vm on start up.
93
// or
94
// set System.setProperty("debug", "true"); before constructing this Object
95

96     private static boolean DEBUG = false;
97
98     /**
99      * Creates the action manager. Use this constuctor if the application should
100      * support many ActionManagers. Otherwise, using the getInstance method will
101      * return a singleton.
102      */

103     public ActionManager() {
104     }
105
106     /**
107      * Return the Action Container Factory associated with this ActionManager
108      * instance. Will always return a factory instance.
109      */

110     public ActionContainerFactory getFactory() {
111         if (factory == null) {
112             factory = new ActionContainerFactory(this);
113         }
114         return factory;
115     }
116
117     /**
118      * This method should be used to associate a subclassed ActionContainerFactory
119      * with this ActionManager.
120      */

121     public void setFactory(ActionContainerFactory factory) {
122         this.factory = factory;
123     }
124
125     /**
126      * Return the instance of the ActionManger. If this has not been explicity
127      * set then it will be created.
128      *
129      * @return the ActionManager instance.
130      * @see #setInstance
131      */

132     public static ActionManager getInstance() {
133         if (INSTANCE == null) {
134             INSTANCE = new ActionManager();
135         }
136         return INSTANCE;
137     }
138
139     /**
140      * Sets the ActionManager instance.
141      */

142     public static void setInstance(ActionManager manager) {
143         INSTANCE = manager;
144     }
145
146     /**
147      * Returns the ids for all the managed actions.
148      * <p>
149      * An action id is a unique idenitfier which can
150      * be used to retrieve the corrspondng Action from the ActionManager.
151      * This identifier can also
152      * be used to set the properties of the action through the action
153      * manager like setting the state of the enabled or selected flags.
154      *
155      * @return a set which represents all the action ids
156      */

157     public Set JavaDoc getActionIDs() {
158         if (actionMap == null) {
159             return null;
160         }
161         return actionMap.keySet();
162     }
163
164     public Action addAction(Action action) {
165         return addAction(action.getValue(Action.ACTION_COMMAND_KEY), action);
166     }
167
168     /**
169      * Adds an action to the ActionManager
170      * @param id value of the action id - which is value of the ACTION_COMMAND_KEY
171      * @param action Action to be managed
172      * @return the action that was added
173      */

174     public Action addAction(Object JavaDoc id, Action action) {
175         if (actionMap == null) {
176             actionMap = new HashMap JavaDoc();
177         }
178         actionMap.put(id, action);
179
180         return action;
181     }
182
183     /**
184      * Retrieves the action corresponding to an action id.
185      *
186      * @param id value of the action id
187      * @return an Action or null if id
188      */

189     public Action getAction(Object JavaDoc id) {
190         if (actionMap != null) {
191             return (Action)actionMap.get(id);
192         }
193         return null;
194     }
195
196     /**
197      * Convenience method for returning the TargetableAction
198      *
199      * @param id value of the action id
200      * @return the TargetableAction referenced by the named id or null
201      */

202     public TargetableAction getTargetableAction(Object JavaDoc id) {
203         Action a = getAction(id);
204         if (a instanceof TargetableAction) {
205             return (TargetableAction)a;
206         }
207         return null;
208     }
209
210     /**
211      * Convenience method for returning the BoundAction
212      *
213      * @param id value of the action id
214      * @return the TargetableAction referenced by the named id or null
215      */

216     public BoundAction getBoundAction(Object JavaDoc id) {
217         Action a = getAction(id);
218         if (a instanceof BoundAction) {
219             return (BoundAction)a;
220         }
221         return null;
222     }
223
224     /**
225      * Convenience method for returning the ServerAction
226      *
227      * @param id value of the action id
228      * @return the TargetableAction referenced by the named id or null
229      */

230     public ServerAction getServerAction(Object JavaDoc id) {
231         Action a = getAction(id);
232         if (a instanceof ServerAction) {
233             return (ServerAction)a;
234         }
235         return null;
236     }
237
238     /**
239      * Convenience method for returning the CompositeAction
240      *
241      * @param id value of the action id
242      * @return the TargetableAction referenced by the named id or null
243      */

244     public CompositeAction getCompositeAction(Object JavaDoc id) {
245         Action a = getAction(id);
246         if (a instanceof CompositeAction) {
247             return (CompositeAction)a;
248         }
249         return null;
250     }
251
252     /**
253      * Convenience method for returning the StateChangeAction
254      *
255      * @param id value of the action id
256      * @return the StateChangeAction referenced by the named id or null
257      */

258     private AbstractActionExt getStateChangeAction(Object JavaDoc id) {
259         Action a = getAction(id);
260         if (a != null && a instanceof AbstractActionExt) {
261             AbstractActionExt aa = (AbstractActionExt)a;
262             if (aa.isStateAction()) {
263                 return aa;
264             }
265         }
266         return null;
267     }
268
269     /**
270      * Enables or disables the state of the Action corresponding to the
271      * action id. This method should be used
272      * by application developers to ensure that all components created from an
273      * action remain in synch with respect to their enabled state.
274      *
275      * @param id value of the action id
276      * @param enabled true if the action is to be enabled; otherwise false
277      */

278     public void setEnabled(Object JavaDoc id, boolean enabled) {
279         Action action = getAction(id);
280         if (action != null) {
281             action.setEnabled(enabled);
282         }
283     }
284
285
286     /**
287      * Returns the enabled state of the <code>Action</code>. When enabled,
288      * any component associated with this object is active and
289      * able to fire this object's <code>actionPerformed</code> method.
290      *
291      * @param id value of the action id
292      * @return true if this <code>Action</code> is enabled; false if the
293      * action doesn't exist or disabled.
294      */

295     public boolean isEnabled(Object JavaDoc id) {
296         Action action = getAction(id);
297         if (action != null) {
298             return action.isEnabled();
299         }
300         return false;
301     }
302
303     /**
304      * Sets the selected state of a toggle action. If the id doesn't
305      * correspond to a toggle action then it will fail silently.
306      *
307      * @param id the value of the action id
308      * @param selected true if the action is to be selected; otherwise false.
309      */

310     public void setSelected(Object JavaDoc id, boolean selected) {
311         AbstractActionExt action = getStateChangeAction(id);
312         if (action != null) {
313             action.setSelected(selected);
314         }
315     }
316
317     /**
318      * Gets the selected state of a toggle action. If the id doesn't
319      * correspond to a toggle action then it will fail silently.
320      *
321      * @param id the value of the action id
322      * @return true if the action is selected; false if the action
323      * doesn't exist or is disabled.
324      */

325     public boolean isSelected(Object JavaDoc id) {
326         AbstractActionExt action = getStateChangeAction(id);
327         if (action != null) {
328             return action.isSelected();
329         }
330         return false;
331     }
332
333     /**
334      * A diagnostic which prints the Attributes of an action
335      * on the printStream
336      */

337     static void printAction(PrintStream JavaDoc stream, Action action) {
338         stream.println("Attributes for " + action.getValue(Action.ACTION_COMMAND_KEY));
339
340         if (action instanceof AbstractAction) {
341             Object JavaDoc[] keys = ((AbstractAction)action).getKeys();
342
343             for (int i = 0; i < keys.length; i++) {
344                 stream.println("\tkey: " + keys[i] + "\tvalue: " +
345                                action.getValue((String JavaDoc)keys[i]));
346             }
347         }
348     }
349
350     /**
351      * Convenience method to register a callback method on a <code>BoundAction</code>
352      *
353      * @see BoundAction#registerCallback
354      * @param id value of the action id - which is the value of the ACTION_COMMAND_KEY
355      * @param handler the object which will be perform the action
356      * @param method the name of the method on the handler which will be called.
357      */

358     public void registerCallback(Object JavaDoc id, Object JavaDoc handler, String JavaDoc method) {
359         BoundAction action = getBoundAction(id);
360         if (action != null) {
361             action.registerCallback(handler, method);
362         }
363     }
364
365     /**
366      * A really ugly little hack which registers the text component on all the
367      * ServerActions.
368      * TODO: Should find a way of supporting generic components. Perhaps by
369      * defining a new interface like DataProvider which can
370      * be implemented by all ServerActions.
371      *
372      public void registerDataProvider(ServerActionListener listener) {
373      if (actionMap != null) {
374      Iterator iter = actionMap.values().iterator();
375      while (iter.hasNext()) {
376      AbstractAction action = (AbstractAction)iter.next();
377      if (action instanceof ServerAction) {
378      ((ServerAction)action).addServerActionListener(listener);
379      }
380      }
381      }
382      }*/

383
384     //
385
// Convenience methods for determining the type of action.
386
//
387

388     /**
389      * Determines if the Action corresponding to the action id is a state changed
390      * action (toggle, group type action).
391      *
392      * @param id value of the action id
393      * @return true if the action id represents a multi state action; false otherwise
394      */

395     public boolean isStateAction(Object JavaDoc id) {
396         Action action = getAction(id);
397         if (action != null && action instanceof AbstractActionExt) {
398             return ((AbstractActionExt)action).isStateAction();
399         }
400         return false;
401     }
402
403     /**
404      * Test to determine if the action is a <code>TargetableAction</code>
405      */

406     public boolean isTargetableAction(Object JavaDoc id) {
407         return (getTargetableAction(id) != null);
408     }
409
410     /**
411      * Test to determine if the action is a <code>BoundAction</code>
412      */

413     public boolean isBoundAction(Object JavaDoc id) {
414         return (getBoundAction(id) != null);
415     }
416
417     /**
418      * Test to determine if the action is a <code>BoundAction</code>
419      */

420     public boolean isCompositeAction(Object JavaDoc id) {
421         return (getCompositeAction(id) != null);
422     }
423
424     /**
425      * Test to determine if the action is a <code>ServerAction</code>
426      */

427     public boolean isServerAction(Object JavaDoc id) {
428         return (getServerAction(id) != null);
429     }
430 }
431
Popular Tags