diff --git a/utilities/nbproject/project.xml b/utilities/nbproject/project.xml
--- a/utilities/nbproject/project.xml
+++ b/utilities/nbproject/project.xml
@@ -50,6 +50,15 @@
org.netbeans.modules.utilities
+ org.netbeans.modules.projectapi
+
+
+
+ 1
+ 1.49
+
+
+
org.netbeans.modules.queries
diff --git a/utilities/src/org/netbeans/modules/utilities/CopyPathToClipboardAction.java b/utilities/src/org/netbeans/modules/utilities/CopyPathToClipboardAction.java
--- a/utilities/src/org/netbeans/modules/utilities/CopyPathToClipboardAction.java
+++ b/utilities/src/org/netbeans/modules/utilities/CopyPathToClipboardAction.java
@@ -53,6 +53,7 @@
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
+import org.netbeans.api.project.Project;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences;
@@ -65,15 +66,14 @@
import org.openide.util.Lookup;
import org.openide.util.NbBundle.Messages;
import org.openide.util.datatransfer.ExClipboard;
+import org.openide.windows.TopComponent;
/**
- * Copies the absolute path of selected {@link DataObject}s to the clipboard.
+ * Copies the absolute path of selected {@link DataObject}s or {@link Project}s to the clipboard.
* Action is shown in context menu of tab. It support DataShadows, so the path
* of items in the favorites window can be copied properly. It support items
* within JAR-files.
*
- * Note: It does not support selected Projects.
- *
* @author markiewb
*/
@ActionID(
@@ -90,18 +90,17 @@
"CTL_CopyPaths=Copy File Path(s)",
"CTL_CopyPath=Copy File Path"
})
-public final class CopyPathToClipboardAction implements ActionListener,
+public class CopyPathToClipboardAction implements ActionListener,
ClipboardOwner {
- private final List context;
-
- public CopyPathToClipboardAction(List context) {
- this.context = context;
- }
@Override
public void actionPerformed(ActionEvent ev) {
- Collection paths = getSelectedPaths();
+
+ Collection paths=new TreeSet();
+ paths.addAll(getSelectedPathsForDataObjects(getSelectedDataObjects()));
+ paths.addAll(getSelectedPathsForProjects(getSelectedProjects()));
+
StringBuilder sb = new StringBuilder();
int items = 0;
for (String path : paths) {
@@ -120,11 +119,27 @@
}
/**
+ * Can be overridden in test.
+ * @return selected {@link DataObject}s in current {@link TopComponent}
+ */
+ Collection extends DataObject> getSelectedDataObjects() {
+ return TopComponent.getRegistry().getActivated().getLookup().lookupAll(DataObject.class);
+ }
+
+ /**
+ * Can be overridden in test.
+ * @return selected {@link Project}s in current {@link TopComponent}
+ */
+ Collection extends Project> getSelectedProjects() {
+ return TopComponent.getRegistry().getActivated().getLookup().lookupAll(Project.class);
+ }
+
+ /**
* Get paths of selected DataObjects. Prevent duplicates, see #219014.
*
* @return Sorted collection of unique paths.
*/
- Collection getSelectedPaths() {
+ Collection getSelectedPathsForDataObjects(Collection extends DataObject> context) {
Set paths = new TreeSet();
for (DataObject dataObject : context) {
paths.add(getAbsolutePath(dataObject));
@@ -193,6 +208,36 @@
}
return dataObject.getPrimaryFile();
}
+
+ /**
+ * Get the project directory of the given project.
+ * @param project
+ * @return
+ */
+ private String getProjectDirectory(final Project project) {
+ try {
+ FileObject projectDirectory = project.getProjectDirectory();
+ return getNativePath(projectDirectory);
+ } catch (Exception e) {
+ //ignore the exception
+ return null;
+ }
+ }
+ /**
+ * Get paths of selected projects. Prevent duplicates, see #219014.
+ *
+ * @return Sorted collection of unique paths.
+ */
+ Collection getSelectedPathsForProjects(Collection extends Project> projects) {
+ Set paths = new TreeSet();
+ for (Project project : projects) {
+ String projectDir = getProjectDirectory(project);
+ if (null != projectDir) {
+ paths.add(projectDir);
+ }
+ }
+ return paths;
+ }
/**
* Sets the clipboard context in textual-format.
@@ -202,7 +247,7 @@
@Messages({
"# {0} - copied file path",
"CTL_Status_CopyToClipboardSingle=Copy to Clipboard: {0}",
- "# {0} - numer of copied paths",
+ "# {0} - number of copied paths",
"CTL_Status_CopyToClipboardMulti={0} paths were copied to clipboard"
})
private void setClipboardContents(String content, int items) {
diff --git a/utilities/test/unit/src/org/netbeans/modules/utilities/CopyPathToClipboardActionTest.java b/utilities/test/unit/src/org/netbeans/modules/utilities/CopyPathToClipboardActionTest.java
--- a/utilities/test/unit/src/org/netbeans/modules/utilities/CopyPathToClipboardActionTest.java
+++ b/utilities/test/unit/src/org/netbeans/modules/utilities/CopyPathToClipboardActionTest.java
@@ -45,18 +45,21 @@
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import org.junit.Test;
+import org.netbeans.api.project.Project;
import org.netbeans.junit.NbTestCase;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataFolder;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataShadow;
+import org.openide.util.Lookup;
/**
*
@@ -66,6 +69,7 @@
List dataObjects;
CopyPathToClipboardAction action;
+ List projects = new ArrayList();
public CopyPathToClipboardActionTest(String name) {
super(name);
@@ -73,6 +77,11 @@
@Override
public void setUp() throws IOException, PropertyVetoException {
+
+ // create projects
+ projects.add(createProject("projectDir1"));
+ projects.add(createProject("projectDir2"));
+
List l = new LinkedList();
clearWorkDir();
FileObject root = FileUtil.toFileObject(getWorkDir());
@@ -99,7 +108,16 @@
// /testDataShadows/testShadowFile -> test2/data.txt
l.add(shadowFile);
dataObjects = l;
- action = new CopyPathToClipboardAction(dataObjects);
+ action = new CopyPathToClipboardAction(){
+ @Override
+ Collection extends DataObject> getSelectedDataObjects() {
+ return dataObjects;
+ }
+ @Override
+ Collection extends Project> getSelectedProjects() {
+ return projects;
+ }
+ };
}
@Override
@@ -133,6 +151,13 @@
assertTrue(action.getAbsolutePath(dataObjects.get(3)).matches(
".*test2[/\\\\]data\\.txt$")); // Shadow File for data.txt
}
+
+ @Test
+ public void testGetSelectedPathsForProjects() {
+ List paths = new ArrayList(action.getSelectedPathsForProjects(projects));
+ assertTrue(paths.get(0).endsWith("projectDir1")); // path for project 1
+ assertTrue(paths.get(1).endsWith("projectDir2")); // path for project 2
+ }
/**
* Creates ZIP file archive.zip that contains three files, a.txt, b.txt and
@@ -168,8 +193,8 @@
return testShadowFile;
}
- public void testGetSelectedPaths() {
- Collection paths = action.getSelectedPaths();
+ public void testGetSelectedDataObjectPaths() {
+ Collection paths = action.getSelectedPathsForDataObjects(dataObjects);
assertEquals("Duplicate shadow file should be ignored",
3, paths.size());
String[] pathsArray = paths.toArray(new String[paths.size()]);
@@ -178,4 +203,29 @@
assertTrue(pathsArray[1].contains("archive.zip")); //test2/archive.zip?
assertTrue(pathsArray[2].contains("data.txt")); //test2/data.txt
}
+ /**
+ * Creates a mocked {@link Project} with the given dir.
+ * @param projectDir
+ * @return
+ */
+ private Project createProject(String projectDir) {
+ try {
+ FileObject root = FileUtil.toFileObject(getWorkDir());
+ final FileObject dir = root.createFolder(projectDir);
+ return new Project() {
+
+ @Override
+ public FileObject getProjectDirectory() {
+ return dir;
+ }
+
+ @Override
+ public Lookup getLookup() {
+ throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
+ }
+ };
+ } catch (IOException ex) {
+ throw new IllegalArgumentException("should not happen in test");
+ }
+ }
}