1 19 20 21 package org.netbeans.progress.module; 22 23 import java.awt.Component ; 24 import java.awt.event.ActionListener ; 25 import java.util.ArrayList ; 26 import java.util.Collection ; 27 import java.util.Collections ; 28 import java.util.HashMap ; 29 import java.util.Iterator ; 30 import java.util.List ; 31 import java.util.logging.Level ; 32 import java.util.logging.Logger ; 33 import javax.swing.SwingUtilities ; 34 import javax.swing.Timer ; 35 import org.netbeans.progress.spi.InternalHandle; 36 import org.netbeans.progress.spi.ProgressEvent; 37 import org.netbeans.progress.spi.ProgressUIWorker; 38 import org.netbeans.progress.spi.ProgressUIWorkerProvider; 39 import org.netbeans.progress.spi.ProgressUIWorkerWithModel; 40 import org.netbeans.progress.spi.TaskModel; 41 import org.openide.util.Lookup; 42 43 47 public class Controller implements Runnable , ActionListener { 48 49 public static Controller defaultInstance; 51 52 private ProgressUIWorker component; 53 private TaskModel model; 54 private List <ProgressEvent> eventQueue; 55 private boolean dispatchRunning; 56 protected Timer timer; 57 private long timerStart = 0; 58 private static final int TIMER_QUANTUM = 400; 59 60 64 public static final int INITIAL_DELAY = 500; 65 66 67 public Controller(ProgressUIWorker comp) { 68 component = comp; 69 model = new TaskModel(); 70 eventQueue = new ArrayList <ProgressEvent>(); 71 dispatchRunning = false; 72 timer = new Timer (TIMER_QUANTUM, this); 73 timer.setRepeats(false); 74 } 75 76 public static synchronized Controller getDefault() { 77 if (defaultInstance == null) { 78 ProgressUIWorkerProvider prov = Lookup.getDefault().lookup(ProgressUIWorkerProvider.class); 79 if (prov == null) { 80 Logger.getLogger(Controller.class.getName()).log(Level.CONFIG, "Using fallback trivial progress implementation"); 81 prov = new TrivialProgressUIWorkerProvider(); 82 } 83 ProgressUIWorkerWithModel component = prov.getDefaultWorker(); 84 defaultInstance = new Controller(component); 85 component.setModel(defaultInstance.getModel()); 86 } 87 return defaultInstance; 88 } 89 90 Component getVisualComponent() { 92 if (component instanceof Component ) { 93 return (Component )component; 94 } 95 return null; 96 } 97 98 99 public TaskModel getModel() { 100 return model; 101 } 102 103 public void start(InternalHandle handle) { 104 ProgressEvent event = new ProgressEvent(handle, ProgressEvent.TYPE_START, isWatched(handle)); 105 if (this == getDefault() && handle.getInitialDelay() > 100) { 106 postEvent(event, true); 108 } else { 109 runImmediately(Collections.singleton(event)); 110 } 111 } 112 113 public void finish(InternalHandle handle) { 114 ProgressEvent event = new ProgressEvent(handle, ProgressEvent.TYPE_FINISH, isWatched(handle)); 115 postEvent(event); 116 } 117 118 public void toIndeterminate(InternalHandle handle) { 119 ProgressEvent event = new ProgressEvent(handle, ProgressEvent.TYPE_SWITCH, isWatched(handle)); 120 postEvent(event); 121 } 122 123 public void toSilent(InternalHandle handle, String message) { 124 ProgressEvent event = new ProgressEvent(handle, ProgressEvent.TYPE_SILENT, isWatched(handle), message); 125 postEvent(event); 126 } 127 128 129 public void toDeterminate(InternalHandle handle) { 130 ProgressEvent event = new ProgressEvent(handle, ProgressEvent.TYPE_SWITCH, isWatched(handle)); 131 postEvent(event); 132 } 133 134 public void progress(InternalHandle handle, String msg, 135 int units, int percentage, long estimate) { 136 ProgressEvent event = new ProgressEvent(handle, msg, units, percentage, estimate, isWatched(handle)); 137 postEvent(event); 138 } 139 140 public ProgressEvent snapshot(InternalHandle handle, String msg, 141 int units, int percentage, long estimate) { 142 if (handle.isInSleepMode()) { 143 return new ProgressEvent(handle, ProgressEvent.TYPE_SILENT, isWatched(handle), msg); 144 } 145 return new ProgressEvent(handle, msg, units, percentage, estimate, isWatched(handle)); 146 } 147 148 149 public void explicitSelection(InternalHandle handle) { 150 InternalHandle old = model.getExplicitSelection(); 151 model.explicitlySelect(handle); 152 Collection <ProgressEvent> evnts = new ArrayList <ProgressEvent>(); 153 evnts.add(handle.requestStateSnapshot()); 154 if (old != null && old != handle) { 155 evnts.add(old.requestStateSnapshot()); 157 } 158 runImmediately(evnts); 159 } 160 161 public void displayNameChange(InternalHandle handle, int units, int percentage, long estimate, String display) { 162 Collection <ProgressEvent> evnts = new ArrayList <ProgressEvent>(); 163 evnts.add(new ProgressEvent(handle, null, units, percentage, estimate, isWatched(handle), display)); 164 runImmediately(evnts); 165 } 166 167 private boolean isWatched(InternalHandle hndl) { 168 return model.getExplicitSelection() == hndl; 169 } 170 171 174 void runImmediately(Collection <ProgressEvent> events) { 175 synchronized (this) { 176 eventQueue.addAll(events); 178 dispatchRunning = true; 179 } 180 if (SwingUtilities.isEventDispatchThread()) { 182 run(); 183 } else { 184 SwingUtilities.invokeLater(this); 185 } 186 187 } 188 189 void postEvent(final ProgressEvent event) { 190 postEvent(event, false); 191 } 192 193 void postEvent(final ProgressEvent event, boolean shortenPeriod) { 194 synchronized (this) { 195 eventQueue.add(event); 196 if (!dispatchRunning) { 197 timerStart = System.currentTimeMillis(); 198 int delay = timer.getInitialDelay(); 199 if (shortenPeriod && timer.getInitialDelay() > event.getSource().getInitialDelay()) { 201 delay = event.getSource().getInitialDelay(); 202 } 203 dispatchRunning = true; 204 resetTimer(delay, true); 205 } else if (shortenPeriod) { 206 if (System.currentTimeMillis() - timerStart > event.getSource().getInitialDelay()) { 209 resetTimer(event.getSource().getInitialDelay(), true); 210 } 211 } 212 } 213 } 214 215 protected void resetTimer(int initialDelay, boolean restart) { 216 timer.setInitialDelay(initialDelay); 217 if (restart) { 218 timer.restart(); 219 } 220 } 221 222 223 226 public void run() { 227 HashMap <InternalHandle, ProgressEvent> map = new HashMap <InternalHandle, ProgressEvent>(); 228 boolean hasShortOne = false; 229 long minDiff = TIMER_QUANTUM; 230 231 InternalHandle oldSelected = model.getSelectedHandle(); 232 long stamp = System.currentTimeMillis(); 233 synchronized (this) { 234 Iterator <ProgressEvent> it = eventQueue.iterator(); 235 Collection <InternalHandle> justStarted = new ArrayList <InternalHandle>(); 236 while (it.hasNext()) { 237 ProgressEvent event = it.next(); 238 boolean isShort = (stamp - event.getSource().getTimeStampStarted()) < event.getSource().getInitialDelay(); 239 if (event.getType() == ProgressEvent.TYPE_START) { 240 if (event.getSource().isCustomPlaced() || !isShort) { 241 model.addHandle(event.getSource()); 242 } else { 243 justStarted.add(event.getSource()); 244 } 245 } 246 else if (event.getType() == ProgressEvent.TYPE_FINISH && 247 (! justStarted.contains(event.getSource()))) 248 { 249 model.removeHandle(event.getSource()); 250 } 251 ProgressEvent lastEvent = (ProgressEvent)map.get(event.getSource()); 252 if (lastEvent != null && event.getType() == ProgressEvent.TYPE_FINISH && 253 justStarted.contains(event.getSource()) && isShort) 254 { 255 map.remove(event.getSource()); 258 justStarted.remove(event.getSource()); 259 } else { 260 if (lastEvent != null) { 261 event.copyMessageFromEarlier(lastEvent); 263 if (lastEvent.isSwitched()) { 265 event.markAsSwitched(); 266 } 267 } 268 map.put(event.getSource(), event); 269 } 270 it.remove(); 271 } 272 Iterator <InternalHandle> startIt = justStarted.iterator(); 276 while (startIt.hasNext()) { 277 InternalHandle hndl = startIt.next(); 278 long diff = stamp - hndl.getTimeStampStarted(); 279 if (diff >= hndl.getInitialDelay()) { 280 model.addHandle(hndl); 281 } else { 282 eventQueue.add(new ProgressEvent(hndl, ProgressEvent.TYPE_START, isWatched(hndl))); 283 ProgressEvent evnt = (ProgressEvent)map.remove(hndl); 284 if (evnt.getType() != ProgressEvent.TYPE_START) { 285 eventQueue.add(evnt); 286 } 287 hasShortOne = true; 288 minDiff = Math.min(minDiff, hndl.getInitialDelay() - diff); 289 } 290 } 291 } 292 InternalHandle selected = model.getSelectedHandle(); 293 selected = selected == null ? oldSelected : selected; 294 Iterator <ProgressEvent> it = map.values().iterator(); 295 while (it.hasNext()) { 296 ProgressEvent event = it.next(); 297 if (selected == event.getSource()) { 298 component.processSelectedProgressEvent(event); 299 } 300 component.processProgressEvent(event); 301 } 302 synchronized (this) { 303 timer.stop(); 304 if (hasShortOne) { 305 timerStart = System.currentTimeMillis(); 306 resetTimer((int)Math.max(100, minDiff), true); 307 } else { 308 dispatchRunning = false; 309 resetTimer(TIMER_QUANTUM, false); 310 } 311 } 312 } 313 314 317 public void actionPerformed(java.awt.event.ActionEvent actionEvent) { 318 run(); 319 } 320 321 322 323 } 324 | Popular Tags |