blob: b4821f52fddbd77390643a7bd272eee514fe1bbb [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.application.impl.LaterInvocator;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.TaskInfo;
import com.intellij.openapi.wm.ex.ProgressIndicatorEx;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.WeakList;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class ProgressIndicatorBase extends AbstractProgressIndicatorBase implements ProgressIndicatorEx {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.progress.util.ProgressIndicatorBase");
private final boolean myReusable;
private volatile boolean myModalityEntered;
private volatile List<ProgressIndicatorEx> myStateDelegates;
private volatile WeakList<TaskInfo> myFinished;
private volatile boolean myWasStarted;
private TaskInfo myOwnerTask;
private static final IndicatorAction CHECK_CANCELED_ACTION = new IndicatorAction() {
@Override
public void execute(@NotNull ProgressIndicatorEx each) {
each.checkCanceled();
}
};
private static final IndicatorAction STOP_ACTION = new IndicatorAction() {
@Override
public void execute(@NotNull final ProgressIndicatorEx each) {
each.stop();
}
};
private static final IndicatorAction START_ACTION = new IndicatorAction() {
@Override
public void execute(@NotNull final ProgressIndicatorEx each) {
each.start();
}
};
private static final IndicatorAction CANCEL_ACTION = new IndicatorAction() {
@Override
public void execute(@NotNull final ProgressIndicatorEx each) {
each.cancel();
}
};
private static final IndicatorAction PUSH_ACTION = new IndicatorAction() {
@Override
public void execute(@NotNull final ProgressIndicatorEx each) {
each.pushState();
}
};
private static final IndicatorAction POP_ACTION = new IndicatorAction() {
@Override
public void execute(@NotNull final ProgressIndicatorEx each) {
each.popState();
}
};
private static final IndicatorAction STARTNC_ACTION = new IndicatorAction() {
@Override
public void execute(@NotNull final ProgressIndicatorEx each) {
each.startNonCancelableSection();
}
};
private static final IndicatorAction FINISHNC_ACTION = new IndicatorAction() {
@Override
public void execute(@NotNull final ProgressIndicatorEx each) {
each.finishNonCancelableSection();
}
};
public ProgressIndicatorBase() { this(false); }
public ProgressIndicatorBase(boolean reusable) {
myReusable = reusable;
}
@Override
public void start() {
synchronized (this) {
super.start();
delegateRunningChange(START_ACTION);
}
myWasStarted = true;
enterModality();
}
protected final void enterModality() {
if (myModalityProgress == this) {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
doEnterModality();
}
});
}
}
private void doEnterModality() {
if (!myModalityEntered) {
LaterInvocator.enterModal(this);
myModalityEntered = true;
}
}
@Override
public void stop() {
super.stop();
delegateRunningChange(STOP_ACTION);
exitModality();
}
protected final void exitModality() {
if (myModalityProgress == this) {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
doExitModality();
}
});
}
}
private void doExitModality() {
if (myModalityEntered) {
LaterInvocator.leaveModal(this);
myModalityEntered = false;
}
}
@Override
public void cancel() {
super.cancel();
delegateRunningChange(CANCEL_ACTION);
}
@Override
public void finish(@NotNull final TaskInfo task) {
WeakList<TaskInfo> finished = myFinished;
if (finished == null) {
synchronized (this) {
finished = myFinished;
if (finished == null) {
myFinished = finished = new WeakList<TaskInfo>();
}
}
}
if (!finished.addIfAbsent(task)) return;
delegateRunningChange(new IndicatorAction() {
@Override
public void execute(@NotNull final ProgressIndicatorEx each) {
each.finish(task);
}
});
}
@Override
public boolean isFinished(@NotNull final TaskInfo task) {
List<TaskInfo> list = myFinished;
return list != null && list.contains(task);
}
protected void setOwnerTask(TaskInfo owner) {
myOwnerTask = owner;
}
@Override
public void processFinish() {
if (myOwnerTask != null) {
finish(myOwnerTask);
myOwnerTask = null;
}
}
@Override
public final void checkCanceled() {
super.checkCanceled();
delegate(CHECK_CANCELED_ACTION);
}
@Override
public void setText(final String text) {
super.setText(text);
delegateProgressChange(new IndicatorAction() {
@Override
public void execute(@NotNull final ProgressIndicatorEx each) {
each.setText(text);
}
});
}
@Override
public void setText2(final String text) {
super.setText2(text);
delegateProgressChange(new IndicatorAction() {
@Override
public void execute(@NotNull final ProgressIndicatorEx each) {
each.setText2(text);
}
});
}
@Override
public void setFraction(final double fraction) {
super.setFraction(fraction);
delegateProgressChange(new IndicatorAction() {
@Override
public void execute(@NotNull final ProgressIndicatorEx each) {
each.setFraction(fraction);
}
});
}
@Override
public synchronized void pushState() {
super.pushState();
delegateProgressChange(PUSH_ACTION);
}
@Override
public synchronized void popState() {
super.popState();
delegateProgressChange(POP_ACTION);
}
@Override
public void startNonCancelableSection() {
super.startNonCancelableSection();
delegateProgressChange(STARTNC_ACTION);
}
@Override
public void finishNonCancelableSection() {
super.finishNonCancelableSection();
delegateProgressChange(FINISHNC_ACTION);
}
@Override
protected boolean isReuseable() {
return myReusable;
}
@Override
public void setIndeterminate(final boolean indeterminate) {
super.setIndeterminate(indeterminate);
delegateProgressChange(new IndicatorAction() {
@Override
public void execute(@NotNull final ProgressIndicatorEx each) {
each.setIndeterminate(indeterminate);
}
});
}
@Override
public final void addStateDelegate(@NotNull ProgressIndicatorEx delegate) {
delegate.initStateFrom(this);
synchronized (this) {
List<ProgressIndicatorEx> stateDelegates = myStateDelegates;
if (stateDelegates == null) {
myStateDelegates = stateDelegates = ContainerUtil.createLockFreeCopyOnWriteList();
}
else {
LOG.assertTrue(!stateDelegates.contains(delegate), "Already registered: " + delegate);
}
stateDelegates.add(delegate);
}
}
private void delegateProgressChange(@NotNull IndicatorAction action) {
delegate(action);
onProgressChange();
}
private void delegateRunningChange(@NotNull IndicatorAction action) {
delegate(action);
onRunningChange();
}
private void delegate(@NotNull IndicatorAction action) {
List<ProgressIndicatorEx> list = myStateDelegates;
if (list != null && !list.isEmpty()) {
for (ProgressIndicatorEx each : list) {
action.execute(each);
}
}
}
private interface IndicatorAction {
void execute(@NotNull ProgressIndicatorEx each);
}
protected void onProgressChange() {
}
protected void onRunningChange() {
}
@Override
public boolean isModalityEntered() {
return myModalityEntered;
}
@Override
public synchronized void initStateFrom(@NotNull final ProgressIndicator indicator) {
super.initStateFrom(indicator);
if (indicator instanceof ProgressIndicatorEx) {
myModalityEntered = ((ProgressIndicatorEx)indicator).isModalityEntered();
}
}
@Override
public boolean wasStarted() {
return myWasStarted;
}
}