/******************************************************************************* * Copyright (c) 2005, 2011 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 *******************************************************************************/ package org.eclipse.debug.internal.ui.viewers; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.debug.internal.ui.commands.actions.AbstractRequestMonitor; import org.eclipse.ui.progress.WorkbenchJob; /** * Base implementation of an asynchronous request monitor. * <p> * Not intended to be sub-classed or instantiated by clients. For internal use * with the <code>AsynchronousViewer</code> implementation. * </p> * @since 3.2 */ public abstract class AsynchronousRequestMonitor extends AbstractRequestMonitor { /** * Model node the update is rooted at */ private ModelNode fNode; /** * Model the update is being performed for */ private AsynchronousModel fModel; /** * Whether this request's 'done' method has been called. */ private boolean fDone = false; protected WorkbenchJob fViewerUpdateJob = new WorkbenchJob("Asynchronous viewer update") { //$NON-NLS-1$ @Override public IStatus runInUIThread(IProgressMonitor monitor) { // necessary to check if widget is disposed. The item may // have been removed from the tree when another children update // occurred. getModel().viewerUpdateScheduled(AsynchronousRequestMonitor.this); if (fDone) { getModel().requestComplete(AsynchronousRequestMonitor.this); } if (!isCanceled() && !getNode().isDisposed()) { IStatus status = getStatus(); if (status != null && !status.isOK()) { getModel().getViewer().handlePresentationFailure(AsynchronousRequestMonitor.this, status); } else { performUpdate(); } } getModel().viewerUpdateComplete(AsynchronousRequestMonitor.this); return Status.OK_STATUS; } }; /** * Constructs an update rooted at the given item. * * @param node model node * @param model model the node is in */ public AsynchronousRequestMonitor(ModelNode node, AsynchronousModel model) { fNode = node; fModel = model; // serialize updates per viewer fViewerUpdateJob.setRule(getUpdateSchedulingRule()); fViewerUpdateJob.setSystem(true); } /** * Returns the scheduling rule for viewer update job. * * @return rule or <code>null</code> */ protected ISchedulingRule getUpdateSchedulingRule() { return AsynchronousSchedulingRuleFactory.getDefault().newSerialPerObjectRule(getModel().getViewer()); } /** * Returns the model this update is being performed for * * @return the model this update is being performed for */ protected AsynchronousModel getModel() { return fModel; } /** * Returns the model node this update is rooted at * * @return the model node this update is rooted at */ protected ModelNode getNode() { return fNode; } /** * Returns whether this update contains the given node. * That is, whether this update is for the same node or a child of * the given node. * * @param node node to test containment on * @return whether this update contains the given node */ protected boolean contains(ModelNode node) { if (node == getNode()) { return true; } ModelNode parentNode = getNode().getParentNode(); while (parentNode != null) { if (parentNode.equals(getNode())) { return true; } parentNode = parentNode.getParentNode(); } return false; } /* (non-Javadoc) * @see org.eclipse.core.runtime.IProgressMonitor#setCanceled(boolean) */ @Override public void setCanceled(boolean value) { super.setCanceled(value); if (value) { getModel().requestCanceled(this); } } /* (non-Javadoc) * @see org.eclipse.core.runtime.IProgressMonitor#done() */ @Override public final void done() { synchronized (this) { fDone = true; } scheduleViewerUpdate(0L); } /** * Returns whether this request is done yet. * * @return if the request is done */ protected synchronized boolean isDone() { return fDone; } protected void scheduleViewerUpdate(long ms) { if(!isCanceled()) fViewerUpdateJob.schedule(ms); } /** * Notification this update has been completed and should now be applied to * this update's viewer. This method is called in the UI thread. */ protected abstract void performUpdate(); /** * Returns whether this update effectively contains the given update. * That is, whether this update will also perform the given update. * * @param update update to compare to * @return whether this update will also perform the given update */ protected abstract boolean contains(AsynchronousRequestMonitor update); }