diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/DebugViewSelectionRootLayoutNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/DebugViewSelectionRootLayoutNode.java
index 18d00b8d4b4..a147deafe8f 100644
--- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/DebugViewSelectionRootLayoutNode.java
+++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/DebugViewSelectionRootLayoutNode.java
@@ -10,14 +10,15 @@
*******************************************************************************/
package org.eclipse.dd.dsf.debug.ui.viewmodel;
-import org.eclipse.dd.dsf.concurrent.DsfExecutor;
-import org.eclipse.dd.dsf.concurrent.DsfRunnable;
import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.datamodel.IDMEvent;
+import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin;
+import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMRootLayoutNode;
import org.eclipse.dd.dsf.ui.viewmodel.IVMRootLayoutNode;
-import org.eclipse.dd.dsf.ui.viewmodel.DMContextVMLayoutNode.DMContextVMContext;
+import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode.DMVMContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.contexts.DebugContextEvent;
import org.eclipse.debug.ui.contexts.IDebugContextListener;
@@ -27,21 +28,26 @@ import org.eclipse.ui.IWorkbenchWindow;
/**
* This is is a standard root node which listens to the selection in Debug View.
- * Views such as variables and registers base their content based on the
+ * Views such as variables and registers base their content on the
* selection in Debug view, and this node provides tracking of that selection.
+ *
+ * Note: The variables/registers views track the selection using the same
+ * IDebugContextListener interface, but they only use the first element of the
+ * selection, as in IStructuredSelection.getFirstElement(). Therefore the root
+ * node also has to use the first element as the root object instead of the
+ * whole selection.
*/
+@SuppressWarnings("restriction")
public class DebugViewSelectionRootLayoutNode extends AbstractVMRootLayoutNode
implements IVMRootLayoutNode, IDebugContextListener
{
- private RootVMC fRootVMC;
+ private ISelection fSelection;
- public DebugViewSelectionRootLayoutNode(DsfExecutor executor, IWorkbenchWindow window) {
- super(executor);
- ISelection selection = DebugUITools.getDebugContextManager().getContextService(window).getActiveContext();
- if (selection instanceof IStructuredSelection) {
- fRootVMC = new RootVMC( this, ((IStructuredSelection)selection).getFirstElement() );
- } else {
- fRootVMC = new RootVMC( this, null );
+ public DebugViewSelectionRootLayoutNode(AbstractVMProvider provider) {
+ super(provider);
+ IWorkbenchWindow activeWindow = DsfDebugUIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
+ if (activeWindow != null) {
+ fSelection = DebugUITools.getDebugContextManager().getContextService(activeWindow).getActiveContext();
}
DebugUITools.getDebugContextManager().addDebugContextListener(this);
}
@@ -53,7 +59,7 @@ public class DebugViewSelectionRootLayoutNode extends AbstractVMRootLayoutNode
}
/**
- * If the input object is a DMC-VMC, and the event is a DMC event.
+ * If the input object is a Data Model context, and the event is a DMC event.
* Then we can filter the event to make sure that the view does not
* react to events that relate to objects outside this view.
*
@@ -74,45 +80,58 @@ public class DebugViewSelectionRootLayoutNode extends AbstractVMRootLayoutNode
* determine whether a delta is needed.
*/
@Override
- public boolean hasDeltaFlags(Object event) {
- if (event instanceof IDMEvent && fRootVMC.getInputObject() instanceof DMContextVMContext) {
+ public int getDeltaFlags(Object event) {
+ IDMContext> inputDmc = getSelectedDMC();
+ if (event instanceof IDMEvent && inputDmc != null) {
boolean potentialMatchFound = false;
boolean matchFound = false;
IDMContext> eventDmc = ((IDMEvent)event).getDMContext();
- IDMContext> inputDmc = ((DMContextVMContext)fRootVMC.getInputObject()).getDMC();
for (IDMContext> eventDmcAncestor : DMContexts.toList(eventDmc)) {
IDMContext> inputDmcAncestor = DMContexts.getAncestorOfType(inputDmc, eventDmcAncestor.getClass());
if (inputDmcAncestor != null) {
potentialMatchFound = true;
if (inputDmcAncestor.equals(eventDmcAncestor)) {
- matchFound = true;
+ return super.getDeltaFlags(event);
}
}
}
if (potentialMatchFound && !matchFound) {
- return false;
+ return IModelDelta.NO_CHANGE;
}
}
- return super.hasDeltaFlags(event);
+ return super.getDeltaFlags(event);
}
- public IRootVMC getRootVMC() {
- return fRootVMC;
+ /**
+ * Returns the full selection as it came from the DebugContextManager.
+ * @return
+ */
+ public ISelection getSelection() {
+ return fSelection;
+ }
+
+ public Object getRootObject() {
+ if (fSelection instanceof IStructuredSelection) {
+ return ((IStructuredSelection)fSelection).getFirstElement();
+ }
+ return null;
}
public void debugContextChanged(DebugContextEvent event) {
- final ISelection selection = event.getContext();
- getExecutor().execute(new DsfRunnable() {
- public void run() {
- if (selection instanceof IStructuredSelection) {
- fRootVMC = new RootVMC( DebugViewSelectionRootLayoutNode.this,
- ((IStructuredSelection)selection).getFirstElement() );
- } else {
- fRootVMC = new RootVMC( DebugViewSelectionRootLayoutNode.this, null );
- }
+ fSelection = event.getContext();
+ }
+
+ private IDMContext> getSelectedDMC() {
+ Object selection = fSelection;
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection structSelection = (IStructuredSelection)selection;
+ if (structSelection.getFirstElement() instanceof DMVMContext)
+ {
+ return ((DMVMContext)structSelection.getFirstElement()).getDMC();
}
- });
+ }
+ return null;
}
}
diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/LaunchViewModelProvider.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/LaunchViewModelProvider.java
deleted file mode 100644
index 1999f647def..00000000000
--- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/LaunchViewModelProvider.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006 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.dd.dsf.debug.ui.viewmodel.launch;
-
-import org.eclipse.dd.dsf.concurrent.DsfRunnable;
-import org.eclipse.dd.dsf.concurrent.GetDataDone;
-import org.eclipse.dd.dsf.concurrent.ThreadSafe;
-import org.eclipse.dd.dsf.service.DsfSession;
-import org.eclipse.dd.dsf.ui.viewmodel.IVMRootLayoutNode;
-import org.eclipse.dd.dsf.ui.viewmodel.VMProvider;
-import org.eclipse.debug.core.DebugEvent;
-import org.eclipse.debug.core.DebugPlugin;
-import org.eclipse.debug.core.IDebugEventSetListener;
-import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta;
-
-
-/**
- *
- */
-@SuppressWarnings("restriction")
-public class LaunchViewModelProvider extends VMProvider
- implements IDebugEventSetListener
-{
- @ThreadSafe
- public LaunchViewModelProvider(DsfSession session, IVMRootLayoutNode rootLayoutNode) {
- super(session, rootLayoutNode);
- DebugPlugin.getDefault().addDebugEventListener(this);
- }
-
-
- public void handleDebugEvents(final DebugEvent[] events) {
- getSession().getExecutor().execute(new DsfRunnable() {
- public void run() {
- for (DebugEvent event : events) {
- handleDebugEvent(event);
- }
- }
- });
- }
-
- private void handleDebugEvent(DebugEvent event) {
- /*
- * Just like with DMC events, go through all the layout nodes and
- * collect delta information for the received event.
- */
- if (getRootLayoutNode() != null && getRootLayoutNode().hasDeltaFlags(event)) {
- getRootLayoutNode().createDelta(event, new GetDataDone() {
- public void run() {
- if (getStatus().isOK()) {
- getModelProxy().fireModelChangedNonDispatch(getData());
- }
- }
- });
- }
- }
-
- @Override
- public void dispose() {
- DebugPlugin.getDefault().removeDebugEventListener(this);
- super.dispose();
- }
-}
diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StackFramesLayoutNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StackFramesLayoutNode.java
index 91458bd6894..0bd4d240637 100644
--- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StackFramesLayoutNode.java
+++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StackFramesLayoutNode.java
@@ -10,9 +10,11 @@
*******************************************************************************/
package org.eclipse.dd.dsf.debug.ui.viewmodel.launch;
-import org.eclipse.core.runtime.MultiStatus;
+import java.util.List;
+
import org.eclipse.dd.dsf.concurrent.Done;
import org.eclipse.dd.dsf.concurrent.GetDataDone;
+import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.datamodel.IDMEvent;
import org.eclipse.dd.dsf.debug.service.IRunControl;
import org.eclipse.dd.dsf.debug.service.IStack;
@@ -21,66 +23,77 @@ import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.StateChangeReason;
import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMData;
-import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin;
import org.eclipse.dd.dsf.service.DsfSession;
-import org.eclipse.dd.dsf.ui.viewmodel.DMContextVMLayoutNode;
+import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
-import org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor;
-import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta;
+import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugUIConstants;
-import org.eclipse.jface.resource.ImageDescriptor;
-
@SuppressWarnings("restriction")
-public class StackFramesLayoutNode extends DMContextVMLayoutNode {
+public class StackFramesLayoutNode extends AbstractDMVMLayoutNode {
- public IVMContext[] fCachedOldFramesVMCs;
+ public IVMContext[] fCachedOldFrameVMCs;
- public StackFramesLayoutNode(DsfSession session) {
- super(session, IStack.IFrameDMContext.class);
+ public StackFramesLayoutNode(AbstractVMProvider provider, DsfSession session) {
+ super(provider, session, IStack.IFrameDMContext.class);
}
- public void hasElements(IVMContext parentVmc, final GetDataDone done) {
- IExecutionDMContext execDmc = findDmcInVmc(parentVmc, IExecutionDMContext.class);
- if (execDmc == null || getServicesTracker().getService(IStack.class) == null || getServicesTracker().getService(IRunControl.class) == null) {
- done.setData(false);
- getExecutor().execute(done);
- return;
- }
+ @Override
+ protected void updateHasElementsInSessionThread(IHasChildrenUpdate[] updates) {
- done.setData(getServicesTracker().getService(IStack.class).isStackAvailable(execDmc));
- getExecutor().execute(done);
+ for (IHasChildrenUpdate update : updates) {
+ if (!checkService(IStack.class, null, update)) return;
+
+ IExecutionDMContext execDmc = findDmcInPath(update.getElementPath(), IExecutionDMContext.class);
+ if (execDmc == null) {
+ handleFailedUpdate(update);
+ return;
+ }
+
+ update.setHasChilren(getServicesTracker().getService(IStack.class).isStackAvailable(execDmc));
+ update.done();
+ }
}
- public void getElements(final IVMContext parentVmc, final GetDataDone done) {
- final IExecutionDMContext execDmc = findDmcInVmc(parentVmc, IExecutionDMContext.class);
- if (execDmc == null || getServicesTracker().getService(IStack.class) == null || getServicesTracker().getService(IRunControl.class) == null) {
- done.setData(new IVMContext[0]);
- getExecutor().execute(done);
+ @Override
+ protected void updateElementsInSessionThread(final IChildrenUpdate update) {
+ if (!checkService(IStack.class, null, update)) return;
+
+ final IExecutionDMContext execDmc = findDmcInPath(update.getElementPath(), IExecutionDMContext.class);
+ if (execDmc == null) {
+ handleFailedUpdate(update);
return;
}
getServicesTracker().getService(IStack.class).getFrames(
execDmc,
- new GetDataDone() { public void run() {
- if (!getStatus().isOK()) {
- // Failed to retrieve frames. If we are stepping, we
- // might still be able to retrieve just the top stack
- // frame, which would still be useful in Debug View.
- if (getServicesTracker().getService(IRunControl.class).isStepping(execDmc)) {
- getElementsTopStackFrameOnly(parentVmc, done);
- } else {
- propagateError(getExecutor(), done, "Failed retrieving stack frames"); //$NON-NLS-1$
+ new GetDataDone() {
+ public void run() {
+ if (!getStatus().isOK()) {
+ // Failed to retrieve frames. If we are stepping, we
+ // might still be able to retrieve just the top stack
+ // frame, which would still be useful in Debug View.
+ if (!checkService(IRunControl.class, null, update)) return;
+ if (getServicesTracker().getService(IRunControl.class).isStepping(execDmc)) {
+ getElementsTopStackFrameOnly(update);
+ } else {
+ update.done();
+ }
+ return;
}
- return;
+ // Store the VMC element array, in case we need to use it when
+ fCachedOldFrameVMCs = dmcs2vmcs(getData());
+ for (int i = 0; i < fCachedOldFrameVMCs.length; i++) update.setChild(fCachedOldFrameVMCs[i], i);
+ update.done();
}
- // Store the VMC element array, in case we need to use it when
- fCachedOldFramesVMCs = dmcs2vmcs(parentVmc, getData());
- done.setData(fCachedOldFramesVMCs);
- getExecutor().execute(done);
- }});
+ });
}
/**
@@ -89,184 +102,197 @@ public class StackFramesLayoutNode extends DMContextVMLayoutNode done) {
- final IExecutionDMContext execDmc = findDmcInVmc(parentVmc, IExecutionDMContext.class);
+ private void getElementsTopStackFrameOnly(final IChildrenUpdate update) {
+ final IExecutionDMContext execDmc = findDmcInPath(update.getElementPath(), IExecutionDMContext.class);
+ if (execDmc == null) {
+ handleFailedUpdate(update);
+ return;
+ }
getServicesTracker().getService(IStack.class).getTopFrame(
execDmc,
new GetDataDone() { public void run() {
- if (propagateError(getExecutor(), done, "Failed retrieving top stack frame")) return; //$NON-NLS-1$
- IVMContext topFrameVmc = new DMContextVMContext(parentVmc, getData());
+ if (!getStatus().isOK()) {
+ handleFailedUpdate(update);
+ return;
+ }
+ IVMContext topFrameVmc = new DMVMContext(getData());
+
+ update.setChild(topFrameVmc, 0);
// If there are old frames cached, use them and only substitute the top frame object. Otherwise, create
// an array of VMCs with just the top frame.
- if (fCachedOldFramesVMCs != null && fCachedOldFramesVMCs.length >= 1) {
- fCachedOldFramesVMCs[0] = topFrameVmc;
- done.setData(fCachedOldFramesVMCs);
+ if (fCachedOldFrameVMCs != null && fCachedOldFrameVMCs.length >= 1) {
+ fCachedOldFrameVMCs[0] = topFrameVmc;
+ for (int i = 0; i < fCachedOldFrameVMCs.length; i++) update.setChild(fCachedOldFrameVMCs[i], i);
} else {
- done.setData(new IVMContext[] { topFrameVmc });
+ update.setChild(topFrameVmc, 0);
}
- getExecutor().execute(done);
+ update.done();
}});
}
- public void retrieveLabel(IVMContext vmc, final ILabelRequestMonitor result, String[] columns) {
- final IExecutionDMContext execDmc = findDmcInVmc(vmc, IExecutionDMContext.class);
- if (execDmc == null || getServicesTracker().getService(IStack.class) == null || getServicesTracker().getService(IRunControl.class) == null) {
- result.done();
- return;
- }
-
+ @Override
+ protected void fillColumnLabel(IDMContext dmContext, IFrameDMData dmData, String columnId, int idx,
+ ILabelUpdate update)
+ {
+ if (idx != 0) return;
+
+ final IExecutionDMContext execDmc = findDmcInPath(update.getElementPath(), IExecutionDMContext.class);
+ IRunControl runControlService = getServicesTracker().getService(IRunControl.class);
+ IStepQueueManager stepQueueMgrService = getServicesTracker().getService(IStepQueueManager.class);
+ if (execDmc == null || runControlService == null || stepQueueMgrService == null) return;
+
String imageKey = null;
- IRunControl rc = getServicesTracker().getService(IRunControl.class);
- if (rc.isSuspended(execDmc) ||
- (rc.isStepping(execDmc) && !getServicesTracker().getService(IStepQueueManager.class).isSteppingTimedOut(execDmc)))
+ if (runControlService.isSuspended(execDmc) ||
+ (runControlService.isStepping(execDmc) && !stepQueueMgrService.isSteppingTimedOut(execDmc)))
{
imageKey = IDebugUIConstants.IMG_OBJS_STACKFRAME;
} else {
imageKey = IDebugUIConstants.IMG_OBJS_STACKFRAME_RUNNING;
}
- result.setImageDescriptors(new ImageDescriptor[] { DebugUITools.getImageDescriptor(imageKey) });
+ update.setImageDescriptor(DebugUITools.getImageDescriptor(imageKey), 0);
- IFrameDMContext frameDmc = (IFrameDMContext)((DMContextVMContext)vmc).getDMC();
- getServicesTracker().getService(IStack.class).getModelData(
- frameDmc,
- new GetDataDone() { public void run() {
- // Check if services are still available.
- if (getServicesTracker().getService(IRunControl.class) == null) {
- result.done();
- return;
- }
-
- if (!getStatus().isOK()) {
- // If failed set a dummy label, and only propagate the
- // error if we are not stepping, since that would be a
- // common cause of failure.
- result.setLabels(new String[] { "..." }); //$NON-NLS-1$
- if (!getServicesTracker().getService(IRunControl.class).isStepping(execDmc)) {
- MultiStatus status = new MultiStatus(DsfDebugUIPlugin.PLUGIN_ID, 0, "Failed to retrieve stack frame label", null); //$NON-NLS-1$
- status.add(getStatus());
- result.setStatus(status);
- }
- result.done();
- return;
- }
-
- //
- // Finally, if all goes well, set the label.
- //
- StringBuilder label = new StringBuilder();
-
- // Add frame number (if total number of frames in known)
- if (fCachedOldFramesVMCs != null) {
- label.append(fCachedOldFramesVMCs.length - getData().getLevel());
- }
-
- // Add the function name
- if (getData().getFunction() != null && getData().getFunction().length() != 0) {
- label.append(" "); //$NON-NLS-1$
- label.append(getData().getFunction());
- label.append("()"); //$NON-NLS-1$
- }
-
- // Add full file name
- if (getData().getFile() != null && getData().getFile().length() != 0) {
- label.append(" at "); //$NON-NLS-1$
- label.append(getData().getFile());
- }
-
- // Add line number
- if (getData().getLine() >= 0) {
- label.append(":"); //$NON-NLS-1$
- label.append(getData().getLine());
- label.append(" "); //$NON-NLS-1$
- }
-
- // Add the address
- label.append(getData().getAddress());
-
- // Set the label to the result listener
- result.setLabels(new String[] { label.toString() });
- result.done();
- }});
+ //
+ // Finally, if all goes well, set the label.
+ //
+ StringBuilder label = new StringBuilder();
+
+ // Add frame number (if total number of frames in known)
+ if (fCachedOldFrameVMCs != null) {
+ label.append(fCachedOldFrameVMCs.length - dmData.getLevel());
+ }
+
+ // Add the function name
+ if (dmData.getFunction() != null && dmData.getFunction().length() != 0) {
+ label.append(" "); //$NON-NLS-1$
+ label.append(dmData.getFunction());
+ label.append("()"); //$NON-NLS-1$
+ }
+
+ // Add full file name
+ if (dmData.getFile() != null && dmData.getFile().length() != 0) {
+ label.append(" at "); //$NON-NLS-1$
+ label.append(dmData.getFile());
+ }
+
+ // Add line number
+ if (dmData.getLine() >= 0) {
+ label.append(":"); //$NON-NLS-1$
+ label.append(dmData.getLine());
+ label.append(" "); //$NON-NLS-1$
+ }
+
+ // Add the address
+ label.append(dmData.getAddress());
+
+ // Set the label to the result listener
+ update.setLabel(label.toString(), 0);
}
- public boolean hasDeltaFlagsForDMEvent(IDMEvent> e) {
+ protected void handleFailedUpdate(IViewerUpdate update) {
+ if (update instanceof ILabelUpdate) {
+ // Avoid repainting the label if it's not available. This only slows
+ // down the display.
+ } else {
+ super.handleFailedUpdate(update);
+ }
+ }
+
+
+ @Override
+ protected int getNodeDeltaFlagsForDMEvent(org.eclipse.dd.dsf.datamodel.IDMEvent> e) {
// This node generates delta if the timers have changed, or if the
// label has changed.
- return e instanceof IRunControl.ISuspendedDMEvent ||
- e instanceof IRunControl.IResumedDMEvent ||
- e instanceof IStepQueueManager.ISteppingTimedOutEvent ||
- super.hasDeltaFlagsForDMEvent(e);
+ if (e instanceof IRunControl.ISuspendedDMEvent) {
+ return IModelDelta.CONTENT | IModelDelta.EXPAND | IModelDelta.SELECT;
+ } else if (e instanceof IRunControl.IResumedDMEvent) {
+ if (((IRunControl.IResumedDMEvent)e).getReason() == StateChangeReason.STEP) {
+ return IModelDelta.STATE;
+ } else {
+ return IModelDelta.CONTENT;
+ }
+ } else if (e instanceof IStepQueueManager.ISteppingTimedOutEvent) {
+ return IModelDelta.CONTENT;
+ }
+ return 0;
}
- public void buildDeltaForDMEvent(final IDMEvent> e, final VMDelta parent, final Done done) {
- if (getServicesTracker().getService(IStack.class) == null || getServicesTracker().getService(IRunControl.class) == null) {
+ @Override
+ protected void buildDeltaForDMEvent(final IDMEvent> e, final VMDelta parent, final int nodeOffset, final Done done) {
+ if (e instanceof IRunControl.ISuspendedDMEvent) {
+ buildDeltaForSuspendedEvent((IRunControl.ISuspendedDMEvent)e, parent, nodeOffset, done);
+ } else if (e instanceof IRunControl.IResumedDMEvent) {
+ buildDeltaForResumedEvent((IRunControl.IResumedDMEvent)e, parent, nodeOffset, done);
+ } else if (e instanceof IStepQueueManager.ISteppingTimedOutEvent) {
+ buildDeltaForSteppingTimedOutEvent((IStepQueueManager.ISteppingTimedOutEvent)e, parent, nodeOffset, done);
+ } else {
+ // Call super-class to build sub-node delta's.
+ super.buildDeltaForDMEvent(e, parent, nodeOffset, done);
+ }
+ }
+
+ private void buildDeltaForSuspendedEvent(final IRunControl.ISuspendedDMEvent e, final VMDelta parent, final int nodeOffset, final Done done) {
+ IRunControl runControlService = getServicesTracker().getService(IRunControl.class);
+ IStack stackService = getServicesTracker().getService(IStack.class);
+ if (stackService == null || runControlService == null) {
// Required services have not initialized yet. Ignore the event.
- super.buildDeltaForDMEvent(e, parent, done);
+ super.buildDeltaForDMEvent(e, parent, nodeOffset, done);
return;
}
- if (e instanceof IRunControl.ISuspendedDMEvent) {
- IRunControl.ISuspendedDMEvent suspendedEvent = (IRunControl.ISuspendedDMEvent)e;
-
- // Refresh the whole list of stack frames unless the target is already stepping the next command. In
- // which case, the refresh will occur when the stepping sequence slows down or stops. Trying to
- // refresh the whole stack trace with every step would slow down stepping too much.
- if (!getServicesTracker().getService(IRunControl.class).isStepping(suspendedEvent.getDMContext())) {
- parent.addFlags(IModelDelta.CONTENT);
- }
-
- // Always expand the thread node to show the stack frames.
- parent.addFlags(IModelDelta.EXPAND);
-
- // Retrieve the list of stack frames, and mark the top frame to be selected.
- getElementsTopStackFrameOnly(
- parent.getVMC(),
- new GetDataDone() { public void run() {
- if (getStatus().isOK() && getData().length != 0) {
- parent.addNode( getData()[0], IModelDelta.SELECT | IModelDelta.STATE);
- // If second frame is available repaint it, so that a "..." appears. This gives a better
- // impression that the frames are not up-to date.
- if (getData().length >= 2) {
- parent.addNode( getData()[1], IModelDelta.STATE);
- }
- }
- // Even in case of errors, call super-class to complete building of the delta.
- StackFramesLayoutNode.super.buildDeltaForDMEvent(e, parent, done);
- }});
-
- } else if (e instanceof IRunControl.IResumedDMEvent) {
- IRunControl.IResumedDMEvent resumedEvent = (IRunControl.IResumedDMEvent)e;
- getExecutor().execute(done);
- if (resumedEvent.getReason() == StateChangeReason.STEP) {
- // TODO: Refreshing the state of the top stack frame is only necessary to re-enable the step button.
- // This is because platform disables the step action every time after it is invoked. Need to file
- // a bug on this.
- getServicesTracker().getService(IStack.class).getTopFrame(
- resumedEvent.getDMContext(),
- new GetDataDone() { public void run() {
- if (getStatus().isOK()) {
- parent.addNode(new DMContextVMContext(parent.getVMC(), getData()), IModelDelta.STATE);
- }
- StackFramesLayoutNode.super.buildDeltaForDMEvent(e, parent, done);
- }});
- StackFramesLayoutNode.super.buildDeltaForDMEvent(e, parent, done);
- } else {
- // Refresh the list of stack frames only if the run operation is not a step. Also, clear the list
- // of cached frames.
- parent.addFlags(IModelDelta.CONTENT);
- fCachedOldFramesVMCs = null;
- // Call super-class to build sub-node delta's.
- super.buildDeltaForDMEvent(e, parent, done);
- }
- } else if (e instanceof IStepQueueManager.ISteppingTimedOutEvent) {
- // Repaint the stack frame images to have the running symbol.
+ // Refresh the whole list of stack frames unless the target is already stepping the next command. In
+ // which case, the refresh will occur when the stepping sequence slows down or stops. Trying to
+ // refresh the whole stack trace with every step would slow down stepping too much.
+ if (!runControlService.isStepping(e.getDMContext())) {
parent.addFlags(IModelDelta.CONTENT);
- super.buildDeltaForDMEvent(e, parent, done);
- } else {
- // Call super-class to build sub-node delta's.
- super.buildDeltaForDMEvent(e, parent, done);
}
+
+ // Always expand the thread node to show the stack frames.
+ parent.addFlags(IModelDelta.EXPAND);
+
+ // Retrieve the list of stack frames, and mark the top frame to be selected.
+ getElementsTopStackFrameOnly(
+ new ElementsUpdate(
+ new GetDataDone>() {
+ public void run() {
+ if (getStatus().isOK() && getData().size() != 0) {
+ parent.addNode( getData().get(0), IModelDelta.SELECT | IModelDelta.STATE);
+ // If second frame is available repaint it, so that a "..." appears. This gives a better
+ // impression that the frames are not up-to date.
+ if (getData().size() >= 2) {
+ parent.addNode( getData().get(1), IModelDelta.STATE);
+ }
+ }
+ // Even in case of errors, call super-class to complete building of the delta.
+ StackFramesLayoutNode.super.buildDeltaForDMEvent(e, parent, nodeOffset, done);
+ }
+ },
+ parent)
+ );
+ }
+
+ private void buildDeltaForResumedEvent(final IRunControl.IResumedDMEvent e, final VMDelta parent, final int nodeOffset, final Done done) {
+ IStack stackService = getServicesTracker().getService(IStack.class);
+ if (stackService == null) {
+ // Required services have not initialized yet. Ignore the event.
+ super.buildDeltaForDMEvent(e, parent, nodeOffset, done);
+ return;
+ }
+
+ IRunControl.IResumedDMEvent resumedEvent = (IRunControl.IResumedDMEvent)e;
+ if (resumedEvent.getReason() != StateChangeReason.STEP) {
+ // Refresh the list of stack frames only if the run operation is not a step. Also, clear the list
+ // of cached frames.
+ parent.addFlags(IModelDelta.CONTENT);
+ fCachedOldFrameVMCs = null;
+ }
+ super.buildDeltaForDMEvent(e, parent, nodeOffset, done);
+ }
+
+ private void buildDeltaForSteppingTimedOutEvent(final IStepQueueManager.ISteppingTimedOutEvent e, final VMDelta parent, final int nodeOffset, final Done done) {
+ // Repaint the stack frame images to have the running symbol.
+ parent.addFlags(IModelDelta.CONTENT);
+ super.buildDeltaForDMEvent(e, parent, nodeOffset, done);
}
}
diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StandardLaunchRootLayoutNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StandardLaunchRootLayoutNode.java
index ac19bf205f3..e45c8623912 100644
--- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StandardLaunchRootLayoutNode.java
+++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StandardLaunchRootLayoutNode.java
@@ -10,20 +10,24 @@
*******************************************************************************/
package org.eclipse.dd.dsf.debug.ui.viewmodel.launch;
-import org.eclipse.dd.dsf.concurrent.DoneCollector;
-import org.eclipse.dd.dsf.concurrent.DsfExecutor;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.dd.dsf.concurrent.Done;
import org.eclipse.dd.dsf.concurrent.GetDataDone;
+import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMRootLayoutNode;
-import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode;
import org.eclipse.dd.dsf.ui.viewmodel.IVMRootLayoutNode;
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.model.IDebugElement;
import org.eclipse.debug.core.model.IProcess;
-import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
/**
* Layout node for the standard ILaunch object. This node can only be used at
@@ -34,34 +38,29 @@ import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta;
public class StandardLaunchRootLayoutNode extends AbstractVMRootLayoutNode
implements IVMRootLayoutNode
{
- final private RootVMC fRootVMC;
- final IVMContext[] fElements;
+ final private ILaunch fLaunch;
- public StandardLaunchRootLayoutNode(DsfExecutor executor, ILaunch launch) {
- super(executor);
- fRootVMC = new RootVMC(this, launch);
- fElements = new IVMContext[] { fRootVMC };
+ public StandardLaunchRootLayoutNode(AbstractVMProvider provider, ILaunch launch) {
+ super(provider);
+ fLaunch = launch;
}
@Override
- public boolean hasDeltaFlags(Object e) {
- /*
- * Launch deltas for standard platform DebugEvent events are handled by
- * org.eclipse.debug.internal.ui.viewers.update.LaunchManagerProxy.
- * Here only control the deltas of child nodes. This is necessary to avoid
- * IProcess layout node from processing events that are intended for a
- * different launch. This is not a problem with DMC events, because the
- * full path of the DMC object is built into the DMC itself.
- */
+ public int getDeltaFlags(Object e) {
if (e instanceof DebugEvent) {
DebugEvent de = (DebugEvent)e;
- if (de.getSource() instanceof IProcess) {
- return ((IProcess)de.getSource()).getLaunch().equals(getRootVMC().getInputObject()) && super.hasDeltaFlags(e);
- } else if (de.getSource() instanceof IDebugElement) {
- return ((IDebugElement)de.getSource()).getLaunch().equals(getRootVMC().getInputObject()) && super.hasDeltaFlags(e);
+ if (de.getSource() instanceof IProcess &&
+ !((IProcess)de.getSource()).getLaunch().equals(fLaunch) )
+ {
+ return IModelDelta.NO_CHANGE;
+ }
+ else if (de.getSource() instanceof IDebugElement &&
+ !((IDebugElement)de.getSource()).getLaunch().equals(fLaunch) )
+ {
+ return IModelDelta.NO_CHANGE;
}
}
- return super.hasDeltaFlags(e);
+ return super.getDeltaFlags(e);
}
public void createDelta(Object event, final GetDataDone done) {
@@ -70,34 +69,26 @@ public class StandardLaunchRootLayoutNode extends AbstractVMRootLayoutNode
* root of the view, create the delta with the path to the launch, then
* pass that to the child layout nodes.
*/
- final VMDelta delta = new VMDelta(DebugPlugin.getDefault().getLaunchManager(), null);
- done.setData(delta);
- final VMDelta rootDelta = delta.addNode(getRootVMC().getInputObject(), getRootVMC());
+ ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
+ List launchList = Arrays.asList(manager.getLaunches());
+ final VMDelta viewRootDelta = new VMDelta(manager, 0, IModelDelta.NO_CHANGE, launchList.size());
+ final VMDelta rootDelta = viewRootDelta.addNode(getRootObject(), launchList.indexOf(fLaunch), IModelDelta.NO_CHANGE);
- final IVMLayoutNode[] childNodes = getChildNodesWithDeltas(event);
- if (childNodes.length == 0) {
- done.setData(delta);
- getExecutor().execute(done);
- return;
- }
+ final Map childNodeDeltas = getChildNodesWithDeltas(event);
+ assert childNodeDeltas.size() != 0 : "Caller should make sure that there are deltas for given event."; //$NON-NLS-1$
- /*
- * The execution for this node is not done until all the child nodes
- * are done. Use the tracker to wait for all children to complete.
- */
- final DoneCollector doneCollector = new DoneCollector(getExecutor()) {
- public void run() {
- if (propagateError(getExecutor(), done, "Failed to generate child deltas.")) return; //$NON-NLS-1$
- done.setData(delta);
- getExecutor().execute(done);
- }
- };
- for (final IVMLayoutNode childNode : childNodes) {
- childNode.buildDelta(event, rootDelta, doneCollector.addNoActionDone());
- }
+ callChildNodesToBuildDelta(
+ childNodeDeltas, rootDelta, event,
+ new Done() {
+ public void run() {
+ if (propagateError(getExecutor(), done, "Failed to create delta.")); //$NON-NLS-1$
+ done.setData(viewRootDelta);
+ getExecutor().execute(done);
+ }
+ });
}
- public IRootVMC getRootVMC() {
- return fRootVMC;
+ public Object getRootObject() {
+ return fLaunch;
}
}
diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StandardProcessLayoutNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StandardProcessLayoutNode.java
index 652034f9416..78f34c3eaa9 100644
--- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StandardProcessLayoutNode.java
+++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StandardProcessLayoutNode.java
@@ -10,25 +10,23 @@
*******************************************************************************/
package org.eclipse.dd.dsf.debug.ui.viewmodel.launch;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
import org.eclipse.dd.dsf.concurrent.Done;
-import org.eclipse.dd.dsf.concurrent.DsfExecutor;
-import org.eclipse.dd.dsf.concurrent.GetDataDone;
-import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin;
-import org.eclipse.dd.dsf.service.IDsfService;
import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMLayoutNode;
+import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode;
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
-import org.eclipse.dd.dsf.ui.viewmodel.IVMRootLayoutNode.IRootVMC;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.IStreamsProxy;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
import org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor;
-import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta;
+import org.eclipse.jface.viewers.TreePath;
/**
* Layout node for the standard platform debug model IProcess object. This
@@ -43,19 +41,20 @@ public class StandardProcessLayoutNode extends AbstractVMLayoutNode {
* VMC element implementation, it is a proxy for the IProcess class, to
* allow the standard label adapter to be used with this object.
*/
- private class VMC implements IVMContext, IProcess
+ private class VMC extends AbstractVMContext
+ implements IProcess
{
- private final IVMContext fParentVmc;
private final IProcess fProcess;
- VMC(IVMContext parentVmc, IProcess process) {
- fParentVmc = parentVmc;
+ VMC(IProcess process) {
+ super(getVMProvider().getVMAdapter(), StandardProcessLayoutNode.this);
fProcess = process;
}
- public IVMContext getParent() { return fParentVmc; }
public IVMLayoutNode getLayoutNode() { return StandardProcessLayoutNode.this; }
- @SuppressWarnings("unchecked") public Object getAdapter(Class adapter) { return fProcess.getAdapter(adapter); }
+ @SuppressWarnings("unchecked") public Object getAdapter(Class adapter) {
+ return fProcess.getAdapter(adapter);
+ }
public String toString() { return "IProcess " + fProcess.toString(); } //$NON-NLS-1$
public String getAttribute(String key) { return fProcess.getAttribute(key); }
@@ -72,21 +71,17 @@ public class StandardProcessLayoutNode extends AbstractVMLayoutNode {
public int hashCode() { return fProcess.hashCode(); }
}
- public StandardProcessLayoutNode(DsfExecutor executor) {
- super(executor);
+ public StandardProcessLayoutNode(AbstractVMProvider provider) {
+ super(provider);
}
- // @see org.eclipse.dd.dsf.ui.viewmodel.IViewModelLayoutNode#getElements(org.eclipse.dd.dsf.ui.viewmodel.IVMContext, org.eclipse.dd.dsf.concurrent.GetDataDone)
- public void getElements(IVMContext parentVmc, GetDataDone done) {
- ILaunch launch = findLaunch(parentVmc);
+ public void updateElements(IChildrenUpdate update) {
+ ILaunch launch = findLaunch(update.getElementPath());
if (launch == null) {
- /*
- * There is no launch in the parent of this node. This means that the
- * layout is misconfigured.
- */
+ // There is no launch in the parent of this node. This means that the
+ // layout is misconfigured.
assert false;
- done.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Can't get list of processes, because there is no launch.", null)); //$NON-NLS-1$
- getExecutor().execute(done);
+ update.done();
return;
}
@@ -95,30 +90,43 @@ public class StandardProcessLayoutNode extends AbstractVMLayoutNode {
* retrieve them on dispatch thread.
*/
IProcess[] processes = launch.getProcesses();
- IVMContext[] processVmcs = new IVMContext[processes.length];
for (int i = 0; i < processes.length; i++) {
- processVmcs[i] = new VMC(parentVmc, processes[i]);
+ update.setChild(new VMC(processes[i]), i);
}
- done.setData(processVmcs);
- getExecutor().execute(done);
+ update.done();
}
-
- // @see org.eclipse.dd.dsf.ui.viewmodel.IViewModelLayoutNode#hasElements(org.eclipse.dd.dsf.ui.viewmodel.IVMContext, org.eclipse.dd.dsf.concurrent.GetDataDone)
- public void hasElements(IVMContext parentVmc, GetDataDone done) {
- ILaunch launch = findLaunch(parentVmc);
+
+ public void updateElementCount(IChildrenCountUpdate update) {
+ ILaunch launch = findLaunch(update.getElementPath());
if (launch == null) {
- assert false;
- done.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Can't get list of processes, because there is no launch.", null)); //$NON-NLS-1$
- getExecutor().execute(done);
+ assert false;
+ update.setChildCount(0);
+ update.done();
return;
}
- done.setData(launch.getProcesses().length != 0);
- getExecutor().execute(done);
+ update.setChildCount(launch.getProcesses().length);
+ update.done();
+ }
+
+ // @see org.eclipse.dd.dsf.ui.viewmodel.IViewModelLayoutNode#hasElements(org.eclipse.dd.dsf.ui.viewmodel.IVMContext, org.eclipse.dd.dsf.concurrent.GetDataDone)
+ public void updateHasElements(IHasChildrenUpdate[] updates) {
+ for (IHasChildrenUpdate update : updates) {
+ ILaunch launch = findLaunch(update.getElementPath());
+ if (launch == null) {
+ assert false;
+ update.setHasChilren(false);
+ update.done();
+ return;
+ }
+
+ update.setHasChilren(launch.getProcesses().length != 0);
+ update.done();
+ }
}
// @see org.eclipse.dd.dsf.ui.viewmodel.IViewModelLayoutNode#retrieveLabel(org.eclipse.dd.dsf.ui.viewmodel.IVMContext, org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor)
- public void retrieveLabel(IVMContext vmc, ILabelRequestMonitor result, String[] columns) {
+ public void updateLabel(IVMContext vmc, ILabelRequestMonitor result, String[] columns) {
/*
* The implementation of IAdapterFactory that uses this node should not
@@ -134,30 +142,33 @@ public class StandardProcessLayoutNode extends AbstractVMLayoutNode {
* Recursively searches the VMC for Launch VMC, and returns its ILaunch.
* Returns null if an ILaunch is not found.
*/
- private ILaunch findLaunch(IVMContext vmc) {
- if (vmc == null) {
- return null;
- } else if (vmc instanceof IRootVMC || ((IRootVMC)vmc).getInputObject() instanceof ILaunch) {
- return (ILaunch)(((IRootVMC)vmc)).getInputObject();
- } else {
- return findLaunch(vmc.getParent());
+ private ILaunch findLaunch(TreePath path) {
+ for (int i = path.getSegmentCount() - 1; i >= 0; i--) {
+ if (path.getSegment(i) instanceof ILaunch) {
+ return (ILaunch)path.getSegment(i);
+ }
}
+ return null;
}
@Override
- public boolean hasDeltaFlags(Object e) {
+ public int getDeltaFlags(Object e) {
+ int myFlags = 0;
if (e instanceof DebugEvent) {
DebugEvent de = (DebugEvent)e;
- return de.getSource() instanceof IProcess &&
- (de.getKind() == DebugEvent.CHANGE ||
- de.getKind() == DebugEvent.CREATE ||
- de.getKind() == DebugEvent.TERMINATE);
+ if ( de.getSource() instanceof IProcess &&
+ (de.getKind() == DebugEvent.CHANGE ||
+ de.getKind() == DebugEvent.CREATE ||
+ de.getKind() == DebugEvent.TERMINATE) )
+ {
+ myFlags = IModelDelta.STATE;
+ }
}
- return super.hasDeltaFlags(e);
+ return myFlags | super.getDeltaFlags(e);
}
@Override
- public void buildDelta(Object e, VMDelta parent, Done done) {
+ public void buildDelta(Object e, VMDelta parent, int nodeOffset, Done done) {
if (e instanceof DebugEvent && ((DebugEvent)e).getSource() instanceof IProcess) {
DebugEvent de = (DebugEvent)e;
if (de.getKind() == DebugEvent.CHANGE) {
@@ -173,12 +184,12 @@ public class StandardProcessLayoutNode extends AbstractVMLayoutNode {
*/
getExecutor().execute(done);
} else {
- super.buildDelta(e, parent, done);
+ super.buildDelta(e, parent, nodeOffset, done);
}
}
protected void handleChange(DebugEvent event, VMDelta parent) {
- parent.addNode(new VMC(parent.getVMC(), (IProcess)event.getSource()), IModelDelta.STATE);
+ parent.addNode(new VMC((IProcess)event.getSource()), IModelDelta.STATE);
}
protected void handleCreate(DebugEvent event, VMDelta parent) {
diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterColumnPresentation.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterColumnPresentation.java
index c259d78b3a1..779980b0586 100644
--- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterColumnPresentation.java
+++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterColumnPresentation.java
@@ -11,8 +11,8 @@
package org.eclipse.dd.dsf.debug.ui.viewmodel.register;
import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin;
-import org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation;
-import org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
import org.eclipse.jface.resource.ImageDescriptor;
/**
diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterGroupLayoutNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterGroupLayoutNode.java
index ef96b6ac340..f924d815f3b 100644
--- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterGroupLayoutNode.java
+++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterGroupLayoutNode.java
@@ -10,84 +10,58 @@
*******************************************************************************/
package org.eclipse.dd.dsf.debug.ui.viewmodel.register;
-import org.eclipse.dd.dsf.concurrent.Done;
import org.eclipse.dd.dsf.concurrent.GetDataDone;
import org.eclipse.dd.dsf.datamodel.IDMContext;
-import org.eclipse.dd.dsf.datamodel.IDMEvent;
import org.eclipse.dd.dsf.debug.service.IRegisters;
import org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterGroupDMContext;
import org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterGroupData;
import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.dd.dsf.service.DsfSession;
-import org.eclipse.dd.dsf.ui.viewmodel.DMContextVMLayoutNode;
-import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
-import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.swt.graphics.FontData;
-import org.eclipse.swt.graphics.RGB;
+import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
+import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
@SuppressWarnings("restriction")
-public class RegisterGroupLayoutNode extends DMContextVMLayoutNode {
+public class RegisterGroupLayoutNode extends AbstractDMVMLayoutNode {
- public RegisterGroupLayoutNode(DsfSession session) {
- super(session, IRegisters.IRegisterGroupDMContext.class);
- }
-
- public void hasElements( final IVMContext parentVmc , final GetDataDone done ) {
- final IExecutionDMContext execDmc = findDmcInVmc(parentVmc, IExecutionDMContext.class);
-
- if (execDmc == null || getServicesTracker().getService(IRegisters.class) == null) {
- done.setData(Boolean.FALSE);
- getExecutor().execute(done);
- return;
- }
-
- getServicesTracker().getService(IRegisters.class).getRegisterGroups(
- execDmc, null,
- new GetDataDone() { public void run() {
- if (propagateError(getExecutor(), done, "Failed to retrieve register groups")) return; //$NON-NLS-1$
- done.setData(getData().length != 0);
- getExecutor().execute(done);
- }});
- }
-
- public void getElements( final IVMContext parentVmc, final GetDataDone done ) {
- final IExecutionDMContext execDmc = findDmcInVmc(parentVmc, IExecutionDMContext.class) ;
-
- if ( execDmc == null || getServicesTracker().getService( IRegisters.class ) == null ) {
- done.setData(new IVMContext[0]);
- getExecutor().execute( done );
- return;
- }
-
- getServicesTracker().getService(IRegisters.class).getRegisterGroups(
- execDmc, null,
- new GetDataDone() { public void run() {
- if (propagateError(getExecutor(), done, "Failed to retrieve register groups")) return; //$NON-NLS-1$
- done.setData(dmcs2vmcs(parentVmc, getData()));
- getExecutor().execute(done);
- }});
+ public RegisterGroupLayoutNode(AbstractVMProvider provider, DsfSession session) {
+ super(provider, session, IRegisters.IRegisterGroupDMContext.class);
}
@Override
- protected void fillColumnLabel(IDMContext dmContext, IRegisterGroupData dmData,
- String columnId, int idx, String[] text, ImageDescriptor[] image,
- FontData[] fontData, RGB[] foreground, RGB[] background)
- {
- if (RegisterColumnPresentation.COL_NAME.equals(columnId)) {
- text[idx] = dmData.getName();
- } else if (RegisterColumnPresentation.COL_VALUE.equals(columnId)) {
- text[idx] = ""; //$NON-NLS-1$
- } else if (RegisterColumnPresentation.COL_DESCRIPTION.equals(columnId)) {
- text[idx] = dmData.getDescription();
- }
+ protected void updateElementsInSessionThread(final IChildrenUpdate update) {
+ if (!checkService(IRegisters.class, null, update)) return;
+
+ final IExecutionDMContext execDmc = findDmcInPath(update.getElementPath(), IExecutionDMContext.class) ;
+
+ if (execDmc != null) {
+ getServicesTracker().getService(IRegisters.class).getRegisterGroups(
+ execDmc, null,
+ new GetDataDone() { public void run() {
+ if (!getStatus().isOK()) {
+ update.done();
+ return;
+ }
+ fillUpdateWithVMCs(update, getData());
+ update.done();
+ }});
+ } else {
+ handleFailedUpdate(update);
+ }
+
}
- public boolean hasDeltaFlagsForDMEvent(IDMEvent> e) {
- return super.hasDeltaFlagsForDMEvent(e);
- }
-
- public void buildDeltaForDMEvent(final IDMEvent> e, final VMDelta parent, final Done done) {
- super.buildDeltaForDMEvent(e, parent, done);
+ @Override
+ protected void fillColumnLabel(IDMContext dmContext, IRegisterGroupData dmData,
+ String columnId, int idx, ILabelUpdate update)
+ {
+ if (RegisterColumnPresentation.COL_NAME.equals(columnId)) {
+ update.setLabel(dmData.getName(), idx);
+ } else if (RegisterColumnPresentation.COL_VALUE.equals(columnId)) {
+ update.setLabel("", idx); //$NON-NLS-1$
+ } else if (RegisterColumnPresentation.COL_DESCRIPTION.equals(columnId)) {
+ update.setLabel(dmData.getDescription(), idx);
+ }
}
}
diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterLayoutNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterLayoutNode.java
index dce21df6358..dfdf80b19fd 100644
--- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterLayoutNode.java
+++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterLayoutNode.java
@@ -12,6 +12,7 @@ package org.eclipse.dd.dsf.debug.ui.viewmodel.register;
import org.eclipse.dd.dsf.concurrent.Done;
import org.eclipse.dd.dsf.concurrent.GetDataDone;
+import org.eclipse.dd.dsf.datamodel.IDMContext;
import org.eclipse.dd.dsf.datamodel.IDMEvent;
import org.eclipse.dd.dsf.debug.service.IRegisters;
import org.eclipse.dd.dsf.debug.service.IRunControl;
@@ -19,112 +20,86 @@ import org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterDMContext;
import org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterDMData;
import org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterGroupDMContext;
import org.eclipse.dd.dsf.service.DsfSession;
-import org.eclipse.dd.dsf.service.IDsfService;
-import org.eclipse.dd.dsf.ui.viewmodel.DMContextVMLayoutNode;
+import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
-import org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor;
-import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta;
+import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
@SuppressWarnings("restriction")
-public class RegisterLayoutNode extends DMContextVMLayoutNode {
+public class RegisterLayoutNode extends AbstractDMVMLayoutNode {
public IVMContext[] fCachedRegisterVMCs;
- public RegisterLayoutNode(DsfSession session) {
- super(session, IRegisters.IRegisterDMContext.class);
+ public RegisterLayoutNode(AbstractVMProvider provider, DsfSession session) {
+ super(provider, session, IRegisters.IRegisterDMContext.class);
}
- public void hasElements( final IVMContext parentVmc , final GetDataDone done ) {
- final IRegisterGroupDMContext registerGroupDmc = findDmcInVmc(parentVmc, IRegisterGroupDMContext.class);
+ @Override
+ protected void updateElementsInSessionThread(final IChildrenUpdate update) {
+ final IRegisterGroupDMContext execDmc = findDmcInPath(update.getElementPath(), IRegisterGroupDMContext.class);
- if (registerGroupDmc == null || getServicesTracker().getService(IRegisters.class) == null) {
- done.setData(Boolean.FALSE);
- getExecutor().execute(done);
+ if (execDmc == null) {
+ handleFailedUpdate(update);
return;
}
- getServicesTracker().getService( IRegisters.class ).getRegisters(
- registerGroupDmc,
+ getServicesTracker().getService(IRegisters.class).getRegisters(
+ execDmc,
new GetDataDone() {
public void run() {
- if (propagateError(getExecutor(), done, "Failed to retrieve registers")) return; //$NON-NLS-1$
- done.setData(getData().length != 0);
- getExecutor().execute(done);
+ if (!getStatus().isOK()) {
+ handleFailedUpdate(update);
+ }
+ fillUpdateWithVMCs(update, getData());
+ update.done();
}
});
}
-
- public void getElements( final IVMContext parentVmc , final GetDataDone done ) {
- final IRegisterGroupDMContext execDmc = findDmcInVmc(parentVmc, IRegisterGroupDMContext.class);
-
- if (execDmc == null || getServicesTracker().getService(IRegisters.class) == null) {
- getExecutor().execute(done);
- return;
- }
-
- getServicesTracker().getService( IRegisters.class ).getRegisters(
- execDmc,
- new GetDataDone() { public void run() {
- if (propagateError(getExecutor(), done, "Failed to retrieve registers")) return; //$NON-NLS-1$
- done.setData( dmcs2vmcs( parentVmc, getData()) );
- getExecutor().execute(done);
- }});
- }
- public void retrieveLabel(final IVMContext vmc , final ILabelRequestMonitor result, String[] columns) {
-
- if ( getServicesTracker().getService( IRegisters.class ) == null ) {
- result.done();
- return;
- }
-
- final IRegisterDMContext registerDmc = (IRegisterDMContext) ( (DMContextVMContext) vmc ).getDMC() ;
-
- getServicesTracker().getService( IRegisters.class ).getModelData(
- registerDmc ,
- new GetDataDone() {
- public void run() {
- if ( !getStatus().isOK() ) {
- assert getStatus().getCode() == IDsfService.INVALID_STATE || getStatus().getCode() == IDsfService.INVALID_HANDLE : getStatus().toString();
- // Some error conditions are expected.
- result.setLabels( new String[] { "...", "...", "..." } ) ; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- } else {
- String size = getData().getDescription();
- String value = getData().getHexValue();
- if ("".equals(size)) { //$NON-NLS-1$
- if ( value.contains( "uint64" ) ) { //$NON-NLS-1$
- size = "64 bit register" ; //$NON-NLS-1$
- } else if ( value.contains( "v4_float" ) ) { //$NON-NLS-1$
- size = "128 bit register" ; //$NON-NLS-1$
- }
- }
-
- result.setLabels(new String[] { getData().getName(), getData().getHexValue(), size });
- }
-
- result.done() ;
- return ;
+ @Override
+ protected void fillColumnLabel(IDMContext dmContext, IRegisterDMData dmData, String columnId,
+ int idx, ILabelUpdate update)
+ {
+ if (RegisterColumnPresentation.COL_NAME.equals(columnId)) {
+ update.setLabel(dmData.getName(), idx);
+ } else if (RegisterColumnPresentation.COL_VALUE.equals(columnId)) {
+ update.setLabel(dmData.getHexValue(), idx);
+ } else if (RegisterColumnPresentation.COL_DESCRIPTION.equals(columnId)) {
+ String size = dmData.getDescription();
+ String value = dmData.getHexValue();
+ if ("".equals(size)) { //$NON-NLS-1$
+ if ( value.contains( "uint64" ) ) { //$NON-NLS-1$
+ size = "64 bit register" ; //$NON-NLS-1$
+ } else if ( value.contains( "v4_float" ) ) { //$NON-NLS-1$
+ size = "128 bit register" ; //$NON-NLS-1$
}
}
- ) ;
+ update.setLabel(size, idx);
+ }
}
- public boolean hasDeltaFlagsForDMEvent( IDMEvent> e ) {
- return (e instanceof IRunControl.ISuspendedDMEvent) || super.hasDeltaFlagsForDMEvent(e) ;
+ @Override
+ protected int getNodeDeltaFlagsForDMEvent(IDMEvent> e) {
+ if (e instanceof IRunControl.ISuspendedDMEvent) {
+ return IModelDelta.CONTENT;
+ } else if (e instanceof IRegisters.IRegisterChangedDMEvent) {
+ return IModelDelta.STATE;
+ }
+ return IModelDelta.NO_CHANGE;
}
- public void buildDeltaForDMEvent( final IDMEvent> e, final VMDelta parent, final Done done ) {
+ @Override
+ protected void buildDeltaForDMEvent(IDMEvent> e, VMDelta parent, int nodeOffset, Done done) {
if (e instanceof IRunControl.ISuspendedDMEvent) {
// Create a delta that the whole register group has changed.
parent.addFlags(IModelDelta.CONTENT);
}
if (e instanceof IRegisters.IRegisterChangedDMEvent) {
- parent.addNode(
- new DMContextVMContext(parent.getVMC(), ((IRegisters.IRegisterChangedDMEvent)e).getDMContext()),
- IModelDelta.STATE);
+ parent.addNode( new DMVMContext(((IRegisters.IRegisterChangedDMEvent)e).getDMContext()), IModelDelta.STATE );
}
-
- super.buildDeltaForDMEvent(e, parent, done);
+ super.buildDeltaForDMEvent(e, parent, nodeOffset, done);
}
}
diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterVMProvider.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterVMProvider.java
index 24e9527c19a..f40284a2fc2 100644
--- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterVMProvider.java
+++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/RegisterVMProvider.java
@@ -12,35 +12,35 @@ package org.eclipse.dd.dsf.debug.ui.viewmodel.register;
import org.eclipse.dd.dsf.debug.ui.viewmodel.DebugViewSelectionRootLayoutNode;
import org.eclipse.dd.dsf.service.DsfSession;
+import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode;
import org.eclipse.dd.dsf.ui.viewmodel.IVMRootLayoutNode;
-import org.eclipse.dd.dsf.ui.viewmodel.VMProvider;
-import org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation;
-import org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext;
+import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
/**
*
*/
@SuppressWarnings("restriction")
-public class RegisterVMProvider extends VMProvider {
- public RegisterVMProvider(DsfSession session, IPresentationContext context) {
- super(session, null);
- IVMRootLayoutNode debugViewSelection = new DebugViewSelectionRootLayoutNode(
- getSession().getExecutor(), context.getPart().getSite().getWorkbenchWindow() );
- IVMLayoutNode registerGroupNode = new RegisterGroupLayoutNode(getSession());
+public class RegisterVMProvider extends AbstractDMVMProvider {
+ public RegisterVMProvider(AbstractVMAdapter adapter, IPresentationContext context, DsfSession session) {
+ super(adapter, context, session);
+ IVMRootLayoutNode debugViewSelection = new DebugViewSelectionRootLayoutNode(this);
+ IVMLayoutNode registerGroupNode = new RegisterGroupLayoutNode(this, getSession());
debugViewSelection.setChildNodes(new IVMLayoutNode[] { registerGroupNode });
- IVMLayoutNode registerNode = new RegisterLayoutNode(getSession());
+ IVMLayoutNode registerNode = new RegisterLayoutNode(this, getSession());
registerGroupNode.setChildNodes(new IVMLayoutNode[] { registerNode });
setRootLayoutNode(debugViewSelection);
}
-
+
@Override
- public IColumnPresentation createColumnPresentation(Object element) {
+ public IColumnPresentation createColumnPresentation(IPresentationContext context, Object element) {
return new RegisterColumnPresentation();
}
@Override
- public String getColumnPresentationId(Object element) {
+ public String getColumnPresentationId(IPresentationContext context, Object element) {
return RegisterColumnPresentation.ID;
}
}
diff --git a/plugins/org.eclipse.dd.dsf.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.dd.dsf.ui/META-INF/MANIFEST.MF
index bc80cddac17..6070a58d0f0 100644
--- a/plugins/org.eclipse.dd.dsf.ui/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.dd.dsf.ui/META-INF/MANIFEST.MF
@@ -11,5 +11,6 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.dd.dsf,
org.eclipse.debug.ui
Eclipse-LazyStart: true
-Export-Package: org.eclipse.dd.dsf.ui.viewmodel
+Export-Package: org.eclipse.dd.dsf.ui.viewmodel,
+ org.eclipse.dd.dsf.ui.viewmodel.dm
Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMAdapter.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMAdapter.java
index a759c952ec6..163e67a9593 100644
--- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMAdapter.java
+++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMAdapter.java
@@ -13,46 +13,39 @@ package org.eclipse.dd.dsf.ui.viewmodel;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
-import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
+import org.eclipse.dd.dsf.concurrent.DefaultDsfExecutor;
import org.eclipse.dd.dsf.concurrent.DsfRunnable;
import org.eclipse.dd.dsf.concurrent.ThreadSafe;
-import org.eclipse.dd.dsf.service.DsfSession;
import org.eclipse.dd.dsf.service.IDsfService;
import org.eclipse.dd.dsf.ui.DsfUIPlugin;
-import org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousContentAdapter;
-import org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousLabelAdapter;
-import org.eclipse.debug.internal.ui.viewers.provisional.IChildrenRequestMonitor;
-import org.eclipse.debug.internal.ui.viewers.provisional.IColumnEditor;
-import org.eclipse.debug.internal.ui.viewers.provisional.IColumnEditorFactoryAdapter;
-import org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation;
-import org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentationFactoryAdapter;
-import org.eclipse.debug.internal.ui.viewers.provisional.IContainerRequestMonitor;
-import org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor;
-import org.eclipse.debug.internal.ui.viewers.provisional.IModelProxy;
-import org.eclipse.debug.internal.ui.viewers.provisional.IModelProxyFactoryAdapter;
-import org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
/**
- * Base implementation for DSF-based view model adapters.
+ * Base implementation for View Model Adapters. The implementation uses
+ * its own single-thread executor for communicating with providers and
+ * layout nodes.
*/
@ThreadSafe
@SuppressWarnings("restriction")
-abstract public class AbstractVMAdapter
- implements IAsynchronousLabelAdapter,
- IAsynchronousContentAdapter,
- IModelProxyFactoryAdapter,
- IColumnPresentationFactoryAdapter,
- IColumnEditorFactoryAdapter
+abstract public class AbstractVMAdapter implements IVMAdapter
{
- private final DsfSession fSession;
+ private final ExecutorService fExecutor;
+ private boolean fDisposed;
- @ConfinedToDsfExecutor("getSession().getExecutor()")
- private final Map fViewModelProviders =
- Collections.synchronizedMap( new HashMap() );
+ private final Map fViewModelProviders =
+ Collections.synchronizedMap( new HashMap() );
/**
* Constructor for the View Model session. It is tempting to have the
@@ -62,21 +55,32 @@ abstract public class AbstractVMAdapter
* to have the owner of this object register it with the session.
* @param session
*/
- public AbstractVMAdapter(DsfSession session) {
- fSession = session;
+ public AbstractVMAdapter() {
+ fExecutor = new DefaultDsfExecutor();
}
- @ThreadSafe
- abstract protected VMProvider createViewModelProvider(IPresentationContext context);
-
- protected DsfSession getSession() { return fSession; }
+ /**
+ * Returns the executor that will be used to communicate with the providers
+ * and the layout nodes.
+ * @return
+ */
+ public Executor getExecutor() {
+ return fExecutor;
+ }
+ /**
+ * Creates a new View Model Provider for given presentation context. Returns null
+ * if the presentation context is not supported.
+ */
+ @ThreadSafe
+ abstract protected IVMProvider createViewModelProvider(IPresentationContext context);
+
@ThreadSafe
- private VMProvider getViewModelProvider(IPresentationContext context) {
- assert DsfSession.isSessionActive(getSession().getId());
-
+ private IVMProvider getViewModelProvider(IPresentationContext context) {
synchronized(fViewModelProviders) {
- VMProvider provider = fViewModelProviders.get(context);
+ if (fDisposed) return null;
+
+ IVMProvider provider = fViewModelProviders.get(context);
if (provider == null) {
provider = createViewModelProvider(context);
if (provider != null) {
@@ -87,129 +91,113 @@ abstract public class AbstractVMAdapter
}
}
- @ConfinedToDsfExecutor("getSession().getExecutor()")
- public void install(IPresentationContext context) {
- }
-
- @ConfinedToDsfExecutor("getSession().getExecutor()")
public void dispose() {
- assert getSession().getExecutor().isInExecutorThread();
+ // Execute the shutdown in adapter's dispatch thread.
+ getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ synchronized(fViewModelProviders) {
+ fDisposed = true;
+ for (IVMProvider provider : fViewModelProviders.values()) {
+ provider.dispose();
+ }
+ fViewModelProviders.clear();
+ }
+ fExecutor.shutdown();
+ }
+ });
+ }
+
+ public void update(IHasChildrenUpdate[] updates) {
+ handleUpdates(updates);
+ }
+
+ public void update(IChildrenCountUpdate[] updates) {
+ handleUpdates(updates);
+ }
+
+ public void update(final IChildrenUpdate[] updates) {
+ handleUpdates(updates);
+ }
+
+ private void handleUpdates(final IViewerUpdate[] updates) {
+ try {
+ getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ IPresentationContext context = null;
+ int firstIdx = 0;
+ int curIdx = 0;
+ for (curIdx = 0; curIdx < updates.length; curIdx++) {
+ if (!updates[curIdx].getPresentationContext().equals(context)) {
+ if (context != null) {
+ callProviderWithUpdate(updates, firstIdx, curIdx);
+ }
+ context = updates[curIdx].getPresentationContext();
+ firstIdx = curIdx;
+ }
+ }
+ callProviderWithUpdate(updates, firstIdx, curIdx);
+ }
+ });
+ } catch(RejectedExecutionException e) {
+ }
+ }
+
+ private void callProviderWithUpdate(IViewerUpdate[] updates, int startIdx, int endIdx) {
+ final IVMProvider provider = getViewModelProvider(updates[0].getPresentationContext());
+ if (provider == null) {
+ for (IViewerUpdate update : updates) {
+ update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR,
+ "No model provider for update " + update, null)); //$NON-NLS-1$
+ update.done();
+ }
+ return;
+ }
+ if (startIdx == 0 && endIdx == updates.length) {
+ if (updates instanceof IHasChildrenUpdate[]) provider.update((IHasChildrenUpdate[])updates);
+ else if (updates instanceof IChildrenCountUpdate[]) provider.update((IChildrenCountUpdate[])updates);
+ else if (updates instanceof IChildrenUpdate[]) provider.update((IChildrenUpdate[])updates);
+ } else {
+ if (updates instanceof IHasChildrenUpdate[]) {
+ IHasChildrenUpdate[] providerUpdates = new IHasChildrenUpdate[endIdx - startIdx];
+ System.arraycopy(updates, startIdx, providerUpdates, 0, endIdx - startIdx);
+ provider.update(providerUpdates);
+ }
+ else if (updates instanceof IChildrenCountUpdate[]) {
+ IChildrenCountUpdate[] providerUpdates = new IChildrenCountUpdate[endIdx - startIdx];
+ System.arraycopy(updates, startIdx, providerUpdates, 0, endIdx - startIdx);
+ provider.update(providerUpdates);
+ }
+ else if (updates instanceof IChildrenUpdate[]) {
+ IChildrenUpdate[] providerUpdates = new IChildrenUpdate[endIdx - startIdx];
+ System.arraycopy(updates, startIdx, providerUpdates, 0, endIdx - startIdx);
+ provider.update(providerUpdates);
+ }
+ }
+ }
- for (VMProvider provider : fViewModelProviders.values()) {
- provider.dispose();
- }
- fViewModelProviders.clear();
- }
-
- public void retrieveLabel(final Object object, final IPresentationContext context, final ILabelRequestMonitor result) {
- try {
- getSession().getExecutor().execute(new DsfRunnable() {
- public void run() {
- if (result.isCanceled()) return;
-
- VMProvider provider = getViewModelProvider(context);
- if (provider == null) {
- result.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "No model provider for object: " + object.toString(), null)); //$NON-NLS-1$
- result.done();
- }
- provider.retrieveLabel(object, result, context.getColumns());
- }
- @Override
- public String toString() { return "Switch to dispatch thread to execute retrieveLabel()"; } //$NON-NLS-1$
- });
- } catch(RejectedExecutionException e) {
- // This can happen if session is being shut down.
- result.done();
- }
- }
-
- public void isContainer(final Object element, final IPresentationContext context, final IContainerRequestMonitor result) {
- try {
- getSession().getExecutor().execute(new DsfRunnable() {
- public void run() {
- if (result.isCanceled()) return;
-
- VMProvider provider = getViewModelProvider(context);
- if (provider == null) {
- result.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "No model provider for object: " + element.toString(), null)); //$NON-NLS-1$
- result.done();
- }
- provider.isContainer(element, result);
- }
- public String toString() { return "Switch to dispatch thread to execute isContainer()"; } //$NON-NLS-1$
- });
- } catch(RejectedExecutionException e) {
- // This can happen if session is being shut down.
- result.done();
- }
- }
-
- public void retrieveChildren(final Object element, final IPresentationContext context, final IChildrenRequestMonitor result) {
- try {
- getSession().getExecutor().execute(new DsfRunnable() {
- public void run() {
- if (result.isCanceled()) return;
-
- VMProvider provider = getViewModelProvider(context);
- if (provider == null) {
- result.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "No model provider for object: " + element.toString(), null)); //$NON-NLS-1$
- result.done();
- }
- provider.retrieveChildren(element, result);
- }
- public String toString() { return "Switch to dispatch thread to execute retrieveChildren()"; } //$NON-NLS-1$
- });
- } catch(RejectedExecutionException e) {
- // This can happen if session is being shut down.
- result.done();
- }
- }
-
public IModelProxy createModelProxy(Object element, IPresentationContext context) {
- /*
- * Model proxy is the object that correlates events from the data model
- * into view model deltas that the view can process. We only need to
- * create a proxy for the root element of the tree.
- */
- VMProvider provider = getViewModelProvider(context);
- if (provider != null &&
- provider.getRootLayoutNode() != null &&
- element.equals(provider.getRootLayoutNode().getRootVMC().getInputObject()))
- {
- return provider.getModelProxy();
- }
- return null;
- }
-
- public String getColumnPresentationId(IPresentationContext context, Object element) {
- VMProvider provider = getViewModelProvider(context);
+ IVMProvider provider = getViewModelProvider(context);
if (provider != null) {
- return provider.getColumnPresentationId(element);
+ return provider.createModelProxy(element, context);
}
return null;
}
public IColumnPresentation createColumnPresentation(IPresentationContext context, Object element) {
- VMProvider provider = getViewModelProvider(context);
+ final IVMProvider provider = getViewModelProvider(context);
if (provider != null) {
- return provider.createColumnPresentation(element);
+ return provider.createColumnPresentation(context, element);
}
return null;
}
- public IColumnEditor createColumnEditor(IPresentationContext context, Object element) {
- VMProvider provider = getViewModelProvider(context);
+ public String getColumnPresentationId(IPresentationContext context, Object element) {
+ final IVMProvider provider = getViewModelProvider(context);
if (provider != null) {
- return provider.createColumnEditor(element);
+ return provider.getColumnPresentationId(context, element);
}
return null;
}
- public String getColumnEditorId(IPresentationContext context, Object element) {
- VMProvider provider = getViewModelProvider(context);
- if (provider != null) {
- return provider.getColumnEditorId(element);
- }
- return null;
- }
+
}
diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMLayoutNode.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMLayoutNode.java
index 3fca9124448..2d1b36ab055 100644
--- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMLayoutNode.java
+++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMLayoutNode.java
@@ -11,39 +11,57 @@
package org.eclipse.dd.dsf.ui.viewmodel;
import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionException;
+import org.eclipse.core.runtime.IStatus;
import org.eclipse.dd.dsf.concurrent.Done;
import org.eclipse.dd.dsf.concurrent.DoneCollector;
-import org.eclipse.dd.dsf.concurrent.DsfExecutor;
import org.eclipse.dd.dsf.concurrent.GetDataDone;
-import org.eclipse.debug.internal.ui.viewers.provisional.IColumnEditor;
-import org.eclipse.debug.internal.ui.viewers.provisional.IColumnEditorFactoryAdapter;
-import org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor;
-import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta;
-import org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactoryAdapter;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactoryAdapter;
+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;
/**
- *
+ * Base implementation of the View Model layout node.
+ * The main functionality implemented here is for building the view model
+ * deltas (IModelDelta), based on the flags returned by child nodes.
*/
@SuppressWarnings("restriction")
abstract public class AbstractVMLayoutNode implements IVMLayoutNode {
- private final DsfExecutor fExecutor;
+ private final AbstractVMProvider fProvider;
+ private boolean fDisposed = false;
/** Child schema nodes of this node. */
private IVMLayoutNode[] fChildNodes = new IVMLayoutNode[0];
- public AbstractVMLayoutNode(DsfExecutor executor) {
- fExecutor = executor;
+ public AbstractVMLayoutNode(AbstractVMProvider provider) {
+ fProvider = provider;
}
/**
* Accessor method for sub-classes.
*/
- protected DsfExecutor getExecutor() {
- return fExecutor;
+ protected Executor getExecutor() {
+ return fProvider.getExecutor();
+ }
+
+ protected IVMProvider getVMProvider() {
+ return fProvider;
}
public void setChildNodes(IVMLayoutNode[] childNodes) {
@@ -55,6 +73,7 @@ abstract public class AbstractVMLayoutNode implements IVMLayoutNode {
}
public void dispose() {
+ fDisposed = true;
for (IVMLayoutNode childNode : getChildLayoutNodes()) {
childNode.dispose();
}
@@ -64,11 +83,12 @@ abstract public class AbstractVMLayoutNode implements IVMLayoutNode {
* If any of the children nodes have delta flags, that means that this
* node has to generate a delta as well.
*/
- public boolean hasDeltaFlags(Object e) {
+ public int getDeltaFlags(Object e) {
+ int retVal = 0;
for (IVMLayoutNode childNode : getChildLayoutNodes()) {
- if (childNode.hasDeltaFlags(e)) return true;
+ retVal |= childNode.getDeltaFlags(e);
}
- return false;
+ return retVal;
}
/**
@@ -76,72 +96,159 @@ abstract public class AbstractVMLayoutNode implements IVMLayoutNode {
* schema nodes have deltas, this schema node has to provide the
* IModelDelta objects that the child shema node can build on.
*/
- public void buildDelta(final Object e, final VMDelta parent, final Done done) {
- /*
- * Find the child nodes that have deltas for the given event. If no
- * child layout nodes have deltas, just invoke the done.
- */
- final IVMLayoutNode[] childNodes = getChildNodesWithDeltas(e);
- if (childNodes.length == 0) {
+ 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 childNodeDeltas = getChildNodesWithDeltas(event);
+
+ // If no child layout nodes have deltas we can stop here.
+ if (childNodeDeltas.size() == 0) {
getExecutor().execute(done);
return;
}
+
+ // Check if the child delta only has an IModelDelta.CONTENT or
+ // IModelDelta.STATE flags. If that's the case, we can skip
+ // creating a delta for this node, because the TreeUpdatePolicy does not
+ // 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()) {
+ if ((childDelta & ~IModelDelta.CONTENT & ~IModelDelta.STATE) != 0) {
+ mustGetElements = true;
+ }
+ }
+ if (!mustGetElements) {
+ callChildNodesToBuildDelta(childNodeDeltas, 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
+ // each element as the parent of their delta.
+ updateElements(new ElementsUpdate(
+ new GetDataDone>() {
+ public void run() {
+ if (fDisposed) return;
+
+ // Check for an empty list of elements. If it's empty then we
+ // don't have to call the children nodes, so return here.
+ // No need to propagate error, there's no means or need to display it.
+ if (!getStatus().isOK() || getData().size() == 0) {
+ getExecutor().execute(done);
+ return;
+ }
+
+ final DoneCollector elementsDeltasDoneCollector = new DoneCollector() {
+ public void run() {
+ if (isDisposed()) return;
+ getExecutor().execute(done);
+ }
+ };
- /*
- * The given child layout nodes have deltas potentially for all elements
- * from this node. Retrieve all elements and call the child nodes with
- * each element as the parent of their delta.
- */
- getElements(
- parent.getVMC(),
- new GetDataDone() {
- public void run() {
- if (propagateError(getExecutor(), done, "Failed to retrieve elements in layout node " + AbstractVMLayoutNode.this)) return; //$NON-NLS-1$
-
- /*
- * Check for an empty list of elements. If it's empty then we
- * don't have to call the children nodes, so return here.
- */
- if (getData().length == 0) {
- getExecutor().execute(done);
- }
-
- /*
- * The execution for this node is not done until all the child nodes
- * are done. Use the tracker to wait for all children to complete.
- */
- final DoneCollector doneCollector = new DoneCollector(getExecutor()) { public void run() {
- getExecutor().execute(done);
- }};
- for (IVMContext element : getData()) {
- for (final IVMLayoutNode childNode : childNodes) {
- childNode.buildDelta(
- e,
- parent.addNode(element, IModelDelta.NO_CHANGE),
- doneCollector.addNoActionDone());
+ // 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);
+ callChildNodesToBuildDelta(
+ childNodeDeltas, delta, event,
+ elementsDeltasDoneCollector.add(new Done() {
+ public void run() {
+ elementsDeltasDoneCollector.doneDone(this);
+ }
+ }));
}
}
- }
- });
+ },
+ parentDelta));
+ }
}
- /**
- * Default implementation of the IColumnEditorFactoryAdapter delegate. It
- * returns null, which means that no cell editor is configured.
- * @see IColumnEditorFactoryAdapter#createColumnEditor(IPresentationContext, Object)
- */
- public IColumnEditor createColumnEditor(IVMContext vmc) {
- return null;
+ protected void callChildNodesToBuildDelta(final Map nodes, final VMDelta delta, final Object event, final Done done) {
+ assert nodes.size() != 0;
+
+ // Check if any of the child nodes are will generate IModelDelta.SELECT or
+ // IModelDelta.EXPAND flags. If so, we must calcuate the index for this
+ // VMC.
+ boolean calculateOffsets = false;
+ for (int childDelta : nodes.values()) {
+ if ( (childDelta & (IModelDelta.SELECT | IModelDelta.EXPAND)) != 0 ) {
+ calculateOffsets = true;
+ break;
+ }
+ }
+
+ getChildNodesElementOffsets(delta, !calculateOffsets, new GetDataDone>() {
+ public void run() {
+ final DoneCollector childrenBuildDeltaDoneCollector = new DoneCollector() {
+ public void run() {
+ if (isDisposed()) return;
+ getExecutor().execute(done);
+ }
+ };
+
+ // Set the total count of number of children in the parent delta.
+ delta.setChildCount(getData().get(null));
+
+ for (IVMLayoutNode node : nodes.keySet()) {
+ node.buildDelta(
+ event, delta, getData().get(node),
+ childrenBuildDeltaDoneCollector.add(new Done() {
+ public void run() {
+ childrenBuildDeltaDoneCollector.doneDone(this);
+ }})
+ );
+ }
+ }
+ });
}
- /**
- * Default implementation of the IColumnEditorFactoryAdapter delegate. It
- * returns null, which means that no cell editor is configured.
- * @see IColumnEditorFactoryAdapter#getColumnEditorId(IPresentationContext, Object)
- */
- public String getColumnEditorId(IVMContext vmc) {
- return null;
+ private void getChildNodesElementOffsets(IModelDelta delta, boolean fakeIt, final GetDataDone> done) {
+ assert getChildLayoutNodes().length != 0;
+
+ if (!fakeIt) {
+ final Integer[] counts = new Integer[getChildLayoutNodes().length];
+ final DoneCollector childrenCountDoneCollector = new DoneCollector() {
+ public void run() {
+ if (isDisposed()) return;
+ if (propagateError(getExecutor(), done, "")) return; //$NON-NLS-1$
+ Map data = new HashMap();
+ int offset = 0;
+ for (int i = 0; i < getChildLayoutNodes().length; i++) {
+ data.put(getChildLayoutNodes()[i], offset);
+ offset += counts[i];
+ }
+ // As the final value, put the total count in the return map, with null key.
+ data.put(null, offset);
+ done.setData(data);
+ getExecutor().execute(done);
+ }
+ };
+
+ for (int i = 0; i < getChildLayoutNodes().length; i++) {
+ final int nodeIndex = i;
+ getChildLayoutNodes()[i].updateElementCount(
+ new ElementsCountUpdate(
+ childrenCountDoneCollector.add(new GetDataDone() {
+ public void run() {
+ counts[nodeIndex] = getData();
+ childrenCountDoneCollector.doneDone(this);
+ }
+ }),
+ delta)
+ );
+ }
+ } else {
+ Map data = new HashMap();
+ for (int i = 0; i < getChildLayoutNodes().length; i++) {
+ data.put(getChildLayoutNodes()[i], -1);
+ }
+ data.put(null, -1);
+ done.setData(data);
+ getExecutor().execute(done);
+ }
+ }
+
+ protected boolean isDisposed() {
+ return fDisposed;
}
/**
@@ -149,41 +256,173 @@ abstract public class AbstractVMLayoutNode implements IVMLayoutNode {
* true
to the hasDeltaFlags()
test for the given
* event.
*/
- protected IVMLayoutNode[] getChildNodesWithDeltas(Object e) {
- List nodes = new ArrayList();
+ protected Map getChildNodesWithDeltas(Object e) {
+ Map nodes = new HashMap();
for (final IVMLayoutNode childNode : getChildLayoutNodes()) {
- if (childNode.hasDeltaFlags(e)) {
- nodes.add(childNode);
+ int delta = childNode.getDeltaFlags(e);
+ if (delta != IModelDelta.NO_CHANGE) {
+ nodes.put(childNode, delta);
}
}
- return nodes.toArray(new IVMLayoutNode[nodes.size()]);
- }
-
- /**
- * Convenience method that returns a token value in case when the services
- * that the layout node depends on, are not available.
- */
- protected void handleFailedHasElements(GetDataDone done) {
- done.setData(false);
- getExecutor().execute(done);
- }
-
- /**
- * Convenience method that returns a token value in case when the services
- * that the layout node depends on, are not available.
- */
- protected void handleFailedGetElements(GetDataDone done) {
- done.setData(new IVMContext[0]);
- getExecutor().execute(done);
- }
-
- /**
- * Convenience method that returns a token value in case when the services
- * that the layout node depends on, are not available.
- */
- protected void handleFailedRetrieveLabel(ILabelRequestMonitor result) {
- result.setLabels(new String[] { "..."} ); //$NON-NLS-1$
- result.done();
+ return nodes;
}
+ /**
+ * Convenience method that returns a token value in case when the services
+ * that the layout node depends on, are not available.
+ */
+ protected boolean checkUpdate(IViewerUpdate update) {
+ if (update.isCanceled()) return false;
+ if (fDisposed) {
+ handleFailedUpdate(update);
+ return false;
+ }
+ return true;
+ }
+
+ protected void handleFailedUpdate(IViewerUpdate update) {
+ if (update instanceof IHasChildrenUpdate) {
+ ((IHasChildrenUpdate)update).setHasChilren(false);
+ } else if (update instanceof IChildrenCountUpdate) {
+ ((IChildrenCountUpdate)update).setChildCount(0);
+ } else if (update instanceof ILabelUpdate) {
+ ILabelUpdate labelUpdate = (ILabelUpdate)update;
+ String[] columns = labelUpdate.getPresentationContext().getColumns();
+ for (int i = 0; i < (columns != null ? columns.length : 1); i++) {
+ labelUpdate.setLabel("...", i); //$NON-NLS-1$
+ }
+ }
+ update.done();
+ }
+
+ public static class AbstractVMContext implements IVMContext {
+ protected final IVMAdapter fVMAdapter;
+ protected final IVMLayoutNode fLayoutNode;
+
+ public AbstractVMContext(IVMAdapter adapter, IVMLayoutNode node) {
+ fVMAdapter = adapter;
+ fLayoutNode = node;
+ }
+
+ public IVMLayoutNode getLayoutNode() { return fLayoutNode; }
+
+ /**
+ * IAdapter implementation returns the IVMAdapter instance for the
+ * interfaces that are actually implemented by the VM Adapter. These
+ * should at least include {@link IElementContentProvider},
+ * {@link IModelProxyFactoryAdapter}, and
+ * {@link IColumnPresentationFactoryAdapter}.
+ */
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Class adapter) {
+ if (adapter.isInstance(fVMAdapter)) {
+ return fVMAdapter;
+ } else if (adapter.isInstance(fLayoutNode)) {
+ return fLayoutNode;
+ }
+ return null;
+ }
+ }
+
+ protected class ViewerUpdate implements IViewerUpdate {
+ final private Done fDone;
+ private boolean fDoneInvoked = false;
+ final private TreePath fTreePath;
+ private IStatus fStatus;
+ private boolean fCancelled = false;
+
+ public ViewerUpdate(Done done, IModelDelta delta) {
+ fDone = done;
+ List elementList = new LinkedList();
+ IModelDelta listDelta = delta;
+ elementList.add(0, listDelta.getElement());
+ while (listDelta.getParentDelta() != null) {
+ elementList.add(0, listDelta.getElement());
+ listDelta = listDelta.getParentDelta();
+ }
+ fTreePath = new TreePath(elementList.toArray());
+ }
+
+ public ViewerUpdate(Done done, TreePath path) {
+ fDone = done;
+ fTreePath = path;
+ }
+
+ public Object getElement(TreePath path) {
+ // If not asking for root, just return the last segment in path.
+ if (path.getSegmentCount() > 0) {
+ return path.getLastSegment();
+ }
+ // Calculate the root of the viewer.
+ return getVMProvider().getRootLayoutNode().getRootObject();
+ }
+
+ public Object getElement() {
+ return getElementPath().getLastSegment();
+ }
+
+ public IPresentationContext getPresentationContext() { return getVMProvider().getPresentationContext(); }
+ 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 done() {
+ assert !fDoneInvoked;
+ fDoneInvoked = true;
+ try {
+ getExecutor().execute(fDone);
+ } catch (RejectedExecutionException e) {
+ }
+ }
+ }
+
+ protected class ElementsCountUpdate extends ViewerUpdate implements IChildrenCountUpdate {
+ private final GetDataDone fDone;
+
+ public ElementsCountUpdate(GetDataDone done, IModelDelta delta) {
+ super(done, delta);
+ fDone = done;
+ }
+
+ public void setChildCount(int numChildren) {
+ fDone.setData(numChildren);
+ }
+ }
+
+ protected class ElementsUpdate extends ViewerUpdate implements IChildrenUpdate {
+ private final List fChildren = new ArrayList();
+ private GetDataDone> fDone;
+
+ public ElementsUpdate(GetDataDone> done, IModelDelta delta) {
+ super(done, delta);
+ fDone = done;
+ fDone.setData(fChildren);
+ }
+
+ public ElementsUpdate(GetDataDone> done, TreePath path) {
+ super(done, path);
+ fDone = done;
+ fDone.setData(fChildren);
+ }
+
+ public int getOffset() {
+ return -1;
+ }
+
+ public int getLength() {
+ return -1;
+ }
+
+ public void setChild(Object child, int offset) {
+ fChildren.add(offset, child);
+ }
+ }
+
}
diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMProvider.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMProvider.java
new file mode 100644
index 00000000000..821b1e1184c
--- /dev/null
+++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMProvider.java
@@ -0,0 +1,648 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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.dd.dsf.ui.viewmodel;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executor;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.atomic.AtomicReference;
+
+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.core.runtime.jobs.Job;
+import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
+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;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactoryAdapter;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
+import org.eclipse.debug.internal.ui.viewers.provisional.AbstractModelProxy;
+import org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousContentAdapter;
+import org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousLabelAdapter;
+import org.eclipse.debug.internal.ui.viewers.provisional.IColumnEditorFactoryAdapter;
+import org.eclipse.jface.viewers.TreePath;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * View model provider implements the asynchronous view model functionality for
+ * a single view. This provider is just a holder which further delegates the
+ * model provider functionality to the view model layout nodes that need
+ * to be configured with each provider.
+ *
+ * The view model provider, often does not provide the model for the entire
+ * view. Rather, it needs to be able to plug in at any level in the viewer's
+ * content model and provide data for a sub-tree.
+ *
+ * @see IAsynchronousContentAdapter
+ * @see IAsynchronousLabelAdapter
+ * @see IModelProxy
+ * @see IVMLayoutNode
+ */
+@ConfinedToDsfExecutor("getVMAdapter#getExecutor")
+@SuppressWarnings("restriction")
+abstract public class AbstractVMProvider implements IVMProvider
+{
+ private final AbstractVMAdapter fVMAdapter;
+ private final IPresentationContext fPresentationContext;
+ private final ModelProxy fModelProxy = new ModelProxy();
+ private boolean fDisposed = false;
+
+ /**
+ * The root node for this model provider. The root layout node could be
+ * null when first created, to allow sub-classes to prorperly configure the
+ * root node in the sub-class constructor.
+ */
+ private AtomicReference fRootLayoutNodeRef = new AtomicReference();
+
+ /**
+ * Constructs the view model provider for given DSF session. The
+ * constructor is thread-safe to allow VM provider to be constructed
+ * synchronously when a call to getAdapter() is made on an element
+ * in a view.
+ */
+ public AbstractVMProvider(AbstractVMAdapter adapter, IPresentationContext presentationContext) {
+ fVMAdapter = adapter;
+ fPresentationContext = presentationContext;
+ }
+
+ public IVMAdapter getVMAdapter() {
+ return fVMAdapter;
+ }
+
+ public IPresentationContext getPresentationContext() {
+ return fPresentationContext;
+ }
+
+ /**
+ * Sets the root node for this provider.
+ */
+ @ThreadSafe
+ protected void setRootLayoutNode(IVMRootLayoutNode rootLayoutNode) {
+ final IVMRootLayoutNode oldRootLayoutNode = fRootLayoutNodeRef.getAndSet(rootLayoutNode);
+ if (oldRootLayoutNode != null) {
+ oldRootLayoutNode.dispose();
+ }
+ }
+
+ protected ModelProxy getModelProxy() {
+ return fModelProxy;
+ }
+
+ @ThreadSafe
+ public IVMRootLayoutNode getRootLayoutNode() {
+ return fRootLayoutNodeRef.get();
+ }
+
+ /** Called to dispose the provider. */
+ public void dispose() {
+ fDisposed = true;
+ if (fRootLayoutNodeRef.get() != null) {
+ fRootLayoutNodeRef.get().dispose();
+ }
+ }
+
+ protected boolean isDisposed() {
+ return fDisposed;
+ }
+
+ /**
+ * Convenience method to access the View Model's executor.
+ */
+ public Executor getExecutor() { return fVMAdapter.getExecutor(); }
+
+
+ public void update(IHasChildrenUpdate[] updates) {
+ // Sort the updates by the layout node.
+ Map> nodeUpdatesMap = new HashMap>();
+ for (IHasChildrenUpdate update : updates) {
+ // Get the VM Context for last element in path.
+ IVMLayoutNode layoutNode = getLayoutNodeObject(update.getElement());
+ if (layoutNode == null) {
+ // Stale update, most likely as a result of the layout nodes being
+ // changed. Just ignore it.
+ if (!update.isCanceled()) update.done();
+ continue;
+ }
+ if (!nodeUpdatesMap.containsKey(layoutNode)) {
+ nodeUpdatesMap.put(layoutNode, new ArrayList());
+ }
+ nodeUpdatesMap.get(layoutNode).add(update);
+ }
+
+ // Iterate through the nodes in the sorted map.
+ for (IVMLayoutNode node : nodeUpdatesMap.keySet()) {
+ updateNode(node, nodeUpdatesMap.get(node).toArray(new IHasChildrenUpdate[nodeUpdatesMap.get(node).size()]));
+ }
+ }
+
+ private void updateNode(IVMLayoutNode node, final IHasChildrenUpdate[] updates) {
+ // If parent element's layout node has no children, just set the
+ // result and coninue to next element.
+ if (node.getChildLayoutNodes().length == 0) {
+ for (IHasChildrenUpdate update : updates) {
+ update.setHasChilren(false);
+ }
+ return;
+ }
+
+ HasElementsUpdate[][] elementsUpdates =
+ new HasElementsUpdate[node.getChildLayoutNodes().length][updates.length];
+ for (int i = 0; i < updates.length; i ++)
+ {
+ final IHasChildrenUpdate update = updates[i];
+ for (int j = 0; j < node.getChildLayoutNodes().length; j++)
+ {
+ final DoneCollector> hasChildrenDoneCollector =
+ new DoneCollector>() {
+ public void run() {
+ // Status is OK, only if all dones are OK.
+ if (getStatus().isOK()) {
+ boolean isContainer = false;
+ for (GetDataDone hasElementsDone : getDones().keySet()) {
+ isContainer |= hasElementsDone.getStatus().isOK() &&
+ hasElementsDone.getData().booleanValue();
+ }
+ update.setHasChilren(isContainer);
+ update.done();
+ }
+ }
+ };
+
+ elementsUpdates[j][i] = new HasElementsUpdate(
+ update,
+ hasChildrenDoneCollector.add(new GetDataDone() {
+ public void run() {
+ hasChildrenDoneCollector.doneDone(this);
+ }
+ }));
+ }
+ }
+
+ for (int j = 0; j < node.getChildLayoutNodes().length; j++) {
+ node.getChildLayoutNodes()[j].updateHasElements(elementsUpdates[j]);
+ }
+ }
+
+
+ public void update(final IChildrenCountUpdate[] updates) {
+ for (final IChildrenCountUpdate update : updates) {
+ if (update.isCanceled()) continue;
+
+ getChildrenCountsForNode(
+ update, update.getElementPath(),
+ new GetDataDone() {
+ public void run() {
+ if (getStatus().isOK()) {
+ int numChildren = 0;
+ for (Integer count : getData()) {
+ numChildren += count.intValue();
+ }
+ update.setChildCount(numChildren);
+ } else {
+ update.setChildCount(0);
+ }
+ update.done();
+ }
+ });
+ }
+ }
+
+ public void update(IChildrenUpdate[] updates) {
+ for (final IChildrenUpdate update : updates) {
+ getChildrenCountsForNode(
+ update, update.getElementPath(),
+ new GetDataDone() {
+ public void run() {
+ if (!getStatus().isOK()) {
+ update.done();
+ return;
+ }
+ updateChildrenWithCounts(update, getData());
+ }
+ });
+ }
+ }
+
+
+ private void getChildrenCountsForNode(IViewerUpdate update, TreePath elementPath, final GetDataDone done) {
+ if (isDisposed()) return;
+
+ // Get the VM Context for last element in path.
+ final IVMLayoutNode layoutNode = getLayoutNodeObject(update.getElement());
+ if (layoutNode == null) {
+ // Stale update. Just ignore.
+ done.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.INVALID_HANDLE,
+ "Stale update.", null)); //$NON-NLS-1$
+ getExecutor().execute(done);
+ return;
+ }
+
+ IVMLayoutNode[] childNodes = layoutNode.getChildLayoutNodes();
+
+ // If parent element's layout node has no children, just mark done and
+ // return.
+ if (childNodes.length == 0) {
+ done.setData(new Integer[0]);
+ getExecutor().execute(done);
+ return;
+ }
+
+
+ // Get the mapping of all the counts.
+ final Integer[] counts = new Integer[childNodes.length];
+ final DoneCollector childrenCountDoneCollector =
+ new DoneCollector() {
+ public void run() {
+ if (fDisposed) return;
+ if (propagateError(getExecutor(), done, "")) return; //$NON-NLS-1$
+ done.setData(counts);
+ getExecutor().execute(done);
+ }
+ };
+
+ for (int i = 0; i < childNodes.length; i++) {
+ final int nodeIndex = i;
+ childNodes[i].updateElementCount(
+ new ElementsCountUpdate(
+ update,
+ childrenCountDoneCollector.add(new GetDataDone() {
+ public void run() {
+ if (getStatus().isOK()) {
+ assert getData() != null;
+ counts[nodeIndex] = getData();
+ }
+ childrenCountDoneCollector.doneDone(this);
+ }
+ }),
+ elementPath)
+ );
+ }
+ }
+
+ private void updateChildrenWithCounts(final IChildrenUpdate update, Integer[] nodeElementCounts) {
+ final IVMLayoutNode layoutNode = getLayoutNodeObject(update.getElement());
+ if (layoutNode == null) {
+ // Stale update. Just ignore.
+ if (!update.isCanceled()) update.done();
+ }
+
+ // Create the done collector to mark update when querying all children nodes is finished.
+ final DoneCollector elementsDoneCollector =
+ new DoneCollector() {
+ public void run() {
+ if (!update.isCanceled()) update.done();
+ }
+ };
+
+ // Iterate through all child nodes and if requested range matches, call them to
+ // get their elements.
+ int updateStartIdx = update.getOffset();
+ int updateEndIdx = update.getOffset() + update.getLength();
+ int idx = 0;
+ IVMLayoutNode[] layoutNodes = layoutNode.getChildLayoutNodes();
+ for (int i = 0; i < layoutNodes.length; i++) {
+ final int nodeStartIdx = idx;
+ final int nodeEndIdx = idx + nodeElementCounts[i];
+ idx = nodeEndIdx;
+
+ // Check if update range overlaps the node's range.
+ if (updateStartIdx <= nodeEndIdx && updateEndIdx > nodeStartIdx) {
+ final int elementsStartIdx = Math.max(updateStartIdx - nodeStartIdx, 0);
+ final int elementsEndIdx = Math.min(updateEndIdx - nodeStartIdx, nodeElementCounts[i]);
+
+ layoutNodes[i].updateElements(
+ new ElementsUpdate(
+ update,
+ elementsDoneCollector.add(new Done() {
+ public void run() {
+ elementsDoneCollector.doneDone(this);
+ }
+ }),
+ nodeStartIdx, elementsStartIdx, elementsEndIdx - elementsStartIdx)
+ );
+ }
+ }
+
+ // Guard against invalid queries.
+ if (elementsDoneCollector.getDones().isEmpty()) {
+ update.done();
+ }
+
+ }
+
+ public ModelProxy createModelProxy(Object element, IPresentationContext context) {
+ /*
+ * Model proxy is the object that correlates events from the data model
+ * into view model deltas that the view can process. We only need to
+ * create a proxy for the root element of the tree.
+ */
+ if (getRootLayoutNode() != null &&
+ element.equals(getRootLayoutNode().getRootObject()))
+ {
+ return fModelProxy;
+ }
+ return null;
+ }
+
+ /**
+ * Creates the column presentation for the given object. This method is meant
+ * to be overriden by deriving class to provide view-specific functionality.
+ * The default is to return null, meaning no columns.
+ *
+ * The viewer only reads the column presentation for the root/input element of
+ * the tree/table, so the VMProvider must be configured to own the root element
+ * in the view in order for this setting to be effective.
+ *
+ * Note: since the IColumnEditorFactoryAdapter interface is synchronous, and since
+ * column info is fairly static, this method is thread-safe, and it will
+ * not be called on the executor thread.
+ *
+ * @see IColumnPresentationFactoryAdapter#createColumnPresentation(IPresentationContext, Object)
+ */
+ public IColumnPresentation createColumnPresentation(IPresentationContext context, Object element) {
+ return null;
+ }
+
+ /**
+ * Returns the ID of the column presentation for the given object. This method
+ * is meant to be overriden by deriving class to provide view-specific
+ * functionality. The default is to return null, meaning no columns.
+ *
+ * The viewer only reads the column presentation for the root/input element of
+ * the tree/table, so the VMProvider must be configured to own the root element
+ * in the view in order for this setting to be effective.
+ *
+ * Note: since the IColumnEditorFactoryAdapter interface is synchronous, and since
+ * column info is fairly static, this method is thread-safe, and it will
+ * not be called on the executor thread.
+ *
+ * @see IColumnEditorFactoryAdapter#getColumnEditorId(IPresentationContext, Object)
+ */
+ public String getColumnPresentationId(IPresentationContext context, Object element) {
+ return null;
+ }
+
+
+ /**
+ * Convenience method that finds the VMC corresponding to given parent
+ * argument given to isContainer() or retrieveChildren().
+ * @param object Object to find the VMC for.
+ * @return parent VMC, if null it indicates that the object did not originate
+ * from this view or is stale.
+ */
+ private IVMLayoutNode getLayoutNodeObject(Object element) {
+ /*
+ * First check to see if the parent object is the root object of the
+ * hierarchy. If that's the case, then retrieve the correcponding
+ * root VMC from the root node, and pass this root vmc to the root's
+ * child layout nodes.
+ */
+ IVMRootLayoutNode rootLayoutNode = getRootLayoutNode();
+ if (rootLayoutNode == null) {
+ return null;
+ }
+ else if (element.equals(rootLayoutNode.getRootObject())) {
+ return rootLayoutNode;
+ }
+ else if (element instanceof IVMContext){
+ /*
+ * The parent is a VMC. Check to make sure that the VMC
+ * originated from a node in this ViewModelProvider. If it didn't
+ * it is most likely a result of a change in view layout, and this
+ * request is a stale request. So just ignore it.
+ */
+ if (isOurLayoutNode( ((IVMContext)element).getLayoutNode(),
+ new IVMLayoutNode[] { rootLayoutNode } ))
+ {
+ return ((IVMContext)element).getLayoutNode();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Convenience method which checks whether given layout node is a node
+ * that is configured in this ViewModelProvider. Implementation
+ * recursively walks the layout hierarchy, and returns true if it finds
+ * the node.
+ */
+ private boolean isOurLayoutNode(IVMLayoutNode layoutNode, IVMLayoutNode[] nodesToSearch) {
+ for (IVMLayoutNode node : nodesToSearch) {
+ if (node == layoutNode) return true;
+ if (isOurLayoutNode(layoutNode, node.getChildLayoutNodes())) return true;
+ }
+ 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() {
+ 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 {
+ /**
+ * Counter for whether the model proxy is currently installed in the viewer.
+ * Data model events are processed only if the model proxy is active.
+ */
+ private int fProxyActive = 0;
+
+ /**
+ * Scheduling rule for running the update jobs.
+ */
+ private ISchedulingRule fModelChangeRule = new ISchedulingRule() {
+ public boolean contains(ISchedulingRule rule) { return this == rule; }
+ public boolean isConflicting(ISchedulingRule rule) { return rule == this; }
+ };
+
+ public void installed(Viewer viewer) {
+ fProxyActive++;
+ }
+
+ public void dispose() {
+ fProxyActive--;
+ super.dispose();
+ }
+
+ /**
+ * Fires given delta using a job. Processing the delta on the dispatch
+ * thread can lead to dead-locks.
+ * @param delta
+ */
+ public void fireModelChangedNonDispatch(final IModelDelta delta) {
+ if (fProxyActive <= 0) return;
+
+ Job job = new Job("Processing view model delta.") { //$NON-NLS-1$
+ protected IStatus run(IProgressMonitor monitor) {
+ fireModelChanged(delta);
+ return Status.OK_STATUS;
+ }
+ };
+ job.setPriority(Job.INTERACTIVE);
+ job.setRule(fModelChangeRule);
+ job.schedule();
+ }
+
+ }
+
+ class ViewerUpdate implements IViewerUpdate {
+ private IStatus fStatus;
+ private boolean fDoneInvoked = false;
+ final private Done fDone;
+ final protected IViewerUpdate fClientUpdate;
+
+ public ViewerUpdate(IViewerUpdate clientUpdate, Done done) {
+ fDone = done;
+ fClientUpdate = clientUpdate;
+ }
+
+ public Object getElement() { return fClientUpdate.getElement(); }
+ public TreePath getElementPath() { return fClientUpdate.getElementPath(); }
+ public IPresentationContext getPresentationContext() { return fClientUpdate.getPresentationContext(); }
+
+ 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) { fClientUpdate.setCanceled(value); }
+ public void setTaskName(String name) {}
+ public void subTask(String name) {}
+ public void worked(int work) {}
+
+ public void done() {
+ assert !fDoneInvoked;
+ fDoneInvoked = true;
+ try {
+ getExecutor().execute(fDone);
+ } catch (RejectedExecutionException e) { // Ignore
+ }
+ }
+
+ }
+
+ class HasElementsUpdate extends ViewerUpdate implements IHasChildrenUpdate {
+
+ final private GetDataDone fDone;
+
+ HasElementsUpdate(IHasChildrenUpdate clientUpdate, GetDataDone done) {
+ super(clientUpdate, done);
+ fDone = done;
+ }
+
+ public TreePath getElementPath() {
+ return ((IHasChildrenUpdate)fClientUpdate).getElementPath();
+ }
+
+ public void setHasChilren(boolean hasChildren) {
+ fDone.setData(hasChildren);
+ }
+
+ public void done() {
+ assert fDone.getData() != null || !fDone.getStatus().isOK();
+ super.done();
+ }
+ }
+
+ class ElementsCountUpdate extends ViewerUpdate implements IChildrenCountUpdate {
+ final private GetDataDone fDone;
+ final private TreePath fElementPath;
+
+ ElementsCountUpdate(IViewerUpdate clientUpdate, GetDataDone done, TreePath elementPath) {
+ super(clientUpdate, done);
+ fElementPath = elementPath;
+ fDone = done;
+ }
+
+ public TreePath getElementPath() {
+ return fElementPath;
+ }
+
+ public void setChildCount(int count) {
+ fDone.setData(count);
+ }
+
+ public void done() {
+ assert fDone.getData() != null || !fDone.getStatus().isOK();
+ super.done();
+ }
+
+ }
+
+ class ElementsUpdate extends ViewerUpdate implements IChildrenUpdate {
+ private final int fClientOffset;
+ private final int fOffset;
+ private final int fLength;
+
+ ElementsUpdate(IChildrenUpdate clientUpdate, Done done, int clientOffset, int offset, int length) {
+ super(clientUpdate, done);
+ fClientOffset = clientOffset;
+ fOffset = offset;
+ fLength = length;
+ }
+
+ public int getOffset() {
+ return fOffset;
+ }
+
+ public int getLength() {
+ return fLength;
+ }
+
+ public TreePath getElementPath() {
+ return ((IChildrenUpdate)fClientUpdate).getElementPath();
+ }
+
+ public void setChild(Object child, int offset) {
+ if (offset >= fOffset && offset < (fOffset + fLength)) {
+ ((IChildrenUpdate)fClientUpdate).setChild(child, fClientOffset + offset);
+ }
+ }
+
+ }
+}
diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMRootLayoutNode.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMRootLayoutNode.java
index baacc1cfc7c..53d5650d917 100644
--- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMRootLayoutNode.java
+++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMRootLayoutNode.java
@@ -10,12 +10,15 @@
*******************************************************************************/
package org.eclipse.dd.dsf.ui.viewmodel;
-import org.eclipse.core.runtime.IAdaptable;
-import org.eclipse.dd.dsf.concurrent.DoneCollector;
-import org.eclipse.dd.dsf.concurrent.DsfExecutor;
+import java.util.Map;
+
+import org.eclipse.dd.dsf.concurrent.Done;
import org.eclipse.dd.dsf.concurrent.GetDataDone;
-import org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor;
-import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
/**
*
@@ -23,44 +26,8 @@ import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta;
@SuppressWarnings("restriction")
abstract public class AbstractVMRootLayoutNode extends AbstractVMLayoutNode implements IVMRootLayoutNode {
- protected static class RootVMC implements IRootVMC {
- private final V fInputObject;
- private final IVMRootLayoutNode fVMRootLayoutNode;
-
- public RootVMC(IVMRootLayoutNode vmRootLayoutNode, V inputObject) {
- fVMRootLayoutNode = vmRootLayoutNode;
- fInputObject = inputObject;
- }
-
- /** Returns the ILaunch object belonging to this launch VMC. */
- public V getInputObject() { return fInputObject; }
-
- public IVMContext getParent() { return null; }
-
- public IVMLayoutNode getLayoutNode() { return fVMRootLayoutNode; }
-
- @SuppressWarnings("unchecked")
- public Object getAdapter(Class adapter) {
- if (fInputObject instanceof IAdaptable) {
- return ((IAdaptable)fInputObject).getAdapter(adapter);
- }
- return null;
- }
-
- public boolean equals(Object other) {
- return getClass().equals( other.getClass() ) &&
- fInputObject.equals( ((RootVMC)other).getInputObject() );
- }
-
- public int hashCode() {
- return fInputObject.hashCode();
- }
-
- public String toString() { return "Root VMC for " + fInputObject.toString(); } //$NON-NLS-1$
- }
-
- public AbstractVMRootLayoutNode(DsfExecutor executor) {
- super(executor);
+ public AbstractVMRootLayoutNode(AbstractVMProvider provider) {
+ super(provider);
}
/**
@@ -68,9 +35,20 @@ abstract public class AbstractVMRootLayoutNode extends AbstractVMLayoutNode impl
* There is no use case for a root node implementing this method, but its
* easier to just impelemnt it for sake of uniformity of model.
*/
- public void getElements(IVMContext parentVmc, GetDataDone done) {
- done.setData(new IVMContext[] { getRootVMC() });
- getExecutor().execute(done);
+ public void updateElements(IChildrenUpdate update) {
+ // Ignore startIdx, endIdx, since there's only one element to be had.
+ update.setChild(getRootObject(), 0);
+ update.done();
+ }
+
+ /**
+ * This implementation only fulfils the requirements of the super-interface.
+ * There is no use case for a root node implementing this method, but its
+ * easier to just impelemnt it for sake of uniformity of model.
+ */
+ public void updateElementCount(IChildrenCountUpdate update) {
+ update.setChildCount(1);
+ update.done();
}
/**
@@ -78,9 +56,11 @@ abstract public class AbstractVMRootLayoutNode extends AbstractVMLayoutNode impl
* There is no use case for a root node implementing this method, but its
* easier to just impelemnt it for sake of uniformity of model.
*/
- public void hasElements(IVMContext parentVmc, GetDataDone done) {
- done.setData(true);
- getExecutor().execute(done);
+ public void updateHasElements(IHasChildrenUpdate[] updates) {
+ for (IHasChildrenUpdate update : updates) {
+ update.setHasChilren(true);
+ update.done();
+ }
}
/**
@@ -88,8 +68,8 @@ abstract public class AbstractVMRootLayoutNode extends AbstractVMLayoutNode impl
* There is no use case for a root node implementing this method, but its
* easier to just impelemnt it for sake of uniformity of model.
*/
- public void retrieveLabel(IVMContext vmc, ILabelRequestMonitor result, String[] columns) {
- result.done();
+ public void updateLabel(IVMContext vmc, ILabelUpdate update) {
+ update.done();
}
/**
@@ -97,28 +77,21 @@ abstract public class AbstractVMRootLayoutNode extends AbstractVMLayoutNode impl
* is the input object into the view.
*/
public void createDelta(Object event, final GetDataDone done) {
- final VMDelta rootDelta = new VMDelta(getRootVMC().getInputObject(), getRootVMC());
+ final Map childNodeDeltas = getChildNodesWithDeltas(event);
+ assert childNodeDeltas.size() != 0 : "Caller should make sure that there are deltas for given event."; //$NON-NLS-1$
- final IVMLayoutNode[] childNodes = getChildNodesWithDeltas(event);
- if (childNodes.length == 0) {
- done.setData(rootDelta);
- getExecutor().execute(done);
- return;
- }
+ // Always create the rootDelta, no matter what delta flags the child nodes have.
+ final VMDelta rootDelta = new VMDelta(getRootObject(), IModelDelta.NO_CHANGE);
- /*
- * The execution for this node is not done until all the child nodes
- * are done. Use the tracker to wait for all children to complete.
- */
- final DoneCollector doneCollector = new DoneCollector(getExecutor()) {
- public void run() {
- if (propagateError(getExecutor(), done, "Failed to generate child deltas.")) return; //$NON-NLS-1$
- done.setData(rootDelta);
- getExecutor().execute(done);
- }
- };
- for (final IVMLayoutNode childNode : childNodes) {
- childNode.buildDelta(event, rootDelta, doneCollector.addNoActionDone());
- }
+ callChildNodesToBuildDelta(
+ childNodeDeltas, rootDelta, event,
+ new Done() {
+ public void run() {
+ if (isDisposed()) return;
+ if (propagateError(getExecutor(), done, "Failed to create delta.")); //$NON-NLS-1$
+ done.setData(rootDelta);
+ getExecutor().execute(done);
+ }
+ });
}
}
diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/DMContextVMLayoutNode.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/DMContextVMLayoutNode.java
deleted file mode 100644
index eefeebaa56f..00000000000
--- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/DMContextVMLayoutNode.java
+++ /dev/null
@@ -1,360 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006 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.dd.dsf.ui.viewmodel;
-
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-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.Immutable;
-import org.eclipse.dd.dsf.datamodel.DMContexts;
-import org.eclipse.dd.dsf.datamodel.IDMContext;
-import org.eclipse.dd.dsf.datamodel.IDMData;
-import org.eclipse.dd.dsf.datamodel.IDMEvent;
-import org.eclipse.dd.dsf.datamodel.IDMService;
-import org.eclipse.dd.dsf.service.DsfServicesTracker;
-import org.eclipse.dd.dsf.service.DsfSession;
-import org.eclipse.dd.dsf.service.IDsfService;
-import org.eclipse.dd.dsf.ui.DsfUIPlugin;
-import org.eclipse.dd.dsf.ui.viewmodel.IVMRootLayoutNode.IRootVMC;
-import org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousLabelAdapter;
-import org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentationFactoryAdapter;
-import org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor;
-import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta;
-import org.eclipse.jface.resource.ImageDescriptor;
-import org.eclipse.swt.graphics.FontData;
-import org.eclipse.swt.graphics.RGB;
-
-
-/**
- * View model layout node based on a single Data Model Context type.
- * The assumption in this implementation is that elements of this node have
- * a single IDMContext associated with them, and all of these contexts
- * are of the same class type.
- */
-@SuppressWarnings("restriction")
-abstract public class DMContextVMLayoutNode extends AbstractVMLayoutNode {
-
- /**
- * IVMContext implementation used for this schema node.
- */
- @Immutable
- public class DMContextVMContext implements IVMContext {
- private final IVMContext fParent;
- private final IDMContext fDmc;
-
- public DMContextVMContext(IVMContext parent, IDMContext dmc) {
- fParent = parent;
- fDmc = dmc;
- }
-
- public IDMContext getDMC() { return fDmc; }
- public IVMContext getParent() { return fParent; }
- public IVMLayoutNode getLayoutNode() { return DMContextVMLayoutNode.this; }
-
- /**
- * The IAdaptable implementation. If the adapter is the DM context,
- * return the context, otherwise delegate to IDMContext.getAdapter().
- */
- @SuppressWarnings("unchecked")
- public Object getAdapter(Class adapter) {
- if (adapter.isInstance(fDmc)) {
- return fDmc;
- } else {
- return fDmc.getAdapter(adapter);
- }
- }
-
- public boolean equals(Object other) {
- if (!(other instanceof DMContextVMLayoutNode.DMContextVMContext)) return false;
- DMContextVMLayoutNode.DMContextVMContext otherVmc = (DMContextVMLayoutNode.DMContextVMContext)other;
- return DMContextVMLayoutNode.this.equals(otherVmc.getLayoutNode()) &&
- fParent.equals(otherVmc.fParent) &&
- fDmc.equals(otherVmc.fDmc);
- }
-
- public int hashCode() {
- return DMContextVMLayoutNode.this.hashCode() + fParent.hashCode() + fDmc.hashCode();
- }
-
- public String toString() {
- return fParent.toString() + "->" + fDmc.toString(); //$NON-NLS-1$
- }
- }
-
- /** Service tracker to be used by sub-classes */
- private DsfServicesTracker fServices;
-
- private DsfSession fSession;
-
- /**
- * Concrete class type that the elements of this schema node are based on.
- * Even though the data model type is a parameter the DMContextVMLayoutNode,
- * this type is erased at runtime, so a concrete class typs of the DMC
- * is needed for instanceof chacks.
- */
- private Class extends IDMContext> fDMCClassType;
-
- /**
- * Constructor initializes instance data, except for the child nodes.
- * Child nodes must be initialized by calling setChildNodes()
- * @param session
- * @param dmcClassType
- * @see #setChildNodes(IVMLayoutNode[])
- */
- public DMContextVMLayoutNode(DsfSession session, Class extends IDMContext> dmcClassType) {
- super(session.getExecutor());
- fSession = session;
- fServices = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), session.getId());
- fDMCClassType = dmcClassType;
- }
-
- /**
- * Returns the session for use by sub-classes.
- */
- protected DsfSession getSession() {
- return fSession;
- }
-
- /**
- * Returns the services tracker for sub-class use.
- */
- protected DsfServicesTracker getServicesTracker() {
- return fServices;
- }
-
- /**
- * The default implementation of the retrieve label method. It acquires
- * the service, using parameters in the DMC, then it fetches the model
- * data from the service, and then it calls the protected method
- * fillColumnLabel() for each column. The deriving classes should override
- * this method if a different method of computing the label is needed.
- *
- * @see #fillColumnLabel(IDMData, String, int, String[], ImageDescriptor[], FontData[], RGB[], RGB[])
- */
- @SuppressWarnings("unchecked")
- public void retrieveLabel(IVMContext vmc, final ILabelRequestMonitor result, final String[] columns) {
- /*
- * Extract the DMContext from the VMContext, see DMContextVMContext.getAdapter().
- * Since the VMContext is supplied by this node, the DMContext should never be null.
- * Note: had to suppress type cast warnings here, because getAdapter() does not support
- * generics, and even if it did, I'm not sure it would help.
- */
- final IDMContext dmc = (IDMContext)(vmc).getAdapter(IDMContext.class);
- if (dmc == null) {
- assert false;
- result.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Invalid VMC type", null)); //$NON-NLS-1$
- result.done();
- return;
- }
-
- /*
- * Get the instance of the service using the service filter in the DMContext
- * If null it could mean that the service already shut down, and the view
- * is holding stale elements which will be cleaned up shortly.
- */
- IDMService dmService = (IDMService)getServicesTracker().getService(null, dmc.getServiceFilter());
- if (dmService == null) {
- handleFailedRetrieveLabel(result);
- return;
- }
-
- dmService.getModelData(
- dmc,
- new GetDataDone() {
- public void run() {
- /*
- * Check that the request was evaluated and data is still
- * valid. The request could fail if the state of the
- * service changed during the request, but the view model
- * has not been updated yet.
- */
- if (!getStatus().isOK() || !getData().isValid()) {
- assert getStatus().isOK() ||
- getStatus().getCode() != IDsfService.INTERNAL_ERROR ||
- getStatus().getCode() != IDsfService.NOT_SUPPORTED;
- handleFailedRetrieveLabel(result);
- return;
- }
-
- /*
- * If columns are configured, call the protected methods to
- * fill in column values.
- */
- String[] localColumns = columns;
- if (localColumns == null) localColumns = new String[] { null };
-
- String[] text = new String[localColumns.length];
- ImageDescriptor[] image = new ImageDescriptor[localColumns.length];
- FontData[] fontData = new FontData[localColumns.length];
- RGB[] foreground = new RGB[localColumns.length];
- RGB[] background = new RGB[localColumns.length];
- for (int i = 0; i < localColumns.length; i++) {
- fillColumnLabel(dmc, getData(), localColumns[i], i, text, image, fontData, foreground, background);
- }
- result.setLabels(text);
- result.setImageDescriptors(image);
- result.setFontDatas(fontData);
- result.setBackgrounds(background);
- result.setForegrounds(foreground);
- result.done();
- }
- });
- }
-
- /**
- * Fills in label information for given column. This method is intended to
- * be overriden by deriving classes, to supply label information specific
- * to the node.
- * The implementation should fill in the correct value in each array at the
- * given index.
- * @param dmContext Data Model Context object for which the label is generated.
- * @param dmData Data Model Data object retrieved from the model service.
- * for the DM Context supplied to the retrieveLabel() call.
- * @param columnId Name of the column to fill in, null if no columns specified.
- * @param idx Index to fill in in the label arrays.
- * @param text
- * @param image
- * @param fontData
- * @param foreground
- * @param background
- *
- * @see IAsynchronousLabelAdapter
- * @see IColumnPresentationFactoryAdapter
- */
- protected void fillColumnLabel(IDMContext dmContext, V dmData, String columnId, int idx, String[] text,
- ImageDescriptor[] image, FontData[] fontData, RGB[] foreground, RGB[] background )
- {
- text[idx] = ""; //$NON-NLS-1$
- }
-
- @Override
- public boolean hasDeltaFlags(Object e) {
- if (e instanceof IDMEvent) {
- return hasDeltaFlagsForDMEvent((IDMEvent)e);
- } else {
- return super.hasDeltaFlags(e);
- }
- }
-
- /**
- * DMC-specific version of {@link IVMLayoutNode#hasDeltaFlags(Object)}.
- * By default, it falls back on the super-class implementation.
- */
- protected boolean hasDeltaFlagsForDMEvent(IDMEvent> e) {
- return super.hasDeltaFlags(e);
- }
-
- @Override
- public void buildDelta(Object e, VMDelta parent, Done done) {
- if (e instanceof IDMEvent) {
- buildDeltaForDMEvent((IDMEvent)e, parent, done);
- } else {
- super.buildDelta(e, parent, done);
- }
- }
-
- /**
- * Adds an optimization (over the AbstractViewModelLayoutNode) which
- * narrows down the list of children based on the DMC within the event.
- */
- public void buildDeltaForDMEvent(final IDMEvent> e, final VMDelta parent, final Done done) {
- /*
- * Take the IDMContext (DMC) that the event is based on, and
- * search its ancestors. Look for the DMC class typs that this schema
- * node is based on. If its found, then only one IModelDelta needs to
- * be generated for this schema node. Otherwise, resort to the default
- * behavior and generate a IModelDelta for every element in this schema
- * node.
- */
- IDMContext dmc = DMContexts.getAncestorOfType(e.getDMContext(), fDMCClassType);
- if (dmc != null) {
- IVMLayoutNode[] childNodes = getChildNodesWithDeltas(e);
- if (childNodes.length == 0) {
- // There are no child nodes with deltas, just return to parent.
- getExecutor().execute(done);
- return;
- }
-
- /*
- * This execution for this node is not done until all the child nodes
- * are done. Use the tracker to wait for all children to complete.
- */
- DoneCollector childDoneTracker = new DoneCollector(getExecutor()) {
- public void run() {
- getExecutor().execute(done);
- }
- };
- for (final IVMLayoutNode childNode : getChildLayoutNodes()) {
- /*
- * Create a delta corresponding to the DMC from the event and pass
- * it as parent VMC to the child node. The child node will build
- * its delta on top of this delta.
- */
- childNode.buildDelta(
- e,
- parent.addNode(new DMContextVMContext(parent.getVMC(), dmc), IModelDelta.NO_CHANGE),
- childDoneTracker.addNoActionDone());
- }
- } else {
- super.buildDelta(e, parent, done);
- }
- }
-
- /**
- * Utility method that takes an array of DMC object and creates a
- * corresponding array of IVMContext elements base on that.
- * @param parent The parent for generated IVMContext elements.
- * @param dmcs Array of DMC objects to build return array on.
- * @return Array of IVMContext objects.
- */
- protected IVMContext[] dmcs2vmcs(IVMContext parent, IDMContext[] dmcs) {
- IVMContext[] vmContexts = new IVMContext[dmcs.length];
- for (int i = 0; i < dmcs.length; i++) {
- vmContexts[i] = new DMContextVMContext(parent, dmcs[i]);
- }
- return vmContexts;
- }
-
- /**
- * Searches for a DMC of given type in the tree patch contained in given
- * VMC. VMCs keep a reference to the parent node that contain them in the
- * tree. This method recursively looks compares the parent until root is
- * reached, or the DMC is found. If the root is reached, and the root's
- * input is also a VMC (which comes from another view), then the hierarchy
- * of the input object will be searched as well.
- * @param Type of the DMC that will be returned.
- * @param vmc VMC element to search.
- * @param dmcType Class object for matching the type.
- * @return DMC, or null if not found.
- */
- @SuppressWarnings("unchecked")
- public static V findDmcInVmc(IVMContext vmc, Class dmcType) {
- if (vmc instanceof IRootVMC && ((IRootVMC)vmc).getInputObject() instanceof IVMContext) {
- vmc = (IVMContext)((IRootVMC)vmc).getInputObject();
- }
-
- if (vmc instanceof DMContextVMLayoutNode.DMContextVMContext &&
- dmcType.isAssignableFrom( ((DMContextVMLayoutNode.DMContextVMContext)vmc).getDMC().getClass() ))
- {
- return (V)((DMContextVMLayoutNode.DMContextVMContext)vmc).getDMC();
- } else if (vmc.getParent() != null) {
- return findDmcInVmc(vmc.getParent(), dmcType);
- }
- return null;
- }
-
- public void dispose() {
- fServices.dispose();
- super.dispose();
- }
-}
diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMAdapter.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMAdapter.java
new file mode 100644
index 00000000000..2d1c9dfaa05
--- /dev/null
+++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMAdapter.java
@@ -0,0 +1,19 @@
+package org.eclipse.dd.dsf.ui.viewmodel;
+
+import org.eclipse.dd.dsf.concurrent.ThreadSafe;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactoryAdapter;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactoryAdapter;
+
+/**
+ * The View Model adapter handles the layout of a given data model within a
+ * set of viewers. This adapter should be returned by an adapter factory for
+ * the input object of the viewer, and this adapter implementation will then
+ * populate the view contents.
+ */
+@ThreadSafe
+@SuppressWarnings("restriction")
+public interface IVMAdapter
+ extends IElementContentProvider, IModelProxyFactoryAdapter, IColumnPresentationFactoryAdapter
+{
+}
diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMContext.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMContext.java
index 9c31035105a..aeacc41e922 100644
--- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMContext.java
+++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMContext.java
@@ -14,7 +14,7 @@ import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.dd.dsf.concurrent.Immutable;
/**
- * View model element which is stored as the data object of nodes in the viewer.
+ * View Model element which is stored as the data object of nodes in the viewer.
*/
@Immutable
public interface IVMContext extends IAdaptable {
@@ -23,10 +23,4 @@ public interface IVMContext extends IAdaptable {
* Returns the layout node that originated this element.
*/
public IVMLayoutNode getLayoutNode();
-
- /**
- * Returns the parent of this element in the viewer layout.
- * @return
- */
- public IVMContext getParent();
}
diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMLayoutNode.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMLayoutNode.java
index 0d2d3f3014f..883d0e23d0d 100644
--- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMLayoutNode.java
+++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMLayoutNode.java
@@ -12,55 +12,67 @@ package org.eclipse.dd.dsf.ui.viewmodel;
import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
import org.eclipse.dd.dsf.concurrent.Done;
-import org.eclipse.dd.dsf.concurrent.GetDataDone;
-import org.eclipse.dd.dsf.concurrent.ThreadSafeAndProhibitedFromDsfExecutor;
-import org.eclipse.debug.internal.ui.viewers.provisional.IColumnEditor;
-import org.eclipse.debug.internal.ui.viewers.provisional.IColumnEditorFactoryAdapter;
-import org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor;
-import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta;
-import org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext;
+import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
/**
* View model layout nodes are combined together into a tree, to collectively
- * define the layout of a view. Each schema node generates elements of type
- * IVMContext, and provide label information about these elements.
+ * define the layout of a view. Each layout node generates elements of type
+ * IVMContext which are then stored in the viewer.
*
* Besides the standard Data Model Context based implementation, this
* node could be implemented to present data from any source, not necessarily
* DSF services. It could also define a static node which operates on basis
* of other data in the view tree.
- * @see VMProvider
+ * @see AbstractDMVMProvider
*/
@ConfinedToDsfExecutor("")
@SuppressWarnings("restriction")
-public interface IVMLayoutNode {
+public interface IVMLayoutNode
+{
/**
- * Retrieves information whether for the given parent node, there are any elements
- * available.
- * @param parentVmc Parent node, for which to calculate elements at the
- * current level.
- * @param done The data return token.
+ * Retrieves information whether for a given path in the viewer,
+ * there are any elements available in this node.
+ *
+ * @param updates The update objects which need to be filled in with results
+ * calculated by this method.
+ * Even though the "children" interface is reused, the updates refer to the
+ * elements of this layout node, and not it's children.
*/
- public void hasElements(IVMContext parentVmc, GetDataDone done);
-
- /**
- * Retrieves the list of elements.
- * @param parentVmc Parent node, for which to calculate elements at the
- * current level.
- * @param done The data return token.
- */
- public void getElements(IVMContext parentVmc, GetDataDone done);
-
- /**
- * Retrieves the label for the given element.
- * @param vmc Element for which to retrieve label information.
- * @param result Monitor which accepts the data.
- * @param columns Currently configured columns in view.
- * @see IPresentationContext
- */
- public void retrieveLabel(IVMContext vmc, ILabelRequestMonitor result, String[] columns);
+ public void updateHasElements(IHasChildrenUpdate[] updates);
+ /**
+ * Retrieves the number of available elements in this node for the given
+ * path in the viewer.
+ *
+ * @param updates The update object which needs to be filled in with result
+ * calculated by this method.
+ * Even though the "children" interface is reused, the updates refer to the
+ * elements of this layout node, and not it's children.
+ */
+ public void updateElementCount(IChildrenCountUpdate update);
+
+
+ /**
+ * Retrieves the element objects of this node for the given path in the
+ * viewer, and for the given range of indexes.
+ * Note: 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.
+ *
+ * @param updates The update object which needs to be filled in with result
+ * calculated by this method.
+ * Even though the "children" interface is reused, the updates refer to the
+ * elements of this layout node, and not it's children.
+ */
+ public void updateElements(IChildrenUpdate update);
+
+
/**
* Configures the child layout nodes for this node.
* @param childNodes
@@ -73,51 +85,28 @@ public interface IVMLayoutNode {
public IVMLayoutNode[] getChildLayoutNodes();
/**
- * Returns true/false indicating whether the given even will cause this
- * schema node to generate a model delta.
+ * Returns the potential delta flags that would be generated by this node
+ * for the given event.
* @param event Event to process.
- * @return True if this node (or its children) would generate delta data
- * due to this event.
+ * @return IModelDelta flags
* @see IModelDelta
*/
- public boolean hasDeltaFlags(Object event);
+ public int getDeltaFlags(Object event);
/**
* Builds model delta information based on the given event.
* @param event Event to process.
* @param parent Parent model delta node that this object should add delta
* data to.
+ * @param nodeOffset The offset of the first element in this node. This offset
+ * depends on the elements returned by the siblings of this layout node.
* @param done Return token, which notifies the caller that the calculation is
* complete.
*/
- public void buildDelta(Object event, VMDelta parent, Done done);
+ public void buildDelta(Object event, VMDelta parent, int nodeOffset, Done done);
/**
- * Creates a column editor for the given element. The interface that this
- * method is delegated to is synchronous, therefore it also needs to be thread
- * safe.
- *
- * @see IColumnEditorFactoryAdapter#createColumnEditor(IPresentationContext, Object)
- * @param vmc VM Context to return the editor for
- * @return
- */
- @ThreadSafeAndProhibitedFromDsfExecutor("")
- public IColumnEditor createColumnEditor(IVMContext vmc);
-
- /**
- * Returns the ID of the editor for the given element. The interface that this
- * method is delegated to is synchronous, therefore it also needs to be thread
- * safe.
- *
- * @see IColumnEditorFactoryAdapter#getColumnEditorId(IPresentationContext, Object)
- * @param vmc VM Context to return the editor ID for
- * @return
- */
- @ThreadSafeAndProhibitedFromDsfExecutor("")
- public String getColumnEditorId(IVMContext vmc);
-
- /**
- * Disposes the resources held by this node.
+ * Releases the resources held by this node.
*/
public void dispose();
}
\ No newline at end of file
diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMProvider.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMProvider.java
new file mode 100644
index 00000000000..44b2a3e6504
--- /dev/null
+++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMProvider.java
@@ -0,0 +1,40 @@
+package org.eclipse.dd.dsf.ui.viewmodel;
+
+import org.eclipse.dd.dsf.concurrent.ThreadSafe;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactoryAdapter;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactoryAdapter;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+
+/**
+ * The View Model Provider handles the layout of a given model within a
+ * single viewer. The View Model Adapter delegates calls for view content to
+ * this object for a view that this provider handles.
+ */
+@ThreadSafe
+@SuppressWarnings("restriction")
+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.
+ */
+ public IVMRootLayoutNode getRootLayoutNode();
+
+ /**
+ * Returns the presentation context of the viewer that this provider
+ * is configured for.
+ */
+ public IPresentationContext getPresentationContext();
+
+ /**
+ * Cleans up the resources associated with this provider.
+ */
+ public void dispose();
+}
diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMRootLayoutNode.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMRootLayoutNode.java
index 251d74c7574..500ff56c64f 100644
--- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMRootLayoutNode.java
+++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMRootLayoutNode.java
@@ -11,7 +11,7 @@
package org.eclipse.dd.dsf.ui.viewmodel;
import org.eclipse.dd.dsf.concurrent.GetDataDone;
-import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
/**
* Special type of the view model layout node, which can be used as a root node
@@ -21,28 +21,13 @@ import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta;
@SuppressWarnings("restriction")
public interface IVMRootLayoutNode extends IVMLayoutNode{
- /**
- * The root VMC object of this root layout node. There can be only element
- * in the root node at a time, and this element must implement this
- * interface.
- */
- public interface IRootVMC extends IVMContext {
- /**
- * Returns the view's "input" object. This could be the actual input
- * object for the whole view, if this view model hierarchy fills the
- * whole view. Or this could an element in the tree from which this
- * hierarchy starts. This is the case
- */
- Object getInputObject();
- }
-
/**
* Returns the single element of this node. Root layout node can only have
* one element, and this is a convenience method to access this element.
* Alternatively getElements() could be used.
* @return
*/
- public IRootVMC getRootVMC();
+ public Object getRootObject();
/**
* Version of the {@link IVMLayoutNode#buildDelta(Object, ViewModelDelta, org.eclipse.dd.dsf.concurrent.Done)}
diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMDelta.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMDelta.java
index 09c2c953bd2..6c524768b3f 100644
--- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMDelta.java
+++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMDelta.java
@@ -11,8 +11,9 @@
*******************************************************************************/
package org.eclipse.dd.dsf.ui.viewmodel;
-import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta;
-import org.eclipse.debug.internal.ui.viewers.provisional.ModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDeltaVisitor;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
/**
* This delta class mostly just duplicates the ModelDelta implemention, but
@@ -25,13 +26,13 @@ import org.eclipse.debug.internal.ui.viewers.provisional.ModelDelta;
public class VMDelta extends ModelDelta {
private VMDelta fParent;
- private IVMContext fVmcElement;
private Object fElement;
private int fFlags;
private VMDelta[] fNodes = EMPTY_NODES;
private Object fReplacement;
private int fIndex;
private static final VMDelta[] EMPTY_NODES = new VMDelta[0];
+ private int fChildCount = -1;
/**
* Constructs a new delta for the given element.
@@ -39,9 +40,9 @@ public class VMDelta extends ModelDelta {
* @param vmcElement model element
* @param flags change flags
*/
- public VMDelta(IVMContext vmcElement, int flags) {
- super(vmcElement, flags);
- fVmcElement = vmcElement;
+ public VMDelta(Object element, int flags) {
+ super(element, flags);
+ fElement = element;
fFlags = flags;
}
@@ -53,9 +54,9 @@ public class VMDelta extends ModelDelta {
* @param replacement replacement element
* @param flags change flags
*/
- public VMDelta(IVMContext vmcElement, Object replacement, int flags) {
- super(vmcElement, replacement, flags);
- fVmcElement = vmcElement;
+ public VMDelta(Object element, Object replacement, int flags) {
+ super(element, replacement, flags);
+ fElement = element;
fReplacement = replacement;
fFlags = flags;
}
@@ -68,40 +69,44 @@ public class VMDelta extends ModelDelta {
* @param index insertion position
* @param flags change flags
*/
- public VMDelta(IVMContext vmcElement, int index, int flags) {
- super(vmcElement, index, flags);
- fVmcElement = vmcElement;
+ public VMDelta(Object element, int index, int flags) {
+ super(element, index, flags);
+ fElement = element;
fIndex = index;
fFlags = flags;
}
/**
- * Constructor for model delta based on non-VMC element. This delta is
- * only needed for creating delta nodes for parent elements in the tree
- * if the VMC elements are not at the root of the tree.
- * @param element Element to create the delta for.
- * @param vmcElement Optional VMC element for this node, it can be used
- * by other nodes in the delta to set their VMC parent element correctly.
+ * Constructs a new delta for the given element at the specified index
+ * relative to its parent with the given number of children.
+ *
+ * @param element model element
+ * @param index insertion position
+ * @param flags change flags
+ * @param childCount number of children this node has
*/
- public VMDelta(Object element, IVMContext vmcElement) {
- super(element, IModelDelta.NO_CHANGE);
+ public VMDelta(Object element, int index, int flags, int childCount) {
+ super(element, index, flags, childCount);
fElement = element;
- fVmcElement = vmcElement;
+ fIndex = index;
+ fFlags = flags;
+ fChildCount = childCount;
}
-
/**
* Returns the non-VMC element if one is set, otherwise returns the VMC
* element of this delta node.
* @see org.eclipse.debug.internal.ui.viewers.IModelDelta#getElement()
*/
+ @Override
public Object getElement() {
- return fElement != null ? fElement : fVmcElement;
+ return fElement;
}
/* (non-Javadoc)
* @see org.eclipse.debug.internal.ui.viewers.IModelDelta#getFlags()
*/
+ @Override
public int getFlags() {
return fFlags;
}
@@ -110,7 +115,9 @@ public class VMDelta extends ModelDelta {
fFlags |= flags;
}
- public IVMContext getVMC() { return fVmcElement; }
+ public void setChildCount(int count) {
+ fChildCount = count;
+ }
/**
* Adds a child node to this delta with the given element and change flags,
@@ -120,7 +127,7 @@ public class VMDelta extends ModelDelta {
* @param flags change flags for child
* @return newly created child delta
*/
- public VMDelta addNode(IVMContext element, int flags) {
+ public VMDelta addNode(Object element, int flags) {
VMDelta node = new VMDelta(element, flags);
node.setParent(this);
addDelta(node);
@@ -137,7 +144,7 @@ public class VMDelta extends ModelDelta {
* @param flags change flags
* @return newly created child delta
*/
- public VMDelta addNode(IVMContext element, Object replacement, int flags) {
+ public VMDelta addNode(Object element, Object replacement, int flags) {
VMDelta node = new VMDelta(element, replacement, flags);
node.setParent(this);
addDelta(node);
@@ -153,7 +160,7 @@ public class VMDelta extends ModelDelta {
* @param flags change flags
* @return newly created child delta
*/
- public VMDelta addNode(IVMContext element, int index, int flags) {
+ public VMDelta addNode(Object element, int index, int flags) {
VMDelta node = new VMDelta(element, index, flags);
node.setParent(this);
addDelta(node);
@@ -161,21 +168,22 @@ public class VMDelta extends ModelDelta {
}
/**
- * Adds a node to the delta for a non-VMC element. This is used to
- * construct the root branch of the delta before it is handed off to
- * ViewModelProvider.handleDataModelEvent()
- * @param element Element in the asynchronous view to create the new node for.
- * @param vmcElement Optional VMC element for this node, it can be used
- * by other nodes in the delta to set their VMC parent element correctly.
- * @return Returns the added delta node.
+ * Adds a child delta to this delta at the specified index with the
+ * given number of children, and returns the newly created child delta.
+ *
+ * @param element child element in insert
+ * @param index index of the element relative to parent
+ * @param flags change flags
+ * @param numChildren the number of children the element has
+ * @return newly created child delta
*/
- public VMDelta addNode(Object element, IVMContext vmcElement) {
- VMDelta node = new VMDelta(element, vmcElement);
+ public ModelDelta addNode(Object element, int index, int flags, int numChildren) {
+ VMDelta node = new VMDelta(element, index, flags, numChildren);
node.setParent(this);
addDelta(node);
return node;
}
-
+
/**
* Sets the parent delta of this delta
*
@@ -184,17 +192,19 @@ public class VMDelta extends ModelDelta {
void setParent(VMDelta node) {
fParent = node;
}
-
+
/* (non-Javadoc)
* @see org.eclipse.debug.internal.ui.viewers.IModelDelta#getParent()
*/
- public IModelDelta getParent() {
+ @Override
+ public IModelDelta getParentDelta() {
return fParent;
}
/* (non-Javadoc)
* @see org.eclipse.debug.internal.ui.viewers.IModelDelta#getReplacementElement()
*/
+ @Override
public Object getReplacementElement() {
return fReplacement;
}
@@ -202,6 +212,7 @@ public class VMDelta extends ModelDelta {
/* (non-Javadoc)
* @see org.eclipse.debug.internal.ui.viewers.IModelDelta#getIndex()
*/
+ @Override
public int getIndex() {
return fIndex;
}
@@ -209,7 +220,8 @@ public class VMDelta extends ModelDelta {
/* (non-Javadoc)
* @see org.eclipse.debug.internal.ui.viewers.IModelDelta#getNodes()
*/
- public VMDelta[] getNodes() {
+ @Override
+ public VMDelta[] getChildDeltas() {
return fNodes;
}
@@ -224,6 +236,7 @@ public class VMDelta extends ModelDelta {
}
}
+ @Override
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("Model Delta Start\n"); //$NON-NLS-1$
@@ -233,43 +246,78 @@ public class VMDelta extends ModelDelta {
}
private void appendDetail(StringBuffer buf, VMDelta delta) {
- buf.append("\tElement: "); //$NON-NLS-1$
- buf.append(delta.getElement());
- buf.append('\n');
- buf.append("\t\tFlags: "); //$NON-NLS-1$
- int flags = delta.getFlags();
- if (flags == 0) {
- buf.append("NO_CHANGE"); //$NON-NLS-1$
- } else {
- if ((flags & IModelDelta.ADDED) > 0) {
- buf.append("ADDED | "); //$NON-NLS-1$
- }
- if ((flags & IModelDelta.CONTENT) > 0) {
- buf.append("CONTENT | "); //$NON-NLS-1$
- }
- if ((flags & IModelDelta.EXPAND) > 0) {
- buf.append("EXPAND | "); //$NON-NLS-1$
- }
- if ((flags & IModelDelta.INSERTED) > 0) {
- buf.append("INSERTED | "); //$NON-NLS-1$
- }
- if ((flags & IModelDelta.REMOVED) > 0) {
- buf.append("REMOVED | "); //$NON-NLS-1$
- }
- if ((flags & IModelDelta.REPLACED) > 0) {
- buf.append("REPLACED | "); //$NON-NLS-1$
- }
- if ((flags & IModelDelta.SELECT) > 0) {
- buf.append("SELECT | "); //$NON-NLS-1$
- }
- if ((flags & IModelDelta.STATE) > 0) {
- buf.append("STATE | "); //$NON-NLS-1$
- }
- }
- buf.append('\n');
- VMDelta[] nodes = delta.getNodes();
- for (int i = 0; i < nodes.length; i++) {
- appendDetail(buf, nodes[i]);
- }
+ buf.append("\tElement: "); //$NON-NLS-1$
+ buf.append(delta.getElement());
+ buf.append('\n');
+ buf.append("\t\tFlags: "); //$NON-NLS-1$
+ int flags = delta.getFlags();
+ if (flags == 0) {
+ buf.append("NO_CHANGE"); //$NON-NLS-1$
+ } else {
+ if ((flags & IModelDelta.ADDED) > 0) {
+ buf.append("ADDED | "); //$NON-NLS-1$
+ }
+ if ((flags & IModelDelta.CONTENT) > 0) {
+ buf.append("CONTENT | "); //$NON-NLS-1$
+ }
+ if ((flags & IModelDelta.EXPAND) > 0) {
+ buf.append("EXPAND | "); //$NON-NLS-1$
+ }
+ if ((flags & IModelDelta.INSERTED) > 0) {
+ buf.append("INSERTED | "); //$NON-NLS-1$
+ }
+ if ((flags & IModelDelta.REMOVED) > 0) {
+ buf.append("REMOVED | "); //$NON-NLS-1$
+ }
+ if ((flags & IModelDelta.REPLACED) > 0) {
+ buf.append("REPLACED | "); //$NON-NLS-1$
+ }
+ if ((flags & IModelDelta.SELECT) > 0) {
+ buf.append("SELECT | "); //$NON-NLS-1$
+ }
+ if ((flags & IModelDelta.STATE) > 0) {
+ buf.append("STATE | "); //$NON-NLS-1$
+ }
+ if ((flags & IModelDelta.INSTALL) > 0) {
+ buf.append("INSTALL | "); //$NON-NLS-1$
+ }
+ if ((flags & IModelDelta.UNINSTALL) > 0) {
+ buf.append("UNINSTALL | "); //$NON-NLS-1$
+ }
+ }
+ buf.append('\n');
+ buf.append("\t\tIndex: "); //$NON-NLS-1$
+ buf.append(delta.fIndex);
+ buf.append(" Child Count: "); //$NON-NLS-1$
+ buf.append(delta.fChildCount);
+ buf.append('\n');
+ IModelDelta[] nodes = delta.getChildDeltas();
+ for (int i = 0; i < nodes.length; i++) {
+ appendDetail(buf, (VMDelta)nodes[i]);
+ }
}
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta#getChildCount()
+ */
+ public int getChildCount() {
+ return fChildCount;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta#accept(org.eclipse.debug.internal.ui.viewers.provisional.IModelDeltaVisitor)
+ */
+ public void accept(IModelDeltaVisitor visitor) {
+ doAccept(visitor, 0);
+ }
+
+ protected void doAccept(IModelDeltaVisitor visitor, int depth) {
+ if (visitor.visit(this, depth)) {
+ ModelDelta[] childDeltas = getChildDeltas();
+ for (int i = 0; i < childDeltas.length; i++) {
+ ((VMDelta)childDeltas[i]).doAccept(visitor, depth+1);
+ }
+ }
+ }
+
}
diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMProvider.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMProvider.java
deleted file mode 100644
index 029b25ff52b..00000000000
--- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMProvider.java
+++ /dev/null
@@ -1,439 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2006 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.dd.dsf.ui.viewmodel;
-
-import java.util.concurrent.atomic.AtomicReference;
-
-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.core.runtime.jobs.Job;
-import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
-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.DsfSession;
-import org.eclipse.debug.internal.ui.viewers.provisional.AbstractModelProxy;
-import org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousContentAdapter;
-import org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousLabelAdapter;
-import org.eclipse.debug.internal.ui.viewers.provisional.IChildrenRequestMonitor;
-import org.eclipse.debug.internal.ui.viewers.provisional.IColumnEditor;
-import org.eclipse.debug.internal.ui.viewers.provisional.IColumnEditorFactoryAdapter;
-import org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation;
-import org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentationFactoryAdapter;
-import org.eclipse.debug.internal.ui.viewers.provisional.IContainerRequestMonitor;
-import org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor;
-import org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta;
-import org.eclipse.debug.internal.ui.viewers.provisional.IModelProxy;
-import org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext;
-
-/**
- * View model provider implements the asynchronous view model functionality for
- * a single view. This provider is just a holder which further delegates the
- * model provider functionality to the view model layout nodes that need
- * to be configured with each provider.
- *
- * The view model provider, often does not provide the model for the entire
- * view. Rather, it needs to be able to plug in at any level in the viewer's
- * content model and provide data for a sub-tree.
- *
- * @see IAsynchronousContentAdapter
- * @see IAsynchronousLabelAdapter
- * @see IModelProxy
- * @see IVMLayoutNode
- */
-@ConfinedToDsfExecutor("fSession#getExecutor")
-@SuppressWarnings("restriction")
-public class VMProvider
-{
- private final DsfSession fSession;
- private final ModelProxy fModelProxy = new ModelProxy();
-
- /**
- * It is theoretically possible for a VMProvider to be disposed before it
- * has a chance to register itself as event listener. This flag is used
- * to avoid removing itself as listener in such situation.
- */
- private boolean fRegisteredAsEventListener = false;
-
- /**
- * The root node for this model provider. The root layout node could be
- * null when first created, to allow sub-classes to prorperly configure the
- * root node in the sub-class constructor.
- */
- private AtomicReference fRootLayoutNodeRef = new AtomicReference();
-
- /**
- * Constructs the view model provider for given DSF session. The
- * constructor is thread-safe to allow VM provider to be constructed
- * synchronously when a call to getAdapter() is made on an element
- * in a view.
- */
- @ThreadSafe
- public VMProvider(DsfSession session, IVMRootLayoutNode rootLayoutNode) {
- fSession = session;
- fRootLayoutNodeRef.set(rootLayoutNode);
- // Add ourselves as listener for DM events events.
- session.getExecutor().execute(new Runnable() {
- public void run() {
- if (DsfSession.isSessionActive(getSession().getId())) {
- getSession().addServiceEventListener(VMProvider.this, null);
- fRegisteredAsEventListener = true;
- }
- }
- });
- }
-
- /**
- * Sets the layout nodes. This method is thread-safe, because it might
- * be called fromthe constructor, which itself is thread-safe.
- */
- @ThreadSafe
- public void setRootLayoutNode(IVMRootLayoutNode rootLayoutNode) {
- final IVMRootLayoutNode oldRootLayoutNode = fRootLayoutNodeRef.getAndSet(rootLayoutNode);
- if (oldRootLayoutNode != null) {
- // IVMLayoutNode has to be called on dispatch thread... for now at least.
- getSession().getExecutor().execute( new Runnable() {
- public void run() {
- oldRootLayoutNode.dispose();
- }
- });
- }
- }
-
- public IVMRootLayoutNode getRootLayoutNode() {
- return fRootLayoutNodeRef.get();
- }
-
- /** Called to dispose the provider. */
- public void dispose() {
- if (fRegisteredAsEventListener) {
- fSession.removeServiceEventListener(this);
- }
- if (fRootLayoutNodeRef != null) {
- fRootLayoutNodeRef.get().dispose();
- }
- }
-
- protected DsfSession getSession() { return fSession; }
-
- /**
- * Performs the query to determine if given VNC is a container.
- * Note: this method must be called on the provider's dispatch thread.
- * @see IAsynchronousContentAdapter#isContainer(Object, org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext, IContainerRequestMonitor)
- */
- @SuppressWarnings("unchecked")
- public void isContainer(Object parent, final IContainerRequestMonitor monitor)
- {
- assert fSession.getExecutor().isInExecutorThread();
-
- IVMContext parentVmc = getVmcForObject(parent);
- if (parentVmc == null) {
- monitor.done();
- return;
- }
-
- /*
- * If the element's model node has no child layout nodes, it's not a
- * container.
- */
- if (parentVmc.getLayoutNode().getChildLayoutNodes().length == 0) {
- monitor.setIsContainer(false);
- monitor.done();
- return;
- }
-
- /*
- * For each child layout node, retrieve the list of elements. When
- * all are done, If any of the child nodes have elements, notify the
- * monitor that there are children.
- */
- final DoneCollector doneCollector = new DoneCollector(fSession.getExecutor()) {
- public void run() {
- if (monitor.isCanceled()) return;
-
- boolean isContainer = false;
- for (Done hasElementsDone : getDones().keySet()) {
- isContainer |= hasElementsDone.getStatus().isOK() &&
- ((GetDataDone)hasElementsDone).getData().booleanValue();
- }
- monitor.setIsContainer(isContainer);
- monitor.done();
- }
- };
- for (IVMLayoutNode childNode : parentVmc.getLayoutNode().getChildLayoutNodes()) {
- childNode.hasElements(
- parentVmc,
- doneCollector.add( new GetDataDone() { public void run() {
- doneCollector.doneDone(this);
- }}));
- }
- }
-
- /**
- * Performs the query to retrieve children for the given VMC.
- * Note: this method must be called on the provider's dispatch thread.
- * @see IAsynchronousContentAdapter#retrieveChildren(Object, org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext, IChildrenRequestMonitor)
- */
- @SuppressWarnings("unchecked")
- public void retrieveChildren(final Object parent, final IChildrenRequestMonitor monitor)
- {
- assert fSession.getExecutor().isInExecutorThread();
-
- IVMContext parentVmc = getVmcForObject(parent);
- if (parentVmc == null) {
- monitor.done();
- return;
- }
-
- /*
- * If the element's model node has no child layout nodes. There is
- * nothing to do, just mark the monitor done.
- */
- if (parentVmc.getLayoutNode().getChildLayoutNodes().length == 0) {
- assert false : "We should never get here, because isContainer() should have returned false"; //$NON-NLS-1$
- monitor.done();
- return;
- }
-
- /*
- * Iterate through the child layout nodes, and request their elements.
- * Requests are async, so use a tracker for the results.
- */
- final DoneCollector doneCollector = new DoneCollector(fSession.getExecutor()) {
- public void run() {
- if (monitor.isCanceled()) return;
- monitor.done();
- }
- };
- for (IVMLayoutNode childNode : parentVmc.getLayoutNode().getChildLayoutNodes()) {
- childNode.getElements(
- parentVmc,
- doneCollector.add( new GetDataDone() {
- public void run() {
- if (getStatus().isOK()) {
- monitor.addChildren(getData());
- }
- doneCollector.doneDone(this);
- }
- }));
- }
- }
-
- /**
- * Retrieves the label information for given object.
- * The implementation converts the object into a VM-Context, then delegates
- * to the context's layout node.
- * Note: this method must be called on the provider's dispatch thread.
-
- * @see IAsynchronousLabelAdapter#retrieveLabel(Object, org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext, ILabelRequestMonitor)
- */
- public void retrieveLabel(Object object, ILabelRequestMonitor result, String[] columns)
- {
- IVMContext vmc = getVmcForObject(object);
- if (vmc == null) {
- result.done();
- return;
- }
-
- vmc.getLayoutNode().retrieveLabel(vmc, result, columns);
- }
-
- public ModelProxy getModelProxy() {
- return fModelProxy;
- }
-
-
- /**
- * Creates the column presentation for the given object. This method is meant
- * to be overriden by deriving class to provide view-specific functionality.
- * The default is to return null, meaning no columns.
- *
- * The viewer only reads the column presentation for the root/input element of
- * the tree/table, so the VMProvider must be configured to own the root element
- * in the view in order for this setting to be effective.
- *
- * Note: since the IColumnEditorFactoryAdapter interface is synchronous, and since
- * column info is fairly static, this method is thread-safe, and it will
- * not be called on the executor thread.
- *
- * @see IColumnPresentationFactoryAdapter#createColumnPresentation(IPresentationContext, Object)
- */
- @ThreadSafe
- public IColumnPresentation createColumnPresentation(Object element) {
- return null;
- }
-
- /**
- * Returns the ID of the column presentation for the given object. This method
- * is meant to be overriden by deriving class to provide view-specific
- * functionality. The default is to return null, meaning no columns.
- *
- * The viewer only reads the column presentation for the root/input element of
- * the tree/table, so the VMProvider must be configured to own the root element
- * in the view in order for this setting to be effective.
- *
- * Note: since the IColumnEditorFactoryAdapter interface is synchronous, and since
- * column info is fairly static, this method is thread-safe, and it will
- * not be called on the executor thread.
- *
- * @see IColumnEditorFactoryAdapter#getColumnEditorId(IPresentationContext, Object)
- */
- @ThreadSafe
- public String getColumnPresentationId(Object element) {
- return null;
- }
-
- public IColumnEditor createColumnEditor(Object element) {
- IVMContext vmc = getVmcForObject(element);
- if (vmc == null) {
- return null;
- }
-
- return vmc.getLayoutNode().createColumnEditor(vmc);
- }
-
- public String getColumnEditorId(Object element) {
- IVMContext vmc = getVmcForObject(element);
- if (vmc == null) {
- return null;
- }
-
- return vmc.getLayoutNode().getColumnEditorId(vmc);
- }
-
-
- /**
- * Convenience method that finds the VMC corresponding to given parent
- * argument given to isContainer() or retrieveChildren().
- * @param object Object to find the VMC for.
- * @return parent VMC, if null it indicates that the object did not originate
- * from this view or is stale.
- */
- private IVMContext getVmcForObject(Object parent) {
- /*
- * First check to see if the parent object is the root object of the
- * hierarchy. If that's the case, then retrieve the correcponding
- * root VMC from the root node, and pass this root vmc to the root's
- * child layout nodes.
- */
- IVMRootLayoutNode rootLayoutNode = getRootLayoutNode();
- if (rootLayoutNode == null) {
- return null;
- }
- else if (parent.equals(rootLayoutNode.getRootVMC().getInputObject())) {
- return rootLayoutNode.getRootVMC();
- }
- else if (parent instanceof IVMContext){
- /*
- * The parent is a VMC. Check to make sure that the VMC
- * originated from a node in this ViewModelProvider. If it didn't
- * it is most likely a result of a change in view layout, and this
- * request is a stale request. So just ignore it.
- */
- if (isOurLayoutNode( ((IVMContext)parent).getLayoutNode(),
- new IVMLayoutNode[] { rootLayoutNode } ))
- {
- return (IVMContext)parent;
- }
- }
- return null;
- }
-
- /**
- * Convenience method which checks whether given layout node is a node
- * that is configured in this ViewModelProvider. Implementation
- * recursively walks the layout hierarchy, and returns true if it finds
- * the node.
- */
- private boolean isOurLayoutNode(IVMLayoutNode layoutNode, IVMLayoutNode[] nodesToSearch) {
- for (IVMLayoutNode node : nodesToSearch) {
- if (node == layoutNode) return true;
- if (isOurLayoutNode(layoutNode, node.getChildLayoutNodes())) return true;
- }
- 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.hasDeltaFlags(event)) {
- rootLayoutNode.createDelta(event, new GetDataDone() {
- public void run() {
- if (getStatus().isOK()) {
- fModelProxy.fireModelChangedNonDispatch(getData());
- }
- }
- @Override public String toString() {
- return "Result of a delta for event: '" + event.toString() + "' in VMP: '" + VMProvider.this + "'"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
- });
- }
- }
-
- @ThreadSafe
- public class ModelProxy extends AbstractModelProxy {
- /**
- * Counter for whether the model proxy is currently installed in the viewer.
- * Data model events are processed only if the model proxy is active.
- */
- private int fProxyActive = 0;
-
- /**
- * Scheduling rule for running the update jobs.
- */
- private ISchedulingRule fModelChangeRule = new ISchedulingRule() {
- public boolean contains(ISchedulingRule rule) { return this == rule; }
- public boolean isConflicting(ISchedulingRule rule) { return rule == this; }
- };
-
- public void installed() {
- fProxyActive++;
- }
-
- public void dispose() {
- fProxyActive--;
- super.dispose();
- }
-
- /**
- * Fires given delta using a job. Processing the delta on the dispatch
- * thread can lead to dead-locks.
- * @param delta
- */
- public void fireModelChangedNonDispatch(final IModelDelta delta) {
- if (fProxyActive <= 0) return;
-
- Job job = new Job("Processing view model delta.") { //$NON-NLS-1$
- protected IStatus run(IProgressMonitor monitor) {
- fireModelChanged(delta);
- return Status.OK_STATUS;
- }
- };
- job.setPriority(Job.INTERACTIVE);
- job.setRule(fModelChangeRule);
- job.schedule();
- }
-
- }
-}
diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/dm/AbstractDMVMAdapter.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/dm/AbstractDMVMAdapter.java
new file mode 100644
index 00000000000..5035419519a
--- /dev/null
+++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/dm/AbstractDMVMAdapter.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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.dd.dsf.ui.viewmodel.dm;
+
+import org.eclipse.dd.dsf.concurrent.ThreadSafe;
+import org.eclipse.dd.dsf.service.DsfSession;
+import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
+
+/**
+ * Base implementation for DSF-based view model adapters.
+ */
+@ThreadSafe
+abstract public class AbstractDMVMAdapter extends AbstractVMAdapter
+{
+ private final DsfSession fSession;
+
+ /**
+ * Constructor for the View Model session. It is tempting to have the
+ * adapter register itself here with the session as the model adapter, but
+ * that would mean that the adapter might get accessed on another thread
+ * even before the deriving class is fully constructed. So it it better
+ * to have the owner of this object register it with the session.
+ * @param session
+ */
+ public AbstractDMVMAdapter(DsfSession session) {
+ super();
+ fSession = session;
+ }
+
+ /**
+ * Returns the DSF session that this adapter is associated with.
+ * @return
+ */
+ protected DsfSession getSession() { return fSession; }
+
+}
diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/dm/AbstractDMVMLayoutNode.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/dm/AbstractDMVMLayoutNode.java
new file mode 100644
index 00000000000..775ecdf61ab
--- /dev/null
+++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/dm/AbstractDMVMLayoutNode.java
@@ -0,0 +1,501 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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.dd.dsf.ui.viewmodel.dm;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.dd.dsf.concurrent.Done;
+import org.eclipse.dd.dsf.concurrent.DsfRunnable;
+import org.eclipse.dd.dsf.concurrent.GetDataDone;
+import org.eclipse.dd.dsf.concurrent.Immutable;
+import org.eclipse.dd.dsf.datamodel.DMContexts;
+import org.eclipse.dd.dsf.datamodel.IDMContext;
+import org.eclipse.dd.dsf.datamodel.IDMData;
+import org.eclipse.dd.dsf.datamodel.IDMEvent;
+import org.eclipse.dd.dsf.datamodel.IDMService;
+import org.eclipse.dd.dsf.service.DsfServicesTracker;
+import org.eclipse.dd.dsf.service.DsfSession;
+import org.eclipse.dd.dsf.service.IDsfService;
+import org.eclipse.dd.dsf.ui.DsfUIPlugin;
+import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMLayoutNode;
+import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
+import org.eclipse.dd.dsf.ui.viewmodel.IVMContext;
+import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode;
+import org.eclipse.dd.dsf.ui.viewmodel.VMDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactoryAdapter;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeSelection;
+import org.eclipse.jface.viewers.TreePath;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.RGB;
+
+
+/**
+ * View model layout node based on a single Data Model Context type.
+ * The assumption in this implementation is that elements of this node have
+ * a single IDMContext associated with them, and all of these contexts
+ * are of the same class type.
+ */
+@SuppressWarnings("restriction")
+abstract public class AbstractDMVMLayoutNode extends AbstractVMLayoutNode
+ implements IElementLabelProvider
+{
+
+ /**
+ * IVMContext implementation used for this schema node.
+ */
+ @Immutable
+ public class DMVMContext extends AbstractVMContext {
+ private final IDMContext> fDmc;
+
+ public DMVMContext(IDMContext> dmc) {
+ super(getVMProvider().getVMAdapter(), AbstractDMVMLayoutNode.this);
+ fDmc = dmc;
+ }
+
+ public IDMContext> getDMC() { return fDmc; }
+
+ /**
+ * The IAdaptable implementation. If the adapter is the DM context,
+ * return the context, otherwise delegate to IDMContext.getAdapter().
+ */
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Class adapter) {
+ Object superAdapter = super.getAdapter(adapter);
+ if (superAdapter != null) {
+ return superAdapter;
+ } else if (adapter.isInstance(fDmc)) {
+ return fDmc;
+ } else {
+ return fDmc.getAdapter(adapter);
+ }
+ }
+
+ public boolean equals(Object other) {
+ if (!(other instanceof AbstractDMVMLayoutNode.DMVMContext)) return false;
+ DMVMContext otherVmc = (DMVMContext)other;
+ return AbstractDMVMLayoutNode.this.equals(otherVmc.getLayoutNode()) &&
+ fDmc.equals(otherVmc.fDmc);
+ }
+
+ public int hashCode() {
+ return AbstractDMVMLayoutNode.this.hashCode() + fDmc.hashCode();
+ }
+
+ public String toString() {
+ return fDmc.toString();
+ }
+ }
+
+ private DsfSession fSession;
+
+ private DsfServicesTracker fServicesTracker;
+
+ /**
+ * Concrete class type that the elements of this schema node are based on.
+ * Even though the data model type is a parameter the DMContextVMLayoutNode,
+ * this type is erased at runtime, so a concrete class typs of the DMC
+ * is needed for instanceof chacks.
+ */
+ private Class extends IDMContext> fDMCClassType;
+
+ /**
+ * Constructor initializes instance data, except for the child nodes.
+ * Child nodes must be initialized by calling setChildNodes()
+ * @param session
+ * @param dmcClassType
+ * @see #setChildNodes(IVMLayoutNode[])
+ */
+ public AbstractDMVMLayoutNode(AbstractVMProvider provider, DsfSession session, Class extends IDMContext> dmcClassType) {
+ super(provider);
+ fSession = session;
+ fServicesTracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), session.getId());
+ fDMCClassType = dmcClassType;
+ }
+
+
+ public void dispose() {
+ fServicesTracker.dispose();
+ super.dispose();
+ }
+
+ protected DsfSession getSession() {
+ return fSession;
+ }
+
+ protected DsfServicesTracker getServicesTracker() {
+ return fServicesTracker;
+ }
+
+ @Override
+ protected boolean checkUpdate(IViewerUpdate update) {
+ if (!super.checkUpdate(update)) return false;
+
+ // Extract the VMC from the update (whatever the update sub-class.
+ Object element = update.getElement();
+ if (element instanceof AbstractDMVMLayoutNode.DMVMContext) {
+ // If update element is a DMC, check if session is still alive.
+ IDMContext> dmc = ((DMVMContext)element).getDMC();
+ if (dmc.getSessionId() != getSession().getId() || !DsfSession.isSessionActive(dmc.getSessionId())) {
+ handleFailedUpdate(update);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ protected boolean checkService(Class extends IDsfService> serviceClass, String filter, IViewerUpdate update) {
+ if (getServicesTracker().getService(serviceClass, filter) == null) {
+ update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE,
+ "Service " + serviceClass.getName() + " not available.", null)); //$NON-NLS-1$ //$NON-NLS-2$
+ handleFailedUpdate(update);
+ return false;
+ }
+ return true;
+ }
+
+ public void updateHasElements(final IHasChildrenUpdate[] updates) {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ updateHasElementsInSessionThread(updates);
+ }});
+ }
+
+ protected void updateHasElementsInSessionThread(IHasChildrenUpdate[] updates) {
+ for (final IHasChildrenUpdate update : updates) {
+ if (!checkUpdate(update)) return;
+
+ updateElementsInSessionThread(
+ new ElementsUpdate(
+ new GetDataDone>() {
+ public void run() {
+ if (!checkUpdate(update)) return;
+ if (getStatus().isOK()) {
+ update.setHasChilren(getData().size() != 0);
+ } else {
+ update.setHasChilren(false);
+ }
+ update.done();
+ }
+ },
+ update.getElementPath())
+ );
+ }
+ }
+
+ public void updateElementCount(final IChildrenCountUpdate update) {
+ if (!checkUpdate(update)) return;
+
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ // After every dispatch, must check if update still valid.
+ if (!checkUpdate(update)) return;
+ updateElementCountInSessionThread(update);
+ }});
+ }
+
+ protected void updateElementCountInSessionThread(final IChildrenCountUpdate update) {
+ updateElementsInSessionThread(
+ new ElementsUpdate(
+ new GetDataDone>() {
+ public void run() {
+ if (!checkUpdate(update)) return;
+ if (getStatus().isOK()) {
+ update.setChildCount(getData().size());
+ } else {
+ update.setChildCount(0);
+ }
+ update.done();
+ }
+ },
+ update.getElementPath())
+ );
+ }
+
+ public void updateElements(final IChildrenUpdate update) {
+ if (!checkUpdate(update)) return;
+
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ // After every dispatch, must check if update still valid.
+ if (!checkUpdate(update)) return;
+ updateElementsInSessionThread(update);
+ }});
+ }
+
+ abstract protected void updateElementsInSessionThread(IChildrenUpdate update);
+
+ public void update(final ILabelUpdate[] updates) {
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ // After every dispatch, must check if update still valid.
+ updateLabelInSessionThread(updates);
+ }});
+ } catch (RejectedExecutionException e) {
+ for (ILabelUpdate update : updates) {
+ handleFailedUpdate(update);
+ }
+ }
+ }
+
+ /**
+ * The default implementation of the retrieve label method. It acquires
+ * the service, using parameters in the DMC, then it fetches the model
+ * data from the service, and then it calls the protected method
+ * fillColumnLabel() for each column. The deriving classes should override
+ * this method if a different method of computing the label is needed.
+ *
+ * @see #fillColumnLabel(IDMData, String, int, String[], ImageDescriptor[], FontData[], RGB[], RGB[])
+ */
+ protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
+ for (final ILabelUpdate update : updates) {
+ final DMVMContext vmc = (DMVMContext)update.getElement();
+ if (!checkService(null, vmc.getDMC().getServiceFilter(), update)) return;
+
+ final IDMContext dmc = findDmcInPath(update.getElementPath(), fDMCClassType);
+
+ ((IDMService)getServicesTracker().getService(null, vmc.getDMC().getServiceFilter())).getModelData(
+ dmc,
+ new GetDataDone() {
+ public void run() {
+ /*
+ * Check that the request was evaluated and data is still
+ * valid. The request could fail if the state of the
+ * service changed during the request, but the view model
+ * has not been updated yet.
+ */
+ if (!getStatus().isOK() || !getData().isValid()) {
+ assert getStatus().isOK() ||
+ getStatus().getCode() != IDsfService.INTERNAL_ERROR ||
+ getStatus().getCode() != IDsfService.NOT_SUPPORTED;
+ handleFailedUpdate(update);
+ return;
+ }
+
+ /*
+ * If columns are configured, call the protected methods to
+ * fill in column values.
+ */
+ String[] localColumns = update.getPresentationContext().getColumns();
+ if (localColumns == null) localColumns = new String[] { null };
+
+ for (int i = 0; i < localColumns.length; i++) {
+ fillColumnLabel(dmc, getData(), localColumns[i], i, update);
+ }
+ update.done();
+ }
+ });
+ }
+ }
+
+ /**
+ * Fills in label information for given column. This method is intended to
+ * be overriden by deriving classes, to supply label information specific
+ * to the node.
+ * The implementation should fill in the correct value in each array at the
+ * given index.
+ * @param dmContext Data Model Context object for which the label is generated.
+ * @param dmData Data Model Data object retrieved from the model service.
+ * for the DM Context supplied to the retrieveLabel() call.
+ * @param columnId Name of the column to fill in, null if no columns specified.
+ * @param idx Index to fill in in the label arrays.
+ * @param update Update object to fill information to
+ *
+ * @see IElementLabelProvider
+ * @see IColumnPresentationFactoryAdapter
+ */
+ protected void fillColumnLabel(IDMContext dmContext, V dmData, String columnId, int idx, ILabelUpdate update) {
+ update.setLabel("", idx); //$NON-NLS-1$
+ }
+
+ @Override
+ public int getDeltaFlags(Object e) {
+ int flags = 0;
+ if (e instanceof IDMEvent) {
+ flags = getNodeDeltaFlagsForDMEvent((IDMEvent)e);
+ }
+ return flags | super.getDeltaFlags(e);
+ }
+
+ protected int getNodeDeltaFlagsForDMEvent(IDMEvent> e) {
+ return IModelDelta.NO_CHANGE;
+ }
+
+ @Override
+ public void buildDelta(final Object e, final VMDelta parentDelta, final int nodeOffset, final Done done) {
+ if (e instanceof IDMEvent) {
+ // Call handler for Data Model events. But check to make sure
+ // that session is still active.
+ if (DsfSession.isSessionActive(getSession().getId())) {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ buildDeltaForDMEvent((IDMEvent)e, parentDelta, nodeOffset, done);
+ }
+ });
+ } else {
+ if (isDisposed()) return;
+ getExecutor().execute(done);
+ }
+ } else {
+ super.buildDelta(e, parentDelta, nodeOffset, done);
+ }
+ }
+
+ /**
+ * Handle all Data Model events. If a DM context in the event contains
+ * a context of the type tracked by this node, then this base implementation
+ * will only create a delta node for this one element.
+ */
+ protected void buildDeltaForDMEvent(final IDMEvent> event, final VMDelta parentDelta, final int nodeOffset, final Done done) {
+ IDMContext dmc = DMContexts.getAncestorOfType(event.getDMContext(), fDMCClassType);
+
+ if (dmc != null) {
+ // 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 childNodeDeltas = getChildNodesWithDeltas(event);
+ if (childNodeDeltas.size() == 0) {
+ // There are no child nodes with deltas, just return to parent.
+ getExecutor().execute(done);
+ return;
+ }
+
+ // Check if any of the child nodes are will generate IModelDelta.SELECT or
+ // IModelDelta.EXPAND flags. If so, we must calcuate the index for this
+ // VMC.
+ boolean calculateIndex = false;
+ for (int childDelta : childNodeDeltas.values()) {
+ if ( (childDelta & (IModelDelta.SELECT | IModelDelta.EXPAND)) != 0 ) {
+ calculateIndex = true;
+ break;
+ }
+ }
+
+ if (calculateIndex) {
+ // Calculate the index of this node by retrieving all the
+ // elements and then finding the DMC that the event is for.
+ updateElements(new ElementsUpdate(
+ new GetDataDone>() {
+ public void run() {
+ if (isDisposed()) return;
+
+ // Check for an empty list of elements. If it's empty then we
+ // don't have to call the children nodes, so return here.
+ // No need to propagate error, there's no means or need to display it.
+ if (!getStatus().isOK()) {
+ getExecutor().execute(done);
+ return;
+ }
+
+ // Find the index.
+ int i;
+ for (i = 0; i < getData().size(); i++) {
+ if (vmc.equals(getData().get(i))) break;
+ }
+ if (i == getData().size()) {
+ // Element not found, no need to generate the delta.
+ getExecutor().execute(done);
+ }
+
+ VMDelta delta = parentDelta.addNode(vmc, nodeOffset + i, IModelDelta.NO_CHANGE);
+ callChildNodesToBuildDelta(childNodeDeltas, delta, event, done);
+ }
+ },
+ parentDelta));
+ } else {
+ VMDelta delta = parentDelta.addNode(vmc, IModelDelta.NO_CHANGE);
+ callChildNodesToBuildDelta(childNodeDeltas, delta, event, done);
+ }
+ } else {
+ // The for this node was not found in the event. Call the
+ // super-class to resort to the default behavior which may add a
+ // delta node for every element in this node.
+ super.buildDelta(event, parentDelta, nodeOffset, done);
+ }
+ }
+
+ /**
+ * Utility method that takes an array of DMC object and creates a
+ * corresponding array of IVMContext elements base on that.
+ * @param parent The parent for generated IVMContext elements.
+ * @param dmcs Array of DMC objects to build return array on.
+ * @return Array of IVMContext objects.
+ */
+ protected IVMContext[] dmcs2vmcs(IDMContext[] dmcs) {
+ IVMContext[] vmContexts = new IVMContext[dmcs.length];
+ for (int i = 0; i < dmcs.length; i++) {
+ vmContexts[i] = new DMVMContext(dmcs[i]);
+ }
+ return vmContexts;
+ }
+
+ protected void fillUpdateWithVMCs(IChildrenUpdate update, IDMContext[] dmcs) {
+ int startIdx = update.getOffset() != -1 ? update.getOffset() : 0;
+ int endIdx = update.getLength() != -1 ? startIdx + update.getLength() : dmcs.length;
+ for (int i = startIdx; i < endIdx; i++) {
+ update.setChild(new DMVMContext(dmcs[i]), i);
+ }
+ }
+
+ /**
+ * Searches for a DMC of given type in the tree patch contained in given
+ * VMC. Only a DMC in the same session will be returned.
+ * @param Type of the DMC that will be returned.
+ * @param vmc VMC element to search.
+ * @param dmcType Class object for matching the type.
+ * @return DMC, or null if not found.
+ */
+ @SuppressWarnings("unchecked")
+ public T findDmcInPath(TreePath path, Class dmcType) {
+ T retVal = null;
+ for (int i = path.getSegmentCount() - 1; i >= 0; i--) {
+ if (path.getSegment(i) instanceof AbstractDMVMLayoutNode.DMVMContext) {
+ IDMContext> dmc = ((DMVMContext)path.getSegment(i)).getDMC();
+ if ( dmc.getSessionId().equals(getSession().getId()) ) {
+ retVal = DMContexts.getAncestorOfType(dmc, dmcType);
+ if (retVal != null) break;
+ }
+ }
+ }
+ // Search the root object of the layout hierarchy.
+ if (retVal == null) {
+ Object inputObject = getVMProvider().getRootLayoutNode().getRootObject();
+ if (inputObject instanceof ITreeSelection) {
+ ITreeSelection inputSelection = (ITreeSelection)inputObject;
+ if (inputSelection.getPaths().length == 1) {
+ retVal = findDmcInPath(inputSelection.getPaths()[0], dmcType);
+ }
+ } else if (inputObject instanceof IStructuredSelection) {
+ Object rootElement = ((IStructuredSelection)inputObject).getFirstElement();
+ if (rootElement instanceof AbstractDMVMLayoutNode.DMVMContext) {
+ retVal = DMContexts.getAncestorOfType(((DMVMContext)rootElement).getDMC(), dmcType);
+ }
+ } else if (inputObject instanceof AbstractDMVMLayoutNode.DMVMContext) {
+ retVal = DMContexts.getAncestorOfType(((DMVMContext)inputObject).getDMC(), dmcType);
+ }
+ }
+
+ return retVal;
+ }
+}
diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/dm/AbstractDMVMProvider.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/dm/AbstractDMVMProvider.java
new file mode 100644
index 00000000000..788b370ea09
--- /dev/null
+++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/dm/AbstractDMVMProvider.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2006 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.dd.dsf.ui.viewmodel.dm;
+
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor;
+import org.eclipse.dd.dsf.concurrent.GetDataDone;
+import org.eclipse.dd.dsf.datamodel.IDMEvent;
+import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
+import org.eclipse.dd.dsf.service.DsfSession;
+import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter;
+import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider;
+import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode;
+import org.eclipse.dd.dsf.ui.viewmodel.IVMRootLayoutNode;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousContentAdapter;
+import org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousLabelAdapter;
+
+/**
+ * View model provider implements the asynchronous view model functionality for
+ * a single view. This provider is just a holder which further delegates the
+ * model provider functionality to the view model layout nodes that need
+ * to be configured with each provider.
+ *
+ * The view model provider, often does not provide the model for the entire
+ * view. Rather, it needs to be able to plug in at any level in the viewer's
+ * content model and provide data for a sub-tree.
+ *
+ * @see IAsynchronousContentAdapter
+ * @see IAsynchronousLabelAdapter
+ * @see IModelProxy
+ * @see IVMLayoutNode
+ */
+@ConfinedToDsfExecutor("fSession#getExecutor")
+@SuppressWarnings("restriction")
+abstract public class AbstractDMVMProvider extends AbstractVMProvider
+{
+ private final DsfSession fSession;
+
+ /**
+ * It is theoretically possible for a VMProvider to be disposed before it
+ * has a chance to register itself as event listener. This flag is used
+ * to avoid removing itself as listener in such situation.
+ */
+ private boolean fRegisteredAsEventListener = false;
+
+ /**
+ * Constructs the view model provider for given DSF session. The
+ * constructor is thread-safe to allow VM provider to be constructed
+ * synchronously when a call to getAdapter() is made on an element
+ * in a view.
+ */
+ public AbstractDMVMProvider(AbstractVMAdapter adapter, IPresentationContext presentationContext, DsfSession session) {
+ super(adapter, presentationContext);
+ fSession = session;
+ // Add ourselves as listener for DM events events.
+ try {
+ session.getExecutor().execute(new Runnable() {
+ public void run() {
+ if (DsfSession.isSessionActive(getSession().getId())) {
+ getSession().addServiceEventListener(AbstractDMVMProvider.this, null);
+ fRegisteredAsEventListener = true;
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ // Session shut down, not much we can do but wait to be disposed.
+ }
+ }
+
+ /** Called to dispose the provider. */
+ public void dispose() {
+ try {
+ getSession().getExecutor().execute(new Runnable() {
+ public void run() {
+ if (DsfSession.isSessionActive(getSession().getId()) && fRegisteredAsEventListener ) {
+ fSession.removeServiceEventListener(AbstractDMVMProvider.this);
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ // Session shut down.
+ }
+ super.dispose();
+ }
+
+ protected DsfSession getSession() { return fSession; }
+
+
+
+ /**
+ * 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) {
+ if (isDisposed()) return;
+
+ // We're in session's executor thread. Re-dispach to VM Adapter
+ // executor thread and then call root layout node.
+ try {
+ getExecutor().execute(new Runnable() {
+ public void run() {
+ if (isDisposed()) return;
+
+ IVMRootLayoutNode rootLayoutNode = getRootLayoutNode();
+ if (rootLayoutNode != null && rootLayoutNode.getDeltaFlags(event) != 0) {
+ rootLayoutNode.createDelta(event, new GetDataDone() {
+ public void run() {
+ if (getStatus().isOK()) {
+ getModelProxy().fireModelChangedNonDispatch(getData());
+ }
+ }
+ @Override public String toString() {
+ return "Result of a delta for event: '" + event.toString() + "' in VMP: '" + AbstractDMVMProvider.this + "'" + "\n" + getData().toString(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ }
+ });
+ }
+ }});
+ } catch (RejectedExecutionException e) {
+ // Ignore. This exception could be thrown if the provider is being
+ // shut down.
+ }
+ }
+}
diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DefaultDsfExecutor.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DefaultDsfExecutor.java
index d4feb038cb5..7c212d3734b 100644
--- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DefaultDsfExecutor.java
+++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DefaultDsfExecutor.java
@@ -86,7 +86,10 @@ public class DefaultDsfExecutor extends ScheduledThreadPoolExecutor
}
static void logException(Throwable t) {
- ILog log = DsfPlugin.getDefault().getLog();
+ DsfPlugin plugin = DsfPlugin.getDefault();
+ if (plugin == null) return;
+
+ ILog log = plugin.getLog();
if (log != null) {
log.log(new Status(
IStatus.ERROR, DsfPlugin.PLUGIN_ID, -1, "Uncaught exception in DSF executor thread", t)); //$NON-NLS-1$
@@ -222,6 +225,12 @@ public class DefaultDsfExecutor extends ScheduledThreadPoolExecutor
public TracingWrapperRunnable(Runnable runnable, int offset) {
super(offset);
fRunnable = runnable;
+
+ // Check if executable wasn't executed already.
+ if (DEBUG_EXECUTOR && fRunnable instanceof DsfExecutable) {
+ assert !((DsfExecutable)fRunnable).getSubmitted() : "Executable was previously executed."; //$NON-NLS-1$
+ ((DsfExecutable)fRunnable).setSubmitted();
+ }
}
protected Object getExecutable() { return fRunnable; }
@@ -229,11 +238,6 @@ public class DefaultDsfExecutor extends ScheduledThreadPoolExecutor
public void run() {
traceExecution();
- // If debugging a DSF exeutable, mark that it was executed.
- if (DEBUG_EXECUTOR && fRunnable instanceof DsfExecutable) {
- ((DsfExecutable)fRunnable).setExecuted();
- }
-
// Finally invoke the runnable code.
fRunnable.run();
}
@@ -251,11 +255,6 @@ public class DefaultDsfExecutor extends ScheduledThreadPoolExecutor
public T call() throws Exception {
traceExecution();
- // If debugging a DSF exeutable, mark that it was executed.
- if (DEBUG_EXECUTOR && fCallable instanceof DsfExecutable) {
- ((DsfExecutable)fCallable).setExecuted();
- }
-
// Finally invoke the runnable code.
return fCallable.call();
}
diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DoneCollector.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DoneCollector.java
index 8fce539f983..e21dc82d494 100644
--- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DoneCollector.java
+++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DoneCollector.java
@@ -35,9 +35,8 @@ import org.eclipse.dd.dsf.DsfPlugin;
* }
*
*/
-public abstract class DoneCollector extends Done {
- private final DsfExecutor fExecutor;
- private Map fDones = new HashMap();
+public abstract class DoneCollector extends Done {
+ private Map fDones = new HashMap();
private int fDoneCounter;
/**
@@ -47,39 +46,25 @@ public abstract class DoneCollector extends Done {
* execution of the last done, and in the same dispatch loop.
*
*/
- public DoneCollector(DsfExecutor executor) {
+ public DoneCollector() {
setStatus(new MultiStatus(DsfPlugin.PLUGIN_ID, 0, "Collective status for set of sub-operations.", null)); //$NON-NLS-1$
- fExecutor = executor;
}
/**
* Adds a new Done callback to this tracker's list.
- * @param Service-specific class of the Done callback, to avoid an
- * unnecessary cast.
+ * @param Client-specific class of the Done callback, it's used here to avoid an
+ * unnecessary cast by the client.
* @param done callback object to add to the tracker
* @return the done that was just added, it allows this method to be used
* inlined in service method calls
*/
- public V add(V done) {
+ public T add(T done) {
assert !fDones.containsKey(done);
fDones.put(done, false);
fDoneCounter++;
return done;
}
- /**
- * Adds a Done which performs no actions. This is useful if all work
- * is performed inside DoneCollector.run().
- * @return Done which is to be passed as an argument to a service method.
- */
- public Done addNoActionDone() {
- return add(new Done() {
- public void run() {
- doneDone(this);
- }
- });
- }
-
/**
* Marks the given Done callback as completed. Client implementations of
* the Done callback have to call this method in order for the tracker
@@ -88,13 +73,15 @@ public abstract class DoneCollector extends Done {
* Note: funniest method signature ever!
* @param done
*/
- public void doneDone(Done done) {
+ public void doneDone(V done) {
((MultiStatus)getStatus()).merge(done.getStatus());
+ assert fDones.containsKey(done);
fDones.put(done, true);
+ assert fDoneCounter > 0;
fDoneCounter--;
if (fDoneCounter == 0) {
assert !fDones.containsValue(false);
- fExecutor.execute(this);
+ run();
}
}
@@ -104,10 +91,15 @@ public abstract class DoneCollector extends Done {
* done callbacks.
* @return map of the done callbacks.
*/
- public Map getDones() { return fDones; }
+ public Map getDones() { return fDones; }
@Override
public String toString() {
return "Done Collector: " + getStatus().toString(); //$NON-NLS-1$
}
+
+ @Override
+ protected boolean isExecutionRequired() {
+ return false;
+ }
}
diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DsfExecutable.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DsfExecutable.java
index 748aa8d2772..7620478eca9 100644
--- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DsfExecutable.java
+++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DsfExecutable.java
@@ -62,7 +62,7 @@ public class DsfExecutable {
* Flag indicating whether this executable was ever executed by an
* executor. Used for tracing only.
*/
- private boolean fExecuted = false;
+ private boolean fSubmitted = false;
@SuppressWarnings("unchecked")
public DsfExecutable() {
@@ -97,17 +97,31 @@ public class DsfExecutable {
}
}
+ boolean getSubmitted() {
+ return fSubmitted;
+ }
+
/**
* Marks this executable to indicate that it has been executed by the
* executor. To be invoked only by DsfExecutor.
*/
- void setExecuted() {
- fExecuted = true;
+ void setSubmitted() {
+ fSubmitted = true;
+ }
+
+ /**
+ * Returns whether the runnable/callable is expected to be always executed.
+ * Overriding classes can implement this method and return false, to avoid
+ * unnecessary trace output.
+ * @return true if this runnable is expected to run.
+ */
+ protected boolean isExecutionRequired() {
+ return true;
}
@Override
protected void finalize() {
- if (DEBUG_EXECUTOR && !fExecuted) {
+ if (DEBUG_EXECUTOR && !fSubmitted && isExecutionRequired()) {
StringBuilder traceBuilder = new StringBuilder();
// Record the time
diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/datamodel/AbstractDMContext.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/datamodel/AbstractDMContext.java
index b428ba83337..778295eea21 100644
--- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/datamodel/AbstractDMContext.java
+++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/datamodel/AbstractDMContext.java
@@ -12,7 +12,6 @@ package org.eclipse.dd.dsf.datamodel;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.dd.dsf.concurrent.Immutable;
-import org.eclipse.dd.dsf.service.AbstractDsfService;
import org.eclipse.dd.dsf.service.DsfSession;
/**
@@ -40,12 +39,10 @@ abstract public class AbstractDMContext extends PlatformObjec
}
/** Convenience constructor */
- public AbstractDMContext(AbstractDsfService service, IDMContext> parent) {
- this(service.getSession().getId(),
- service.getServiceFilter(),
- parent == null ? new IDMContext[] {} : new IDMContext[] { parent });
+ public AbstractDMContext(IDMService service, IDMContext>[] parents) {
+ this(service.getSession().getId(), service.getServiceFilter(), parents);
}
-
+
/**
* Should be used by the deriving class to compare the basic context object
* information.
diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/datamodel/ServiceDMContext.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/datamodel/ServiceDMContext.java
index 1f71becf043..481abf680f9 100644
--- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/datamodel/ServiceDMContext.java
+++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/datamodel/ServiceDMContext.java
@@ -10,7 +10,6 @@
*******************************************************************************/
package org.eclipse.dd.dsf.datamodel;
-import org.eclipse.dd.dsf.service.AbstractDsfService;
/**
* The Data Model Context representing the owner service. The service DM Context
@@ -22,8 +21,8 @@ import org.eclipse.dd.dsf.service.AbstractDsfService;
public class ServiceDMContext extends AbstractDMContext {
String fServiceDMID;
- public ServiceDMContext(AbstractDsfService service, String serviceDMID) {
- super(service, null);
+ public ServiceDMContext(IDMService service, String serviceDMID) {
+ super(service, new IDMContext>[0]);
fServiceDMID = serviceDMID;
}
diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/service/IDsfService.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/service/IDsfService.java
index 77bd7654078..a5b527ac02a 100644
--- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/service/IDsfService.java
+++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/service/IDsfService.java
@@ -74,10 +74,14 @@ public interface IDsfService {
*/
final static int INTERNAL_ERROR = 10005;
+ /**
+ * Returns the DSF Session that this service belongs to.
+ */
+ DsfSession getSession();
/**
* Returns the executor that should be used to call methods of this service.
- * @return
+ * This method is equivalent to calling getSession().getExecutor()
*/
DsfExecutor getExecutor();