001: /*
002: * WbAction.java
003: *
004: * This file is part of SQL Workbench/J, http://www.sql-workbench.net
005: *
006: * Copyright 2002-2008, Thomas Kellerer
007: * No part of this code maybe reused without the permission of the author
008: *
009: * To contact the author please send an email to: support@sql-workbench.net
010: *
011: */
012: package workbench.gui.actions;
013:
014: import java.awt.EventQueue;
015: import java.awt.event.ActionEvent;
016: import java.awt.event.ActionListener;
017: import java.awt.event.InputEvent;
018: import java.awt.event.KeyEvent;
019: import javax.swing.AbstractAction;
020: import javax.swing.Action;
021: import javax.swing.ActionMap;
022: import javax.swing.ImageIcon;
023: import javax.swing.InputMap;
024: import javax.swing.JButton;
025: import javax.swing.JComponent;
026: import javax.swing.JMenu;
027: import javax.swing.JMenuItem;
028: import javax.swing.JToolBar;
029: import javax.swing.KeyStroke;
030: import javax.swing.UIManager;
031: import workbench.gui.components.WbMenuItem;
032: import workbench.gui.components.WbToolbarButton;
033: import workbench.resource.ResourceMgr;
034: import workbench.resource.Settings;
035: import workbench.resource.ShortcutManager;
036:
037: /**
038: * Base class for Actions in SQL Workbench/J
039: * the actual work should be implemented in executeAction()
040: * which is guaranteed to be called on the EDT.
041: *
042: * @author support@sql-workbench.net
043: */
044: public class WbAction extends AbstractAction {
045: private static final String MAIN_MENU_ITEM = "MainMenuItem";
046: private static final String MENU_SEPARATOR = "MenuSep";
047: private static final String TBAR_SEPARATOR = "TbarSep";
048: private static final String ALTERNATE_ACCELERATOR = "AltAcc";
049: private static final String DEFAULT_ACCELERATOR = "DefaultAcc";
050: private static final String MNEMONIC_INDEX = "MnemonicIndex";
051:
052: private String actionName;
053: // protected JMenuItem menuItem;
054: protected JButton toolbarButton;
055: private ActionListener delegate = null;
056: protected WbAction proxy;
057: private WbAction original;
058:
059: public WbAction() {
060: String c = this .getClass().getName();
061: this .actionName = "wb-" + c.substring(c.lastIndexOf('.') + 1);
062: this .putValue(ACTION_COMMAND_KEY, this .actionName);
063: }
064:
065: /**
066: * Creates a WbAction which dispatches its {@link #executeAction(ActionEvent)}
067: * event to the passed ActionListener, instead of executing it itself.
068: * This is intended for situations where an Action is needed, but not
069: * implemented with a subclass of WbAction, but with an ActionListener
070: * instead.
071: */
072: public WbAction(ActionListener l, String aName) {
073: this ();
074: this .delegate = l;
075: this .actionName = aName;
076: this .putValue(ACTION_COMMAND_KEY, this .actionName);
077: }
078:
079: public static boolean isAltPressed(ActionEvent e) {
080: boolean altPressed = ((e.getModifiers() & ActionEvent.ALT_MASK) == ActionEvent.ALT_MASK);
081: return altPressed;
082: }
083:
084: public static boolean isShiftPressed(ActionEvent e) {
085: boolean shiftPressed = ((e.getModifiers() & ActionEvent.SHIFT_MASK) == ActionEvent.SHIFT_MASK);
086: return shiftPressed;
087: }
088:
089: public static boolean isCtrlPressed(ActionEvent e) {
090: boolean ctrlPressed = ((e.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK);
091: return ctrlPressed;
092: }
093:
094: public boolean allowDuplicate() {
095: return false;
096: }
097:
098: public boolean hasShiftModifier() {
099: return false;
100: }
101:
102: public boolean hasCtrlModifier() {
103: return false;
104: }
105:
106: public void setTooltip(String aText) {
107: this .putValue(Action.SHORT_DESCRIPTION, aText);
108: }
109:
110: public String getTooltipText() {
111: return (String) getValue(Action.SHORT_DESCRIPTION);
112: }
113:
114: public String getTooltipTextWithKeys() {
115: return getTooltipText() + " (" + this .getAcceleratorDisplay()
116: + ")";
117: }
118:
119: public void clearAccelerator() {
120: this .putValue(Action.ACCELERATOR_KEY, null);
121: }
122:
123: public String getActionCommand() {
124: return (String) getValue(ACTION_COMMAND_KEY);
125: }
126:
127: protected void setActionName(String aName) {
128: this .actionName = aName;
129: }
130:
131: public String getMenuLabel() {
132: return (String) this .getValue(Action.NAME);
133: }
134:
135: /**
136: * Initialize the menu definition for this action. The passed key will
137: * be used to initialize the menu label and tooltip.
138: * This method will register the action with the ShortcutManager even though
139: * no shortcut is defined.
140: * @param aKey Translation key for ResourceMgr
141: * @see #setMenuTextByKey(String)
142: * @see workbench.resource.ShortcutManager#registerAction(WbAction)
143: */
144: public void initMenuDefinition(String aKey) {
145: this .initMenuDefinition(aKey, null);
146: }
147:
148: /**
149: * Initialize the menu definition for this action. The passed key will
150: * be used to initialize the menu label and tooltip.
151: * This method will register the action with the ShortcutManager.
152: * @param aKey Translation key for ResourceMgr
153: * @param defaultKey Default shortcut key, may be null
154: * @see #setMenuTextByKey(String)
155: * @see workbench.resource.ShortcutManager#registerAction(WbAction)
156: */
157: public void initMenuDefinition(String aKey, KeyStroke defaultKey) {
158: this .setMenuTextByKey(aKey);
159: this .setDefaultAccelerator(defaultKey);
160: initializeShortcut();
161: }
162:
163: protected void initializeShortcut() {
164: ShortcutManager mgr = Settings.getInstance()
165: .getShortcutManager();
166: mgr.registerAction(this );
167: KeyStroke key = mgr.getCustomizedKeyStroke(this );
168: this .setAccelerator(key);
169: }
170:
171: /**
172: * Initialize the menu definition for this action. The menu text and tooltip
173: * will be used directly without retrieving it from the ResourceMgr.
174: * This method will register the action with the ShortcutManager.
175: * @param aMenuText The text to be displayed in the menu item
176: * @param aTooltip The tooltip for the menu item
177: * @param defaultKey Default shortcut key, may be null
178: * @see workbench.resource.ShortcutManager#registerAction(WbAction)
179: */
180: public void initMenuDefinition(String aMenuText, String aTooltip,
181: KeyStroke defaultKey) {
182: this .setMenuText(aMenuText);
183: this .setTooltip(aTooltip);
184: this .setDefaultAccelerator(defaultKey);
185: initializeShortcut();
186: }
187:
188: /**
189: * Define the displayed menu text and tooltip. The passed key
190: * will be used to retrieve the real text from the ResourceManager.
191: * This will not register the Action with the ShortcutManager.
192: * @param aKey The key for the ResourceManager
193: * @see workbench.resource.ResourceMgr#getString(String)
194: * @see workbench.resource.ResourceMgr#getDescription(String)
195: * @see #setMenuText(String)
196: */
197: public void setMenuTextByKey(String aKey) {
198: this .setMenuText(ResourceMgr.getString(aKey));
199: this .setTooltip(ResourceMgr.getDescription(aKey, true));
200: }
201:
202: /**
203: * Define the displayed text for the associcated menu item
204: * If the text contains a & sign, the character after the
205: * & sign will be used as the Mnemonic for the menu item.
206: * Once the mnemonic is identified the passed text (after
207: * removing the & sign) will be set using
208: * putValue(Actin.NAME, Object)
209: *
210: * @param text the text for the menu item
211: * @see #setMenuTextByKey(String)
212: */
213: public void setMenuText(String text) {
214: if (text == null)
215: return;
216: int pos = text.indexOf('&');
217: if (pos > -1) {
218: char mnemonic = text.charAt(pos + 1);
219: text = text.substring(0, pos) + text.substring(pos + 1);
220: Integer keycode = new Integer((int) mnemonic);
221: Integer index = new Integer(pos);
222: this .putValue(Action.MNEMONIC_KEY, keycode);
223: this .putValue(WbAction.MNEMONIC_INDEX, index);
224: }
225: putValue(Action.NAME, text);
226: }
227:
228: public void setAlternateAccelerator(KeyStroke key) {
229: this .putValue(ALTERNATE_ACCELERATOR, key);
230: }
231:
232: public KeyStroke getAlternateAccelerator() {
233: return (KeyStroke) this .getValue(ALTERNATE_ACCELERATOR);
234: }
235:
236: public void setAccelerator(KeyStroke key) {
237: KeyStroke old = this .getAccelerator();
238: this .putValue(Action.ACCELERATOR_KEY, key);
239:
240: boolean isNew = false;
241: if (old != null && key != null) {
242: isNew = !key.equals(old);
243: } else {
244: isNew = (old != null || key != null);
245: }
246: }
247:
248: public KeyStroke getAccelerator() {
249: return (KeyStroke) this .getValue(Action.ACCELERATOR_KEY);
250: }
251:
252: public JButton getToolbarButton() {
253: return this .getToolbarButton(false);
254: }
255:
256: public JButton getToolbarButton(boolean createNew) {
257: JButton result;
258: if (this .toolbarButton == null || createNew) {
259: WbToolbarButton b = new WbToolbarButton();
260: b.setAction(this );
261: b.setMnemonic(0);
262: if (this .toolbarButton == null) {
263: this .toolbarButton = b;
264: }
265: result = b;
266: } else {
267: result = this .toolbarButton;
268: }
269:
270: return result;
271: }
272:
273: public void addToToolbar(JToolBar aToolbar) {
274: aToolbar.add(this .getToolbarButton());
275: }
276:
277: public void addToMenu(JMenu aMenu) {
278: aMenu.add(this .getMenuItem());
279: }
280:
281: public JMenuItem getMenuItem() {
282: JMenuItem item = new WbMenuItem();
283: item.setAction(this );
284: item.setAccelerator(this .getAccelerator());
285: Integer index = (Integer) this
286: .getValue(WbAction.MNEMONIC_INDEX);
287: if (index != null) {
288: try {
289: item.setDisplayedMnemonicIndex(index.intValue());
290: } catch (Exception e) {
291: }
292: }
293:
294: return item;
295: }
296:
297: public String getMenuItemName() {
298: return (String) this .getValue(WbAction.MAIN_MENU_ITEM);
299: }
300:
301: public void setMenuItemName(String aKey) {
302: this .putValue(WbAction.MAIN_MENU_ITEM, aKey);
303: }
304:
305: public boolean getCreateToolbarSeparator() {
306: Boolean flag = (Boolean) getValue(WbAction.TBAR_SEPARATOR);
307: if (flag == null)
308: return false;
309: return flag.booleanValue();
310: }
311:
312: public void setCreateToolbarSeparator(boolean flag) {
313: putValue(WbAction.TBAR_SEPARATOR, (flag ? Boolean.TRUE
314: : Boolean.FALSE));
315: }
316:
317: public boolean getCreateMenuSeparator() {
318: Boolean flag = (Boolean) getValue(WbAction.MENU_SEPARATOR);
319: if (flag == null)
320: return false;
321: return flag.booleanValue();
322: }
323:
324: public void setCreateMenuSeparator(boolean flag) {
325: this .putValue(WbAction.MENU_SEPARATOR, (flag ? Boolean.TRUE
326: : Boolean.FALSE));
327: }
328:
329: public String getActionName() {
330: return this .actionName;
331: }
332:
333: public void addToInputMap(JComponent c) {
334: addToInputMap(c.getInputMap(), c.getActionMap());
335: }
336:
337: public void addToInputMap(InputMap im, ActionMap am) {
338: if (this .getAccelerator() == null)
339: return;
340:
341: im.put(this .getAccelerator(), this .getActionName());
342: am.put(this .getActionName(), this );
343:
344: KeyStroke alternate = getAlternateAccelerator();
345: if (alternate != null) {
346: im.put(alternate, getActionName());
347: }
348:
349: int key = this .getAccelerator().getKeyCode();
350: int modifiers = this .getAccelerator().getModifiers();
351:
352: if (this .hasShiftModifier()) {
353: im.put(KeyStroke.getKeyStroke(key, modifiers
354: | InputEvent.SHIFT_MASK), this .getActionName());
355: }
356:
357: if (this .hasCtrlModifier()) {
358: im.put(KeyStroke.getKeyStroke(key, modifiers
359: | InputEvent.CTRL_MASK), this .getActionName());
360: }
361: }
362:
363: public void removeFromInputMap(InputMap im, ActionMap am) {
364: am.remove(this .getActionName());
365: im.remove(this .getAccelerator());
366: KeyStroke alternate = this .getAlternateAccelerator();
367: if (alternate != null) {
368: im.remove(alternate);
369: }
370:
371: int key = this .getAccelerator().getKeyCode();
372: int modifiers = this .getAccelerator().getModifiers();
373:
374: if (this .hasShiftModifier()) {
375: im.remove(KeyStroke.getKeyStroke(key, modifiers
376: | InputEvent.SHIFT_MASK));
377: }
378: if (this .hasCtrlModifier()) {
379: im.remove(KeyStroke.getKeyStroke(key, modifiers
380: | InputEvent.CTRL_MASK));
381: }
382: }
383:
384: public void setDefaultAccelerator(KeyStroke key) {
385: this .putValue(DEFAULT_ACCELERATOR, key);
386: }
387:
388: public KeyStroke getDefaultAccelerator() {
389: return (KeyStroke) this .getValue(DEFAULT_ACCELERATOR);
390: }
391:
392: public void setIcon(ImageIcon icon) {
393: this .putValue(Action.SMALL_ICON, icon);
394: }
395:
396: public void removeIcon() {
397: this .putValue(Action.SMALL_ICON, null);
398: }
399:
400: public void actionPerformed(final ActionEvent e) {
401: if (this .isEnabled()) {
402: EventQueue.invokeLater(new Runnable() {
403: public void run() {
404: if (original != null) {
405: original.executeAction(e);
406: } else {
407: executeAction(e);
408: }
409: }
410: });
411: }
412: }
413:
414: public void executeAction(ActionEvent e) {
415: if (this .isEnabled() && this .delegate != null) {
416: e.setSource(this );
417: this .delegate.actionPerformed(e);
418: }
419: }
420:
421: private String getAcceleratorDisplay() {
422: String acceleratorDelimiter = UIManager
423: .getString("MenuItem.acceleratorDelimiter");
424: if (acceleratorDelimiter == null) {
425: acceleratorDelimiter = "-";
426: }
427: KeyStroke key = getDefaultAccelerator();
428: int mod = key.getModifiers();
429: int keycode = key.getKeyCode();
430:
431: String display = KeyEvent.getKeyModifiersText(mod)
432: + acceleratorDelimiter + KeyEvent.getKeyText(keycode);
433: return display;
434: }
435:
436: public void setEnabled(boolean flag) {
437: super .setEnabled(flag);
438: if (this .proxy != null)
439: this .proxy.setEnabled(flag);
440: }
441:
442: public void setOriginal(WbAction org) {
443: if (this .original != null) {
444: this .original.setProxy(null);
445: if (org == null)
446: setEnabled(false);
447: }
448: this .original = null;
449: if (org != null) {
450: setEnabled(org.isEnabled());
451: this .original = org;
452: this .original.setProxy(this );
453: }
454: }
455:
456: protected void setProxy(WbAction p) {
457: this.proxy = p;
458: }
459: }
|