001: /*
002: * ShortcutManager.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.resource;
013:
014: import java.io.File;
015: import java.util.HashMap;
016: import java.util.Iterator;
017: import java.util.LinkedList;
018: import java.util.List;
019: import java.util.Map.Entry;
020:
021: import javax.swing.Action;
022: import javax.swing.KeyStroke;
023:
024: import workbench.gui.actions.WbAction;
025: import workbench.log.LogMgr;
026: import workbench.util.WbPersistence;
027:
028: /**
029: * @author support@sql-workbench.net
030: *
031: */
032: public class ShortcutManager {
033:
034: private String filename;
035:
036: // key to the map is the action's class name,
037: private HashMap<String, ShortcutDefinition> keyMap;
038:
039: private HashMap<String, String> actionNames;
040:
041: // we need the list of registered actions, in order to be able to
042: // display the label for the action for the customization dialog
043: private List<WbAction> allActions = new LinkedList<WbAction>();
044:
045: private HashMap<KeyStroke, WbAction> keyDebugMap;
046:
047: ShortcutManager(String aFilename) {
048: this .filename = aFilename;
049: try {
050: WbPersistence reader = new WbPersistence(this .filename);
051: this .keyMap = (HashMap) reader.readObject();
052: } catch (Exception e) {
053: this .keyMap = null;
054: }
055:
056: if (this .keyMap == null) {
057: this .keyMap = new HashMap<String, ShortcutDefinition>(30);
058: this .actionNames = new HashMap<String, String>(30);
059: } else {
060: this .actionNames = new HashMap<String, String>(this .keyMap
061: .size());
062: }
063: }
064:
065: public void removeShortcut(String clazz) {
066: this .assignKey(clazz, null);
067: }
068:
069: public void registerAction(WbAction anAction) {
070: String clazz = anAction.getClass().getName();
071: ShortcutDefinition def = this .getDefinition(clazz);
072: if (def == null) {
073: def = new ShortcutDefinition(clazz);
074: this .keyMap.put(clazz, def);
075: }
076:
077: if (!actionNames.containsKey(clazz)) {
078: String label = anAction.getMenuLabel();
079:
080: if (label == null)
081: label = anAction.getActionName();
082: if (label != null) {
083: this .actionNames.put(clazz, label);
084: }
085: }
086:
087: if (!def.hasDefault()) {
088: KeyStroke defaultkey = anAction.getDefaultAccelerator();
089: if (defaultkey != null) {
090: def.assignDefaultKey(defaultkey);
091: }
092: }
093:
094: if (LogMgr.isDebugEnabled()) {
095: KeyStroke key = anAction.getAccelerator();
096: if (key != null) {
097: if (this .keyDebugMap == null)
098: this .keyDebugMap = new HashMap<KeyStroke, WbAction>(
099: 100);
100: WbAction a = this .keyDebugMap.get(key);
101: if (a != null && !anAction.allowDuplicate()) {
102: LogMgr.logWarning("ShortcutManager.registerAction",
103: "Duplicate key assignment for keyStroke "
104: + key + " from " + clazz
105: + ", already registered for "
106: + a.getClass().getName());
107: } else {
108: this .keyDebugMap.put(key, anAction);
109: }
110: }
111: }
112:
113: // a list of all instances is needed when updating
114: // the shortcuts at runtime
115: this .allActions.add(anAction);
116: }
117:
118: public String getTooltip(String clazz) {
119: Iterator itr = allActions.iterator();
120: while (itr.hasNext()) {
121: WbAction action = (WbAction) itr.next();
122: String actionClass = action.getClass().getName();
123: if (actionClass.equals(clazz)) {
124: return action.getTooltipText();
125: }
126: }
127: return null;
128: }
129:
130: public WbAction getActionForClass(String clazz) {
131: for (WbAction a : allActions) {
132: if (a.getClass().getName().equals(clazz))
133: return a;
134: }
135: return null;
136: }
137:
138: /**
139: * Return the class name of the action to which the passed key is mapped.
140: * @param key
141: * @return the action's class name or null if the key is not mapped
142: */
143: public String getActionClassForKey(KeyStroke key) {
144: String clazz = null;
145: Iterator itr = this .keyMap.values().iterator();
146:
147: while (itr.hasNext()) {
148: ShortcutDefinition def = (ShortcutDefinition) itr.next();
149: if (def.isMappedTo(key)) {
150: clazz = def.getActionClass();
151: break;
152: }
153: }
154:
155: return clazz;
156: }
157:
158: public String getActionNameForKey(KeyStroke key) {
159: String clazz = this .getActionClassForKey(key);
160: String name = null;
161:
162: if (clazz != null) {
163: name = this .actionNames.get(clazz);
164: if (name == null)
165: name = clazz;
166: }
167: return name;
168: }
169:
170: public void resetToDefault(String actionClass) {
171: ShortcutDefinition def = this .getDefinition(actionClass);
172: if (def == null)
173: return;
174: def.resetToDefault();
175: }
176:
177: public void assignKey(String actionClass, KeyStroke key) {
178: ShortcutDefinition def = this .getDefinition(actionClass);
179: if (def == null)
180: return;
181: if (key == null) {
182: def.setShortcutRemoved(true);
183: } else {
184: def.assignKey(key);
185: }
186: }
187:
188: public void updateActions() {
189: for (WbAction action : allActions) {
190: String actionClass = action.getClass().getName();
191: ShortcutDefinition def = this .getDefinition(actionClass);
192: KeyStroke key = def.getActiveKeyStroke();
193: action.setAccelerator(key);
194: }
195: }
196:
197: public String getActionNameForClass(String className) {
198: return this .actionNames.get(className);
199: }
200:
201: /**
202: * Saves the current key assignments into an external file.
203: * Only mappings which are different from the default are saved.
204: * If a definition file exists, and the current map contains only
205: * default mappings, then the existing file is deleted.
206: */
207: public void saveSettings() {
208: // we only want to save those definitions where a different mapping is defined
209: HashMap<String, ShortcutDefinition> toSave = new HashMap<String, ShortcutDefinition>(
210: this .keyMap);
211: for (Entry<String, ShortcutDefinition> entry : keyMap
212: .entrySet()) {
213: ShortcutDefinition def = entry.getValue();
214: if (!def.isCustomized()) {
215: toSave.remove(entry.getKey());
216: }
217: }
218: // if no mapping at all is defined, then don't save it
219: if (toSave.size() > 0) {
220: WbPersistence writer = new WbPersistence(this .filename);
221: try {
222: writer.writeObject(toSave);
223: } catch (Throwable th) {
224: }
225: } else {
226: // but we need to make sure that, an existing definition
227: // is removed, otherwise we'll load it at the next startup
228: File f = new File(this .filename);
229: if (f.exists()) {
230: f.delete();
231: }
232: }
233: }
234:
235: public ShortcutDefinition[] getDefinitions() {
236: ShortcutDefinition[] list = new ShortcutDefinition[this .keyMap
237: .size()];
238: Iterator itr = this .keyMap.values().iterator();
239: int i = 0;
240: while (itr.hasNext()) {
241: list[i] = (ShortcutDefinition) itr.next();
242: i++;
243: }
244: return list;
245: }
246:
247: public KeyStroke getCustomizedKeyStroke(Action anAction) {
248: ShortcutDefinition def = this .getDefinition(anAction);
249: if (def == null)
250: return null;
251: return def.getActiveKeyStroke();
252: }
253:
254: public void setCustomizedKeyStroke(String aClassName, KeyStroke aKey) {
255: String oldclass = this .getActionClassForKey(aKey);
256: if (oldclass != null) {
257: ShortcutDefinition old = this .keyMap.get(oldclass);
258: if (old != null)
259: old.clearKeyStroke();
260: }
261: ShortcutDefinition def = this .keyMap.get(aClassName);
262: if (def == null)
263: return;
264: def.assignKey(aKey);
265: }
266:
267: private ShortcutDefinition getDefinition(Action anAction) {
268: return this .getDefinition(anAction.getClass().getName());
269: }
270:
271: private ShortcutDefinition getDefinition(String aClassname) {
272: ShortcutDefinition def = this.keyMap.get(aClassname);
273: return def;
274: }
275:
276: }
|