OSDN Git Service

5286df53f72a05b5de3a86b17ceec8d58b7c5cc1
[android-x86/sdk.git] / sdkmanager / libs / sdkuilib / src / com / android / sdkuilib / internal / tasks / TaskMonitorImpl.java
1 /*\r
2  * Copyright (C) 2011 The Android Open Source Project\r
3  *\r
4  * Licensed under the Apache License, Version 2.0 (the "License");\r
5  * you may not use this file except in compliance with the License.\r
6  * You may obtain a copy of the License at\r
7  *\r
8  *      http://www.apache.org/licenses/LICENSE-2.0\r
9  *\r
10  * Unless required by applicable law or agreed to in writing, software\r
11  * distributed under the License is distributed on an "AS IS" BASIS,\r
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13  * See the License for the specific language governing permissions and\r
14  * limitations under the License.\r
15  */\r
16 \r
17 package com.android.sdkuilib.internal.tasks;\r
18 \r
19 import com.android.sdklib.internal.repository.ITaskMonitor;\r
20 \r
21 import org.eclipse.swt.widgets.ProgressBar;\r
22 \r
23 /**\r
24  * Internal class that implements the logic of an {@link ITaskMonitor}.\r
25  * It doesn't deal with any UI directly. Instead it delegates the UI to\r
26  * the provided {@link IProgressUiProvider}.\r
27  */\r
28 class TaskMonitorImpl implements ITaskMonitor {\r
29 \r
30     private static final double MAX_COUNT = 10000.0;\r
31 \r
32     private interface ISubTaskMonitor extends ITaskMonitor {\r
33         public void subIncProgress(double realDelta);\r
34     }\r
35 \r
36     private double mIncCoef = 0;\r
37     private double mValue = 0;\r
38     private final IProgressUiProvider mUi;\r
39 \r
40     /**\r
41      * Returns true if the given {@code monitor} is an instance of {@link TaskMonitorImpl}\r
42      * or its private SubTaskMonitor.\r
43      */\r
44     public static boolean isTaskMonitorImpl(ITaskMonitor monitor) {\r
45         return monitor instanceof TaskMonitorImpl || monitor instanceof SubTaskMonitor;\r
46     }\r
47 \r
48     /**\r
49      * Constructs a new {@link TaskMonitorImpl} that relies on the given\r
50      * {@link IProgressUiProvider} to change the user interface.\r
51      * @param ui The {@link IProgressUiProvider}. Cannot be null.\r
52      */\r
53     public TaskMonitorImpl(IProgressUiProvider ui) {\r
54         mUi = ui;\r
55     }\r
56 \r
57     /** Returns the {@link IProgressUiProvider} passed to the constructor. */\r
58     public IProgressUiProvider getUiProvider() {\r
59         return mUi;\r
60     }\r
61 \r
62     /**\r
63      * Sets the description in the current task dialog.\r
64      * This method can be invoked from a non-UI thread.\r
65      */\r
66     public void setDescription(String format, Object... args) {\r
67         final String text = String.format(format, args);\r
68         mUi.setDescription(text);\r
69     }\r
70 \r
71     /**\r
72      * Logs a "normal" information line.\r
73      * This method can be invoked from a non-UI thread.\r
74      */\r
75     public void log(String format, Object... args) {\r
76         String text = String.format(format, args);\r
77         mUi.log(text);\r
78     }\r
79 \r
80     /**\r
81      * Logs an "error" information line.\r
82      * This method can be invoked from a non-UI thread.\r
83      */\r
84     public void logError(String format, Object... args) {\r
85         String text = String.format(format, args);\r
86         mUi.logError(text);\r
87     }\r
88 \r
89     /**\r
90      * Logs a "verbose" information line, that is extra details which are typically\r
91      * not that useful for the end-user and might be hidden until explicitly shown.\r
92      * This method can be invoked from a non-UI thread.\r
93      */\r
94     public void logVerbose(String format, Object... args) {\r
95         String text = String.format(format, args);\r
96         mUi.logVerbose(text);\r
97     }\r
98 \r
99     /**\r
100      * Sets the max value of the progress bar.\r
101      * This method can be invoked from a non-UI thread.\r
102      *\r
103      * Weird things will happen if setProgressMax is called multiple times\r
104      * *after* {@link #incProgress(int)}: we don't try to adjust it on the\r
105      * fly.\r
106      *\r
107      * @see ProgressBar#setMaximum(int)\r
108      */\r
109     public void setProgressMax(int max) {\r
110         assert max > 0;\r
111         // Always set the dialog's progress max to 10k since it only handles\r
112         // integers and we want to have a better inner granularity. Instead\r
113         // we use the max to compute a coefficient for inc deltas.\r
114         mUi.setProgressMax((int) MAX_COUNT);\r
115         mIncCoef = max > 0 ? MAX_COUNT / max : 0;\r
116         assert mIncCoef > 0;\r
117     }\r
118 \r
119     public int getProgressMax() {\r
120         return mIncCoef > 0 ? (int) (MAX_COUNT / mIncCoef) : 0;\r
121     }\r
122 \r
123     /**\r
124      * Increments the current value of the progress bar.\r
125      *\r
126      * This method can be invoked from a non-UI thread.\r
127      */\r
128     public void incProgress(int delta) {\r
129         if (delta > 0 && mIncCoef > 0) {\r
130             internalIncProgress(delta * mIncCoef);\r
131         }\r
132     }\r
133 \r
134     private void internalIncProgress(double realDelta) {\r
135         mValue += realDelta;\r
136         mUi.setProgress((int)mValue);\r
137     }\r
138 \r
139     /**\r
140      * Returns the current value of the progress bar,\r
141      * between 0 and up to {@link #setProgressMax(int)} - 1.\r
142      *\r
143      * This method can be invoked from a non-UI thread.\r
144      */\r
145     public int getProgress() {\r
146         // mIncCoef is 0 if setProgressMax hasn't been used yet.\r
147         return mIncCoef > 0 ? (int)(mUi.getProgress() / mIncCoef) : 0;\r
148     }\r
149 \r
150     /**\r
151      * Returns true if the "Cancel" button was selected.\r
152      * It is up to the task thread to pool this and exit.\r
153      */\r
154     public boolean isCancelRequested() {\r
155         return mUi.isCancelRequested();\r
156     }\r
157 \r
158     /**\r
159      * Display a yes/no question dialog box.\r
160      *\r
161      * This implementation allow this to be called from any thread, it\r
162      * makes sure the dialog is opened synchronously in the ui thread.\r
163      *\r
164      * @param title The title of the dialog box\r
165      * @param message The error message\r
166      * @return true if YES was clicked.\r
167      */\r
168     public boolean displayPrompt(final String title, final String message) {\r
169         return mUi.displayPrompt(title, message);\r
170     }\r
171 \r
172     /**\r
173      * Creates a sub-monitor that will use up to tickCount on the progress bar.\r
174      * tickCount must be 1 or more.\r
175      */\r
176     public ITaskMonitor createSubMonitor(int tickCount) {\r
177         assert mIncCoef > 0;\r
178         assert tickCount > 0;\r
179         return new SubTaskMonitor(this, null, mValue, tickCount * mIncCoef);\r
180     }\r
181 \r
182     // ----- ISdkLog interface ----\r
183 \r
184     public void error(Throwable throwable, String errorFormat, Object... arg) {\r
185         if (errorFormat != null) {\r
186             logError("Error: " + errorFormat, arg);\r
187         }\r
188 \r
189         if (throwable != null) {\r
190             logError("%s", throwable.getMessage()); //$NON-NLS-1$\r
191         }\r
192     }\r
193 \r
194     public void warning(String warningFormat, Object... arg) {\r
195         log("Warning: " + warningFormat, arg);\r
196     }\r
197 \r
198     public void printf(String msgFormat, Object... arg) {\r
199         log(msgFormat, arg);\r
200     }\r
201 \r
202     // ----- Sub Monitor -----\r
203 \r
204     private static class SubTaskMonitor implements ISubTaskMonitor {\r
205 \r
206         private final TaskMonitorImpl mRoot;\r
207         private final ISubTaskMonitor mParent;\r
208         private final double mStart;\r
209         private final double mSpan;\r
210         private double mSubValue;\r
211         private double mSubCoef;\r
212 \r
213         /**\r
214          * Creates a new sub task monitor which will work for the given range [start, start+span]\r
215          * in its parent.\r
216          *\r
217          * @param taskMonitor The ProgressTask root\r
218          * @param parent The immediate parent. Can be the null or another sub task monitor.\r
219          * @param start The start value in the root's coordinates\r
220          * @param span The span value in the root's coordinates\r
221          */\r
222         public SubTaskMonitor(TaskMonitorImpl taskMonitor,\r
223                 ISubTaskMonitor parent,\r
224                 double start,\r
225                 double span) {\r
226             mRoot = taskMonitor;\r
227             mParent = parent;\r
228             mStart = start;\r
229             mSpan = span;\r
230             mSubValue = start;\r
231         }\r
232 \r
233         public boolean isCancelRequested() {\r
234             return mRoot.isCancelRequested();\r
235         }\r
236 \r
237         public void setDescription(String format, Object... args) {\r
238             mRoot.setDescription(format, args);\r
239         }\r
240 \r
241         public void log(String format, Object... args) {\r
242             mRoot.log(format, args);\r
243         }\r
244 \r
245         public void logError(String format, Object... args) {\r
246             mRoot.logError(format, args);\r
247         }\r
248 \r
249         public void logVerbose(String format, Object... args) {\r
250             mRoot.logVerbose(format, args);\r
251         }\r
252 \r
253         public void setProgressMax(int max) {\r
254             assert max > 0;\r
255             mSubCoef = max > 0 ? mSpan / max : 0;\r
256             assert mSubCoef > 0;\r
257         }\r
258 \r
259         public int getProgressMax() {\r
260             return mSubCoef > 0 ? (int) (mSpan / mSubCoef) : 0;\r
261         }\r
262 \r
263         public int getProgress() {\r
264             assert mSubCoef > 0;\r
265             return mSubCoef > 0 ? (int)((mSubValue - mStart) / mSubCoef) : 0;\r
266         }\r
267 \r
268         public void incProgress(int delta) {\r
269             if (delta > 0 && mSubCoef > 0) {\r
270                 subIncProgress(delta * mSubCoef);\r
271             }\r
272         }\r
273 \r
274         public void subIncProgress(double realDelta) {\r
275             mSubValue += realDelta;\r
276             if (mParent != null) {\r
277                 mParent.subIncProgress(realDelta);\r
278             } else {\r
279                 mRoot.internalIncProgress(realDelta);\r
280             }\r
281         }\r
282 \r
283         public boolean displayPrompt(String title, String message) {\r
284             return mRoot.displayPrompt(title, message);\r
285         }\r
286 \r
287         public ITaskMonitor createSubMonitor(int tickCount) {\r
288             assert mSubCoef > 0;\r
289             assert tickCount > 0;\r
290             return new SubTaskMonitor(mRoot,\r
291                     this,\r
292                     mSubValue,\r
293                     tickCount * mSubCoef);\r
294         }\r
295 \r
296         // ----- ISdkLog interface ----\r
297 \r
298         public void error(Throwable throwable, String errorFormat, Object... arg) {\r
299             mRoot.error(throwable, errorFormat, arg);\r
300         }\r
301 \r
302         public void warning(String warningFormat, Object... arg) {\r
303             mRoot.warning(warningFormat, arg);\r
304         }\r
305 \r
306         public void printf(String msgFormat, Object... arg) {\r
307             mRoot.printf(msgFormat, arg);\r
308         }\r
309     }\r
310 }\r