Merge remote-tracking branch 'origin/master'
[idea/community.git] / platform / core-api / src / com / intellij / openapi / progress / ProgressManager.java
1 /*
2  * Copyright 2000-2014 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.openapi.progress;
17
18 import com.intellij.openapi.components.ServiceManager;
19 import com.intellij.openapi.project.Project;
20 import com.intellij.openapi.util.Computable;
21 import com.intellij.openapi.util.ThrowableComputable;
22 import org.jetbrains.annotations.Nls;
23 import org.jetbrains.annotations.NotNull;
24 import org.jetbrains.annotations.Nullable;
25
26 import javax.swing.*;
27
28 public abstract class ProgressManager {
29   static {
30     ProgressIndicatorProvider.ourInstance = new ProgressIndicatorProvider() {
31       @Override
32       public ProgressIndicator getProgressIndicator() {
33         ProgressManager manager = ProgressManager.getInstance();
34         return manager != null ? manager.getProgressIndicator() : null;
35       }
36
37       @Override
38       protected void doCheckCanceled() throws ProcessCanceledException {
39         ProgressManager manager = ProgressManager.getInstance();
40         if (manager != null) {
41           manager.doCheckCanceled();
42         }
43       }
44
45       @Override
46       public NonCancelableSection startNonCancelableSection() {
47         ProgressManager manager = ProgressManager.getInstance();
48         return manager != null ? manager.startNonCancelableSection() : NonCancelableSection.EMPTY;
49       }
50     };
51   }
52
53   private static volatile ProgressManager ourInstance;
54
55   public static ProgressManager getInstance() {
56     ProgressManager progressManager = ourInstance;
57     if (progressManager == null) {
58       ourInstance = progressManager = ServiceManager.getService(ProgressManager.class);
59     }
60     return progressManager;
61   }
62
63   public abstract boolean hasProgressIndicator();
64   public abstract boolean hasModalProgressIndicator();
65   public abstract boolean hasUnsafeProgressIndicator();
66
67   public abstract void runProcess(@NotNull Runnable process, ProgressIndicator progress) throws ProcessCanceledException;
68   public abstract <T> T runProcess(@NotNull Computable<T> process, ProgressIndicator progress) throws ProcessCanceledException;
69
70   public ProgressIndicator getProgressIndicator() {
71     return myThreadIndicator.get();
72   }
73
74   protected static volatile boolean ourNeedToCheckCancel = false;
75   public static void checkCanceled() throws ProcessCanceledException {
76     // smart optimization! There's a thread started in ProgressManagerImpl, that set's this flag up once in 10 milliseconds
77     if (ourNeedToCheckCancel) {
78       getInstance().doCheckCanceled();
79       ourNeedToCheckCancel = false;
80     }
81   }
82
83   public static void progress(final String text) throws ProcessCanceledException {
84     progress(text, "");
85   }
86
87   public static void progress2(@NotNull final String text) throws ProcessCanceledException {
88     final ProgressIndicator pi = getInstance().getProgressIndicator();
89     if (pi != null) {
90       pi.checkCanceled();
91       pi.setText2(text);
92     }
93   }
94
95   public static void progress(final String text, @Nullable String text2) throws ProcessCanceledException {
96     final ProgressIndicator pi = getInstance().getProgressIndicator();
97     if (pi != null) {
98       pi.checkCanceled();
99       pi.setText(text);
100       pi.setText2(text2 == null ? "" : text2);
101     }
102   }
103
104   protected abstract void doCheckCanceled() throws ProcessCanceledException;
105
106   public abstract void executeNonCancelableSection(@NotNull Runnable runnable);
107   public abstract NonCancelableSection startNonCancelableSection();
108
109   public abstract void setCancelButtonText(String cancelButtonText);
110
111
112   /**
113    * Runs the specified operation in a background thread and shows a modal progress dialog in the
114    * main thread while the operation is executing.
115    *
116    * @param process       the operation to execute.
117    * @param progressTitle the title of the progress window.
118    * @param canBeCanceled whether "Cancel" button is shown on the progress window.
119    * @param project       the project in the context of which the operation is executed.
120    * @return true if the operation completed successfully, false if it was cancelled.
121    */
122   public abstract boolean runProcessWithProgressSynchronously(@NotNull Runnable process,
123                                                               @NotNull @Nls String progressTitle,
124                                                               boolean canBeCanceled,
125                                                               @Nullable Project project);
126
127   /**
128    * Runs the specified operation in a background thread and shows a modal progress dialog in the
129    * main thread while the operation is executing.
130    *
131    * @param process       the operation to execute.
132    * @param progressTitle the title of the progress window.
133    * @param canBeCanceled whether "Cancel" button is shown on the progress window.
134    * @param project       the project in the context of which the operation is executed.
135    * @return true result of operation
136    * @throws E exception thrown by process
137    */
138   public abstract <T, E extends Exception> T runProcessWithProgressSynchronously(@NotNull ThrowableComputable<T, E> process,
139                                                               @NotNull @Nls String progressTitle,
140                                                               boolean canBeCanceled,
141                                                               @Nullable Project project) throws E;
142
143   /**
144    * Runs the specified operation in a background thread and shows a modal progress dialog in the
145    * main thread while the operation is executing.
146    *
147    * @param process         the operation to execute.
148    * @param progressTitle   the title of the progress window.
149    * @param canBeCanceled   whether "Cancel" button is shown on the progress window.
150    * @param project         the project in the context of which the operation is executed.
151    * @param parentComponent the component which will be used to calculate the progress window ancestor
152    * @return true if the operation completed successfully, false if it was cancelled.
153    */
154   public abstract boolean runProcessWithProgressSynchronously(@NotNull Runnable process,
155                                                               @NotNull @Nls String progressTitle,
156                                                               boolean canBeCanceled,
157                                                               @Nullable Project project,
158                                                               @Nullable JComponent parentComponent);
159
160   /**
161    * Runs a specified <code>process</code> in a background thread and shows a progress dialog, which can be made non-modal by pressing
162    * background button. Upon successful termination of the process a <code>successRunnable</code> will be called in Swing UI thread and
163    * <code>canceledRunnable</code> will be called if terminated on behalf of the user by pressing either cancel button, while running in
164    * a modal state or stop button if running in background.
165    *
166    * @param project          the project in the context of which the operation is executed.
167    * @param progressTitle    the title of the progress window.
168    * @param process          the operation to execute.
169    * @param successRunnable  a callback to be called in Swing UI thread upon normal termination of the process.
170    * @param canceledRunnable a callback to be called in Swing UI thread if the process have been canceled by the user.
171    * @deprecated use {@link #run(com.intellij.openapi.progress.Task)}
172    */
173   public abstract void runProcessWithProgressAsynchronously(@NotNull Project project,
174                                                             @NotNull @Nls String progressTitle,
175                                                             @NotNull Runnable process,
176                                                             @Nullable Runnable successRunnable,
177                                                             @Nullable Runnable canceledRunnable);
178   /**
179    * Runs a specified <code>process</code> in a background thread and shows a progress dialog, which can be made non-modal by pressing
180    * background button. Upon successful termination of the process a <code>successRunnable</code> will be called in Swing UI thread and
181    * <code>canceledRunnable</code> will be called if terminated on behalf of the user by pressing either cancel button, while running in
182    * a modal state or stop button if running in background.
183    *
184    * @param project          the project in the context of which the operation is executed.
185    * @param progressTitle    the title of the progress window.
186    * @param process          the operation to execute.
187    * @param successRunnable  a callback to be called in Swing UI thread upon normal termination of the process.
188    * @param canceledRunnable a callback to be called in Swing UI thread if the process have been canceled by the user.
189    * @param option           progress indicator behavior controller.
190    * @deprecated use {@link #run(com.intellij.openapi.progress.Task)}
191    */
192   public abstract void runProcessWithProgressAsynchronously(@NotNull Project project,
193                                                             @NotNull @Nls String progressTitle,
194                                                             @NotNull Runnable process,
195                                                             @Nullable Runnable successRunnable,
196                                                             @Nullable Runnable canceledRunnable,
197                                                             @NotNull PerformInBackgroundOption option);
198
199   /**
200    * Runs a specified <code>task</code> in either background/foreground thread and shows a progress dialog.
201    *
202    * @param task task to run (either {@link com.intellij.openapi.progress.Task.Modal}
203    *             or {@link com.intellij.openapi.progress.Task.Backgroundable}).
204    */
205   public abstract void run(@NotNull Task task);
206
207   public abstract void runProcessWithProgressAsynchronously(@NotNull Task.Backgroundable task, @NotNull ProgressIndicator progressIndicator);
208
209   protected static final ThreadLocal<ProgressIndicator> myThreadIndicator = new ThreadLocal<ProgressIndicator>();
210   public void executeProcessUnderProgress(@NotNull Runnable process, ProgressIndicator progress) throws ProcessCanceledException {
211     ProgressIndicator oldIndicator = null;
212
213     boolean set = progress != null && progress != (oldIndicator = myThreadIndicator.get());
214     if (set) {
215       myThreadIndicator.set(progress);
216     }
217
218     try {
219       process.run();
220     }
221     finally {
222       if (set) {
223         myThreadIndicator.set(oldIndicator);
224       }
225     }
226   }
227 }