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