Skip to content

Commit 613436d

Browse files
committed
Support Reuse of Last Opened Editor when JDT Plugin is present
Adds `OpenFileWithReuseActionProvider` that wraps the current OPEN handler (dependsOn org.eclipse.jdt.ui.navigator.actions.OpenActions) and installs a wrapper OPEN action in Project Explorer. For single IFile selections (pref enabled), reuse the last editor via `OpenFileWithReuseAction`. For all other selections (e.g., IJavaElement), delegate to the previously installed OPEN handler (JDT's OpenAction), preserving Java behavior.
1 parent 9abfd8a commit 613436d

File tree

2 files changed

+132
-0
lines changed

2 files changed

+132
-0
lines changed

bundles/org.eclipse.ui.navigator.resources/plugin.xml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,17 @@
233233
</enablement>
234234
</actionProvider>
235235

236+
<!-- Wrapper OPEN handler for Project Explorer: applies reuse-last-open-editor for IFile, delegates otherwise -->
237+
<actionProvider
238+
class="org.eclipse.ui.internal.navigator.resources.actions.OpenFileWithReuseActionProvider"
239+
id="org.eclipse.ui.navigator.resources.ReuseOpenActions"
240+
dependsOn="org.eclipse.jdt.ui.navigator.actions.OpenActions">
241+
<!-- true: always enabled so we can wrap any OPEN handler and delegate when needed -->
242+
<enablement>
243+
<or/>
244+
</enablement>
245+
</actionProvider>
246+
236247
<actionProvider
237248
class="org.eclipse.ui.internal.navigator.resources.actions.ResourceMgmtActionProvider"
238249
id="org.eclipse.ui.navigator.resources.ResourceMgmtActions">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2025 Vegard IT GmbH and others.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*
11+
* Contributors:
12+
* Sebastian Thomschke (Vegard IT GmbH) - initial API and implementation
13+
*******************************************************************************/
14+
package org.eclipse.ui.internal.navigator.resources.actions;
15+
16+
import org.eclipse.core.resources.IFile;
17+
import org.eclipse.core.runtime.Adapters;
18+
import org.eclipse.jface.action.Action;
19+
import org.eclipse.jface.action.IAction;
20+
import org.eclipse.jface.viewers.ISelection;
21+
import org.eclipse.jface.viewers.IStructuredSelection;
22+
import org.eclipse.jface.viewers.StructuredSelection;
23+
import org.eclipse.ui.IActionBars;
24+
import org.eclipse.ui.IPageLayout;
25+
import org.eclipse.ui.IWorkbenchPage;
26+
import org.eclipse.ui.actions.ActionContext;
27+
import org.eclipse.ui.actions.OpenFileWithReuseAction;
28+
import org.eclipse.ui.navigator.CommonActionProvider;
29+
import org.eclipse.ui.navigator.ICommonActionConstants;
30+
import org.eclipse.ui.navigator.ICommonActionExtensionSite;
31+
import org.eclipse.ui.navigator.ICommonViewerWorkbenchSite;
32+
33+
/**
34+
* Installs a wrapper OPEN handler in Project Explorer that applies last opened
35+
* editor reuse for single {@link IFile} selections, and delegates to the
36+
* previous OPEN handler otherwise (e.g., JDT OpenAction for Java elements).
37+
*/
38+
public class OpenFileWithReuseActionProvider extends CommonActionProvider {
39+
40+
private ICommonViewerWorkbenchSite viewSite;
41+
private OpenFileWithReuseAction reuseAction;
42+
private IWorkbenchPage reusePage;
43+
44+
@Override
45+
public void init(ICommonActionExtensionSite aConfig) {
46+
if (aConfig.getViewSite() instanceof ICommonViewerWorkbenchSite) {
47+
viewSite = (ICommonViewerWorkbenchSite) aConfig.getViewSite();
48+
}
49+
}
50+
51+
@Override
52+
public void fillActionBars(IActionBars actionBars) {
53+
if (viewSite == null) {
54+
return;
55+
}
56+
// Scope strictly to Project Explorer (including secondary ids)
57+
String partId = viewSite.getSite().getId();
58+
if (partId == null || !partId.startsWith(IPageLayout.ID_PROJECT_EXPLORER)) {
59+
return;
60+
}
61+
62+
// Capture current OPEN delegate (e.g., JDT's OpenAction) to call when reuse
63+
// doesn't apply
64+
IAction delegate = actionBars.getGlobalActionHandler(ICommonActionConstants.OPEN);
65+
66+
IAction wrapper = new Action() {
67+
@Override
68+
public void run() {
69+
ISelection sel = getSelection();
70+
if (!(sel instanceof IStructuredSelection)) {
71+
if (delegate != null) {
72+
delegate.run();
73+
}
74+
return;
75+
}
76+
IStructuredSelection ss = (IStructuredSelection) sel;
77+
if (ss.size() == 1) {
78+
Object element = ss.getFirstElement();
79+
IFile file = Adapters.adapt(element, IFile.class);
80+
if (file != null) {
81+
IWorkbenchPage page = viewSite.getPage();
82+
if (reuseAction == null || reusePage != page) {
83+
reuseAction = new OpenFileWithReuseAction(page, IPageLayout.ID_PROJECT_EXPLORER);
84+
reusePage = page;
85+
}
86+
reuseAction.selectionChanged(new StructuredSelection(file));
87+
reuseAction.run();
88+
return;
89+
}
90+
}
91+
// Fallback: delegate to prior handler (e.g., JDT)
92+
if (delegate != null) {
93+
delegate.run();
94+
}
95+
}
96+
97+
@Override
98+
public void setEnabled(boolean enabled) {
99+
super.setEnabled(enabled);
100+
if (delegate != null) {
101+
delegate.setEnabled(enabled);
102+
}
103+
}
104+
};
105+
106+
// Install synchronously; plugin.xml dependsOn ensures we run after JDT's
107+
// provider
108+
actionBars.setGlobalActionHandler(ICommonActionConstants.OPEN, wrapper);
109+
actionBars.updateActionBars();
110+
}
111+
112+
private ISelection getSelection() {
113+
ActionContext ctx = getContext();
114+
if (ctx != null && ctx.getSelection() != null) {
115+
return ctx.getSelection();
116+
}
117+
return viewSite.getSelectionProvider() != null //
118+
? viewSite.getSelectionProvider().getSelection()
119+
: StructuredSelection.EMPTY;
120+
}
121+
}

0 commit comments

Comments
 (0)