diff --git a/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationUtil.java b/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationUtil.java
index c7cf4a8da64c..451d3e587ed0 100644
--- a/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationUtil.java
+++ b/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationUtil.java
@@ -17,6 +17,7 @@ package com.intellij.openapi.application.ex;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Ref;
@@ -53,25 +54,30 @@ public class ApplicationUtil {
* Allows to interrupt a process which does not performs checkCancelled() calls by itself.
* Note that the process may continue to run in background indefinitely - so avoid using this method unless absolutely needed.
*/
- public static T runWithCheckCanceled(@NotNull final Callable callable) throws Exception {
+ public static T runWithCheckCanceled(@NotNull final Callable callable, @NotNull final ProgressIndicator indicator) throws Exception {
+ final Ref result = Ref.create();
final Ref error = Ref.create();
- Future future = ApplicationManager.getApplication().executeOnPooledThread(new Callable() {
+ Future> future = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
- public T call() throws Exception {
- try {
- return callable.call();
- }
- catch (Throwable t) {
- error.set(t);
- return null;
- }
+ public void run() {
+ ProgressManager.getInstance().executeProcessUnderProgress(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ result.set(callable.call());
+ }
+ catch (Throwable t) {
+ error.set(t);
+ }
+ }
+ }, indicator);
}
});
while (true) {
try {
- ProgressManager.checkCanceled();
+ indicator.checkCanceled();
}
catch (ProcessCanceledException e) {
future.cancel(true);
@@ -79,9 +85,9 @@ public class ApplicationUtil {
}
try {
- T result = future.get(200, TimeUnit.MILLISECONDS);
+ future.get(200, TimeUnit.MILLISECONDS);
ExceptionUtil.rethrowAll(error.get());
- return result;
+ return result.get();
}
catch (TimeoutException ignored) { }
}
diff --git a/platform/core-impl/src/com/intellij/openapi/fileEditor/impl/LoadTextUtil.java b/platform/core-impl/src/com/intellij/openapi/fileEditor/impl/LoadTextUtil.java
index ca194dd5ce65..6f1d24e4a8c3 100644
--- a/platform/core-impl/src/com/intellij/openapi/fileEditor/impl/LoadTextUtil.java
+++ b/platform/core-impl/src/com/intellij/openapi/fileEditor/impl/LoadTextUtil.java
@@ -390,7 +390,7 @@ public final class LoadTextUtil {
public CharSequence call() {
return decompiler.decompile(file);
}
- }));
+ }, indicator));
}
catch (Throwable t) {
error.set(t);
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesViewManager.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesViewManager.java
index 8630f7ffbe50..075927b4fa80 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesViewManager.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesViewManager.java
@@ -201,7 +201,7 @@ public class ChangesViewManager implements ChangesViewI, JDOMExternalizable, Pro
}
});
if (ApplicationManager.getApplication().isHeadlessEnvironment()) return;
- myContent = ContentFactory.SERVICE.getInstance().createContent(createChangeViewComponent(), "Local", false);
+ myContent = ContentFactory.SERVICE.getInstance().createContent(createChangeViewComponent(), ChangesViewContentManager.LOCAL_CHANGES, false);
myContent.setCloseable(false);
myContentManager.addContent(myContent);
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/SelectInChangesViewTarget.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/SelectInChangesViewTarget.java
index f91bbc63f9e4..2a2f759716d7 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/SelectInChangesViewTarget.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/SelectInChangesViewTarget.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -53,7 +53,7 @@ public class SelectInChangesViewTarget implements SelectInTarget, DumbAware {
final VirtualFile file = context.getVirtualFile();
Runnable runnable = new Runnable() {
public void run() {
- ChangesViewContentManager.getInstance(myProject).selectContent("Local");
+ ChangesViewContentManager.getInstance(myProject).selectContent(ChangesViewContentManager.LOCAL_CHANGES);
ChangesViewManager.getInstance(myProject).selectFile(file);
}
};
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelvedChangesViewManager.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelvedChangesViewManager.java
index 22efde10e5dc..8cad5f820d96 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelvedChangesViewManager.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelvedChangesViewManager.java
@@ -185,7 +185,7 @@ public class ShelvedChangesViewManager implements ProjectComponent {
if (changeLists.size() == 0) {
if (myContent != null) {
myContentManager.removeContent(myContent);
- myContentManager.selectContent("Local");
+ myContentManager.selectContent(ChangesViewContentManager.LOCAL_CHANGES);
}
myContent = null;
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesViewContentManager.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesViewContentManager.java
index feddadcacfd3..5923ed170556 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesViewContentManager.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesViewContentManager.java
@@ -283,7 +283,11 @@ public class ChangesViewContentManager extends AbstractProjectComponent implemen
}
}
- private static final String[] ourPresetOrder = {"Local", "Repository", "Incoming", "Shelf"};
+ public static final String LOCAL_CHANGES = Registry.is("vcs.merge.toolwindows") ? "Local Changes" : "Local";
+ public static final String REPOSITORY = "Repository";
+ public static final String INCOMING = "Incoming";
+ public static final String SHELF = "Shelf";
+ private static final String[] ourPresetOrder = {LOCAL_CHANGES, REPOSITORY, INCOMING, SHELF};
private static List doPresetOrdering(final List contents) {
final List result = new ArrayList(contents.size());
for (final String preset : ourPresetOrder) {
diff --git a/plugins/java-decompiler/plugin/src/org/jetbrains/java/decompiler/IdeaDecompiler.java b/plugins/java-decompiler/plugin/src/org/jetbrains/java/decompiler/IdeaDecompiler.java
index b67f88b8b1ed..cfae319bae13 100644
--- a/plugins/java-decompiler/plugin/src/org/jetbrains/java/decompiler/IdeaDecompiler.java
+++ b/plugins/java-decompiler/plugin/src/org/jetbrains/java/decompiler/IdeaDecompiler.java
@@ -27,6 +27,8 @@ import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.fileEditor.*;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.DefaultProjectFactory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
@@ -47,6 +49,7 @@ import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
import org.jetbrains.java.decompiler.main.decompiler.BaseDecompiler;
import org.jetbrains.java.decompiler.main.extern.IBytecodeProvider;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
@@ -74,6 +77,7 @@ public class IdeaDecompiler extends ClassFileDecompilers.Light {
private final IFernflowerLogger myLogger = new IdeaLogger();
private final Map myOptions = new HashMap();
private boolean myLegalNoticeAccepted;
+ private final Map myProgress = ContainerUtil.newConcurrentMap();
public IdeaDecompiler() {
myOptions.put(IFernflowerPreferences.HIDE_DEFAULT_CONSTRUCTOR, "0");
@@ -140,6 +144,9 @@ public class IdeaDecompiler extends ClassFileDecompilers.Light {
return ClsFileImpl.decompile(file);
}
+ ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
+ if (indicator != null) myProgress.put(file, indicator);
+
try {
Map files = ContainerUtil.newLinkedHashMap();
files.put(file.getPath(), file);
@@ -193,6 +200,15 @@ public class IdeaDecompiler extends ClassFileDecompilers.Light {
throw new CannotDecompileException(e);
}
}
+ finally {
+ myProgress.remove(file);
+ }
+ }
+
+ @TestOnly
+ @Nullable
+ public ProgressIndicator getProgress(@NotNull VirtualFile file) {
+ return myProgress.get(file);
}
private static class MyBytecodeProvider implements IBytecodeProvider {
diff --git a/plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java b/plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java
index 81df4dd82859..2947d18c9e7a 100644
--- a/plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java
+++ b/plugins/java-decompiler/plugin/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java
@@ -18,8 +18,12 @@ package org.jetbrains.java.decompiler;
import com.intellij.codeInsight.daemon.impl.IdentifierHighlighterPassFactory;
import com.intellij.codeInsight.navigation.actions.GotoDeclarationAction;
import com.intellij.debugger.PositionManager;
+import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.PluginPathManager;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
@@ -28,9 +32,11 @@ import com.intellij.openapi.vfs.*;
import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
+import com.intellij.psi.compiled.ClassFileDecompilers;
import com.intellij.psi.impl.compiled.ClsFileImpl;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
+import com.intellij.util.Alarm;
import com.intellij.util.ThrowableRunnable;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.io.URLUtil;
@@ -169,4 +175,31 @@ public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase {
}
}).cpuBound().assertTiming();
}
+
+ public void testCancellation() {
+ final VirtualFile file = getTestFile(PlatformTestUtil.getRtJarPath() + "!/javax/swing/JTable.class");
+
+ final IdeaDecompiler decompiler = (IdeaDecompiler)ClassFileDecompilers.find(file);
+ assertNotNull(decompiler);
+
+ final Alarm alarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, getProject());
+ alarm.addRequest(new Runnable() {
+ @Override
+ public void run() {
+ ProgressIndicator progress = decompiler.getProgress(file);
+ if (progress != null) {
+ progress.cancel();
+ }
+ else {
+ alarm.addRequest(this, 200, ModalityState.any());
+ }
+ }
+ }, 750, ModalityState.any());
+
+ try {
+ FileDocumentManager.getInstance().getDocument(file);
+ fail("should have been cancelled");
+ }
+ catch (ProcessCanceledException ignored) { }
+ }
}
diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/panels/IpnbFilePanel.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/panels/IpnbFilePanel.java
index 7de8b3282b78..5017073ebf15 100644
--- a/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/panels/IpnbFilePanel.java
+++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/editor/panels/IpnbFilePanel.java
@@ -14,6 +14,7 @@ import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.VerticalFlowLayout;
+import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.ui.JBColor;
@@ -326,6 +327,8 @@ public class IpnbFilePanel extends JPanel implements Scrollable, DataProvider, D
if (project.isDisposed()) {
return;
}
+ if (Disposer.isDisposed(myParent))
+ return;
PsiDocumentManager.getInstance(project).commitDocument(myDocument);
final IpnbEditablePanel selectedCell = getSelectedCell();
final int index = myIpnbPanels.indexOf(selectedCell);