diff options
author | Steffen Pingel | 2011-09-15 22:59:11 +0000 |
---|---|---|
committer | Steffen Pingel | 2011-09-15 22:59:11 +0000 |
commit | 264433dbf31add331fd43c47eeedd73df84e4242 (patch) | |
tree | 97324e2fc2cc2857a79c4798c6701e44d101eb28 /org.eclipse.mylyn.commons.ui | |
parent | e4ff3ed6f92fe52c24baebd6e1e990b212f188b4 (diff) | |
download | org.eclipse.mylyn.commons-264433dbf31add331fd43c47eeedd73df84e4242.tar.gz org.eclipse.mylyn.commons-264433dbf31add331fd43c47eeedd73df84e4242.tar.xz org.eclipse.mylyn.commons-264433dbf31add331fd43c47eeedd73df84e4242.zip |
NEW - bug 245152: opening "Task Search" blocks UI when page is first
shown
https://bugs.eclipse.org/bugs/show_bug.cgi?id=245152
Diffstat (limited to 'org.eclipse.mylyn.commons.ui')
-rw-r--r-- | org.eclipse.mylyn.commons.ui/src/org/eclipse/mylyn/internal/provisional/commons/ui/ProgressContainer.java | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/org.eclipse.mylyn.commons.ui/src/org/eclipse/mylyn/internal/provisional/commons/ui/ProgressContainer.java b/org.eclipse.mylyn.commons.ui/src/org/eclipse/mylyn/internal/provisional/commons/ui/ProgressContainer.java new file mode 100644 index 00000000..69285e67 --- /dev/null +++ b/org.eclipse.mylyn.commons.ui/src/org/eclipse/mylyn/internal/provisional/commons/ui/ProgressContainer.java @@ -0,0 +1,256 @@ +/******************************************************************************* + * Copyright (c) 2000, 2010 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Chris Gross (schtoo@schtoo.com) - patch for bug 16179 + * Tasktop Technologies - extracted code for Mylyn + *******************************************************************************/ + +package org.eclipse.mylyn.internal.provisional.commons.ui; + +import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.ProgressMonitorWrapper; +import org.eclipse.jface.operation.IRunnableContext; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.operation.ModalContext; +import org.eclipse.jface.wizard.ProgressMonitorPart; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.graphics.Cursor; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +/** + * A helper class for running operations in dialogs. Based on {@link WizardDialog}. + * + * @author Steffen Pingel + */ +public class ProgressContainer implements IRunnableContext { + + private static final String FOCUS_CONTROL = "focusControl"; //$NON-NLS-1$ + + // The number of long running operation executed from the dialog. + private long activeRunningOperations = 0; + + private Cursor arrowCursor; + + private Button cancelButton; + + private boolean lockedUI = false; + + // The progress monitor + private final ProgressMonitorPart progressMonitorPart; + + private final Shell shell; + + private Cursor waitCursor; + + private boolean useWaitCursor; + + public ProgressContainer(Shell shell, ProgressMonitorPart progressMonitorPart) { + Assert.isNotNull(shell); + Assert.isNotNull(progressMonitorPart); + this.shell = shell; + this.progressMonitorPart = progressMonitorPart; + init(); + } + + private void init() { + this.shell.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + progressMonitorPart.setCanceled(true); + } + }); + } + + public boolean useWaitCursor() { + return useWaitCursor; + } + + public void setUseWaitCursor(boolean useWaitCursor) { + this.useWaitCursor = useWaitCursor; + } + + /** + * About to start a long running operation triggered through the wizard. Shows the progress monitor and disables the + * wizard's buttons and controls. + * + * @param enableCancelButton + * <code>true</code> if the Cancel button should be enabled, and <code>false</code> if it should be + * disabled + * @return the saved UI state + */ + private Object aboutToStart(boolean enableCancelButton) { + Map<Object, Object> savedState = null; + if (getShell() != null) { + // Save focus control + Control focusControl = getShell().getDisplay().getFocusControl(); + if (focusControl != null && focusControl.getShell() != getShell()) { + focusControl = null; + } + // Set the busy cursor to all shells. + Display d = getShell().getDisplay(); + if (useWaitCursor()) { + waitCursor = new Cursor(d, SWT.CURSOR_WAIT); + setDisplayCursor(waitCursor); + // Set the arrow cursor to the cancel component. + arrowCursor = new Cursor(d, SWT.CURSOR_ARROW); + if (cancelButton != null) { + cancelButton.setCursor(arrowCursor); + } + } + // Deactivate shell + savedState = new HashMap<Object, Object>(10); + saveUiState(savedState); + if (focusControl != null) { + savedState.put(FOCUS_CONTROL, focusControl); + } + // Attach the progress monitor part to the cancel button + if (cancelButton != null) { + progressMonitorPart.attachToCancelComponent(cancelButton); + } + progressMonitorPart.setVisible(true); + } + return savedState; + } + + public Button getCancelButton() { + return cancelButton; + } + + private IProgressMonitor getProgressMonitor() { + return new ProgressMonitorWrapper(progressMonitorPart) { + @Override + public void internalWorked(double work) { + if (progressMonitorPart.isDisposed()) { + this.setCanceled(true); + return; + } + super.internalWorked(work); + } + }; + } + + public Shell getShell() { + return shell; + } + + public boolean isActive() { + return activeRunningOperations > 0; + } + + public boolean isLockedUI() { + return lockedUI; + } + + protected void restoreUiState(Map<Object, Object> state) { + // ignore + + } + + /** + * This implementation of IRunnableContext#run(boolean, boolean, IRunnableWithProgress) blocks until the runnable + * has been run, regardless of the value of <code>fork</code>. It is recommended that <code>fork</code> is set to + * true in most cases. If <code>fork</code> is set to <code>false</code>, the runnable will run in the UI thread and + * it is the runnable's responsibility to call <code>Display.readAndDispatch()</code> to ensure UI responsiveness. + * UI state is saved prior to executing the long-running operation and is restored after the long-running operation + * completes executing. Any attempt to change the UI state of the wizard in the long-running operation will be + * nullified when original UI state is restored. + */ + public void run(boolean fork, boolean cancelable, IRunnableWithProgress runnable) throws InvocationTargetException, + InterruptedException { + // The operation can only be canceled if it is executed in a separate + // thread. + // Otherwise the UI is blocked anyway. + Object state = null; + if (activeRunningOperations == 0) { + state = aboutToStart(fork && cancelable); + } + activeRunningOperations++; + try { + if (!fork) { + lockedUI = true; + } + ModalContext.run(runnable, fork, getProgressMonitor(), getShell().getDisplay()); + lockedUI = false; + } finally { + activeRunningOperations--; + // Stop if this is the last one + if (state != null) { + stopped(state); + } + } + } + + protected void saveUiState(Map<Object, Object> savedState) { + // ignore + + } + + public void setCancelButton(Button cancelButton) { + this.cancelButton = cancelButton; + } + + /** + * Sets the given cursor for all shells currently active for this window's display. + * + * @param c + * the cursor + */ + private void setDisplayCursor(Cursor c) { + Shell[] shells = getShell().getDisplay().getShells(); + for (Shell shell2 : shells) { + shell2.setCursor(c); + } + } + + /** + * A long running operation triggered through the wizard was stopped either by user input or by normal end. Hides + * the progress monitor and restores the enable state wizard's buttons and controls. + * + * @param savedState + * the saved UI state as returned by <code>aboutToStart</code> + * @see #aboutToStart + */ + @SuppressWarnings("unchecked") + private void stopped(Object savedState) { + if (getShell() != null && !getShell().isDisposed()) { + progressMonitorPart.setVisible(false); + if (cancelButton != null) { + progressMonitorPart.removeFromCancelComponent(cancelButton); + } + + Map<Object, Object> state = (Map<Object, Object>) savedState; + restoreUiState(state); + if (waitCursor != null) { + setDisplayCursor(null); + if (cancelButton != null) { + cancelButton.setCursor(null); + } + waitCursor.dispose(); + waitCursor = null; + arrowCursor.dispose(); + arrowCursor = null; + } + Control focusControl = (Control) state.get(FOCUS_CONTROL); + if (focusControl != null && !focusControl.isDisposed()) { + focusControl.setFocus(); + } + } + } + +}
\ No newline at end of file |