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