/* * 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.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.TransactionGuard; import com.intellij.openapi.application.TransactionGuardImpl; import com.intellij.openapi.application.impl.ModalityStateEx; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.impl.CoreProgressManager; import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.ui.mac.foundation.MacUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.DoubleArrayList; import com.intellij.util.containers.Stack; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.util.Set; public class AbstractProgressIndicatorBase extends UserDataHolderBase implements ProgressIndicatorStacked { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.progress.util.ProgressIndicatorBase"); private volatile String myText; private volatile double myFraction; private volatile String myText2; private volatile boolean myCanceled; private volatile boolean myRunning; private volatile boolean myFinished; private volatile boolean myIndeterminate; private volatile Object myMacActivity; private volatile boolean myShouldStartActivity = true; private Stack<String> myTextStack; private DoubleArrayList myFractionStack; private Stack<String> myText2Stack; private volatile int myNonCancelableCount; protected ProgressIndicator myModalityProgress; private volatile ModalityState myModalityState = ModalityState.NON_MODAL; @Override public synchronized void start() { LOG.assertTrue(!isRunning(), "Attempt to start ProgressIndicator which is already running"); if (myFinished) { if (myCanceled && !isReuseable()) { if (ourReportedReuseExceptions.add(getClass())) { LOG.error("Attempt to start ProgressIndicator which is cancelled and already stopped:" + this + "," + getClass()); } } myCanceled = false; myFinished = false; } myText = ""; myFraction = 0; myText2 = ""; startSystemActivity(); myRunning = true; } private static final Set<Class> ourReportedReuseExceptions = ContainerUtil.newConcurrentSet(); protected boolean isReuseable() { return false; } @Override public synchronized void stop() { LOG.assertTrue(myRunning, "stop() should be called only if start() called before"); myRunning = false; myFinished = true; stopSystemActivity(); } protected void startSystemActivity() { myMacActivity = myShouldStartActivity ? MacUtil.wakeUpNeo(toString()) : null; } protected void stopSystemActivity() { if (myMacActivity != null) { synchronized (myMacActivity) { MacUtil.matrixHasYou(myMacActivity); myMacActivity = null; } } } @Override public boolean isRunning() { return myRunning; } @Override public void cancel() { myCanceled = true; stopSystemActivity(); if (ApplicationManager.getApplication() != null) { ProgressManager.canceled(this); } } @Override public boolean isCanceled() { return myCanceled; } @Override public void checkCanceled() { if (isCanceled() && isCancelable()) { throw new ProcessCanceledException(); } if (CoreProgressManager.runCheckCanceledHooks(this)) { if (isCanceled() && isCancelable()) { throw new ProcessCanceledException(); } } } @Override public void setText(final String text) { myText = text; } @Override public String getText() { return myText; } @Override public void setText2(final String text) { myText2 = text; } @Override public String getText2() { return myText2; } @Override public double getFraction() { return myFraction; } @Override public void setFraction(final double fraction) { myFraction = fraction; } @Override public synchronized void pushState() { getTextStack().push(myText); getFractionStack().add(myFraction); getText2Stack().push(myText2); } @Override public synchronized void popState() { LOG.assertTrue(!myTextStack.isEmpty()); String oldText = myTextStack.pop(); double oldFraction = myFractionStack.remove(myFractionStack.size() - 1); String oldText2 = myText2Stack.pop(); setText(oldText); setFraction(oldFraction); setText2(oldText2); } @Override public void startNonCancelableSection() { myNonCancelableCount++; } @Override public void finishNonCancelableSection() { myNonCancelableCount--; } protected boolean isCancelable() { return myNonCancelableCount == 0; } @Override public final boolean isModal() { return myModalityProgress != null; } @Override @NotNull public ModalityState getModalityState() { return myModalityState; } @Override public void setModalityProgress(ProgressIndicator modalityProgress) { LOG.assertTrue(!isRunning()); myModalityProgress = modalityProgress; ModalityState currentModality = ApplicationManager.getApplication().getCurrentModalityState(); myModalityState = myModalityProgress != null ? ((ModalityStateEx)currentModality).appendProgress(myModalityProgress) : currentModality; if (modalityProgress != null) { ((TransactionGuardImpl)TransactionGuard.getInstance()).enteredModality(myModalityState); } } @Override public boolean isIndeterminate() { return myIndeterminate; } @Override public void setIndeterminate(final boolean indeterminate) { myIndeterminate = indeterminate; } @NonNls @Override public String toString() { return "ProgressIndicator " + System.identityHashCode(this) + ": running="+isRunning()+"; canceled="+isCanceled(); } @Override public boolean isPopupWasShown() { return true; } @Override public boolean isShowing() { return isModal(); } @Override public synchronized void initStateFrom(@NotNull final ProgressIndicator indicator) { myRunning = indicator.isRunning(); myCanceled = indicator.isCanceled(); myFraction = indicator.getFraction(); myIndeterminate = indicator.isIndeterminate(); myText = indicator.getText(); myText2 = indicator.getText2(); myFraction = indicator.getFraction(); if (indicator instanceof ProgressIndicatorStacked) { ProgressIndicatorStacked stacked = (ProgressIndicatorStacked)indicator; myNonCancelableCount = stacked.getNonCancelableCount(); myTextStack = new Stack<>(stacked.getTextStack()); myText2Stack = new Stack<>(stacked.getText2Stack()); myFractionStack = new DoubleArrayList(stacked.getFractionStack()); } myShouldStartActivity = false; } @Override @NotNull public synchronized Stack<String> getTextStack() { if (myTextStack == null) myTextStack = new Stack<>(2); return myTextStack; } @Override @NotNull public synchronized DoubleArrayList getFractionStack() { if (myFractionStack == null) myFractionStack = new DoubleArrayList(2); return myFractionStack; } @Override @NotNull public synchronized Stack<String> getText2Stack() { if (myText2Stack == null) myText2Stack = new Stack<>(2); return myText2Stack; } @Override public int getNonCancelableCount() { return myNonCancelableCount; } }