Issue 102081: make it possible to define single-file actions outside of any project context. diff --git a/projectapi/src/org/netbeans/spi/project/ActionProvider.java b/projectapi/src/org/netbeans/spi/project/ActionProvider.java --- a/projectapi/src/org/netbeans/spi/project/ActionProvider.java +++ b/projectapi/src/org/netbeans/spi/project/ActionProvider.java @@ -46,6 +46,12 @@ /** * Ability for a project to have various actions (e.g. Build) invoked on it. * Should be registered in a project's lookup and will be used by UI infrastructure. + *
+ * Implementations supporting single file commands (command constants ending with + * {@code _SINGLE}) can also be registered in default lookup. If a provider in project + * lookup does not enable the action for a given command on the selected file then + * the first implementation found in default lookup that is enabled will be used. + *
* @see org.netbeans.api.project.Project#getLookup * @seeActionUtils
* @see ProjectSensitiveActions.projectCommandAction(...)
diff --git a/projectui/src/org/netbeans/modules/project/ui/actions/FileCommandAction.java b/projectui/src/org/netbeans/modules/project/ui/actions/FileCommandAction.java
--- a/projectui/src/org/netbeans/modules/project/ui/actions/FileCommandAction.java
+++ b/projectui/src/org/netbeans/modules/project/ui/actions/FileCommandAction.java
@@ -41,12 +41,15 @@
package org.netbeans.modules.project.ui.actions;
+import java.util.Arrays;
+import java.util.Collection;
import javax.swing.Action;
import javax.swing.Icon;
import org.netbeans.api.project.Project;
import org.netbeans.spi.project.ActionProvider;
import org.openide.awt.Actions;
import org.openide.filesystems.FileObject;
+import org.openide.loaders.DataObject;
import org.openide.util.ImageUtilities;
import org.openide.util.Lookup;
@@ -73,8 +76,15 @@
Project[] projects = ActionsUtil.getProjectsFromLookup( context, getCommand() );
if ( projects.length != 1 ) {
- setEnabled( false ); // Zero or more than one projects found or command not supported
- presenterName = ActionsUtil.formatName( getNamePattern(), 0, "" );
+ if (projects.length == 0 && globalProvider(context) != null) {
+ setEnabled(true);
+ Collection extends DataObject> files = context.lookupAll(DataObject.class);
+ presenterName = ActionsUtil.formatName(getNamePattern(), files.size(),
+ files.isEmpty() ? "" : files.iterator().next().getPrimaryFile().getNameExt()); // NOI18N
+ } else {
+ setEnabled(false); // Zero or more than one projects found or command not supported
+ presenterName = ActionsUtil.formatName(getNamePattern(), 0, "");
+ }
}
else {
FileObject[] files = ActionsUtil.getFilesFromLookup( context, projects[0] );
@@ -93,8 +103,13 @@
if ( projects.length == 1 ) {
ActionProvider ap = projects[0].getLookup().lookup(ActionProvider.class);
ap.invokeAction( getCommand(), context );
+ return;
}
+ ActionProvider provider = globalProvider(context);
+ if (provider != null) {
+ provider.invokeAction(getCommand(), context);
+ }
}
@Override
@@ -102,4 +117,13 @@
return new FileCommandAction( getCommand(), getNamePattern(), (Icon)getValue( SMALL_ICON ), actionContext );
}
+ private ActionProvider globalProvider(Lookup context) {
+ for (ActionProvider ap : Lookup.getDefault().lookupAll(ActionProvider.class)) {
+ if (Arrays.asList(ap.getSupportedActions()).contains(getCommand()) && ap.isActionEnabled(getCommand(), context)) {
+ return ap;
+ }
+ }
+ return null;
+ }
+
}
\ No newline at end of file