1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Added an example of a view model with a recursive layout node (bug 178692).

This commit is contained in:
Pawel Piech 2007-03-21 23:52:14 +00:00
parent bd63dcf820
commit 11aaafc829
8 changed files with 96 additions and 78 deletions

View file

@ -114,7 +114,7 @@ public class StandardLaunchRootLayoutNode extends AbstractVMRootLayoutNode
}
// Call the child nodes to generate their delta.
final Map<IVMLayoutNode,Integer> childNodeDeltas = getChildNodesWithDeltas(event);
final Map<IVMLayoutNode,Integer> childNodeDeltas = getChildNodesWithDeltaFlags(event);
if (childNodeDeltas.size() != 0) {
callChildNodesToBuildDelta(
childNodeDeltas, rootDelta, event,

View file

@ -60,7 +60,7 @@ abstract public class AbstractVMLayoutNode implements IVMLayoutNode {
return fProvider.getExecutor();
}
protected IVMProvider getVMProvider() {
protected AbstractVMProvider getVMProvider() {
return fProvider;
}
@ -92,16 +92,19 @@ abstract public class AbstractVMLayoutNode implements IVMLayoutNode {
}
/**
* Handles calling child schema nodes to build the model delta. If child
* schema nodes have deltas, this schema node has to provide the
* IModelDelta objects that the child shema node can build on.
* Base implementation that handles calling child layout nodes to build
* the model delta. The child nodes are called with all the elements
* in this node, which could be very inefficient. In order to build delta
* only for specific elements in this node, the class extending
* <code>AbstractVMLayoutNode</code> should override this method.
* @see IVMLayoutNode#buildDelta(Object, VMDelta, int, Done)
*/
public void buildDelta(final Object event, final VMDelta parentDelta, final int nodeOffset, final Done done) {
// Find the child nodes that have deltas for the given event.
final Map<IVMLayoutNode,Integer> childNodeDeltas = getChildNodesWithDeltas(event);
final Map<IVMLayoutNode,Integer> childNodesWithDeltaFlags = getChildNodesWithDeltaFlags(event);
// If no child layout nodes have deltas we can stop here.
if (childNodeDeltas.size() == 0) {
if (childNodesWithDeltaFlags.size() == 0) {
getExecutor().execute(done);
return;
}
@ -112,14 +115,14 @@ abstract public class AbstractVMLayoutNode implements IVMLayoutNode {
// use the full path from the delta to handle these flags.
// Similarly, the index argument is not necessary either.
boolean mustGetElements = false;
for (int childDelta : childNodeDeltas.values()) {
for (int childDelta : childNodesWithDeltaFlags.values()) {
if ((childDelta & ~IModelDelta.CONTENT & ~IModelDelta.STATE) != 0) {
mustGetElements = true;
}
}
if (!mustGetElements) {
callChildNodesToBuildDelta(childNodeDeltas, parentDelta, event, done);
callChildNodesToBuildDelta(childNodesWithDeltaFlags, parentDelta, event, done);
} else {
// The given child layout nodes have deltas potentially for all elements
// from this node. Retrieve all elements and call the child nodes with
@ -147,9 +150,9 @@ abstract public class AbstractVMLayoutNode implements IVMLayoutNode {
// For each element from this node, create a new delta,
// and then call all the child nodes to build their delta.
for (int i = 0; i < getData().size(); i++) {
VMDelta delta = parentDelta.addNode((IVMContext)getData().get(i), nodeOffset + i, IModelDelta.NO_CHANGE);
VMDelta delta = parentDelta.addNode(getData().get(i), nodeOffset + i, IModelDelta.NO_CHANGE);
callChildNodesToBuildDelta(
childNodeDeltas, delta, event,
childNodesWithDeltaFlags, delta, event,
elementsDeltasDoneCollector.add(new Done() {
public void run() {
elementsDeltasDoneCollector.doneDone(this);
@ -162,6 +165,17 @@ abstract public class AbstractVMLayoutNode implements IVMLayoutNode {
}
}
/**
* Calls the specified child layout nodes to build the delta for the given event.
* @param nodes Map of layout nodes to be invoked, and the corresponding delta
* flags that they will generate. This map is generated with a call to
* {@link #getChildNodesWithDeltaFlags(Object)}.
* @param delta The delta object to build on. This delta should have been
* gerated by this node, unless the full delta path is not being calculated
* due to an optimization.
* @param event The event object that the delta is being built for.
* @param done The result token to invoke when the delta is completed.
*/
protected void callChildNodesToBuildDelta(final Map<IVMLayoutNode,Integer> nodes, final VMDelta delta, final Object event, final Done done) {
assert nodes.size() != 0;
@ -203,6 +217,22 @@ abstract public class AbstractVMLayoutNode implements IVMLayoutNode {
});
}
/**
* Calculates the indexes at which the elements of each of the child
* layout nodes begin. These indexes are necessary to correctly
* calculate the deltas for elements in the child nodes.
* @param delta The delta object to build on. This delta should have been
* gerated by this node, unless the full delta path is not being calculated
* due to an optimization.
* @param fakeIt If true, it causes this method to fill the return data
* structure with dummy values. The dummy values indicate that the indexes
* are not known and are acceptable in the delta if the delta flags being
* generated do not require full index information.
* @param done Return token containing the results. The result data is a
* mapping between the child nodes and the indexes at which the child nodes'
* elements begin. There is a special value in the map with a <code>null</code>
* key, which contains the full element count for all the nodes.
*/
private void getChildNodesElementOffsets(IModelDelta delta, boolean fakeIt, final GetDataDone<Map<IVMLayoutNode, Integer>> done) {
assert getChildLayoutNodes().length != 0;
@ -258,7 +288,7 @@ abstract public class AbstractVMLayoutNode implements IVMLayoutNode {
* <code>true</code> to the <code>hasDeltaFlags()</code> test for the given
* event.
*/
protected Map<IVMLayoutNode, Integer> getChildNodesWithDeltas(Object e) {
protected Map<IVMLayoutNode, Integer> getChildNodesWithDeltaFlags(Object e) {
Map<IVMLayoutNode, Integer> nodes = new HashMap<IVMLayoutNode, Integer>();
for (final IVMLayoutNode childNode : getChildLayoutNodes()) {
int delta = childNode.getDeltaFlags(e);
@ -328,10 +358,6 @@ abstract public class AbstractVMLayoutNode implements IVMLayoutNode {
protected class ViewerUpdate implements IViewerUpdate {
public void cancel() {
// FIXME M5
}
final private Done fDone;
private boolean fDoneInvoked = false;
final private TreePath fTreePath;
@ -372,13 +398,8 @@ abstract public class AbstractVMLayoutNode implements IVMLayoutNode {
public TreePath getElementPath() { return fTreePath; }
public IStatus getStatus() { return fStatus; }
public void setStatus(IStatus status) { fStatus = status; }
public void beginTask(String name, int totalWork) {}
public void internalWorked(double work) {}
public boolean isCanceled() { return fCancelled; }
public void setCanceled(boolean value) { fCancelled = value; }
public void setTaskName(String name) {}
public void subTask(String name) {}
public void worked(int work) {}
public void cancel() { fCancelled = true; }
public void done() {
assert !fDoneInvoked;
@ -430,6 +451,11 @@ abstract public class AbstractVMLayoutNode implements IVMLayoutNode {
public void setChild(Object child, int offset) {
fChildren.add(offset, child);
}
@Override
public String toString() {
return "ElementsUpdate for all elements under parent = " + getElement(); //$NON-NLS-1$
}
}
}

View file

@ -28,8 +28,6 @@ import org.eclipse.dd.dsf.concurrent.Done;
import org.eclipse.dd.dsf.concurrent.DoneCollector;
import org.eclipse.dd.dsf.concurrent.GetDataDone;
import org.eclipse.dd.dsf.concurrent.ThreadSafe;
import org.eclipse.dd.dsf.datamodel.IDMEvent;
import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
import org.eclipse.dd.dsf.service.IDsfService;
import org.eclipse.dd.dsf.ui.DsfUIPlugin;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
@ -90,14 +88,14 @@ abstract public class AbstractVMProvider implements IVMProvider
fPresentationContext = presentationContext;
}
public IVMAdapter getVMAdapter() {
return fVMAdapter;
}
public IPresentationContext getPresentationContext() {
return fPresentationContext;
}
public AbstractVMAdapter getVMAdapter() {
return fVMAdapter;
}
/**
* Sets the root node for this provider.
*/
@ -459,30 +457,6 @@ abstract public class AbstractVMProvider implements IVMProvider
return false;
}
/**
* Handle "data model changed" event by generating a delta object for each
* view and passing it to the corresponding view model provider. The view
* model provider is then responsible for filling-in and sending the delta
* to the viewer.
* @param e
*/
@DsfServiceEventHandler
public void eventDispatched(final IDMEvent<?> event) {
IVMRootLayoutNode rootLayoutNode = getRootLayoutNode();
if (rootLayoutNode != null && rootLayoutNode.getDeltaFlags(event) != 0) {
rootLayoutNode.createDelta(event, new GetDataDone<IModelDelta>() {
public void run() {
if (getStatus().isOK()) {
fModelProxy.fireModelChangedNonDispatch(getData());
}
}
@Override public String toString() {
return "Result of a delta for event: '" + event.toString() + "' in VMP: '" + AbstractVMProvider.this + "'" + "\n" + getData().toString(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
});
}
}
@ThreadSafe
protected class ModelProxy extends AbstractModelProxy {
@ -500,10 +474,12 @@ abstract public class AbstractVMProvider implements IVMProvider
public boolean isConflicting(ISchedulingRule rule) { return rule == this; }
};
@Override
public void installed(Viewer viewer) {
fProxyActive++;
}
@Override
public void dispose() {
fProxyActive--;
super.dispose();
@ -518,6 +494,7 @@ abstract public class AbstractVMProvider implements IVMProvider
if (fProxyActive <= 0) return;
Job job = new Job("Processing view model delta.") { //$NON-NLS-1$
@Override
protected IStatus run(IProgressMonitor monitor) {
fireModelChanged(delta);
return Status.OK_STATUS;
@ -532,10 +509,6 @@ abstract public class AbstractVMProvider implements IVMProvider
class ViewerUpdate implements IViewerUpdate {
public void cancel() {
// FIXME M5
}
private IStatus fStatus;
private boolean fDoneInvoked = false;
final private Done fDone;
@ -552,16 +525,10 @@ abstract public class AbstractVMProvider implements IVMProvider
public IStatus getStatus() { return fStatus; }
public void setStatus(IStatus status) { fStatus = status; }
public void beginTask(String name, int totalWork) {}
public void internalWorked(double work) {}
public boolean isCanceled() { return fClientUpdate.isCanceled(); }
public void setCanceled(boolean value) {
// FIXME M5
// fClientUpdate.setCanceled(value);
public void cancel() {
fClientUpdate.cancel();
}
public void setTaskName(String name) {}
public void subTask(String name) {}
public void worked(int work) {}
public void done() {
assert !fDoneInvoked;
@ -583,6 +550,7 @@ abstract public class AbstractVMProvider implements IVMProvider
fDone = done;
}
@Override
public TreePath getElementPath() {
return ((IHasChildrenUpdate)fClientUpdate).getElementPath();
}
@ -591,6 +559,7 @@ abstract public class AbstractVMProvider implements IVMProvider
fDone.setData(hasChildren);
}
@Override
public void done() {
assert fDone.getData() != null || !fDone.getStatus().isOK();
super.done();
@ -607,6 +576,7 @@ abstract public class AbstractVMProvider implements IVMProvider
fDone = done;
}
@Override
public TreePath getElementPath() {
return fElementPath;
}
@ -615,6 +585,7 @@ abstract public class AbstractVMProvider implements IVMProvider
fDone.setData(count);
}
@Override
public void done() {
assert fDone.getData() != null || !fDone.getStatus().isOK();
super.done();
@ -642,6 +613,7 @@ abstract public class AbstractVMProvider implements IVMProvider
return fLength;
}
@Override
public TreePath getElementPath() {
return ((IChildrenUpdate)fClientUpdate).getElementPath();
}
@ -652,5 +624,10 @@ abstract public class AbstractVMProvider implements IVMProvider
}
}
@Override
public String toString() {
return "ElementsUpdate for elements under parent = " + getElement() + ", in range " + getOffset() + " -> " + (getOffset() + getLength()); //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$
}
}
}

View file

@ -77,7 +77,7 @@ abstract public class AbstractVMRootLayoutNode extends AbstractVMLayoutNode impl
* is the input object into the view.
*/
public void createDelta(Object event, final GetDataDone<IModelDelta> done) {
final Map<IVMLayoutNode,Integer> childNodeDeltas = getChildNodesWithDeltas(event);
final Map<IVMLayoutNode,Integer> childNodeDeltas = getChildNodesWithDeltaFlags(event);
assert childNodeDeltas.size() != 0 : "Caller should make sure that there are deltas for given event."; //$NON-NLS-1$
// Always create the rootDelta, no matter what delta flags the child nodes have.

View file

@ -60,7 +60,8 @@ public interface IVMLayoutNode
/**
* Retrieves the element objects of this node for the given path in the
* viewer, and for the given range of indexes. <br>
* Note: the range of children, denoted by ILabelUpdate.getOffset()
* NOTE: update.getOffset() and update.getLength() may return -1.
* The range of children, denoted by ILabelUpdate.getOffset()
* and ILabelUpdate.getLength(), may not be specified, in which case these
* methods may return -1. This means that all the elements should be
* retrieved for this node.<br>
@ -89,12 +90,31 @@ public interface IVMLayoutNode
* for the given event.
* @param event Event to process.
* @return IModelDelta flags
* @see #buildDelta(Object, VMDelta, int, Done)
* @see IModelDelta
*/
public int getDeltaFlags(Object event);
/**
* Builds model delta information based on the given event.
* <p>
* Model deltas, which are used to control the state of elements in the viewer, are
* generated by the layout nodes by recursively calling this method on all the nodes
* in the layout tree. Each node implements two methods: {@link #getDeltaFlags(Object)},
* and <code>buildDelta()</code>. A parent node which is processing a
* <code>buildDelta</code> operation needs to determine which of its elements are
* affected by a given event, set appropriate flags on these elements, and then
* it needs to call its child nodes with those elements to give the child nodes a
* chance to add onto the delta.
* </p>
* <p>
* The <code>getDeltaFlags()</code> is a synchronous
* call which tells the parent node whether on not to call the child node's
* <code>buildDelta</code> with the given event. If a child node return
* <code>true</code>, it only indicates that the node may add delta flags, but it
* does not require it to do so.
* </p>
*
* @param event Event to process.
* @param parent Parent model delta node that this object should add delta
* data to.

View file

@ -16,11 +16,6 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationCont
public interface IVMProvider
extends IElementContentProvider, IModelProxyFactoryAdapter, IColumnPresentationFactoryAdapter
{
/**
* Returns the View Model Adapter that this provider belongs to.
*/
public IVMAdapter getVMAdapter();
/**
* Returns the root layout node that is configured in this provider.
* It may return null, if a root node is not yet configured.

View file

@ -177,7 +177,7 @@ public class VMDelta extends ModelDelta {
* @param numChildren the number of children the element has
* @return newly created child delta
*/
public ModelDelta addNode(Object element, int index, int flags, int numChildren) {
public VMDelta addNode(Object element, int index, int flags, int numChildren) {
VMDelta node = new VMDelta(element, index, flags, numChildren);
node.setParent(this);
addDelta(node);
@ -197,7 +197,7 @@ public class VMDelta extends ModelDelta {
* @see org.eclipse.debug.internal.ui.viewers.IModelDelta#getParent()
*/
@Override
public IModelDelta getParentDelta() {
public VMDelta getParentDelta() {
return fParent;
}

View file

@ -388,7 +388,7 @@ abstract public class AbstractDMVMLayoutNode<V extends IDMData> extends Abstract
// Create the VM context based on the DM context from the DM event.
final IVMContext vmc = new DMVMContext(DMContexts.getAncestorOfType(event.getDMContext(), fDMCClassType));
final Map<IVMLayoutNode,Integer> childNodeDeltas = getChildNodesWithDeltas(event);
final Map<IVMLayoutNode,Integer> childNodeDeltas = getChildNodesWithDeltaFlags(event);
if (childNodeDeltas.size() == 0) {
// There are no child nodes with deltas, just return to parent.
getExecutor().execute(done);