Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrey Loskutov2015-02-11 20:10:54 +0000
committerLars Vogel2015-02-24 20:04:54 +0000
commitea1e252c1a7f31b29af223acd8ce637d078728e0 (patch)
tree14b2bc6657ea959937874da1d4bfe35227600d63
parentbf270a574099351e2fa3eaa5ddeccaf28db5348a (diff)
downloadeclipse.platform.ui-ea1e252c1a7f31b29af223acd8ce637d078728e0.tar.gz
eclipse.platform.ui-ea1e252c1a7f31b29af223acd8ce637d078728e0.tar.xz
eclipse.platform.ui-ea1e252c1a7f31b29af223acd8ce637d078728e0.zip
Bug 41431 - [EditorMgmt] Affected editors should be closed before
executing project close or delete The patch hooks into standard close/delete IDE actions and tries to find and close opened editors matching closed/deleted resource roots. This is the practical solution wich aims to cover 80% of user complains and doesn't claim to fix all sophisticated ways of closing or deleting resources in the IDE. The matched editors will be closed without confirmation (which happens already in Close/Delete actions), in case of Delete action only if the editor resource does not exists anymore. The editor matching strategy is pretty simple - it uses editor input objects and hopes that they are either FileEditorInput's or can provide adapters to IFile or IResource. This should cover the majority of "standard" IDE editors and works fine with not yet instantiated editor parts. Because real editor parts aren't instantiated there is no risk of unexpected side effects. 3rd party editors can benefit from the provided patch too - all what they need is to add IFile or IResource adapter to their input objects. P.S: The reason not to implement IResourceChangeListener is that this can have permanent negative side effects on performance, because each time such resource change happens the delta must be processed and each opened editor has to be matched against each closed/deleted resource, including extra (eventually redundant) confirmation dialog in case a dirty editor matches. Change-Id: I92af399bf0ceca3dfe8668a6c011c19c12d6ee51 Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
-rw-r--r--bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/CloseResourceAction.java145
-rw-r--r--bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/DeleteResourceAction.java4
-rw-r--r--bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/IDEWorkbenchMessages.java1
-rw-r--r--bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/messages.properties1
4 files changed, 144 insertions, 7 deletions
diff --git a/bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/CloseResourceAction.java b/bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/CloseResourceAction.java
index 50386d1fd4f..2967f2f9e9c 100644
--- a/bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/CloseResourceAction.java
+++ b/bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/CloseResourceAction.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2010 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -7,12 +7,15 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Andrey Loskutov <loskutov@gmx.de> - Bug 41431
*******************************************************************************/
package org.eclipse.ui.actions;
+import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
@@ -24,16 +27,25 @@ import org.eclipse.core.resources.mapping.IResourceChangeDescriptionFactory;
import org.eclipse.core.resources.mapping.ResourceChangeValidator;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.MultiRule;
+import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorReference;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
import org.eclipse.ui.internal.ide.IIDEHelpContextIds;
+import org.eclipse.ui.part.FileEditorInput;
/**
* Standard action for closing the currently selected project(s).
@@ -140,8 +152,7 @@ public class CloseResourceAction extends WorkspaceAction implements
return;
}
- IResource[] projectArray = (IResource[]) projects
- .toArray(new IResource[projects.size()]);
+ final IResource[] projectArray = (IResource[]) projects.toArray(new IResource[projects.size()]);
if (!IDE.saveAllEditors(projectArray, true)) {
return;
@@ -149,13 +160,15 @@ public class CloseResourceAction extends WorkspaceAction implements
if (!validateClose()) {
return;
}
+
+ closeMatchingEditors(projectArray, false);
+
//be conservative and include all projects in the selection - projects
//can change state between now and when the job starts
ISchedulingRule rule = null;
IResourceRuleFactory factory = ResourcesPlugin.getWorkspace().getRuleFactory();
- Iterator resources = getSelectedResources().iterator();
- while (resources.hasNext()) {
- IProject project = (IProject) resources.next();
+ for (int i = 0; i < projectArray.length; i++) {
+ IProject project = (IProject) projectArray[i];
rule = MultiRule.combine(rule, factory.modifyRule(project));
}
runInBackground(rule);
@@ -274,4 +287,124 @@ public class CloseResourceAction extends WorkspaceAction implements
}
return IDE.promptToConfirm(getShell(), IDEWorkbenchMessages.CloseResourceAction_confirm, message, factory.getDelta(), getModelProviderIds(), false /* no need to syncExec */);
}
+
+ /**
+ * Tries to find opened editors matching given resource roots. The editors
+ * will be closed without confirmation and only if the editor resource does
+ * not exists anymore.
+ *
+ * @param resourceRoots
+ * non null array with deleted resource tree roots
+ * @param deletedOnly
+ * true to close only editors on resources which do not exist
+ */
+ static void closeMatchingEditors(final IResource[] resourceRoots, final boolean deletedOnly) {
+ if (resourceRoots.length == 0) {
+ return;
+ }
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ SafeRunner.run(new SafeRunnable(IDEWorkbenchMessages.ErrorOnCloseEditors) {
+ @Override
+ public void run() throws CoreException {
+ IWorkbenchWindow w = getActiveWindow();
+ if (w != null) {
+ List<IEditorReference> toClose = getMatchingEditors(resourceRoots, w, deletedOnly);
+ if (toClose.isEmpty()) {
+ return;
+ }
+ closeEditors(toClose, w);
+ }
+ }
+ });
+ }
+ };
+ BusyIndicator.showWhile(PlatformUI.getWorkbench().getDisplay(), runnable);
+ }
+
+ private static IWorkbenchWindow getActiveWindow() {
+ IWorkbenchWindow w = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (w == null) {
+ IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows();
+ if (windows.length > 0) {
+ w = windows[0];
+ }
+ }
+ return w;
+ }
+
+ private static List<IEditorReference> getMatchingEditors(final IResource[] resourceRoots, IWorkbenchWindow w,
+ boolean deletedOnly) throws CoreException {
+ List<IEditorReference> toClose = new ArrayList<IEditorReference>();
+ IEditorReference[] editors = getEditors(w);
+ for (int i = 0; i < editors.length; i++) {
+ IEditorReference ref = editors[i];
+ IResource resource = getAdapter(ref);
+ // only collect editors for non existing resources
+ if (resource != null && belongsTo(resourceRoots, resource)) {
+ if (deletedOnly && resource.exists()) {
+ continue;
+ }
+ toClose.add(ref);
+ }
+ }
+ return toClose;
+ }
+
+ private static IEditorReference[] getEditors(IWorkbenchWindow w) {
+ if (w != null) {
+ IWorkbenchPage page = w.getActivePage();
+ if (page != null) {
+ return page.getEditorReferences();
+ }
+ }
+ return new IEditorReference[0];
+ }
+
+ private static IResource getAdapter(IEditorReference ref) throws CoreException {
+ IEditorInput input = ref.getEditorInput();
+ if (input instanceof FileEditorInput) {
+ FileEditorInput fi = (FileEditorInput) input;
+ IFile file = fi.getFile();
+ if (file != null) {
+ return file;
+ }
+ }
+ // here we can only guess how the input might be related to a resource
+ Object adapter = input.getAdapter(IFile.class);
+ if (adapter != null) {
+ return (IResource) adapter;
+ }
+ adapter = input.getAdapter(IResource.class);
+ if (adapter != null) {
+ return (IResource) adapter;
+ }
+ adapter = Platform.getAdapterManager().getAdapter(input, IFile.class);
+ if (adapter != null) {
+ return (IResource) adapter;
+ }
+ adapter = Platform.getAdapterManager().getAdapter(input, IResource.class);
+ if (adapter != null) {
+ return (IResource) adapter;
+ }
+ return null;
+ }
+
+ private static boolean belongsTo(IResource[] roots, IResource leaf) {
+ for (int i = 0; i < roots.length; i++) {
+ if (roots[i].contains(leaf)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static void closeEditors(List<IEditorReference> toClose, IWorkbenchWindow w) {
+ IWorkbenchPage page = w.getActivePage();
+ if (page == null) {
+ return;
+ }
+ page.closeEditors(toClose.toArray(new IEditorReference[toClose.size()]), false);
+ }
}
diff --git a/bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/DeleteResourceAction.java b/bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/DeleteResourceAction.java
index c7f7c753d95..33811277121 100644
--- a/bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/DeleteResourceAction.java
+++ b/bundles/org.eclipse.ui.ide/extensions/org/eclipse/ui/actions/DeleteResourceAction.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2013 IBM Corporation and others.
+ * Copyright (c) 2000, 2015 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation
* Benjamin Muskalla <b.muskalla@gmx.net>
* - Fix for bug 172574 - [IDE] DeleteProjectDialog inconsequent selection behavior
+ * Andrey Loskutov <loskutov@gmx.de> - Bug 41431
*******************************************************************************/
package org.eclipse.ui.actions;
@@ -469,6 +470,7 @@ public class DeleteResourceAction extends SelectionListenerAction {
if (!fTestingMode) {
if (LTKLauncher.openDeleteWizard(getStructuredSelection())) {
+ CloseResourceAction.closeMatchingEditors(resources, true);
return;
}
}
diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/IDEWorkbenchMessages.java b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/IDEWorkbenchMessages.java
index 9c6281f7b9d..fec0b82d221 100644
--- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/IDEWorkbenchMessages.java
+++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/IDEWorkbenchMessages.java
@@ -51,6 +51,7 @@ public class IDEWorkbenchMessages extends NLS {
public static String ErrorClosing;
public static String ErrorOnSaveAll;
+ public static String ErrorOnCloseEditors;
public static String ResourceInfoPage_noResource;
diff --git a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/messages.properties b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/messages.properties
index 35d8fa70fb7..a85f354c875 100644
--- a/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/messages.properties
+++ b/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/messages.properties
@@ -47,6 +47,7 @@ ConfigurationLogUpdateSection_timestamp=Profile timestamp\: {0}
ErrorClosing = An error has occurred when closing the workbench. See error log for more details.
ErrorOnSaveAll = An error has occurred while saving all editors. See error log for more details.
+ErrorOnCloseEditors = An error has occurred while closing editors. See error log for more details.
IDEIdleHelper_backgroundGC = Collecting garbage

Back to the top