blob: 950d6ea57978f2a71efdddb2ef67173758491cb3 [file] [log] [blame]
/*
* Copyright 2000-2009 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.ApplicationManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.Disposer;
import com.intellij.util.Alarm;
import com.intellij.util.concurrency.Semaphore;
import javax.swing.*;
public class SmoothProgressAdapter extends BlockingProgressIndicator {
private static final int SHOW_DELAY = 500;
private final Alarm myStartupAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD);
protected ProgressIndicator myOriginal;
private final Project myProject;
private boolean myOriginalStarted;
private DialogWrapper myDialog;
private final Runnable myShowRequest = new Runnable() {
public void run() {
synchronized(SmoothProgressAdapter.this){
if (!isRunning()) {
return;
}
myOriginal.start();
myOriginalStarted = true;
myOriginal.setText(getText());
myOriginal.setFraction(getFraction());
myOriginal.setText2(getText2());
}
}
};
public SmoothProgressAdapter(ProgressIndicator original, Project project){
myOriginal = original;
myProject = project;
if (myOriginal.isModal()) {
myOriginal.setModalityProgress(this);
this.setModalityProgress(this);
}
}
public void setIndeterminate(boolean indeterminate) {
super.setIndeterminate(indeterminate);
myOriginal.setIndeterminate(indeterminate);
}
public boolean isIndeterminate() {
return myOriginal.isIndeterminate();
}
public synchronized void start() {
if (isRunning()) return;
super.start();
myOriginalStarted = false;
myStartupAlarm.addRequest(myShowRequest, SHOW_DELAY);
}
public void startBlocking() {
ApplicationManager.getApplication().assertIsDispatchThread();
start();
if (isModal()) {
showDialog();
}
}
private void showDialog(){
if (myDialog == null){
//System.out.println("showDialog()");
myDialog = new DialogWrapper(myProject, false) {
{
getWindow().setBounds(0, 0, 1, 1);
setResizable(false);
}
protected boolean isProgressDialog() {
return true;
}
protected JComponent createCenterPanel() {
return null;
}
};
myDialog.setModal(true);
myDialog.setUndecorated(true);
myDialog.show();
}
}
public synchronized void stop() {
if (myOriginal.isRunning()) {
myOriginal.stop();
}
else {
myStartupAlarm.cancelAllRequests();
if (!myOriginalStarted && myOriginal instanceof Disposable) {
// dispose original because start & stop were not called so original progress might not have released its resources
Disposer.dispose(((Disposable)myOriginal));
}
}
// needed only for correct assertion of !progress.isRunning() in ApplicationImpl.runProcessWithProgressSynchroniously
final Semaphore semaphore = new Semaphore();
semaphore.down();
SwingUtilities.invokeLater(
new Runnable() {
public void run() {
semaphore.waitFor();
if (myDialog != null){
//System.out.println("myDialog.destroyProcess()");
myDialog.close(DialogWrapper.OK_EXIT_CODE);
myDialog = null;
}
}
}
);
try {
super.stop(); // should be last to not leaveModal before closing the dialog
}
finally {
semaphore.up();
}
}
public synchronized void setText(String text) {
super.setText(text);
if (myOriginal.isRunning()) {
myOriginal.setText(text);
}
}
public synchronized void setFraction(double fraction) {
super.setFraction(fraction);
if (myOriginal.isRunning()) {
myOriginal.setFraction(fraction);
}
}
public synchronized void setText2(String text) {
super.setText2(text);
if (myOriginal.isRunning()) {
myOriginal.setText2(text);
}
}
public void cancel() {
super.cancel();
myOriginal.cancel();
}
public boolean isCanceled() {
if (super.isCanceled()) return true;
if (!myOriginalStarted) return false;
return myOriginal.isCanceled();
}
public ProgressIndicator getOriginal() {
return myOriginal;
}
}