Skip to content

Commit 0390b02

Browse files
committed
Add open containing folder and open in tab actions.
extracted AbstractOpenInAction as common superclass for - (old) OpenInSystemAction - (new) OpenParentInSystemAction - (new) Open(Parent)InTabAction
1 parent 6befb30 commit 0390b02

File tree

4 files changed

+263
-129
lines changed

4 files changed

+263
-129
lines changed

platform/core.ui/nbproject/project.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
# under the License.
1717

1818
javac.compilerargs=-Xlint:unchecked
19-
javac.source=1.8
19+
javac.release=17
2020
javadoc.arch=${basedir}/arch.xml
2121

2222
test.config.stableBTD.includes=**/*Test.class
Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.netbeans.core.ui.sysopen;
20+
21+
import java.awt.Desktop;
22+
import java.awt.event.ActionEvent;
23+
import java.io.File;
24+
import java.io.IOException;
25+
import java.net.MalformedURLException;
26+
import java.util.HashSet;
27+
import java.util.Set;
28+
import java.util.logging.Level;
29+
import java.util.logging.Logger;
30+
import javax.swing.AbstractAction;
31+
import javax.swing.Action;
32+
import org.openide.awt.ActionID;
33+
import org.openide.awt.ActionReference;
34+
import org.openide.awt.ActionReferences;
35+
import org.openide.awt.ActionRegistration;
36+
import org.openide.awt.DynamicMenuContent;
37+
import org.openide.filesystems.FileObject;
38+
import org.openide.filesystems.FileUtil;
39+
import org.openide.loaders.DataObject;
40+
import org.openide.loaders.DataObjectNotFoundException;
41+
import org.openide.nodes.Node;
42+
import org.openide.nodes.NodeOperation;
43+
import org.openide.util.ContextAwareAction;
44+
import org.openide.util.Exceptions;
45+
import org.openide.util.Lookup;
46+
import org.openide.util.LookupListener;
47+
import org.openide.util.NbBundle;
48+
import org.openide.util.RequestProcessor;
49+
import org.openide.util.Utilities;
50+
import org.openide.util.WeakListeners;
51+
52+
/**
53+
* Open the selected file(s) or their parents with the system default tool or
54+
* as explorer tab.
55+
*/
56+
public abstract sealed class AbstractOpenInAction extends AbstractAction implements ContextAwareAction {
57+
58+
private static final RequestProcessor RP = new RequestProcessor(AbstractOpenInAction.class);
59+
60+
protected final Set<File> files;
61+
62+
protected AbstractOpenInAction(String name, Lookup context) {
63+
super(name);
64+
files = new HashSet<>();
65+
putValue(DynamicMenuContent.HIDE_WHEN_DISABLED, true);
66+
Lookup.Result<DataObject> result = context.lookupResult(DataObject.class);
67+
result.addLookupListener(WeakListeners.create(LookupListener.class, e -> updateFileSet(result), result));
68+
updateFileSet(result);
69+
}
70+
71+
private void updateFileSet(Lookup.Result<DataObject> result) {
72+
files.clear();
73+
for (DataObject d : result.allInstances()) {
74+
File f = FileUtil.toFile(d.getPrimaryFile());
75+
if (f != null && !isIgnoredFile(f)) {
76+
files.add(f);
77+
}
78+
}
79+
}
80+
81+
private boolean isIgnoredFile(File f) {
82+
if (Utilities.isWindows() && f.isFile() && !f.getName().contains(".")) {
83+
/* #144575 */
84+
return true;
85+
}
86+
return f.getName().endsWith(".shadow");
87+
}
88+
89+
protected void browse(FileObject fo) {
90+
if (fo != null) {
91+
try {
92+
Node node = DataObject.find(fo).getNodeDelegate();
93+
if (node != null) {
94+
NodeOperation.getDefault().explore(node);
95+
}
96+
} catch (DataObjectNotFoundException ex) {
97+
Exceptions.printStackTrace(ex);
98+
}
99+
}
100+
}
101+
102+
protected void openInSystem(Set<File> files) {
103+
RP.post(() -> {
104+
for (File f : files) {
105+
try {
106+
Desktop.getDesktop().open(f);
107+
} catch (IOException x) {
108+
Logger.getLogger(getClass().getName()).log(Level.INFO, null, x);
109+
}
110+
}
111+
});
112+
}
113+
114+
protected boolean canOpenInSystem() {
115+
return Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.OPEN);
116+
}
117+
118+
@ActionID(id = "org.netbeans.core.ui.sysopen.OpenInSystemAction", category = "Edit")
119+
@ActionRegistration(displayName = "#CTL_OpenInSystemAction", lazy = false)
120+
@ActionReferences ({
121+
@ActionReference(path = "Editors/TabActions", position = 405),
122+
@ActionReference(path = "UI/ToolActions/Files", position = 2045),
123+
@ActionReference(path = "Projects/Actions", position = 101),
124+
@ActionReference(path = "Shortcuts", name = "SO-S")
125+
})
126+
public final static class OpenInSystemAction extends AbstractOpenInAction {
127+
128+
public OpenInSystemAction() {
129+
this(Utilities.actionsGlobalContext());
130+
}
131+
132+
public OpenInSystemAction(Lookup context) {
133+
super(NbBundle.getMessage(AbstractOpenInAction.class, "CTL_OpenInSystemAction"), context);
134+
}
135+
136+
@Override
137+
public Action createContextAwareInstance(Lookup context) {
138+
return new OpenInSystemAction(context);
139+
}
140+
141+
@Override
142+
public void actionPerformed(ActionEvent e) {
143+
openInSystem(files);
144+
}
145+
146+
@Override
147+
public boolean isEnabled() {
148+
return !files.isEmpty() && canOpenInSystem();
149+
}
150+
}
151+
152+
@ActionID(id = "org.netbeans.core.ui.sysopen.OpenParentInSystemAction", category = "Edit")
153+
@ActionRegistration(displayName = "#CTL_OpenParentInSystemAction", lazy = false)
154+
@ActionReferences ({
155+
@ActionReference(path = "Editors/TabActions", position = 410),
156+
@ActionReference(path = "UI/ToolActions/Files", position = 2046),
157+
@ActionReference(path = "Projects/Actions", position = 102)
158+
})
159+
public final static class OpenParentInSystemAction extends AbstractOpenInAction {
160+
161+
public OpenParentInSystemAction() {
162+
this(Utilities.actionsGlobalContext());
163+
}
164+
165+
public OpenParentInSystemAction(Lookup context) {
166+
super(NbBundle.getMessage(AbstractOpenInAction.class, "CTL_OpenParentInSystemAction"), context);
167+
}
168+
169+
@Override
170+
public Action createContextAwareInstance(Lookup context) {
171+
return new OpenParentInSystemAction(context);
172+
}
173+
174+
@Override
175+
public void actionPerformed(ActionEvent e) {
176+
openInSystem(Set.of(files.iterator().next().getParentFile()));
177+
}
178+
179+
@Override
180+
public boolean isEnabled() {
181+
return files.size() == 1 && files.iterator().next().getParent() != null && canOpenInSystem();
182+
}
183+
}
184+
185+
@ActionID(id = "org.netbeans.core.ui.sysopen.OpenInTabAction", category = "Edit")
186+
@ActionRegistration(displayName = "#CTL_OpenInTabAction", lazy = false)
187+
@ActionReferences ({
188+
@ActionReference(path = "Editors/TabActions", position = 415),
189+
@ActionReference(path = "UI/ToolActions/Files", position = 2047),
190+
// @ActionReference(path = "Projects/Actions", position = 103)
191+
})
192+
public final static class OpenInTabAction extends AbstractOpenInAction {
193+
194+
public OpenInTabAction() {
195+
this(Utilities.actionsGlobalContext());
196+
}
197+
198+
public OpenInTabAction(Lookup context) {
199+
super(NbBundle.getMessage(AbstractOpenInAction.class, "CTL_OpenInTabAction"), context);
200+
}
201+
202+
@Override
203+
public Action createContextAwareInstance(Lookup context) {
204+
return new OpenInTabAction(context);
205+
}
206+
207+
@Override
208+
public void actionPerformed(ActionEvent e) {
209+
browse(FileUtil.toFileObject(files.iterator().next()));
210+
}
211+
212+
@Override
213+
public boolean isEnabled() {
214+
if (files.size() == 1) {
215+
File file = files.iterator().next();
216+
try {
217+
return file.isDirectory() || FileUtil.isArchiveFile(Utilities.toURI(file).toURL());
218+
} catch (MalformedURLException ignore) {}
219+
}
220+
return false;
221+
}
222+
}
223+
224+
@ActionID(id = "org.netbeans.core.ui.sysopen.OpenParentInTabAction", category = "Edit")
225+
@ActionRegistration(displayName = "#CTL_OpenParentInTabAction", lazy = false)
226+
@ActionReferences ({
227+
@ActionReference(path = "Editors/TabActions", position = 420),
228+
@ActionReference(path = "UI/ToolActions/Files", position = 2048),
229+
@ActionReference(path = "Projects/Actions", position = 104)
230+
})
231+
public final static class OpenParentInTabAction extends AbstractOpenInAction {
232+
233+
public OpenParentInTabAction() {
234+
this(Utilities.actionsGlobalContext());
235+
}
236+
237+
public OpenParentInTabAction(Lookup context) {
238+
super(NbBundle.getMessage(AbstractOpenInAction.class, "CTL_OpenParentInTabAction"), context);
239+
}
240+
241+
@Override
242+
public Action createContextAwareInstance(Lookup context) {
243+
return new OpenParentInTabAction(context);
244+
}
245+
246+
@Override
247+
public void actionPerformed(ActionEvent e) {
248+
browse(FileUtil.toFileObject(files.iterator().next().getParentFile()));
249+
}
250+
251+
@Override
252+
public boolean isEnabled() {
253+
return files.size() == 1 && files.iterator().next().getParent() != null;
254+
}
255+
}
256+
257+
}

platform/core.ui/src/org/netbeans/core/ui/sysopen/Bundle.properties

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,8 @@
1515
# specific language governing permissions and limitations
1616
# under the License.
1717

18-
CTL_SystemOpenAction=Open in System
18+
CTL_OpenInSystemAction=Open in System
19+
CTL_OpenParentInSystemAction=Open Parent in System
20+
21+
CTL_OpenInTabAction=Open as Tab
22+
CTL_OpenParentInTabAction=Open Parent as Tab

0 commit comments

Comments
 (0)