001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal.dialogs;
011:
012: import org.eclipse.core.runtime.IProgressMonitor;
013: import org.eclipse.core.runtime.IProgressMonitorWithBlocking;
014: import org.eclipse.core.runtime.IStatus;
015: import org.eclipse.core.runtime.ProgressMonitorWrapper;
016: import org.eclipse.jface.dialogs.Dialog;
017: import org.eclipse.swt.widgets.Display;
018: import org.eclipse.ui.internal.ExceptionHandler;
019:
020: /**
021: * Used to run an event loop whenever progress monitor methods
022: * are invoked. <p>
023: * This is needed since editor save operations are done in the UI thread.
024: * Although save operations should be written to do the work in the non-UI thread,
025: * this was not done for 1.0, so this was added to keep the UI live
026: * (including allowing the cancel button to work).
027: */
028: public class EventLoopProgressMonitor extends ProgressMonitorWrapper
029: implements IProgressMonitorWithBlocking {
030: /**
031: * Threshold for how often the event loop is spun, in ms.
032: */
033: private static int T_THRESH = 100;
034:
035: /**
036: * Maximum amount of time to spend processing events, in ms.
037: */
038: private static int T_MAX = 50;
039:
040: /**
041: * Last time the event loop was spun.
042: */
043: private long lastTime = System.currentTimeMillis();
044:
045: /**
046: * The task name is the name of the current task
047: * in the event loop.
048: */
049: private String taskName;
050:
051: /**
052: * Constructs a new instance of the receiver and forwards to monitor.
053: * @param monitor
054: */
055: public EventLoopProgressMonitor(IProgressMonitor monitor) {
056: super (monitor);
057: }
058:
059: /**
060: * @see IProgressMonitor#beginTask
061: */
062: public void beginTask(String name, int totalWork) {
063: super .beginTask(name, totalWork);
064: taskName = name;
065: runEventLoop();
066: }
067:
068: /* (non-Javadoc)
069: * @see org.eclipse.core.runtime.IProgressMonitorWithBlocking#clearBlocked()
070: */
071: public void clearBlocked() {
072: Dialog.getBlockedHandler().clearBlocked();
073: }
074:
075: /**
076: * @see IProgressMonitor#done
077: */
078: public void done() {
079: super .done();
080: taskName = null;
081: runEventLoop();
082: }
083:
084: /**
085: * @see IProgressMonitor#internalWorked
086: */
087: public void internalWorked(double work) {
088: super .internalWorked(work);
089: runEventLoop();
090: }
091:
092: /**
093: * @see IProgressMonitor#isCanceled
094: */
095: public boolean isCanceled() {
096: runEventLoop();
097: return super .isCanceled();
098: }
099:
100: /**
101: * Runs an event loop.
102: */
103: private void runEventLoop() {
104: // Only run the event loop so often, as it is expensive on some platforms
105: // (namely Motif).
106: long t = System.currentTimeMillis();
107: if (t - lastTime < T_THRESH) {
108: return;
109: }
110: lastTime = t;
111: // Run the event loop.
112: Display disp = Display.getDefault();
113: if (disp == null) {
114: return;
115: }
116:
117: //Initialize an exception handler from the window class.
118: ExceptionHandler handler = ExceptionHandler.getInstance();
119:
120: for (;;) {
121: try {
122: if (!disp.readAndDispatch()) {
123: break;
124: }
125: } catch (Throwable e) {//Handle the exception the same way as the workbench
126: handler.handleException(e);
127: break;
128: }
129:
130: // Only run the event loop for so long.
131: // Otherwise, this would never return if some other thread was
132: // constantly generating events.
133: if (System.currentTimeMillis() - t > T_MAX) {
134: break;
135: }
136: }
137: }
138:
139: /* (non-Javadoc)
140: * @see org.eclipse.core.runtime.IProgressMonitorWithBlocking#setBlocked(org.eclipse.core.runtime.IStatus)
141: */
142: public void setBlocked(IStatus reason) {
143: Dialog.getBlockedHandler().showBlocked(this , reason, taskName);
144: }
145:
146: /**
147: * @see IProgressMonitor#setCanceled
148: */
149: public void setCanceled(boolean b) {
150: super .setCanceled(b);
151: taskName = null;
152: runEventLoop();
153: }
154:
155: /**
156: * @see IProgressMonitor#setTaskName
157: */
158: public void setTaskName(String name) {
159: super .setTaskName(name);
160: taskName = name;
161: runEventLoop();
162: }
163:
164: /**
165: * @see IProgressMonitor#subTask
166: */
167: public void subTask(String name) {
168: //Be prepared in case the first task was null
169: if (taskName == null) {
170: taskName = name;
171: }
172: super .subTask(name);
173: runEventLoop();
174: }
175:
176: /**
177: * @see IProgressMonitor#worked
178: */
179: public void worked(int work) {
180: super .worked(work);
181: runEventLoop();
182: }
183:
184: /**
185: * Return the name of the current task.
186: * @return Returns the taskName.
187: */
188: protected String getTaskName() {
189: return taskName;
190: }
191: }
|