1 19 20 21 package org.netbeans.progress.spi; 22 23 import java.awt.event.ActionEvent ; 24 import java.util.logging.Level ; 25 import java.util.logging.Logger ; 26 import javax.swing.Action ; 27 import javax.swing.JComponent ; 28 import javax.swing.JLabel ; 29 import org.netbeans.progress.module.*; 30 import org.openide.util.Cancellable; 31 import org.openide.util.Lookup; 32 33 38 public final class InternalHandle { 39 40 private static final Logger LOG = Logger.getLogger(InternalHandle.class.getName()); 41 42 private String displayName; 43 private boolean customPlaced1 = false; 44 private boolean customPlaced2 = false; 45 private boolean customPlaced3 = false; 46 private int state; 47 private int totalUnits; 48 private int currentUnit; 49 private long initialEstimate; 50 private long timeStarted; 51 private long timeLastProgress; 52 private long timeSleepy = 0; 53 private String lastMessage; 54 private final Cancellable cancelable; 55 private final Action viewAction; 56 private final boolean userInitiated; 57 private int initialDelay = Controller.INITIAL_DELAY; 58 private Controller controller; 59 private ExtractedProgressUIWorker component; 60 61 public static final int STATE_INITIALIZED = 0; 62 public static final int STATE_RUNNING = 1; 63 public static final int STATE_FINISHED = 2; 64 public static final int STATE_REQUEST_STOP = 3; 65 66 public static final int NO_INCREASE = -2; 67 68 69 70 71 public InternalHandle(String displayName, 72 Cancellable cancel, 73 boolean userInitiated, 74 Action view) { 75 this.displayName = displayName; 76 this.userInitiated = userInitiated; 77 state = STATE_INITIALIZED; 78 totalUnits = 0; 79 lastMessage = null; 80 cancelable = cancel; 81 viewAction = view; 82 } 83 84 public String getDisplayName() { 85 return displayName; 86 } 87 88 91 public synchronized int getState() { 92 return state; 93 } 94 95 public boolean isAllowCancel() { 96 return cancelable != null && !isCustomPlaced(); 97 } 98 99 public boolean isAllowView() { 100 return viewAction != null && !isCustomPlaced(); 101 } 102 103 104 public boolean isCustomPlaced() { 105 return component != null; 106 } 107 108 public boolean isUserInitialized() { 109 return userInitiated; 110 } 111 112 private int getCurrentUnit() { 113 return currentUnit; 114 } 115 116 public int getTotalUnits() { 117 return totalUnits; 118 } 119 120 public void setInitialDelay(int millis) { 121 if (state != STATE_INITIALIZED) { 122 LOG.warning("Setting ProgressHandle.setInitialDelay() after the task is started has no effect"); return; 124 } 125 initialDelay = millis; 126 } 127 128 public int getInitialDelay() { 129 return initialDelay; 130 } 131 132 public synchronized void toSilent(String message) { 133 if (state != STATE_RUNNING && state != STATE_REQUEST_STOP) { 134 assert false : "cannot switch to silent mode when not running"; 135 } 136 timeLastProgress = System.currentTimeMillis(); 137 timeSleepy = timeLastProgress; 138 if (message != null) { 139 lastMessage = message; 140 } 141 controller.toSilent(this, message); 142 } 143 144 public boolean isInSleepMode() { 145 return timeSleepy == timeLastProgress; 146 } 147 148 public synchronized void toIndeterminate() { 149 if (state != STATE_RUNNING && state != STATE_REQUEST_STOP) { 150 assert false : "cannot switch to indeterminate mode when not running: " + state; 151 } 152 totalUnits = 0; 153 currentUnit = 0; 154 initialEstimate = -1; 155 timeLastProgress = System.currentTimeMillis(); 156 controller.toIndeterminate(this); 157 } 158 159 public synchronized void toDeterminate(int workunits, long estimate) { 160 if (state != STATE_RUNNING && state != STATE_REQUEST_STOP) { 161 assert false : "cannot switch to determinate mode when not running"; 162 } 163 if (workunits < 0) { 164 throw new IllegalArgumentException ("number of workunits cannot be negative"); 165 } 166 totalUnits = workunits; 167 currentUnit = 0; 168 initialEstimate = estimate; 169 timeLastProgress = System.currentTimeMillis(); 170 controller.toDeterminate(this); 171 } 172 173 181 public synchronized void start(String message, int workunits, long estimate) { 182 if (state != STATE_INITIALIZED) { 183 throw new IllegalStateException ("Cannot call start twice on a handle"); 184 } 185 if (workunits < 0) { 186 throw new IllegalArgumentException ("number of workunits cannot be negative"); 187 } 188 totalUnits = workunits; 189 currentUnit = 0; 190 if (message != null) { 191 lastMessage = message; 192 } 193 if (controller == null) { 194 controller = Controller.getDefault(); 195 } 196 state = STATE_RUNNING; 197 initialEstimate = estimate; 198 timeStarted = System.currentTimeMillis(); 199 timeLastProgress = timeStarted; 200 201 202 controller.start(this); 203 } 204 205 208 public synchronized void finish() { 209 if (state == STATE_INITIALIZED) { 210 throw new IllegalStateException ("Cannot finish not a started task"); 211 } 212 if (state == STATE_FINISHED) { 213 return; 214 } 215 state = STATE_FINISHED; 216 currentUnit = totalUnits; 217 218 controller.finish(this); 219 } 220 221 222 227 public synchronized void progress(String message, int workunit) { 228 if (state != STATE_RUNNING && state != STATE_REQUEST_STOP) { 229 return; 230 } 231 232 if (workunit != NO_INCREASE) { 233 if (workunit < currentUnit) { 234 throw new IllegalArgumentException ("Cannot decrease processed workunit count (" + workunit + ") to lower value than before (" + currentUnit + ")"); 235 } 236 if (workunit > totalUnits) { 237 LOG.log(Level.INFO, 240 "Cannot process more work than scheduled. " + 241 "Progress handle with name \"" + getDisplayName() + "\" has requested progress to workunit no." + workunit + 242 " but the total number of workunits is " + totalUnits + ". That means the progress bar UI will not display real progress and will stay at 100%.", 243 new IllegalArgumentException () 244 ); 245 workunit = totalUnits; 246 } 247 currentUnit = workunit; 248 } 249 if (message != null) { 250 lastMessage = message; 251 } 252 timeLastProgress = System.currentTimeMillis(); 253 254 controller.progress(this, message, currentUnit, 255 totalUnits > 0 ? getPercentageDone() : -1, 256 (initialEstimate == -1 ? -1 : calculateFinishEstimate())); 257 } 258 259 260 262 public void requestCancel() { 263 if (!isAllowCancel()) { 264 return; 265 } 266 synchronized (this) { 267 state = STATE_REQUEST_STOP; 268 } 269 cancelable.cancel(); 273 synchronized (this) { 274 requestStateSnapshot(); 275 } 276 } 277 278 public void requestView() { 280 if (!isAllowView()) { 281 return; 282 } 283 viewAction.actionPerformed(new ActionEvent (viewAction, ActionEvent.ACTION_PERFORMED, "performView")); 284 } 285 286 public synchronized void requestExplicitSelection() { 288 if (!isInSleepMode()) { 289 timeLastProgress = System.currentTimeMillis(); 290 } 291 controller.explicitSelection(this); 292 } 293 294 public synchronized void requestDisplayNameChange(String newDisplayName) { 295 displayName = newDisplayName; 296 if (state == STATE_INITIALIZED) { 297 return; 298 } 299 timeLastProgress = System.currentTimeMillis(); 300 controller.displayNameChange(this, currentUnit, 301 totalUnits > 0 ? getPercentageDone() : -1, 302 (initialEstimate == -1 ? -1 : calculateFinishEstimate()), newDisplayName); 303 } 304 305 public synchronized ProgressEvent requestStateSnapshot() { 307 if (!isInSleepMode()) { 308 timeLastProgress = System.currentTimeMillis(); 309 } 310 return controller.snapshot(this, lastMessage, currentUnit, 311 totalUnits > 0 ? getPercentageDone() : -1, 312 (initialEstimate == -1 ? -1 : calculateFinishEstimate())); 313 } 314 315 private void createExtractedWorker() { 316 if (component == null) { 317 ProgressUIWorkerProvider prov = Lookup.getDefault().lookup(ProgressUIWorkerProvider.class); 318 if (prov == null) { 319 LOG.log(Level.CONFIG, "Using fallback trivial progress implementation"); 320 prov = new TrivialProgressUIWorkerProvider(); 321 } 322 component = prov.getExtractedComponentWorker(); 323 controller = new Controller(component); 324 } 325 } 326 329 public synchronized JComponent extractComponent() { 330 if (customPlaced1) { 331 throw new IllegalStateException ("Cannot retrieve progress component multiple times"); 332 } 333 if (state != STATE_INITIALIZED) { 334 throw new IllegalStateException ("You can request custom placement of progress component only before starting the task"); 335 } 336 customPlaced1 = true; 337 createExtractedWorker(); 338 return component.getProgressComponent(); 339 } 340 341 public synchronized JLabel extractDetailLabel() { 342 if (customPlaced2) { 343 throw new IllegalStateException ("Cannot retrieve progress detail label component multiple times"); 344 } 345 if (state != STATE_INITIALIZED) { 346 throw new IllegalStateException ("You can request custom placement of progress component only before starting the task"); 347 } 348 customPlaced2 = true; 349 createExtractedWorker(); 350 return component.getDetailLabelComponent(); 351 } 352 353 public synchronized JLabel extractMainLabel() { 354 if (customPlaced3) { 355 throw new IllegalStateException ("Cannot retrieve progress main label component multiple times"); 356 } 357 if (state != STATE_INITIALIZED) { 358 throw new IllegalStateException ("You can request custom placement of progress component only before starting the task"); 359 } 360 customPlaced3 = true; 361 createExtractedWorker(); 362 return component.getMainLabelComponent(); 363 } 364 365 long calculateFinishEstimate() { 366 367 double durationSoFar = ((double)(System.currentTimeMillis() - timeStarted)) / 1000; 369 if (initialEstimate == -1) { 370 return (long)(durationSoFar * (totalUnits - currentUnit) / totalUnits); 372 } else { 373 long remainingUnits = (totalUnits - currentUnit); 376 double remainingPortion = (double)remainingUnits / (double)totalUnits; 377 double currentEstimate = durationSoFar / (double)currentUnit * totalUnits; 378 long retValue = (long)(((initialEstimate * remainingUnits * remainingPortion) 379 + (currentEstimate * remainingUnits * (1 - remainingPortion))) 380 / totalUnits); 381 return retValue; 382 } 383 } 384 387 public int getPercentageDone() { 388 return (int)((long)currentUnit * 100 / (long)totalUnits); 389 } 390 391 public long getTimeStampStarted() { 392 return timeStarted; 393 } 394 395 396 397 } 398 | Popular Tags |