diff --git a/editor/src/org/netbeans/modules/editor/impl/ActionsList.java b/editor/src/org/netbeans/modules/editor/impl/ActionsList.java --- a/editor/src/org/netbeans/modules/editor/impl/ActionsList.java +++ b/editor/src/org/netbeans/modules/editor/impl/ActionsList.java @@ -143,6 +143,7 @@ if (toAdd instanceof Action) { actions.add((Action) toAdd); + // XXX } else if (isSeparator(toAdd)) { if (prohibitSeparatorsAndActionNames) { if (LOG.isLoggable(Level.INFO)) { 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 @@ -59,6 +59,7 @@ import javax.swing.Action; import javax.swing.KeyStroke; import javax.swing.text.Keymap; +import org.openide.awt.AcceleratorBinding; import org.openide.awt.StatusDisplayer; import org.openide.cookies.InstanceCookie; import org.openide.filesystems.FileAttributeEvent; @@ -71,6 +72,7 @@ import org.openide.loaders.DataObject; import org.openide.loaders.DataObjectNotFoundException; import org.openide.loaders.DataShadow; +import org.openide.util.Lookup; import org.openide.util.Utilities; import org.openide.util.actions.SystemAction; import org.openide.util.lookup.ServiceProvider; @@ -334,18 +336,22 @@ } public KeyStroke[] getKeyStrokesForAction(Action a) { - FileObject definingFile = (FileObject) a.getValue("definingFile"); // cf. o.o.awt.Toolbar.setAccelerator - if (definingFile == null) { - LOG.log(Level.FINE, "no defining file known for {0}", id(a)); - return new KeyStroke[0]; + return new KeyStroke[0]; + } + + @ServiceProvider(service=AcceleratorBinding.class) + public static final class AcceleratorBindingImpl extends AcceleratorBinding { + public @Override KeyStroke keyStrokeForAction(Action a, FileObject definingFile) { + String id = idForFile(definingFile); + NbKeymap km = Lookup.getDefault().lookup(NbKeymap.class); + km.bindings(); + km.action2Id.put(a, id); + KeyStroke k = km.id2Stroke.get(id); + LOG.log(Level.FINE, "found keystroke {0} for {1} with ID {2}", new Object[] {k, id(a), id}); + return k; } - String id = idForFile(definingFile); - bindings(); - action2Id.put(a, id); - KeyStroke k = id2Stroke.get(id); - LOG.log(Level.FINE, "found keystroke {0} for {1} with ID {2}", new Object[] {k, id(a), id}); - return k != null ? new KeyStroke[] {k} : new KeyStroke[0]; } + /** * Traverses shadow files to origin. * Returns impl class name if that is obvious (common for SystemAction's); diff --git a/o.n.core/test/unit/src/org/netbeans/core/NbKeymapTest.java b/o.n.core/test/unit/src/org/netbeans/core/NbKeymapTest.java --- a/o.n.core/test/unit/src/org/netbeans/core/NbKeymapTest.java +++ b/o.n.core/test/unit/src/org/netbeans/core/NbKeymapTest.java @@ -96,7 +96,7 @@ Action a = km.getAction(stroke); assertNotNull("for " + stroke, a); assertEquals(actionName, a.getValue(Action.NAME)); - a.putValue("definingFile", presenterDefinition); + a.putValue("definingFile", presenterDefinition);//XXX assertEquals("for " + stroke + " from " + presenterDefinition.getPath(), Collections.singletonList(stroke), Arrays.asList(km.getKeyStrokesForAction(a))); } @@ -264,7 +264,7 @@ FileObject def = make("Menu/x.shadow"); def.setAttribute("originalFile", "Action/nonexistent.instance"); Action a = new DummyAction("x"); - a.putValue("definingFile", def); + a.putValue("definingFile", def);//XXX new NbKeymap().getKeyStrokesForAction(a); } diff --git a/openide.loaders/manifest.mf b/openide.loaders/manifest.mf --- a/openide.loaders/manifest.mf +++ b/openide.loaders/manifest.mf @@ -1,6 +1,6 @@ Manifest-Version: 1.0 OpenIDE-Module: org.openide.loaders -OpenIDE-Module-Specification-Version: 7.12 +OpenIDE-Module-Specification-Version: 7.13 OpenIDE-Module-Localizing-Bundle: org/openide/loaders/Bundle.properties OpenIDE-Module-Provides: org.netbeans.modules.templates.v1_0 AutoUpdate-Essential-Module: true diff --git a/openide.loaders/src/org/openide/awt/AcceleratorBinding.java b/openide.loaders/src/org/openide/awt/AcceleratorBinding.java new file mode 100644 --- /dev/null +++ b/openide.loaders/src/org/openide/awt/AcceleratorBinding.java @@ -0,0 +1,85 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2010 Sun Microsystems, Inc. + */ + +package org.openide.awt; + +import javax.swing.Action; +import javax.swing.KeyStroke; +import javax.swing.text.Keymap; +import org.openide.filesystems.FileObject; +import org.openide.util.Lookup; + +/** + * Permits accelerators to be set on actions based on global registrations. + * This class is only intended for use from NetBeans infrastructure code: + * that which either reads shortcut definitions (i.e. the global {@link Keymap}); + * or which loads actions into presenters (e.g. {@link Toolbar}). + * @since org.openide.loaders 7.13 + */ +public abstract class AcceleratorBinding { + + protected AcceleratorBinding() {} + + /** + * XXX + * @param a XXX + * @param definingFile XXX + * @return XXX + */ + public abstract KeyStroke keyStrokeForAction(Action a, FileObject definingFile); + + /** + * Associates an {@link Action#ACCELERATOR_KEY} with an action based on a declared shortcut. + * If an instance of {@link AcceleratorBinding} can be found in default lookup, + * it will be used to determine the binding. Otherwise nothing is done. + * @param a an action defined in layers + * @param definingFile instance file defining the action + */ + public static void setAccelerator(Action a, FileObject definingFile) { + AcceleratorBinding bnd = Lookup.getDefault().lookup(AcceleratorBinding.class); + if (bnd == null) { + return; + } + KeyStroke key = bnd.keyStrokeForAction(a, definingFile); + if (key != null) { + a.putValue(Action.ACCELERATOR_KEY, key); + } + } + +} 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 @@ -86,7 +86,10 @@ while (it.hasNext()) { Object obj = it.next(); if (obj instanceof Action) { - Toolbar.setAccelerator((Action) obj, cookiesToFiles.get(obj)); + FileObject file = cookiesToFiles.get(obj); + if (file != null) { + AcceleratorBinding.setAccelerator((Action) obj, file); + } } if (obj instanceof Presenter.Menu) { // does this still apply?? 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 @@ -58,18 +58,14 @@ import javax.swing.JComponent; import javax.swing.JSeparator; import javax.swing.JToolBar; -import javax.swing.KeyStroke; import javax.swing.UIManager; import javax.swing.plaf.metal.MetalLookAndFeel; -import javax.swing.text.Keymap; import org.netbeans.modules.openide.loaders.DataObjectAccessor; import org.openide.cookies.InstanceCookie; -import org.openide.filesystems.FileObject; import org.openide.loaders.DataFolder; import org.openide.loaders.DataObject; import org.openide.loaders.FolderInstance; import org.openide.util.ImageUtilities; -import org.openide.util.Lookup; import org.openide.util.Task; import org.openide.util.actions.Presenter; @@ -411,7 +407,7 @@ if (obj instanceof Presenter.Toolbar) { if (obj instanceof Action && file != null) { - setAccelerator((Action)obj, file.getPrimaryFile()); + AcceleratorBinding.setAccelerator((Action)obj, file.getPrimaryFile()); } obj = ((Presenter.Toolbar) obj).getToolbarPresenter(); } @@ -447,7 +443,7 @@ b.putClientProperty("file", file); org.openide.awt.Toolbar.this.add(b); if (file != null) { - setAccelerator(a, file.getPrimaryFile()); + AcceleratorBinding.setAccelerator(a, file.getPrimaryFile()); } continue; } @@ -481,25 +477,6 @@ } // 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 { - assert a.getValue("definingFile") == file : a.getClass() + " violated Action.putValue contract"; - 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]); - } - } - @Override public void setUI(javax.swing.plaf.ToolBarUI ui) { super.setUI(ui);