OSDN Git Service

547bc37ba10209bbacb8c820fd37fb59d49e1839
[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      * Constructs a new {@link TaskMonitorImpl} that relies on the given\r
42      * {@link IProgressUiProvider} to change the user interface.\r
43      * @param ui The {@link IProgressUiProvider}. Cannot be null.\r
44      */\r
45     public TaskMonitorImpl(IProgressUiProvider ui) {\r
46         mUi = ui;\r
47     }\r
48 \r
49     /** Returns the {@link IProgressUiProvider} passed to the constructor. */\r
50     public IProgressUiProvider getUiProvider() {\r
51         return mUi;\r
52     }\r
53 \r
54     /**\r
55      * Sets the description in the current task dialog.\r
56      * This method can be invoked from a non-UI thread.\r
57      */\r
58     public void setDescription(String format, Object... args) {\r
59         final String text = String.format(format, args);\r
60         mUi.setDescription(text);\r
61     }\r
62 \r
63     /**\r
64      * Logs a "normal" information line.\r
65      * This method can be invoked from a non-UI thread.\r
66      */\r
67     public void log(String format, Object... args) {\r
68         String text = String.format(format, args);\r
69         mUi.log(text);\r
70     }\r
71 \r
72     /**\r
73      * Logs an "error" information line.\r
74      * This method can be invoked from a non-UI thread.\r
75      */\r
76     public void logError(String format, Object... args) {\r
77         String text = String.format(format, args);\r
78         mUi.logError(text);\r
79     }\r
80 \r
81     /**\r
82      * Logs a "verbose" information line, that is extra details which are typically\r
83      * not that useful for the end-user and might be hidden until explicitly shown.\r
84      * This method can be invoked from a non-UI thread.\r
85      */\r
86     public void logVerbose(String format, Object... args) {\r
87         String text = String.format(format, args);\r
88         mUi.logVerbose(text);\r
89     }\r
90 \r
91     /**\r
92      * Sets the max value of the progress bar.\r
93      * This method can be invoked from a non-UI thread.\r
94      *\r
95      * Weird things will happen if setProgressMax is called multiple times\r
96      * *after* {@link #incProgress(int)}: we don't try to adjust it on the\r
97      * fly.\r
98      *\r
99      * @see ProgressBar#setMaximum(int)\r
100      */\r
101     public void setProgressMax(int max) {\r
102         assert max > 0;\r
103         // Always set the dialog's progress max to 10k since it only handles\r
104         // integers and we want to have a better inner granularity. Instead\r
105         // we use the max to compute a coefficient for inc deltas.\r
106         mUi.setProgressMax((int) MAX_COUNT);\r
107         mIncCoef = max > 0 ? MAX_COUNT / max : 0;\r
108         assert mIncCoef > 0;\r
109     }\r
110 \r
111     public int getProgressMax() {\r
112         return mIncCoef > 0 ? (int) (MAX_COUNT / mIncCoef) : 0;\r
113     }\r
114 \r
115     /**\r
116      * Increments the current value of the progress bar.\r
117      *\r
118      * This method can be invoked from a non-UI thread.\r
119      */\r
120     public void incProgress(int delta) {\r
121         if (delta > 0 && mIncCoef > 0) {\r
122             internalIncProgress(delta * mIncCoef);\r
123         }\r
124     }\r
125 \r
126     private void internalIncProgress(double realDelta) {\r
127         mValue += realDelta;\r
128         mUi.setProgress((int)mValue);\r
129     }\r
130 \r
131     /**\r
132      * Returns the current value of the progress bar,\r
133      * between 0 and up to {@link #setProgressMax(int)} - 1.\r
134      *\r
135      * This method can be invoked from a non-UI thread.\r
136      */\r
137     public int getProgress() {\r
138         // mIncCoef is 0 if setProgressMax hasn't been used yet.\r
139         return mIncCoef > 0 ? (int)(mUi.getProgress() / mIncCoef) : 0;\r
140     }\r
141 \r
142     /**\r
143      * Returns true if the "Cancel" button was selected.\r
144      * It is up to the task thread to pool this and exit.\r
145      */\r
146     public boolean isCancelRequested() {\r
147         return mUi.isCancelRequested();\r
148     }\r
149 \r
150     /**\r
151      * Display a yes/no question dialog box.\r
152      *\r
153      * This implementation allow this to be called from any thread, it\r
154      * makes sure the dialog is opened synchronously in the ui thread.\r
155      *\r
156      * @param title The title of the dialog box\r
157      * @param message The error message\r
158      * @return true if YES was clicked.\r
159      */\r
160     public boolean displayPrompt(final String title, final String message) {\r
161         return mUi.displayPrompt(title, message);\r
162     }\r
163 \r
164     /**\r
165      * Creates a sub-monitor that will use up to tickCount on the progress bar.\r
166      * tickCount must be 1 or more.\r
167      */\r
168     public ITaskMonitor createSubMonitor(int tickCount) {\r
169         assert mIncCoef > 0;\r
170         assert tickCount > 0;\r
171         return new SubTaskMonitor(this, null, mValue, tickCount * mIncCoef);\r
172     }\r
173 \r
174     // ----- ISdkLog interface ----\r
175 \r
176     public void error(Throwable throwable, String errorFormat, Object... arg) {\r
177         if (errorFormat != null) {\r
178             logError("Error: " + errorFormat, arg);\r
179         }\r
180 \r
181         if (throwable != null) {\r
182             logError("%s", throwable.getMessage()); //$NON-NLS-1$\r
183         }\r
184     }\r
185 \r
186     public void warning(String warningFormat, Object... arg) {\r
187         log("Warning: " + warningFormat, arg);\r
188     }\r
189 \r
190     public void printf(String msgFormat, Object... arg) {\r
191         log(msgFormat, arg);\r
192     }\r
193 \r
194     // ----- Sub Monitor -----\r
195 \r
196     private static class SubTaskMonitor implements ISubTaskMonitor {\r
197 \r
198         private final TaskMonitorImpl mRoot;\r
199         private final ISubTaskMonitor mParent;\r
200         private final double mStart;\r
201         private final double mSpan;\r
202         private double mSubValue;\r
203         private double mSubCoef;\r
204 \r
205         /**\r
206          * Creates a new sub task monitor which will work for the given range [start, start+span]\r
207          * in its parent.\r
208          *\r
209          * @param taskMonitor The ProgressTask root\r
210          * @param parent The immediate parent. Can be the null or another sub task monitor.\r
211          * @param start The start value in the root's coordinates\r
212          * @param span The span value in the root's coordinates\r
213          */\r
214         public SubTaskMonitor(TaskMonitorImpl taskMonitor,\r
215                 ISubTaskMonitor parent,\r
216                 double start,\r
217                 double span) {\r
218             mRoot = taskMonitor;\r
219             mParent = parent;\r
220             mStart = start;\r
221             mSpan = span;\r
222             mSubValue = start;\r
223         }\r
224 \r
225         public boolean isCancelRequested() {\r
226             return mRoot.isCancelRequested();\r
227         }\r
228 \r
229         public void setDescription(String format, Object... args) {\r
230             mRoot.setDescription(format, args);\r
231         }\r
232 \r
233         public void log(String format, Object... args) {\r
234             mRoot.log(format, args);\r
235         }\r
236 \r
237         public void logError(String format, Object... args) {\r
238             mRoot.logError(format, args);\r
239         }\r
240 \r
241         public void logVerbose(String format, Object... args) {\r
242             mRoot.logVerbose(format, args);\r
243         }\r
244 \r
245         public void setProgressMax(int max) {\r
246             assert max > 0;\r
247             mSubCoef = max > 0 ? mSpan / max : 0;\r
248             assert mSubCoef > 0;\r
249         }\r
250 \r
251         public int getProgressMax() {\r
252             return mSubCoef > 0 ? (int) (mSpan / mSubCoef) : 0;\r
253         }\r
254 \r
255         public int getProgress() {\r
256             assert mSubCoef > 0;\r
257             return mSubCoef > 0 ? (int)((mSubValue - mStart) / mSubCoef) : 0;\r
258         }\r
259 \r
260         public void incProgress(int delta) {\r
261             if (delta > 0 && mSubCoef > 0) {\r
262                 subIncProgress(delta * mSubCoef);\r
263             }\r
264         }\r
265 \r
266         public void subIncProgress(double realDelta) {\r
267             mSubValue += realDelta;\r
268             if (mParent != null) {\r
269                 mParent.subIncProgress(realDelta);\r
270             } else {\r
271                 mRoot.internalIncProgress(realDelta);\r
272             }\r
273         }\r
274 \r
275         public boolean displayPrompt(String title, String message) {\r
276             return mRoot.displayPrompt(title, message);\r
277         }\r
278 \r
279         public ITaskMonitor createSubMonitor(int tickCount) {\r
280             assert mSubCoef > 0;\r
281             assert tickCount > 0;\r
282             return new SubTaskMonitor(mRoot,\r
283                     this,\r
284                     mSubValue,\r
285                     tickCount * mSubCoef);\r
286         }\r
287 \r
288         // ----- ISdkLog interface ----\r
289 \r
290         public void error(Throwable throwable, String errorFormat, Object... arg) {\r
291             mRoot.error(throwable, errorFormat, arg);\r
292         }\r
293 \r
294         public void warning(String warningFormat, Object... arg) {\r
295             mRoot.warning(warningFormat, arg);\r
296         }\r
297 \r
298         public void printf(String msgFormat, Object... arg) {\r
299             mRoot.printf(msgFormat, arg);\r
300         }\r
301     }\r
302 }\r