001: /*
002: ** $Id: ActionFactory.java,v 1.17 2000/10/26 08:34:15 mrw Exp $
003: **
004: ** Mike Wilson, July 2000, mrw@whisperingwind.co.uk
005: **
006: ** (C) Copyright 2000, Mike Wilson, Reading, Berkshire, UK
007: **
008: ** This program is free software; you can redistribute it and/or modify
009: ** it under the terms of the GNU General Public License as published by
010: ** the Free Software Foundation; either version 2 of the License, or
011: ** (at your option) any later version.
012: **
013: ** This program is distributed in the hope that it will be useful,
014: ** but WITHOUT ANY WARRANTY; without even the implied warranty of
015: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: ** GNU General Public License for more details.
017: **
018: ** You should have received a copy of the GNU Library General
019: ** Public License along with this library; if not, write to the
020: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
021: ** Boston, MA 02111-1307 USA.
022: */
023:
024: package uk.co.whisperingwind.framework;
025:
026: import java.awt.Event;
027: import java.awt.event.ActionEvent;
028: import java.awt.event.ActionListener;
029: import java.awt.event.KeyEvent;
030: import javax.swing.AbstractAction;
031: import javax.swing.Action;
032: import javax.swing.border.Border;
033: import javax.swing.BorderFactory;
034: import javax.swing.event.EventListenerList;
035: import javax.swing.ImageIcon;
036: import javax.swing.JButton;
037: import javax.swing.JCheckBoxMenuItem;
038: import javax.swing.JComponent;
039: import javax.swing.JMenu;
040: import javax.swing.JMenuItem;
041: import javax.swing.JToggleButton;
042: import javax.swing.JToolBar;
043: import javax.swing.KeyStroke;
044:
045: /**
046: ** Factory class to create Action instances. This makes it easier to
047: ** handle Actions, particularly in JDK 1.2 (Action was extended in JSK
048: ** 1.3). The JDK 1.3 version of Action still doesn't behave as I would
049: ** like, in particular, it assignes the same icon to a menu item and a
050: ** button. I would rather it used a smaller icon on the menu item.
051: */
052:
053: public class ActionFactory {
054: protected String imagePath = null;
055:
056: /**
057: ** Construct an ActionFactory which will look for button images in
058: ** the specified path.
059: **
060: ** @param path path to a directory containing button images.
061: */
062:
063: public ActionFactory(String path) {
064: imagePath = path;
065: }
066:
067: /**
068: ** Create and return a DefaultAction for the given command.
069: **
070: ** @param command the name of the command to create.
071: ** @return a DefaultAction for the requested command,
072: ** <code>null</code> if the command is unknown.
073: */
074:
075: public DefaultAction createAction(String command) {
076: DefaultAction action = null;
077:
078: if (command.equals("ok"))
079: action = new OkAction();
080: else if (command.equals("cancel"))
081: action = new CancelAction();
082: else if (command.equals("dismiss"))
083: action = new DismissAction();
084: else if (command.equals("apply"))
085: action = new ApplyAction();
086: else if (command.equals("cut"))
087: action = new CutAction();
088: else if (command.equals("copy"))
089: action = new CopyAction();
090: else if (command.equals("paste"))
091: action = new PasteAction();
092: else if (command.equals("clear"))
093: action = new ClearAction();
094:
095: return action;
096: }
097:
098: /**
099: ** Get an ImageIcon from the given file name.
100: **
101: ** @param fileName the name of the image file (not the full path).
102: ** @return ImageIcon for the requested file name.
103: */
104:
105: protected ImageIcon getIcon(String fileName) {
106: String filePath = imagePath + "/" + fileName;
107: ImageIcon i = new ImageIcon(getClass().getResource(filePath));
108:
109: return i;
110: }
111:
112: /**
113: ** AbstractAction extension which adds the ability to construct
114: ** a JMenuItem or toolbar button with appropriate text, image etc.
115: */
116:
117: public class DefaultAction extends AbstractAction {
118: private EventListenerList listenerList = null;
119:
120: public static final String LARGE_ICON = "LargeIcon";
121: public static final String TOOL_TIP = "ToolTip";
122: public static final String ACCELERATOR_KEY = "AcceleratorKey";
123: public static final String ACTION_COMMAND_KEY = "ActionCommandKey";
124: public static final String MNEMONIC_KEY = "MnemonicKey";
125:
126: public DefaultAction(String name) {
127: super (name);
128: }
129:
130: /**
131: ** Construct a menu item for this action and add it to the
132: ** menu.
133: **
134: ** @param menu the menu to which the new item is added.
135: ** @return the new menu item.
136: */
137:
138: public JMenuItem menuItemFactory(JMenu menu) {
139: JMenuItem menuItem = menu.add(this );
140: menuItem
141: .setAccelerator((KeyStroke) getValue(ACCELERATOR_KEY));
142:
143: return menuItem;
144: }
145:
146: /**
147: ** Contruct a tool button for this action and add it to the
148: ** toolbar.
149: **
150: ** @param toolBar the toolbar to which the new button is
151: ** added.
152: ** @return the new button.
153: */
154:
155: public JButton toolButtonFactory(JToolBar toolBar) {
156: JButton button = toolBar.add(this );
157: button.setToolTipText((String) getValue(TOOL_TIP));
158: ImageIcon image = getLargeIcon();
159:
160: if (image != null) {
161: button.setText("");
162: button.setIcon(image);
163: } else {
164: Border outer = BorderFactory.createEtchedBorder();
165: Border inner = BorderFactory.createEmptyBorder(4, 4, 4,
166: 4);
167: button.setBorder(BorderFactory.createCompoundBorder(
168: outer, inner));
169: Integer mnemonic = (Integer) getValue(DefaultAction.MNEMONIC_KEY);
170:
171: if (mnemonic != null)
172: button.setMnemonic(mnemonic.intValue());
173: }
174:
175: KeyStroke keyStroke = (KeyStroke) getValue(ACCELERATOR_KEY);
176:
177: if (keyStroke != null) {
178: button.registerKeyboardAction(this , keyStroke,
179: JComponent.WHEN_IN_FOCUSED_WINDOW);
180: }
181:
182: return button;
183: }
184:
185: /**
186: ** Get the small icon for this action. This icon is used, for
187: ** example, in menu items.
188: **
189: ** @return the small icon for this action.
190: */
191:
192: public ImageIcon getSmallIcon() {
193: return (ImageIcon) getValue(Action.SMALL_ICON);
194: }
195:
196: /**
197: ** Get the large icon for this action. This icon is used, for
198: ** example, in toolbar button.
199: **
200: ** @return the large icon for this action.
201: */
202:
203: public ImageIcon getLargeIcon() {
204: return (ImageIcon) getValue(LARGE_ICON);
205: }
206:
207: /**
208: ** Messy: Pass on action events to my listeners.
209: */
210:
211: public void actionPerformed(ActionEvent event) {
212: if (listenerList != null) {
213: Object[] listeners = listenerList.getListenerList();
214:
215: ActionEvent e = new ActionEvent(event.getSource(),
216: event.getID(),
217: (String) getValue(ACTION_COMMAND_KEY));
218:
219: for (int i = 0; i <= listeners.length - 2; i += 2) {
220: ((ActionListener) listeners[i + 1])
221: .actionPerformed(e);
222: }
223: }
224: }
225:
226: public void addActionListener(ActionListener listener) {
227: if (listenerList == null)
228: listenerList = new EventListenerList();
229:
230: listenerList.add(ActionListener.class, listener);
231: }
232:
233: public void removeActionListener(ActionListener listener) {
234: if (listenerList != null)
235: listenerList.remove(ActionListener.class, listener);
236: }
237:
238: public boolean getState() {
239: return false;
240: }
241: }
242:
243: /**
244: ** A bi-state extension of ToggleAction. Used for toggle buttons.
245: */
246:
247: public class ToggleAction extends DefaultAction {
248: private JCheckBoxMenuItem menuItem = null;
249: private JToggleButton button = null;
250:
251: public ToggleAction(String name) {
252: super (name);
253: }
254:
255: /**
256: ** Construct a check box menu item for this action and add it
257: ** to the menu.
258: **
259: ** @param menu the menu to which the new menu item is added.
260: ** @return the new menu item.
261: */
262:
263: public JMenuItem menuItemFactory(JMenu menu) {
264: menuItem = new JCheckBoxMenuItem(
265: (String) getValue(Action.NAME));
266:
267: menuItem
268: .setActionCommand((String) getValue(DefaultAction.ACTION_COMMAND_KEY));
269: menuItem
270: .setAccelerator((KeyStroke) getValue(ACCELERATOR_KEY));
271: menuItem.setState(true);
272: menu.add(menuItem);
273: menuItem.addActionListener(this );
274:
275: return menuItem;
276: }
277:
278: /**
279: ** Get the state for the action.
280: **
281: ** @return true if the action's toggle button is selected or
282: ** the action's check box menu item is selected, false
283: ** otherwise.
284: */
285:
286: public boolean getState() {
287: if (menuItem != null)
288: return menuItem.getState();
289: else if (button != null)
290: return button.isSelected();
291: else
292: return false;
293: }
294: }
295:
296: /**
297: ** DefaultAction for an "Ok" button.
298: */
299:
300: private class OkAction extends ActionFactory.DefaultAction {
301: public OkAction() {
302: super ("Ok");
303: putValue(Action.NAME, "Ok");
304: putValue(DefaultAction.ACTION_COMMAND_KEY, "ok");
305: }
306: }
307:
308: /**
309: ** DefaultAction for a "Cancel" button.
310: */
311:
312: private class CancelAction extends ActionFactory.DefaultAction {
313: public CancelAction() {
314: super ("Cancel");
315: putValue(Action.NAME, "Cancel");
316: putValue(DefaultAction.ACTION_COMMAND_KEY, "cancel");
317: putValue(DefaultAction.ACCELERATOR_KEY, KeyStroke
318: .getKeyStroke(KeyEvent.VK_ESCAPE, 0));
319: }
320: }
321:
322: /**
323: ** DefaultAction for a "Dismiss" button.
324: */
325:
326: private class DismissAction extends ActionFactory.DefaultAction {
327: public DismissAction() {
328: super ("Dismiss");
329: putValue(Action.NAME, "Dismiss");
330: putValue(DefaultAction.ACTION_COMMAND_KEY, "dismiss");
331: }
332: }
333:
334: /**
335: ** DefaultAction for an "Apply" button.
336: */
337:
338: private class ApplyAction extends ActionFactory.DefaultAction {
339: public ApplyAction() {
340: super ("Apply");
341: putValue(Action.NAME, "Apply");
342: putValue(DefaultAction.ACTION_COMMAND_KEY, "apply");
343: }
344: }
345:
346: /**
347: ** DefaultAction for an "Apply" button.
348: */
349:
350: private class CutAction extends ActionFactory.DefaultAction {
351: public CutAction() {
352: super ("Cut");
353: putValue(Action.NAME, "Cut");
354: putValue(Action.SMALL_ICON, getIcon("Cut16.gif"));
355: putValue(LARGE_ICON, getIcon("Cut24.gif"));
356: putValue(DefaultAction.ACTION_COMMAND_KEY, "cut");
357: putValue(DefaultAction.ACCELERATOR_KEY, KeyStroke
358: .getKeyStroke('X', Event.CTRL_MASK, false));
359: }
360: }
361:
362: /**
363: ** DefaultAction for a "Copy" button or toolbar button.
364: */
365:
366: private class CopyAction extends ActionFactory.DefaultAction {
367: public CopyAction() {
368: super ("Copy");
369: putValue(Action.NAME, "Copy");
370: putValue(Action.SMALL_ICON, getIcon("Copy16.gif"));
371: putValue(LARGE_ICON, getIcon("Copy24.gif"));
372: putValue(DefaultAction.ACTION_COMMAND_KEY, "copy");
373: putValue(DefaultAction.ACCELERATOR_KEY, KeyStroke
374: .getKeyStroke('C', Event.CTRL_MASK, false));
375: }
376: }
377:
378: /**
379: ** DefaultAction for a "Paste" button or toolbar button.
380: */
381:
382: private class PasteAction extends ActionFactory.DefaultAction {
383: public PasteAction() {
384: super ("Paste");
385: putValue(Action.NAME, "Paste");
386: putValue(Action.SMALL_ICON, getIcon("Paste16.gif"));
387: putValue(LARGE_ICON, getIcon("Paste24.gif"));
388: putValue(DefaultAction.ACTION_COMMAND_KEY, "paste");
389: putValue(DefaultAction.ACCELERATOR_KEY, KeyStroke
390: .getKeyStroke('V', Event.CTRL_MASK, false));
391: }
392: }
393:
394: /**
395: ** DefaultAction for a "Clear" button or toolbar button.
396: */
397:
398: private class ClearAction extends ActionFactory.DefaultAction {
399: public ClearAction() {
400: super ("Clear");
401: putValue(Action.NAME, "Clear");
402: putValue(DefaultAction.ACTION_COMMAND_KEY, "clear");
403: putValue(DefaultAction.ACCELERATOR_KEY, KeyStroke
404: .getKeyStroke(KeyEvent.VK_DELETE, 0));
405: }
406: }
407: }
|