diff --git a/o.n.core/src/org/netbeans/core/NbKeymap.java b/o.n.core/src/org/netbeans/core/NbKeymap.java --- a/o.n.core/src/org/netbeans/core/NbKeymap.java +++ b/o.n.core/src/org/netbeans/core/NbKeymap.java @@ -43,24 +43,26 @@ import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; +import java.io.IOException; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Observable; -import java.util.Set; +import java.util.TreeMap; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.KeyStroke; import javax.swing.text.Keymap; import org.openide.awt.StatusDisplayer; -import org.openide.util.Mutex; +import org.openide.cookies.InstanceCookie; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.Repository; +import org.openide.loaders.DataObject; +import org.openide.util.Exceptions; +import org.openide.util.Utilities; import org.openide.util.lookup.ServiceProvider; /** Implementation of standard key - action mappings. @@ -74,7 +76,7 @@ /** Parent keymap */ Keymap parent; /** Hashtable holding KeyStroke > Action mappings */ - Map bindings; + //Map bindings; /** Default action */ Action defaultAction; /** hash table to map (Action -> ArrayList of KeyStrokes) */ @@ -126,7 +128,7 @@ NbKeymap(final String name, final Keymap parent) { this.name = name; this.parent = parent; - bindings = new HashMap(); +// bindings = new HashMap(); } public Action getDefaultAction() { @@ -153,7 +155,8 @@ Keymap activ = this; for (int i=0; i> localActions = actions; - if (localActions == null) { - localActions = buildReverseMapping (); - } - - List strokes = localActions.get (a); - if (strokes != null) { - return strokes.toArray(new KeyStroke[strokes.size ()]); - } else { +// Map> localActions = actions; +// if (localActions == null) { +// localActions = buildReverseMapping (); +// } +// +// List strokes = localActions.get (a); +// if (strokes != null) { +// return strokes.toArray(new KeyStroke[strokes.size ()]); +// } else { +// return new KeyStroke[0]; +// } + FileObject definingFile = (FileObject) a.getValue("definingFile"); // cf. o.o.awt.Toolbar.setAccelerator + if (definingFile == null) { + System.err.println("XXX no defining file known for " + a); return new KeyStroke[0]; } + synchronized (this) { + if (id2Stroke == null) { + id2Stroke = new TreeMap(); + FileObject shortcuts = Repository.getDefault().getDefaultFileSystem().findResource("Shortcuts"); + for (FileObject f : shortcuts.getChildren()) { + id2Stroke.put(idForFile(f), f.getName()); + } + shortcuts = Repository.getDefault().getDefaultFileSystem().findResource("Keymaps/NetBeans"); + for (FileObject f : shortcuts.getChildren()) { + id2Stroke.put(idForFile(f), f.getName()); + } + { // XXX for debugging + for (Map.Entry entry : id2Stroke.entrySet()) { + System.err.println(entry.getValue() + " => " + entry.getKey()); + } + } + } + } + String id = idForFile(definingFile); + String k = id2Stroke.get(id); + System.err.println("XXX found keystroke " + k + " for " + a + " with ID " + id); + // XXX return all available keystrokes, or make Toolbar.setAccelerator pick the most common, e.g. C-V over PASTE + return k != null ? new KeyStroke[] {Utilities.stringToKey(k)} : new KeyStroke[0]; + } + private Map id2Stroke; + /** + * Traverses shadow files to origin. + * Returns impl class name if that is obvious (common for SystemAction's); + * else just returns file path (usual for more modern registrations). + */ + private static String idForFile(FileObject f) { + if (f.hasExt("shadow")) { + String path = (String) f.getAttribute("originalFile"); + f = Repository.getDefault().getDefaultFileSystem().findResource(path); + } + // Cannot actually load instanceCreate methodvalue=... attribute; just want to see if it is there. + if (f.hasExt("instance") && !Collections.list(f.getAttributes()).contains("instanceCreate")) { + String clazz = (String) f.getAttribute("instanceClass"); + if (clazz != null) { + return clazz; + } else { + return f.getName().replace('-', '.'); + } + } + return f.getPath(); } - private Map> buildReverseMapping () { - Map> localActions = actions = new HashMap> (); - - synchronized (this) { - for (Map.Entry curEntry: bindings.entrySet()) { - Action curAction = curEntry.getValue(); - KeyStroke curKey = curEntry.getKey(); - - List keysForAction = localActions.get (curAction); - if (keysForAction == null) { - keysForAction = Collections.synchronizedList (new ArrayList (1)); - localActions.put (curAction, keysForAction); - } - keysForAction.add (curKey); + private Action find(KeyStroke key) { + FileObject shortcuts = Repository.getDefault().getDefaultFileSystem().findResource("Keymaps/NetBeans"); + String nm = Utilities.keyToString(key); + FileObject def = shortcuts.getFileObject(nm + ".shadow"); + if (def == null) { + def = shortcuts.getFileObject(nm + ".instance"); + } + if (def == null) { + shortcuts = Repository.getDefault().getDefaultFileSystem().findResource("Shortcuts"); + def = shortcuts.getFileObject(nm + ".shadow"); + if (def == null) { + def = shortcuts.getFileObject(nm + ".instance"); + } + if (def == null) { + return null; } } - - return localActions; + try { + DataObject d = DataObject.find(def); + InstanceCookie ic = d.getLookup().lookup(InstanceCookie.class); + if (ic == null) { + return null; + } + return (Action) ic.instanceCreate(); + } catch (ClassNotFoundException x) { + Exceptions.printStackTrace(x); + } catch (IOException x) { + Exceptions.printStackTrace(x); + } + return null; } +// private Map> buildReverseMapping () { +// Map> localActions = actions = new HashMap> (); +// +// synchronized (this) { +// for (Map.Entry curEntry: bindings.entrySet()) { +// Action curAction = curEntry.getValue(); +// KeyStroke curKey = curEntry.getKey(); +// +// List keysForAction = localActions.get (curAction); +// if (keysForAction == null) { +// keysForAction = Collections.synchronizedList (new ArrayList (1)); +// localActions.put (curAction, keysForAction); +// } +// keysForAction.add (curKey); +// } +// } +// +// return localActions; +// } + public synchronized boolean isLocallyDefined(KeyStroke key) { - return bindings.containsKey(key); +// return bindings.containsKey(key); + assert false; + return false; } - /** Updates action accelerator. */ - private void updateActionAccelerator(final Action a) { - if(a == null) { - return; - } - - Mutex.EVENT.writeAccess(new Runnable() { - public void run() { - KeyStroke[] keystrokes = getKeyStrokesForAction(a); - Arrays.sort (keystrokes, NbKeymap.this); - a.putValue(Action.ACCELERATOR_KEY, keystrokes.length > 0 ? keystrokes[0] : null); - } - }); - } +// /** Updates action accelerator. */ +// private void updateActionAccelerator(final Action a) { +// if(a == null) { +// return; +// } +// +// Mutex.EVENT.writeAccess(new Runnable() { +// public void run() { +// KeyStroke[] keystrokes = getKeyStrokesForAction(a); +// Arrays.sort (keystrokes, NbKeymap.this); +// a.putValue(Action.ACCELERATOR_KEY, keystrokes.length > 0 ? keystrokes[0] : null); +// } +// }); +// } public int compare(KeyStroke k1, KeyStroke k2) { //#47024 and 32733 - "Find" should not be shown as an accelerator, @@ -295,65 +387,68 @@ public void addActionForKeyStroke(KeyStroke key, Action a) { - // Update reverse binding for old action too (#30455): - Action old; - synchronized (this) { - old = bindings.put(key, a); - actions = null; - } - - updateActionAccelerator(a); - updateActionAccelerator(old); - setChanged(); - notifyObservers(); +// // Update reverse binding for old action too (#30455): +// Action old; +// synchronized (this) { +// old = bindings.put(key, a); +// actions = null; +// } +// +// updateActionAccelerator(a); +// updateActionAccelerator(old); +// setChanged(); +// notifyObservers(); + assert false; } - void addActionForKeyStrokeMap(Map map) { - Set actionsSet = new HashSet(); - synchronized (this) { - for (Entry entry: map.entrySet ()) { - KeyStroke key = entry.getKey(); - Action value = entry.getValue(); - // Add both old and new action: - actionsSet.add(value); - actionsSet.add(bindings.put(key, value)); - } - actions = null; - } - - for(Action a: actionsSet) { - updateActionAccelerator(a); - } - - setChanged(); - notifyObservers(); - } +// void addActionForKeyStrokeMap(Map map) { +// Set actionsSet = new HashSet(); +// synchronized (this) { +// for (Entry entry: map.entrySet ()) { +// KeyStroke key = entry.getKey(); +// Action value = entry.getValue(); +// // Add both old and new action: +// actionsSet.add(value); +// actionsSet.add(bindings.put(key, value)); +// } +// actions = null; +// } +// +// for(Action a: actionsSet) { +// updateActionAccelerator(a); +// } +// +// setChanged(); +// notifyObservers(); +// } public void removeKeyStrokeBinding(KeyStroke key) { - Action a; - synchronized (this) { - a = bindings.remove(key); - actions = null; - } - updateActionAccelerator(a); - setChanged(); - notifyObservers(); +// Action a; +// synchronized (this) { +// a = bindings.remove(key); +// actions = null; +// } +// updateActionAccelerator(a); +// setChanged(); +// notifyObservers(); + assert false; } public void removeBindings() { - Set actionsSet; - synchronized (this) { - actionsSet = new HashSet(bindings.values()); - bindings.clear(); - actions = null; - } - - for(Action a: actionsSet) { - updateActionAccelerator(a); - } - - setChanged(); - notifyObservers(); +// Set actionsSet; +// synchronized (this) { +// actionsSet = new HashSet(bindings.values()); +// bindings.clear(); +// actions = null; +// } +// +// for(Action a: actionsSet) { +// updateActionAccelerator(a); +// } +// +// setChanged(); +// notifyObservers(); + assert false; } public Keymap getResolveParent() { @@ -366,12 +461,12 @@ notifyObservers(); } - /** Returns string representation - can be looong. - */ - @Override - public String toString() { - return "Keymap[" + name + "]" + bindings; // NOI18N - } +// /** Returns string representation - can be looong. +// */ +// @Override +// public String toString() { +// return "Keymap[" + name + "]" + bindings; // NOI18N +// } public static class SubKeymap implements Keymap { Object hold; diff --git a/o.n.core/src/org/netbeans/core/ShortcutsFolder.java b/o.n.core/src/org/netbeans/core/ShortcutsFolder.java --- a/o.n.core/src/org/netbeans/core/ShortcutsFolder.java +++ b/o.n.core/src/org/netbeans/core/ShortcutsFolder.java @@ -86,13 +86,13 @@ static void initShortcuts () { - StartLog.logStart("initShortcuts"); - try { - if (shortcutsFolder != null) return; - shortcutsFolder = new ShortcutsFolder (); - } finally { - StartLog.logEnd("initShortcuts"); - } +// StartLog.logStart("initShortcuts"); +// try { +// if (shortcutsFolder != null) return; +// shortcutsFolder = new ShortcutsFolder (); +// } finally { +// StartLog.logEnd("initShortcuts"); +// } } private ShortcutsFolder () { diff --git a/openide.awt/src/org/openide/awt/AlwaysEnabledAction.java b/openide.awt/src/org/openide/awt/AlwaysEnabledAction.java --- a/openide.awt/src/org/openide/awt/AlwaysEnabledAction.java +++ b/openide.awt/src/org/openide/awt/AlwaysEnabledAction.java @@ -97,8 +97,9 @@ return ret; } } - - return extractCommonAttribute(map, this, name); + Object o = extractCommonAttribute(map, this, name); + // cf. #137709 JG18: + return o != null ? o : super.getValue(name); } static final Object extractCommonAttribute(Map fo, Action action, String name) { @@ -136,14 +137,6 @@ if ("noIconInMenu".equals(name)) { // NOI18N return fo == null ? null : fo.get("noIconInMenu"); // NOI18N } - if (Action.ACCELERATOR_KEY.equals(name)) { - Keymap map = Lookup.getDefault().lookup(Keymap.class); - if (map != null) { - KeyStroke[] arr = map.getKeyStrokesForAction(action); - return arr.length > 0 ? arr[0] : null; - } - } - return null; } diff --git a/openide.loaders/src/org/openide/awt/DynaMenuModel.java b/openide.loaders/src/org/openide/awt/DynaMenuModel.java --- a/openide.loaders/src/org/openide/awt/DynaMenuModel.java +++ b/openide.loaders/src/org/openide/awt/DynaMenuModel.java @@ -60,6 +60,7 @@ import org.openide.util.ImageUtilities; import org.openide.util.Utilities; import org.openide.awt.DynamicMenuContent; +import org.openide.filesystems.FileObject; import org.openide.util.actions.Presenter; /** @@ -78,7 +79,7 @@ actionToMenuMap = new HashMap(); } - public void loadSubmenu(List cInstances, JMenu m) { + public void loadSubmenu(List cInstances, JMenu m, Map cookiesToFiles) { // clear first - refresh the menu's content boolean addSeparator = false; Icon curIcon = null; @@ -87,6 +88,9 @@ actionToMenuMap.clear(); while (it.hasNext()) { Object obj = it.next(); + if (obj instanceof Action) { + Toolbar.setAccelerator((Action) obj, cookiesToFiles.get(obj)); + } if (obj instanceof Presenter.Menu) { // does this still apply?? obj = ((Presenter.Menu)obj).getMenuPresenter(); diff --git a/openide.loaders/src/org/openide/awt/MenuBar.java b/openide.loaders/src/org/openide/awt/MenuBar.java --- a/openide.loaders/src/org/openide/awt/MenuBar.java +++ b/openide.loaders/src/org/openide/awt/MenuBar.java @@ -50,8 +50,10 @@ import java.io.ObjectOutput; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; +import java.util.Map; import javax.swing.Action; import javax.swing.BorderFactory; import javax.swing.ImageIcon; @@ -614,6 +616,14 @@ super.waitFinished(); } + private Map cookiesToFiles = new HashMap(); + + @Override + protected Object instanceForCookie(DataObject obj, InstanceCookie cookie) throws IOException, ClassNotFoundException { + Object result = super.instanceForCookie(obj, cookie); + cookiesToFiles.put(result, obj.getPrimaryFile()); + return result; + } /** * Accepts only cookies that can provide Menu. @@ -671,7 +681,7 @@ m.add(item); } - m.dynaModel.loadSubmenu(cInstances, m); + m.dynaModel.loadSubmenu(cInstances, m, cookiesToFiles); return m; } diff --git a/openide.loaders/src/org/openide/awt/Toolbar.java b/openide.loaders/src/org/openide/awt/Toolbar.java --- a/openide.loaders/src/org/openide/awt/Toolbar.java +++ b/openide.loaders/src/org/openide/awt/Toolbar.java @@ -65,7 +65,9 @@ import javax.swing.plaf.synth.SynthLookAndFeel; import javax.swing.plaf.synth.SynthStyle; import javax.swing.plaf.synth.SynthStyleFactory; +import javax.swing.text.Keymap; import org.openide.cookies.InstanceCookie; +import org.openide.filesystems.FileObject; import org.openide.loaders.*; import org.openide.nodes.Node; import org.openide.util.*; @@ -994,7 +996,7 @@ return Toolbar.this.getClass(); } - private Map cookiesToObjects = new HashMap(); + private Map cookiesToObjects = new HashMap(); @Override protected Object instanceForCookie (DataObject obj, InstanceCookie cookie) @@ -1053,7 +1055,11 @@ for (int i = 0; i < cookies.length; i++) { try { java.lang.Object obj = cookies[i].instanceCreate(); - java.lang.Object file = cookiesToObjects.get(obj); + DataObject file = cookiesToObjects.get(obj); + + if (obj instanceof Action) { + setAccelerator((Action) obj, file.getPrimaryFile()); + } if (obj instanceof org.openide.util.actions.Presenter.Toolbar) { obj = ((org.openide.util.actions.Presenter.Toolbar) obj).getToolbarPresenter(); @@ -1125,6 +1131,24 @@ } } // end of inner class Folder + + static void setAccelerator(Action a, FileObject file) { + if (file == null) { + return; + } + a.putValue("definingFile", file); // cf. o.n.core.NbKeymap.getKeyStrokesForAction + KeyStroke[] keys; + try { + Keymap keymap = Lookup.getDefault().lookup(Keymap.class); + keys = keymap != null ? keymap.getKeyStrokesForAction(a) : new KeyStroke[0]; + assert keys != null : keymap; + } finally { + a.putValue("definingFile", null); + } + if (keys.length > 0) { + a.putValue(Action.ACCELERATOR_KEY, keys[0]); + } + } /** Bumps for floatable toolbar */ private final class ToolbarBump extends JPanel {