| /* |
| * (c) Copyright IBM Corp. 2000, 2001. |
| * All Rights Reserved. |
| */ |
| package org.eclipse.compare.internal; |
| |
| import java.lang.reflect.InvocationTargetException; |
| |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.graphics.*; |
| import org.eclipse.swt.layout.*; |
| import org.eclipse.swt.widgets.*; |
| |
| import org.eclipse.jface.dialogs.*; |
| import org.eclipse.jface.operation.*; |
| import org.eclipse.jface.resource.JFaceResources; |
| |
| import org.eclipse.core.runtime.*; |
| |
| /** |
| * A modal dialog that displays progress during a long running operation. |
| */ |
| public class TimeoutContext { |
| |
| private static class ModalContextThread extends Thread { |
| |
| private boolean fWorking; |
| private IRunnableWithProgress fRunnable; |
| private Throwable fThrowable; |
| private IProgressMonitor fProgressMonitor; |
| private boolean fContinueEventDispatching= true; |
| private Display fDisplay; |
| |
| private ModalContextThread(IRunnableWithProgress operation, IProgressMonitor monitor) { |
| super("TimeoutContext"); //$NON-NLS-1$ |
| fRunnable= operation; |
| fProgressMonitor= monitor; |
| } |
| |
| synchronized boolean timeout(Display display) { |
| fDisplay= display; |
| return fWorking; |
| } |
| |
| public void run() { |
| try { |
| fWorking= true; |
| if (fRunnable != null) |
| fRunnable.run(fProgressMonitor); |
| } catch (InvocationTargetException e) { |
| fThrowable= e; |
| } catch (InterruptedException e) { |
| fThrowable= e; |
| } catch (RuntimeException e) { |
| fThrowable= e; |
| } catch (ThreadDeath e) { |
| // Make sure to propagate ThreadDeath, or threads will never fully terminate |
| throw e; |
| } catch (Error e) { |
| fThrowable= e; |
| } finally { |
| fWorking= false; |
| |
| if (fDisplay != null) { |
| // Make sure that all events in the asynchronous event queue |
| // are dispatched. |
| fDisplay.syncExec( |
| new Runnable() { |
| public void run() { |
| // do nothing |
| } |
| } |
| ); |
| |
| // Stop event dispatching |
| fContinueEventDispatching= false; |
| |
| // Force the event loop to return from sleep () so that |
| // it stops event dispatching. |
| fDisplay.asyncExec(null); |
| } |
| } |
| } |
| |
| public void block() { |
| while (fContinueEventDispatching) |
| if (!fDisplay.readAndDispatch()) |
| fDisplay.sleep(); |
| } |
| } |
| |
| static class ProgressMonitorDialog extends org.eclipse.jface.dialogs.Dialog { |
| |
| protected ProgressIndicator fProgressIndicator; |
| protected Label fTaskLabel; |
| protected Label fSubTaskLabel; |
| protected Button fCancel; |
| protected boolean fEnableCancelButton; |
| private ProgressMonitor fProgressMonitor; |
| private Cursor fArrowCursor; |
| private Cursor fWaitCursor; |
| private Shell fParentShell; |
| |
| private ProgressMonitorDialog(Shell parent, boolean cancelable, ProgressMonitor pm) { |
| super(parent); |
| fProgressMonitor= pm; |
| fParentShell= parent; |
| fEnableCancelButton= cancelable; |
| this.setBlockOnOpen(false); |
| setShellStyle(SWT.BORDER | SWT.TITLE | SWT.APPLICATION_MODAL); // no close button |
| } |
| |
| public boolean close() { |
| if (fCancel != null && !fCancel.isDisposed()) |
| fCancel.setCursor(null); |
| Shell shell= getShell(); |
| if (shell != null && !shell.isDisposed()) |
| shell.setCursor(null); |
| if (fArrowCursor != null) |
| fArrowCursor.dispose(); |
| if (fWaitCursor != null) |
| fWaitCursor.dispose(); |
| fArrowCursor= null; |
| fWaitCursor= null; |
| return super.close(); |
| } |
| |
| protected void configureShell(Shell shell) { |
| super.configureShell(shell); |
| shell.setText(JFaceResources.getString("ProgressMonitorDialog.title")); //$NON-NLS-1$ |
| if (fWaitCursor == null) |
| fWaitCursor= new Cursor(shell.getDisplay(),SWT.CURSOR_WAIT); |
| shell.setCursor(fWaitCursor); |
| } |
| |
| protected void createButtonsForButtonBar(Composite parent) { |
| // cancel button |
| fCancel= createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, true); |
| if(fArrowCursor == null) |
| fArrowCursor= new Cursor(fCancel.getDisplay(),SWT.CURSOR_ARROW); |
| fCancel.setCursor(fArrowCursor); |
| fCancel.addListener(SWT.Selection, |
| new Listener() { |
| public void handleEvent(Event e) { |
| if (fCancel != null && !fCancel.isDisposed()) |
| fCancel.setEnabled(false); |
| fProgressMonitor.setCanceled(true); |
| } |
| } |
| ); |
| fCancel.setEnabled(fEnableCancelButton); |
| } |
| |
| protected Control createDialogArea(Composite parent) { |
| |
| Composite c= (Composite)super.createDialogArea(parent); |
| ((GridLayout)c.getLayout()).numColumns= 2; |
| |
| // icon |
| Label iconLabel= new Label(c, SWT.LEFT); |
| GridData gd= new GridData(); |
| iconLabel.setLayoutData(gd); |
| iconLabel.setFont(parent.getFont()); |
| Image i= JFaceResources.getImageRegistry().get(org.eclipse.jface.dialogs.Dialog.DLG_IMG_INFO); |
| if (i != null) |
| iconLabel.setImage(i); |
| else |
| iconLabel.setText(JFaceResources.getString("Image_not_found")); //$NON-NLS-1$ |
| |
| // label on right hand side of icon |
| fTaskLabel= new Label(c, SWT.LEFT | SWT.WRAP); |
| fTaskLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| fTaskLabel.setFont(parent.getFont()); |
| |
| // progress indicator |
| fProgressIndicator= new ProgressIndicator(c); |
| gd= new GridData(); |
| gd.heightHint= 15; |
| gd.horizontalAlignment= GridData.FILL; |
| gd.grabExcessHorizontalSpace= true; |
| gd.horizontalSpan= 2; |
| fProgressIndicator.setLayoutData(gd); |
| |
| // label showing current task |
| fSubTaskLabel= new Label(c, SWT.LEFT | SWT.WRAP); |
| gd= new GridData(GridData.FILL_HORIZONTAL); |
| gd.heightHint= 35; |
| gd.horizontalSpan= 2; |
| fSubTaskLabel.setLayoutData(gd); |
| fSubTaskLabel.setFont(parent.getFont()); |
| |
| // update with values fProgressMonitor |
| String s= fProgressMonitor.fTask; |
| if (s == null) |
| s= ""; //$NON-NLS-1$ |
| fTaskLabel.setText(s); |
| |
| if (fProgressMonitor.fMaxWork == IProgressMonitor.UNKNOWN) |
| fProgressIndicator.beginAnimatedTask(); |
| else |
| fProgressIndicator.beginTask(fProgressMonitor.fMaxWork); |
| |
| if (fProgressMonitor.fSubTask != null) |
| fSubTaskLabel.setText(fProgressMonitor.fSubTask); |
| fProgressIndicator.worked(fProgressMonitor.fWorked); |
| |
| fProgressMonitor.activate(this); |
| |
| return c; |
| } |
| |
| void beginTask(final String name, final int totalWork) { |
| fParentShell.getDisplay().syncExec( |
| new Runnable() { |
| public void run() { |
| fTaskLabel.setText(name); |
| |
| if (fProgressIndicator != null && fProgressIndicator.isDisposed()) { |
| if (totalWork == IProgressMonitor.UNKNOWN) |
| fProgressIndicator.beginAnimatedTask(); |
| else |
| fProgressIndicator.beginTask(totalWork); |
| } |
| } |
| } |
| ); |
| } |
| |
| void setTaskName(final String name) { |
| fParentShell.getDisplay().syncExec( |
| new Runnable() { |
| public void run() { |
| if (fTaskLabel != null && fTaskLabel.isDisposed()) |
| fTaskLabel.setText(name); |
| } |
| } |
| ); |
| } |
| |
| void setSubTaskName(final String name) { |
| fParentShell.getDisplay().syncExec( |
| new Runnable() { |
| public void run() { |
| String n= (name == null) ? "" : name; //$NON-NLS-1$ |
| if (fSubTaskLabel != null && !fSubTaskLabel.isDisposed()) |
| fSubTaskLabel.setText(n); |
| } |
| } |
| ); |
| } |
| |
| void done() { |
| fParentShell.getDisplay().syncExec( |
| new Runnable() { |
| public void run() { |
| if (fProgressIndicator != null && !fProgressIndicator.isDisposed()) { |
| fProgressIndicator.sendRemainingWork(); |
| fProgressIndicator.done(); |
| } |
| } |
| } |
| ); |
| } |
| |
| void worked(final double work) { |
| fParentShell.getDisplay().syncExec( |
| new Runnable() { |
| public void run() { |
| if (fProgressIndicator != null && !fProgressIndicator.isDisposed()) |
| fProgressIndicator.worked(work); |
| } |
| } |
| ); |
| } |
| |
| protected Point getInitialSize() { |
| return getShell().computeSize(450, SWT.DEFAULT); |
| } |
| } |
| |
| private static class ProgressMonitor implements IProgressMonitor { |
| |
| private int fMaxWork; |
| private String fTask; |
| private String fSubTask; |
| private int fWorked; |
| private ProgressMonitorDialog fProgressMonitorDialog; |
| private boolean fIsCanceled; |
| |
| public void beginTask(String name, int totalWork) { |
| |
| fTask= name; |
| fMaxWork= totalWork; |
| fWorked= 0; |
| |
| if (fProgressMonitorDialog != null) |
| fProgressMonitorDialog.beginTask(name, totalWork); |
| } |
| |
| void activate(ProgressMonitorDialog dialog) { |
| fProgressMonitorDialog= dialog; |
| } |
| |
| public void done() { |
| if (fProgressMonitorDialog != null) |
| fProgressMonitorDialog.done(); |
| } |
| |
| public void setTaskName(String name) { |
| fTask= name; |
| if (fProgressMonitorDialog != null) |
| fProgressMonitorDialog.setTaskName(name); |
| } |
| |
| public boolean isCanceled() { |
| return fIsCanceled; |
| } |
| |
| public void setCanceled(boolean b) { |
| fIsCanceled= b; |
| } |
| |
| public void subTask(String name) { |
| fSubTask= name; |
| if (fProgressMonitorDialog != null) |
| fProgressMonitorDialog.setSubTaskName(name); |
| } |
| |
| public void worked(int work) { |
| if (fProgressMonitorDialog != null) |
| internalWorked(work); |
| else |
| fWorked+= work; |
| } |
| |
| public void internalWorked(double work) { |
| if (fProgressMonitorDialog != null) |
| fProgressMonitorDialog.worked(work); |
| } |
| } |
| |
| public static void run(boolean cancelable, int timeout, Shell parent, IRunnableWithProgress runnable) throws InvocationTargetException, InterruptedException { |
| |
| Display display= parent.getDisplay(); |
| |
| ProgressMonitor pm= new ProgressMonitor(); |
| |
| ModalContextThread t= new ModalContextThread(runnable, pm); |
| t.start(); // start the long running operation |
| |
| // wait until long operations terminates or timeout |
| try { |
| t.join(timeout); |
| } catch (InterruptedException e) { |
| } |
| |
| if (t.timeout(display)) { // timeout |
| ProgressMonitorDialog dialog= new ProgressMonitorDialog(parent, cancelable, pm); |
| dialog.open(); |
| t.block(); |
| dialog.close(); |
| } |
| |
| Throwable throwable= t.fThrowable; |
| if (throwable != null) { |
| if (throwable instanceof InvocationTargetException) { |
| throw (InvocationTargetException) throwable; |
| } else if (throwable instanceof InterruptedException) { |
| throw (InterruptedException) throwable; |
| } else if (throwable instanceof OperationCanceledException) { |
| throw new InterruptedException(throwable.getMessage()); |
| } else { |
| throw new InvocationTargetException(throwable); |
| } |
| } |
| } |
| } |
| |