/*******************************************************************************
* Copyright (c) 2007, 2012 Wind River Systems 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:
* Wind River Systems - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.ui.viewmodel;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.cdt.dsf.concurrent.DsfExecutable;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.IRequest;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
import org.eclipse.jface.viewers.TreePath;
/**
* Helper class implementation of the update objects used with
* {@link IElementContentProvider}, {@link IElementLabelProvider},
* and {@link IElementMementoProvider}. The viewer update can be constructed
* using a higher level update object or a set of parameters to fulfill the
* <code>IViewerUpdate</code> interface.
*
* @since 1.0
*/
public class VMViewerUpdate extends DsfExecutable implements IViewerUpdate {
/**
* The request monitor to be called when this update is completed.
*/
final private RequestMonitor fRequestMonitor;
/**
* A higher-level update that this update is based on. If specified, the given
* update is used to delegate calls to {@link #cancel()} and {@link #isCanceled()}.
*/
final private IViewerUpdate fClientUpdate;
/**
* Place holder for the client update. It is only used if the client update is
* not specified.
*/
private static class ClientUpdatePlaceHolder implements IViewerUpdate {
ClientUpdatePlaceHolder(TreePath elementPath, Object viewerInput, IPresentationContext presentationContext)
{
fViewerInput = viewerInput;
fElementPath = elementPath;
fPresentationContext = presentationContext;
}
/**
* The flag indicating whether this update was canceled.
*/
private volatile boolean fCanceled;
/**
* The viewer input object for this update.
*/
final private Object fViewerInput;
/**
* The element path of this update.
*/
final private TreePath fElementPath;
/**
* The presentation context of this update.
*/
final private IPresentationContext fPresentationContext;
@Override
public void cancel() {
fCanceled = true;
}
@Override
public boolean isCanceled() {
return fCanceled;
}
@Override
public IPresentationContext getPresentationContext() {
return fPresentationContext;
}
@Override
public Object getElement() {
return fElementPath.getSegmentCount() != 0 ? fElementPath.getLastSegment() : fViewerInput;
}
@Override
public TreePath getElementPath() {
return fElementPath;
}
@Override
public Object getViewerInput() {
return fViewerInput;
}
@Override
public void done() { assert false; } // not used
@Override
public void setStatus(IStatus status) {assert false; } // not used
@Override
public IStatus getStatus() { assert false; return null; } // not used
}
/**
* Creates a viewer update based on a higher-level update. The update element
* information as well as cancel requests are delegated to the given client
* update.
* <p/>
* Note: this update will not automatically call the client update's
* {@link IRequest#done()} method. The user of this update should supply
* a request monitor which properly completes the client update.
*
* @param clientUpdate Client update that this update is based on.
* @param requestMonitor Call-back invoked when this update completes.
*/
public VMViewerUpdate(IViewerUpdate clientUpdate, RequestMonitor requestMonitor) {
fRequestMonitor = requestMonitor;
fClientUpdate = clientUpdate;
}
/**
* Request monitor which uses a model delta to calculate the element information.
* This update is useful when calculating a model delta for a given view model node.
*
* @param delta Model delta of a parent element.
* @param presentationContext Presentation context for this update.
* @param requestMonitor Call-back invoked when this update completes.
*/
public VMViewerUpdate(IModelDelta delta, IPresentationContext presentationContext, RequestMonitor requestMonitor) {
List<Object> elementList = new LinkedList<Object>();
IModelDelta listDelta = delta;
elementList.add(0, listDelta.getElement());
while (listDelta.getParentDelta() != null) {
listDelta = listDelta.getParentDelta();
elementList.add(0, listDelta.getElement());
}
Object viewerInput = elementList.remove(0);
fClientUpdate = new ClientUpdatePlaceHolder(
new TreePath(elementList.toArray()), viewerInput, presentationContext);
fRequestMonitor = requestMonitor;
}
/**
* Creates a viewer update with the given parameters.
*
* @param elementPath The path to the element for which the update is generated.
* @param viewerInput Input into the viewer of the update.
* @param presentationContext Presentation context for this update.
* @param requestMonitor Call-back invoked when this update completes.
*/
public VMViewerUpdate(TreePath elementPath, Object viewerInput, IPresentationContext presentationContext, RequestMonitor requestMonitor) {
fRequestMonitor = requestMonitor;
fClientUpdate = new ClientUpdatePlaceHolder(elementPath, viewerInput, presentationContext);
}
protected RequestMonitor getRequestMonitor() {
return fRequestMonitor;
}
@Override
public Object getViewerInput() { return fClientUpdate.getViewerInput(); }
@Override
public Object getElement() { return fClientUpdate.getElement(); }
@Override
public TreePath getElementPath() { return fClientUpdate.getElementPath(); }
@Override
public IPresentationContext getPresentationContext() { return fClientUpdate.getPresentationContext(); }
@Override
public IStatus getStatus() { return fRequestMonitor.getStatus(); }
@Override
public void setStatus(IStatus status) { fRequestMonitor.setStatus(status); }
@Override
public boolean isCanceled() {
return fClientUpdate.isCanceled();
}
@Override
public void cancel() {
fClientUpdate.cancel();
}
@Override
public void done() {
setSubmitted();
if ( isCanceled() ) {
fRequestMonitor.cancel();
fRequestMonitor.setStatus(new Status( IStatus.CANCEL, DsfUIPlugin.PLUGIN_ID," Update was canceled") ); //$NON-NLS-1$
}
fRequestMonitor.done();
}
}