blob: f942b9a1a8f3259dfabc88de88e4e065154bede7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2003, 2007 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 - Initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal.progress;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.PartSite;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.part.WorkbenchPart;
import org.eclipse.ui.progress.IProgressService;
import org.eclipse.ui.progress.IWorkbenchSiteProgressService;
import org.eclipse.ui.progress.WorkbenchJob;
/**
* The WorkbenchSiteProgressService is the concrete implementation of the
* WorkbenchSiteProgressService used by the workbench components.
*/
public class WorkbenchSiteProgressService implements
IWorkbenchSiteProgressService, IJobBusyListener {
PartSite site;
private Collection busyJobs = Collections.synchronizedSet(new HashSet());
private Object busyLock = new Object();
IJobChangeListener listener;
IPropertyChangeListener[] changeListeners = new IPropertyChangeListener[0];
private Cursor waitCursor;
private SiteUpdateJob updateJob;
/**
* Flag that keeps state from calls to {@link #showBusy(boolean)}
*/
private int busyCount = 0;
private class SiteUpdateJob extends WorkbenchJob {
private boolean busy;
private boolean useWaitCursor = false;
Object lock = new Object();
/**
* Set whether we are updating with the wait or busy cursor.
*
* @param cursorState
*/
void setBusy(boolean cursorState) {
synchronized (lock) {
busy = cursorState;
}
}
private SiteUpdateJob() {
super(ProgressMessages.WorkbenchSiteProgressService_CursorJob);
}
/**
* Get the wait cursor. Initialize it if required.
* @param display the display to create the cursor on.
* @return the created cursor
*/
private Cursor getWaitCursor(Display display) {
if (waitCursor == null) {
waitCursor = new Cursor(display, SWT.CURSOR_APPSTARTING);
}
return waitCursor;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
*/
public IStatus runInUIThread(IProgressMonitor monitor) {
Control control = site.getPane().getControl();
if (control == null || control.isDisposed()) {
return Status.CANCEL_STATUS;
}
synchronized (lock) {
//Update cursors if we are doing that
if (useWaitCursor) {
Cursor cursor = null;
if (busy) {
cursor = getWaitCursor(control.getDisplay());
}
control.setCursor(cursor);
}
site.getPane().setBusy(busy);
IWorkbenchPart part = site.getPart();
if (part instanceof WorkbenchPart) {
((WorkbenchPart) part).showBusy(busy);
}
}
return Status.OK_STATUS;
}
void clearCursors() {
if (waitCursor != null) {
waitCursor.dispose();
waitCursor = null;
}
}
}
/**
* Create a new instance of the receiver with a site of partSite
*
* @param partSite
* PartSite.
*/
public WorkbenchSiteProgressService(final PartSite partSite) {
site = partSite;
updateJob = new SiteUpdateJob();
updateJob.setSystem(true);
}
/**
* Dispose the resources allocated by the receiver.
*
*/
public void dispose() {
if (updateJob != null) {
updateJob.cancel();
}
ProgressManager.getInstance().removeListener(this);
if (waitCursor == null) {
return;
}
waitCursor.dispose();
waitCursor = null;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.progress.IProgressService#busyCursorWhile(org.eclipse.jface.operation.IRunnableWithProgress)
*/
public void busyCursorWhile(IRunnableWithProgress runnable)
throws InvocationTargetException, InterruptedException {
getWorkbenchProgressService().busyCursorWhile(runnable);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.progress.IWorkbenchSiteProgressService#schedule(org.eclipse.core.runtime.jobs.Job,
* long, boolean)
*/
public void schedule(Job job, long delay, boolean useHalfBusyCursor) {
job.addJobChangeListener(getJobChangeListener(job, useHalfBusyCursor));
job.schedule(delay);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.progress.IWorkbenchSiteProgressService#schedule(org.eclipse.core.runtime.jobs.Job,
* int)
*/
public void schedule(Job job, long delay) {
schedule(job, delay, false);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.progress.IWorkbenchSiteProgressService#schedule(org.eclipse.core.runtime.jobs.Job)
*/
public void schedule(Job job) {
schedule(job, 0L, false);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.progress.IWorkbenchSiteProgressService#showBusyForFamily(java.lang.Object)
*/
public void showBusyForFamily(Object family) {
ProgressManager.getInstance().addListenerToFamily(family, this);
}
/**
* Get the job change listener for this site.
*
* @param job
* @param useHalfBusyCursor
* @return IJobChangeListener
*/
public IJobChangeListener getJobChangeListener(final Job job,
boolean useHalfBusyCursor) {
if (listener == null) {
updateJob.useWaitCursor = useHalfBusyCursor;
listener = new JobChangeAdapter() {
/*
* (non-Javadoc)
*
* @see org.eclipse.core.runtime.jobs.JobChangeAdapter#aboutToRun(org.eclipse.core.runtime.jobs.IJobChangeEvent)
*/
public void aboutToRun(IJobChangeEvent event) {
incrementBusy(event.getJob());
}
/*
* (non-Javadoc)
*
* @see org.eclipse.core.runtime.jobs.JobChangeAdapter#done(org.eclipse.core.runtime.jobs.IJobChangeEvent)
*/
public void done(IJobChangeEvent event) {
decrementBusy(event.getJob());
}
};
}
return listener;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.internal.progress.IJobBusyListener#decrementBusy(org.eclipse.core.runtime.jobs.Job)
*/
public void decrementBusy(Job job) {
synchronized (busyLock) {
if (!busyJobs.contains(job)) {
return;
}
busyJobs.remove(job);
}
try {
decrementBusy();
} catch (Exception ex) {
// protecting against assertion failures
WorkbenchPlugin.log(ex);
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.internal.progress.IJobBusyListener#incrementBusy(org.eclipse.core.runtime.jobs.Job)
*/
public void incrementBusy(Job job) {
synchronized (busyLock) {
if (busyJobs.contains(job)) {
return;
}
busyJobs.add(job);
}
incrementBusy();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.progress.IWorkbenchSiteProgressService#warnOfContentChange()
*/
public void warnOfContentChange() {
site.getPane().showHighlight();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.progress.IProgressService#showInDialog(org.eclipse.swt.widgets.Shell,
* org.eclipse.core.runtime.jobs.Job)
*/
public void showInDialog(Shell shell, Job job) {
getWorkbenchProgressService().showInDialog(shell, job);
}
/**
* Get the progress service for the workbnech,
*
* @return IProgressService
*/
private IProgressService getWorkbenchProgressService() {
return site.getWorkbenchWindow().getWorkbench().getProgressService();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.operation.IRunnableContext#run(boolean, boolean,
* org.eclipse.jface.operation.IRunnableWithProgress)
*/
public void run(boolean fork, boolean cancelable,
IRunnableWithProgress runnable) throws InvocationTargetException,
InterruptedException {
getWorkbenchProgressService().run(fork, cancelable, runnable);
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.progress.IProgressService#runInUI(org.eclipse.jface.operation.IRunnableContext, org.eclipse.jface.operation.IRunnableWithProgress, org.eclipse.core.runtime.jobs.ISchedulingRule)
*/
public void runInUI(IRunnableContext context,
IRunnableWithProgress runnable, ISchedulingRule rule)
throws InvocationTargetException, InterruptedException {
getWorkbenchProgressService().runInUI(context, runnable, rule);
}
/* (non-Javadoc)
* @see org.eclipse.ui.progress.IProgressService#getLongOperationTime()
*/
public int getLongOperationTime() {
return getWorkbenchProgressService().getLongOperationTime();
}
/* (non-Javadoc)
* @see org.eclipse.ui.progress.IProgressService#registerIconForFamily(org.eclipse.jface.resource.ImageDescriptor, java.lang.Object)
*/
public void registerIconForFamily(ImageDescriptor icon, Object family) {
getWorkbenchProgressService().registerIconForFamily(icon, family);
}
/* (non-Javadoc)
* @see org.eclipse.ui.progress.IProgressService#getIconFor(org.eclipse.core.runtime.jobs.Job)
*/
public Image getIconFor(Job job) {
return getWorkbenchProgressService().getIconFor(job);
}
/* (non-Javadoc)
* @see org.eclipse.ui.progress.IWorkbenchSiteProgressService#showBusy(boolean)
*/
public void incrementBusy() {
synchronized (busyLock) {
this.busyCount++;
if (busyCount != 1) {
return;
}
updateJob.setBusy(true);
}
if (PlatformUI.isWorkbenchRunning()) {
updateJob.schedule(100);
} else {
updateJob.cancel();
}
}
/* (non-Javadoc)
* @see org.eclipse.ui.progress.IWorkbenchSiteProgressService#showBusy(boolean)
*/
public void decrementBusy() {
synchronized (busyLock) {
Assert
.isTrue(
busyCount > 0,
"Ignoring unexpected call to IWorkbenchSiteProgressService.decrementBusy(). This might be due to an earlier call to this method."); //$NON-NLS-1$
this.busyCount--;
if (busyCount != 0) {
return;
}
updateJob.setBusy(false);
}
if (PlatformUI.isWorkbenchRunning()) {
updateJob.schedule(100);
} else {
updateJob.cancel();
}
}
}