This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 219848
Collapse All | Expand All

(-)a/utilities/nbproject/project.xml (+9 lines)
Lines 50-55 Link Here
50
            <code-name-base>org.netbeans.modules.utilities</code-name-base>
50
            <code-name-base>org.netbeans.modules.utilities</code-name-base>
51
            <module-dependencies>
51
            <module-dependencies>
52
                <dependency>
52
                <dependency>
53
                    <code-name-base>org.netbeans.modules.projectapi</code-name-base>
54
                    <build-prerequisite/>
55
                    <compile-dependency/>
56
                    <run-dependency>
57
                        <release-version>1</release-version>
58
                        <specification-version>1.49</specification-version>
59
                    </run-dependency>
60
                </dependency>
61
                <dependency>
53
                    <code-name-base>org.netbeans.modules.queries</code-name-base>
62
                    <code-name-base>org.netbeans.modules.queries</code-name-base>
54
                    <build-prerequisite/>
63
                    <build-prerequisite/>
55
                    <compile-dependency/>
64
                    <compile-dependency/>
(-)a/utilities/src/org/netbeans/modules/utilities/CopyPathToClipboardAction.java (-12 / +57 lines)
Lines 53-58 Link Here
53
import java.util.List;
53
import java.util.List;
54
import java.util.Set;
54
import java.util.Set;
55
import java.util.TreeSet;
55
import java.util.TreeSet;
56
import org.netbeans.api.project.Project;
56
import org.openide.awt.ActionID;
57
import org.openide.awt.ActionID;
57
import org.openide.awt.ActionReference;
58
import org.openide.awt.ActionReference;
58
import org.openide.awt.ActionReferences;
59
import org.openide.awt.ActionReferences;
Lines 65-79 Link Here
65
import org.openide.util.Lookup;
66
import org.openide.util.Lookup;
66
import org.openide.util.NbBundle.Messages;
67
import org.openide.util.NbBundle.Messages;
67
import org.openide.util.datatransfer.ExClipboard;
68
import org.openide.util.datatransfer.ExClipboard;
69
import org.openide.windows.TopComponent;
68
70
69
/**
71
/**
70
 * Copies the absolute path of selected {@link DataObject}s to the clipboard.
72
 * Copies the absolute path of selected {@link DataObject}s or {@link Project}s to the clipboard.
71
 * Action is shown in context menu of tab. It support DataShadows, so the path
73
 * Action is shown in context menu of tab. It support DataShadows, so the path
72
 * of items in the favorites window can be copied properly. It support items
74
 * of items in the favorites window can be copied properly. It support items
73
 * within JAR-files.
75
 * within JAR-files.
74
 *
76
 *
75
 * Note: It does not support selected Projects.
76
 *
77
 * @author markiewb
77
 * @author markiewb
78
 */
78
 */
79
@ActionID(
79
@ActionID(
Lines 90-107 Link Here
90
    "CTL_CopyPaths=Copy File Path(s)",
90
    "CTL_CopyPaths=Copy File Path(s)",
91
    "CTL_CopyPath=Copy File Path"
91
    "CTL_CopyPath=Copy File Path"
92
})
92
})
93
public final class CopyPathToClipboardAction implements ActionListener,
93
public class CopyPathToClipboardAction implements ActionListener,
94
        ClipboardOwner {
94
        ClipboardOwner {
95
95
96
    private final List<DataObject> context;
97
98
    public CopyPathToClipboardAction(List<DataObject> context) {
99
        this.context = context;
100
    }
101
96
102
    @Override
97
    @Override
103
    public void actionPerformed(ActionEvent ev) {
98
    public void actionPerformed(ActionEvent ev) {
104
        Collection<String> paths = getSelectedPaths();
99
        
100
        Collection<String> paths=new TreeSet<String>();
101
        paths.addAll(getSelectedPathsForDataObjects(getSelectedDataObjects()));
102
        paths.addAll(getSelectedPathsForProjects(getSelectedProjects()));
103
105
        StringBuilder sb = new StringBuilder();
104
        StringBuilder sb = new StringBuilder();
106
        int items = 0;
105
        int items = 0;
107
        for (String path : paths) {
106
        for (String path : paths) {
Lines 120-130 Link Here
120
    }
119
    }
121
120
122
    /**
121
    /**
122
     * Can be overridden in test.
123
     * @return selected {@link DataObject}s in current {@link TopComponent}
124
     */
125
    Collection<? extends DataObject> getSelectedDataObjects() {
126
        return TopComponent.getRegistry().getActivated().getLookup().lookupAll(DataObject.class);
127
    }
128
129
    /**
130
     * Can be overridden in test.
131
     * @return selected {@link Project}s in current {@link TopComponent}
132
     */
133
    Collection<? extends Project> getSelectedProjects() {
134
        return TopComponent.getRegistry().getActivated().getLookup().lookupAll(Project.class);
135
    }
136
137
    /**
123
     * Get paths of selected DataObjects. Prevent duplicates, see #219014.
138
     * Get paths of selected DataObjects. Prevent duplicates, see #219014.
124
     *
139
     *
125
     * @return Sorted collection of unique paths.
140
     * @return Sorted collection of unique paths.
126
     */
141
     */
127
    Collection<String> getSelectedPaths() {
142
    Collection<String> getSelectedPathsForDataObjects(Collection<? extends DataObject> context) {
128
        Set<String> paths = new TreeSet<String>();
143
        Set<String> paths = new TreeSet<String>();
129
        for (DataObject dataObject : context) {
144
        for (DataObject dataObject : context) {
130
            paths.add(getAbsolutePath(dataObject));
145
            paths.add(getAbsolutePath(dataObject));
Lines 193-198 Link Here
193
        }
208
        }
194
        return dataObject.getPrimaryFile();
209
        return dataObject.getPrimaryFile();
195
    }
210
    }
211
    
212
    /**
213
     * Get the project directory of the given project.
214
     * @param project
215
     * @return 
216
     */
217
    private String getProjectDirectory(final Project project) {
218
        try {
219
            FileObject projectDirectory = project.getProjectDirectory();
220
            return getNativePath(projectDirectory);
221
        } catch (Exception e) {
222
            //ignore the exception
223
            return null;
224
        }
225
    }
226
    /**
227
     * Get paths of selected projects. Prevent duplicates, see #219014.
228
     *
229
     * @return Sorted collection of unique paths.
230
     */
231
    Collection<String> getSelectedPathsForProjects(Collection<? extends Project> projects) {
232
        Set<String> paths = new TreeSet<String>();
233
        for (Project project : projects) {
234
            String projectDir = getProjectDirectory(project);
235
            if (null != projectDir) {
236
                paths.add(projectDir);
237
            }
238
        }
239
        return paths;
240
    }
196
241
197
    /**
242
    /**
198
     * Sets the clipboard context in textual-format.
243
     * Sets the clipboard context in textual-format.
Lines 202-208 Link Here
202
    @Messages({
247
    @Messages({
203
        "# {0} - copied file path",
248
        "# {0} - copied file path",
204
        "CTL_Status_CopyToClipboardSingle=Copy to Clipboard: {0}",
249
        "CTL_Status_CopyToClipboardSingle=Copy to Clipboard: {0}",
205
        "# {0} - numer of copied paths",
250
        "# {0} - number of copied paths",
206
        "CTL_Status_CopyToClipboardMulti={0} paths were copied to clipboard"
251
        "CTL_Status_CopyToClipboardMulti={0} paths were copied to clipboard"
207
    })
252
    })
208
    private void setClipboardContents(String content, int items) {
253
    private void setClipboardContents(String content, int items) {
(-)a/utilities/test/unit/src/org/netbeans/modules/utilities/CopyPathToClipboardActionTest.java (-3 / +53 lines)
Lines 45-62 Link Here
45
import java.io.File;
45
import java.io.File;
46
import java.io.IOException;
46
import java.io.IOException;
47
import java.io.OutputStream;
47
import java.io.OutputStream;
48
import java.util.ArrayList;
48
import java.util.Collection;
49
import java.util.Collection;
49
import java.util.LinkedList;
50
import java.util.LinkedList;
50
import java.util.List;
51
import java.util.List;
51
import java.util.zip.ZipEntry;
52
import java.util.zip.ZipEntry;
52
import java.util.zip.ZipOutputStream;
53
import java.util.zip.ZipOutputStream;
53
import org.junit.Test;
54
import org.junit.Test;
55
import org.netbeans.api.project.Project;
54
import org.netbeans.junit.NbTestCase;
56
import org.netbeans.junit.NbTestCase;
55
import org.openide.filesystems.FileObject;
57
import org.openide.filesystems.FileObject;
56
import org.openide.filesystems.FileUtil;
58
import org.openide.filesystems.FileUtil;
57
import org.openide.loaders.DataFolder;
59
import org.openide.loaders.DataFolder;
58
import org.openide.loaders.DataObject;
60
import org.openide.loaders.DataObject;
59
import org.openide.loaders.DataShadow;
61
import org.openide.loaders.DataShadow;
62
import org.openide.util.Lookup;
60
63
61
/**
64
/**
62
 *
65
 *
Lines 66-71 Link Here
66
69
67
    List<DataObject> dataObjects;
70
    List<DataObject> dataObjects;
68
    CopyPathToClipboardAction action;
71
    CopyPathToClipboardAction action;
72
    List<Project> projects = new ArrayList<Project>();
69
73
70
    public CopyPathToClipboardActionTest(String name) {
74
    public CopyPathToClipboardActionTest(String name) {
71
        super(name);
75
        super(name);
Lines 73-78 Link Here
73
77
74
    @Override
78
    @Override
75
    public void setUp() throws IOException, PropertyVetoException {
79
    public void setUp() throws IOException, PropertyVetoException {
80
81
        // create projects
82
        projects.add(createProject("projectDir1"));
83
        projects.add(createProject("projectDir2"));
84
        
76
        List l = new LinkedList<DataObject>();
85
        List l = new LinkedList<DataObject>();
77
        clearWorkDir();
86
        clearWorkDir();
78
        FileObject root = FileUtil.toFileObject(getWorkDir());
87
        FileObject root = FileUtil.toFileObject(getWorkDir());
Lines 99-105 Link Here
99
        // /testDataShadows/testShadowFile -> test2/data.txt
108
        // /testDataShadows/testShadowFile -> test2/data.txt
100
        l.add(shadowFile);
109
        l.add(shadowFile);
101
        dataObjects = l;
110
        dataObjects = l;
102
        action = new CopyPathToClipboardAction(dataObjects);
111
        action = new CopyPathToClipboardAction(){
112
            @Override
113
            Collection<? extends DataObject> getSelectedDataObjects() {
114
                return dataObjects;
115
            }
116
            @Override
117
            Collection<? extends Project> getSelectedProjects() {
118
                return projects;
119
            }
120
        };
103
    }
121
    }
104
122
105
    @Override
123
    @Override
Lines 133-138 Link Here
133
        assertTrue(action.getAbsolutePath(dataObjects.get(3)).matches(
151
        assertTrue(action.getAbsolutePath(dataObjects.get(3)).matches(
134
                ".*test2[/\\\\]data\\.txt$")); // Shadow File for data.txt
152
                ".*test2[/\\\\]data\\.txt$")); // Shadow File for data.txt
135
    }
153
    }
154
    
155
    @Test
156
    public void testGetSelectedPathsForProjects() {
157
        List<String> paths = new ArrayList<String>(action.getSelectedPathsForProjects(projects));
158
        assertTrue(paths.get(0).endsWith("projectDir1")); // path for project 1
159
        assertTrue(paths.get(1).endsWith("projectDir2")); // path for project 2
160
    }
136
161
137
    /**
162
    /**
138
     * Creates ZIP file archive.zip that contains three files, a.txt, b.txt and
163
     * Creates ZIP file archive.zip that contains three files, a.txt, b.txt and
Lines 168-175 Link Here
168
        return testShadowFile;
193
        return testShadowFile;
169
    }
194
    }
170
195
171
    public void testGetSelectedPaths() {
196
    public void testGetSelectedDataObjectPaths() {
172
        Collection<String> paths = action.getSelectedPaths();
197
        Collection<String> paths = action.getSelectedPathsForDataObjects(dataObjects);
173
        assertEquals("Duplicate shadow file should be ignored",
198
        assertEquals("Duplicate shadow file should be ignored",
174
                3, paths.size());
199
                3, paths.size());
175
        String[] pathsArray = paths.toArray(new String[paths.size()]);
200
        String[] pathsArray = paths.toArray(new String[paths.size()]);
Lines 178-181 Link Here
178
        assertTrue(pathsArray[1].contains("archive.zip")); //test2/archive.zip?
203
        assertTrue(pathsArray[1].contains("archive.zip")); //test2/archive.zip?
179
        assertTrue(pathsArray[2].contains("data.txt")); //test2/data.txt
204
        assertTrue(pathsArray[2].contains("data.txt")); //test2/data.txt
180
    }
205
    }
206
    /**
207
     * Creates a mocked {@link Project} with the given dir.
208
     * @param projectDir
209
     * @return 
210
     */
211
    private Project createProject(String projectDir) {
212
        try {
213
            FileObject root = FileUtil.toFileObject(getWorkDir());
214
            final FileObject dir = root.createFolder(projectDir);
215
            return new Project() {
216
217
                @Override
218
                public FileObject getProjectDirectory() {
219
                    return dir;
220
                }
221
222
                @Override
223
                public Lookup getLookup() {
224
                    throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
225
                }
226
            };
227
        } catch (IOException ex) {
228
            throw new IllegalArgumentException("should not happen in test");
229
        }
230
    }
181
}
231
}

Return to bug 219848