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