blob: 368200492cae2310047a73052dcaad4211942098 [file] [log] [blame]
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.progress.util;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationAdapter;
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.ui.AppUIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.ide.PooledThreadExecutor;
import java.util.concurrent.Executor;
/**
* @author gregsh
*/
public class ProgressIndicatorUtils {
private ProgressIndicatorUtils() {
}
@NotNull
public static ProgressIndicator forceWriteActionPriority(@NotNull final ProgressIndicator progress, @NotNull final Disposable builder) {
ApplicationManager.getApplication().addApplicationListener(new ApplicationAdapter() {
@Override
public void beforeWriteActionStart(Object action) {
if (progress.isRunning()) {
progress.cancel();
}
}
}, builder);
return progress;
}
public static void scheduleWithWriteActionPriority(@NotNull ReadTask task) {
scheduleWithWriteActionPriority(new ProgressIndicatorBase(), task);
}
public static void scheduleWithWriteActionPriority(@NotNull ProgressIndicator progressIndicator, @NotNull ReadTask readTask) {
scheduleWithWriteActionPriority(progressIndicator, PooledThreadExecutor.INSTANCE, readTask);
}
public static void scheduleWithWriteActionPriority(@NotNull final ProgressIndicator progressIndicator,
@NotNull final Executor executor,
@NotNull final ReadTask readTask) {
AppUIUtil.invokeOnEdt(new Runnable() {
@Override
public void run() {
final Application application = ApplicationManager.getApplication();
application.assertIsDispatchThread();
final ApplicationAdapter listener = new ApplicationAdapter() {
@Override
public void beforeWriteActionStart(Object action) {
progressIndicator.cancel();
}
};
application.addApplicationListener(listener);
try {
executor.execute(new Runnable() {
@Override
public void run() {
try {
runUnderProgress(progressIndicator, readTask);
}
finally {
application.removeApplicationListener(listener);
}
}
});
}
catch (RuntimeException e) {
application.removeApplicationListener(listener);
throw e;
}
catch (Error e) {
application.removeApplicationListener(listener);
throw e;
}
}
});
}
private static void runUnderProgress(@NotNull final ProgressIndicator progressIndicator, @NotNull final ReadTask task) {
ProgressManager.getInstance().runProcess(new Runnable() {
@Override
public void run() {
// This read action can possible last for a long time, we want it to stop immediately on the first write access.
// For this purpose we launch it under empty progress and invoke progressIndicator#cancel on write access to avoid possible write lock delays.
try {
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
task.computeInReadAction(progressIndicator);
}
});
}
catch (ProcessCanceledException ignore) {
}
finally {
if (progressIndicator.isCanceled()) {
task.onCanceled(progressIndicator);
}
}
}
}, progressIndicator);
}
}