1 11 package org.eclipse.jface.operation; 12 13 import java.lang.reflect.InvocationTargetException ; 14 15 import org.eclipse.core.runtime.IProgressMonitor; 16 import org.eclipse.core.runtime.OperationCanceledException; 17 import org.eclipse.core.runtime.ProgressMonitorWrapper; 18 import org.eclipse.core.runtime.Assert; 19 import org.eclipse.swt.widgets.Display; 20 21 32 public class ModalContext { 33 34 38 private static boolean debug = false; 39 40 44 private static int modalLevel = 0; 45 46 51 private static boolean runInSeparateThread = true; 52 53 56 private static class ModalContextThread extends Thread { 57 60 private IRunnableWithProgress runnable; 61 62 65 private Throwable throwable; 66 67 70 private IProgressMonitor progressMonitor; 71 72 75 private Display display; 76 77 80 private volatile boolean continueEventDispatching = true; 81 82 87 private Thread callingThread; 88 89 97 private ModalContextThread(IRunnableWithProgress operation, 98 IProgressMonitor monitor, Display display) { 99 super("ModalContext"); Assert.isTrue(monitor != null && display != null); 101 runnable = operation; 102 progressMonitor = new AccumulatingProgressMonitor(monitor, display); 103 this.display = display; 104 this.callingThread = Thread.currentThread(); 105 } 106 107 110 public void run() { 111 try { 112 if (runnable != null) { 113 runnable.run(progressMonitor); 114 } 115 } catch (InvocationTargetException e) { 116 throwable = e; 117 } catch (InterruptedException e) { 118 throwable = e; 119 } catch (RuntimeException e) { 120 throwable = e; 121 } catch (ThreadDeath e) { 122 throw e; 124 } catch (Error e) { 125 throwable = e; 126 } finally { 127 if (runnable instanceof IThreadListener) { 129 ((IThreadListener)runnable).threadChange(callingThread); 130 } 131 132 display.syncExec(new Runnable () { 135 public void run() { 136 } 138 }); 139 140 continueEventDispatching = false; 142 143 display.asyncExec(null); 146 } 147 } 148 149 152 public void block() { 153 if (display == Display.getCurrent()) { 154 while (continueEventDispatching) { 155 try { 158 if (!display.readAndDispatch()) { 159 display.sleep(); 160 } 161 } 162 catch (ThreadDeath e) { 165 throw (e); 166 } 167 catch (Throwable e) { 169 System.err.println("Unhandled event loop exception during blocked modal context."); e.printStackTrace(); 171 } 172 } 173 } else { 174 try { 175 join(); 176 } catch (InterruptedException e) { 177 throwable = e; 178 } 179 } 180 } 181 } 182 183 193 public static boolean canProgressMonitorBeUsed(IProgressMonitor monitor1, 194 IProgressMonitor monitor2) { 195 if (monitor1 == monitor2) { 196 return true; 197 } 198 199 while (monitor1 instanceof ProgressMonitorWrapper) { 200 monitor1 = ((ProgressMonitorWrapper) monitor1) 201 .getWrappedProgressMonitor(); 202 if (monitor1 == monitor2) { 203 return true; 204 } 205 } 206 return false; 207 } 208 209 228 public static void checkCanceled(IProgressMonitor monitor) 229 throws InterruptedException { 230 if (monitor.isCanceled()) { 231 throw new InterruptedException (); 232 } 233 } 234 235 238 private static ModalContextThread getCurrentModalContextThread() { 239 Thread t = Thread.currentThread(); 240 if (t instanceof ModalContextThread) { 241 return (ModalContextThread) t; 242 } 243 return null; 244 } 245 246 258 public static int getModalLevel() { 259 return modalLevel; 260 } 261 262 268 public static boolean isModalContextThread(Thread thread) { 269 return thread instanceof ModalContextThread; 270 } 271 272 301 public static void run(IRunnableWithProgress operation, boolean fork, 302 IProgressMonitor monitor, Display display) 303 throws InvocationTargetException , InterruptedException { 304 Assert.isTrue(operation != null && monitor != null); 305 306 modalLevel++; 307 try { 308 if (monitor != null) { 309 monitor.setCanceled(false); 310 } 311 if (!fork || !runInSeparateThread) { 313 runInCurrentThread(operation, monitor); 314 } else { 315 ModalContextThread t = getCurrentModalContextThread(); 316 if (t != null) { 317 Assert.isTrue(canProgressMonitorBeUsed(monitor, 318 t.progressMonitor)); 319 runInCurrentThread(operation, monitor); 320 } else { 321 t = new ModalContextThread(operation, monitor, display); 322 if (operation instanceof IThreadListener) { 323 ((IThreadListener)operation).threadChange(t); 324 } 325 t.start(); 326 t.block(); 327 Throwable throwable = t.throwable; 328 if (throwable != null) { 329 if (debug 330 && !(throwable instanceof InterruptedException ) 331 && !(throwable instanceof OperationCanceledException)) { 332 System.err 333 .println("Exception in modal context operation:"); throwable.printStackTrace(); 335 System.err.println("Called from:"); new InvocationTargetException (null) 339 .printStackTrace(); 340 } 341 if (throwable instanceof InvocationTargetException ) { 342 throw (InvocationTargetException ) throwable; 343 } else if (throwable instanceof InterruptedException ) { 344 throw (InterruptedException ) throwable; 345 } else if (throwable instanceof OperationCanceledException) { 346 throw new InterruptedException (throwable 348 .getMessage()); 349 } else { 350 throw new InvocationTargetException (throwable); 351 } 352 } 353 } 354 } 355 } finally { 356 modalLevel--; 357 } 358 } 359 360 364 private static void runInCurrentThread(IRunnableWithProgress runnable, 365 IProgressMonitor progressMonitor) throws InterruptedException , 366 InvocationTargetException { 367 try { 368 if (runnable != null) { 369 runnable.run(progressMonitor); 370 } 371 } catch (InvocationTargetException e) { 372 throw e; 373 } catch (InterruptedException e) { 374 throw e; 375 } catch (OperationCanceledException e) { 376 throw new InterruptedException (); 377 } catch (ThreadDeath e) { 378 throw e; 380 } catch (RuntimeException e) { 381 throw new InvocationTargetException (e); 382 } catch (Error e) { 383 throw new InvocationTargetException (e); 384 } 385 } 386 387 393 public static void setDebugMode(boolean debugMode) { 394 debug = debugMode; 395 } 396 397 406 public static void setAllowReadAndDispatch(boolean allowReadAndDispatch) { 407 runInSeparateThread = allowReadAndDispatch; 409 } 410 } 411 | Popular Tags |