From 810d315bbfe7b266ec1dbbc8a1bd11a351eca001 Mon Sep 17 00:00:00 2001 From: Pawel Piech Date: Sat, 5 May 2007 00:12:37 +0000 Subject: [PATCH] Added expression view model implementation (bug 185635). --- .../META-INF/MANIFEST.MF | 7 +- .../org.eclipse.dd.dsf.debug.ui/plugin.xml | 5 + .../DebugViewSelectionRootLayoutNode.java | 32 +- .../debug/ui/viewmodel/IDebugVMConstants.java | 13 + .../IFormattedValuePreferenceStore.java | 20 ++ .../viewmodel/IFormattedValueVMContext.java | 20 ++ .../ui/viewmodel/SetDefaultFormatDecimal.java | 47 +++ .../ui/viewmodel/SetDefaultFormatHex.java | 52 +++ .../AbstractExpressionLayoutNode.java | 310 ++++++++++++++++++ .../ExpressionColumnPresentation.java | 75 +++++ .../ExpressionManagerLayoutNode.java | 293 +++++++++++++++++ .../expression/ExpressionVMProvider.java | 123 +++++++ .../expression/IExpressionLayoutNode.java | 31 ++ .../expression/IExpressionVMContext.java | 19 ++ .../expression/MessagesForExpressionVM.java | 24 ++ .../WatchExpressionCellModifier.java | 66 ++++ .../expression/WatchExpressionDelegate.java | 33 ++ .../viewmodel/expression/messages.properties | 7 + .../launch/StackFramesLayoutNode.java | 2 +- .../launch/StandardLaunchRootLayoutNode.java | 2 +- .../register/RegisterColumnPresentation.java | 33 +- .../register/RegisterGroupLayoutNode.java | 233 ++++++++++++- .../register/RegisterLayoutNode.java | 238 +++++++++++++- .../register/RegisterVMProvider.java | 10 +- .../register/SyncRegisterDataAccess.java | 100 +++++- .../viewmodel/variable/LocalsLayoutNode.java | 94 ++++++ .../variable/MessagesForVariablesVM.java | 21 ++ .../variable/VariableColumnPresentation.java | 69 ++++ .../variable/VariableVMProvider.java | 44 +++ .../ui/viewmodel/variable/messages.properties | 3 + .../ui/viewmodel/AbstractVMLayoutNode.java | 24 +- .../dsf/ui/viewmodel/AbstractVMProvider.java | 235 ++++--------- .../ui/viewmodel/VMElementsCountUpdate.java | 41 +++ .../dd/dsf/ui/viewmodel/VMElementsUpdate.java | 77 +++++ .../dsf/ui/viewmodel/VMHasElementsUpdate.java | 40 +++ .../dd/dsf/ui/viewmodel/VMViewerUpdate.java | 54 +++ .../viewmodel/dm/AbstractDMVMLayoutNode.java | 4 +- .../ui/viewmodel/dm/AbstractDMVMProvider.java | 32 +- .../concurrent/CountingRequestMonitor.java | 61 ++++ .../dd/dsf/concurrent/DataRequestMonitor.java | 2 +- .../dsf/concurrent/MultiRequestMonitor.java | 36 +- 41 files changed, 2351 insertions(+), 281 deletions(-) create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/IDebugVMConstants.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/IFormattedValuePreferenceStore.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/IFormattedValueVMContext.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/SetDefaultFormatDecimal.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/SetDefaultFormatHex.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/AbstractExpressionLayoutNode.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/ExpressionColumnPresentation.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/ExpressionManagerLayoutNode.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/ExpressionVMProvider.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/IExpressionLayoutNode.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/IExpressionVMContext.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/MessagesForExpressionVM.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/WatchExpressionCellModifier.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/WatchExpressionDelegate.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/messages.properties create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/LocalsLayoutNode.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/MessagesForVariablesVM.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/VariableColumnPresentation.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java create mode 100644 plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/messages.properties create mode 100644 plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMElementsCountUpdate.java create mode 100644 plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMElementsUpdate.java create mode 100644 plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMHasElementsUpdate.java create mode 100644 plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMViewerUpdate.java create mode 100644 plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/CountingRequestMonitor.java diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/META-INF/MANIFEST.MF b/plugins/org.eclipse.dd.dsf.debug.ui/META-INF/MANIFEST.MF index 36de5b827d1..63fc553607d 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.dd.dsf.debug.ui/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Debug Services Framework Debug UI Bundle-Vendor: Eclipse.org -Bundle-SymbolicName: org.eclipse.dd.dsf.debug.ui +Bundle-SymbolicName: org.eclipse.dd.dsf.debug.ui; singleton:=true Bundle-Version: 0.9.0.qualifier Bundle-Activator: org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin Bundle-Localization: plugin @@ -17,7 +17,10 @@ Require-Bundle: org.eclipse.ui, org.eclipse.dd.dsf.debug Eclipse-LazyStart: true Export-Package: + org.eclipse.dd.dsf.debug.ui, org.eclipse.dd.dsf.debug.ui.viewmodel, + org.eclipse.dd.dsf.debug.ui.viewmodel.expression, + org.eclipse.dd.dsf.debug.ui.viewmodel.launch, org.eclipse.dd.dsf.debug.ui.viewmodel.register, - org.eclipse.dd.dsf.debug.ui.viewmodel.launch + org.eclipse.dd.dsf.debug.ui.viewmodel.variable Bundle-RequiredExecutionEnvironment: J2SE-1.5 diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/plugin.xml b/plugins/org.eclipse.dd.dsf.debug.ui/plugin.xml index 33ca93ceb1b..614503dc5b9 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/plugin.xml +++ b/plugins/org.eclipse.dd.dsf.debug.ui/plugin.xml @@ -1,5 +1,10 @@ + + + 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 73ba8d9e0e9..0128ffaad5e 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 @@ -20,8 +20,6 @@ import org.eclipse.dd.dsf.ui.viewmodel.IVMRootLayoutNode; 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; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.IWorkbenchWindow; @@ -39,25 +37,14 @@ import org.eclipse.ui.IWorkbenchWindow; */ @SuppressWarnings("restriction") public class DebugViewSelectionRootLayoutNode extends AbstractVMRootLayoutNode - implements IVMRootLayoutNode, IDebugContextListener + implements IVMRootLayoutNode { - private ISelection fSelection; - + private final IWorkbenchWindow fWindow; 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); + fWindow = DsfDebugUIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow(); } - @Override - public void dispose() { - DebugUITools.getDebugContextManager().removeDebugContextListener(this); - super.dispose(); - } - /** * 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 @@ -109,22 +96,19 @@ public class DebugViewSelectionRootLayoutNode extends AbstractVMRootLayoutNode * @return */ public ISelection getSelection() { - return fSelection; + return DebugUITools.getDebugContextManager().getContextService(fWindow).getActiveContext(); } public Object getRootObject() { - if (fSelection instanceof IStructuredSelection) { - return ((IStructuredSelection)fSelection).getFirstElement(); + ISelection selection = getSelection(); + if (selection instanceof IStructuredSelection) { + return ((IStructuredSelection)selection).getFirstElement(); } return null; } - public void debugContextChanged(DebugContextEvent event) { - fSelection = event.getContext(); - } - private IDMContext getSelectedDMC() { - Object selection = fSelection; + Object selection = getSelection(); if (selection instanceof IStructuredSelection) { IStructuredSelection structSelection = (IStructuredSelection)selection; if (structSelection.getFirstElement() instanceof DMVMContext) diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/IDebugVMConstants.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/IDebugVMConstants.java new file mode 100644 index 00000000000..3b0b9432139 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/IDebugVMConstants.java @@ -0,0 +1,13 @@ +package org.eclipse.dd.dsf.debug.ui.viewmodel; + +import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin; + +public interface IDebugVMConstants { + public static final String ID = DsfDebugUIPlugin.PLUGIN_ID + ".VARIABLES_COLUMN_PRESENTATION_ID"; //$NON-NLS-1$ + public static final String COLUMN_ID__NAME = DsfDebugUIPlugin.PLUGIN_ID + ".COLUMN_ID__NAME"; //$NON-NLS-1$ + public static final String COLUMN_ID__TYPE = DsfDebugUIPlugin.PLUGIN_ID + ".COLUMN_ID__TYPE"; //$NON-NLS-1$ + public static final String COLUMN_ID__VALUE = DsfDebugUIPlugin.PLUGIN_ID + ".COLUMN_ID__VALUE"; //$NON-NLS-1$ + public static final String COLUMN_ID__DESCRIPTION = DsfDebugUIPlugin.PLUGIN_ID + ".COLUMN_ID__DESCRIPTION"; //$NON-NLS-1$ + public static final String COLUMN_ID__EXPRESSION = DsfDebugUIPlugin.PLUGIN_ID + ".COLUMN_ID__EXPRESSION"; //$NON-NLS-1$ + +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/IFormattedValuePreferenceStore.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/IFormattedValuePreferenceStore.java new file mode 100644 index 00000000000..99e1343e771 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/IFormattedValuePreferenceStore.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * 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; + +/** + * + */ +public interface IFormattedValuePreferenceStore { + public String getDefaultFormatId(); + + public void setDefaultFormatId(String id); +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/IFormattedValueVMContext.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/IFormattedValueVMContext.java new file mode 100644 index 00000000000..3b38afb2f54 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/IFormattedValueVMContext.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * 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; + +import org.eclipse.dd.dsf.ui.viewmodel.IVMContext; + +/** + * + */ +public interface IFormattedValueVMContext extends IVMContext { + IFormattedValuePreferenceStore getPreferenceStore(); +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/SetDefaultFormatDecimal.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/SetDefaultFormatDecimal.java new file mode 100644 index 00000000000..6ba564344e6 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/SetDefaultFormatDecimal.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * 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; + +import org.eclipse.dd.dsf.debug.service.IFormattedValues; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; + +/** + * + */ +public class SetDefaultFormatDecimal implements IViewActionDelegate { + + private IFormattedValueVMContext fFormattedValueVMC; + + public void init(IViewPart view) { + } + + public void run(IAction action) { + if (fFormattedValueVMC != null) { + fFormattedValueVMC.getPreferenceStore().setDefaultFormatId(IFormattedValues.NATURAL_FORMAT); + } + } + + public void selectionChanged(IAction action, ISelection selection) { + fFormattedValueVMC = null; + if (selection instanceof IStructuredSelection) { + Object element = ((IStructuredSelection)selection).getFirstElement(); + if (element instanceof IFormattedValueVMContext) { + fFormattedValueVMC = ((IFormattedValueVMContext)element); + } + } + action.setEnabled(fFormattedValueVMC != null); + } + +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/SetDefaultFormatHex.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/SetDefaultFormatHex.java new file mode 100644 index 00000000000..984abaf9c09 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/SetDefaultFormatHex.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * 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; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.dd.dsf.debug.service.IFormattedValues; +import org.eclipse.dd.dsf.ui.viewmodel.IVMAdapter; +import org.eclipse.dd.dsf.ui.viewmodel.IVMContext; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider; +import org.eclipse.debug.ui.AbstractDebugView; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IViewActionDelegate; +import org.eclipse.ui.IViewPart; + +/** + * + */ +public class SetDefaultFormatHex implements IViewActionDelegate { + + private IFormattedValueVMContext fFormattedValueVMC; + + public void init(IViewPart view) { + } + + public void run(IAction action) { + if (fFormattedValueVMC != null) { + fFormattedValueVMC.getPreferenceStore().setDefaultFormatId(IFormattedValues.HEX_FORMAT); + } + } + + public void selectionChanged(IAction action, ISelection selection) { + fFormattedValueVMC = null; + if (selection instanceof IStructuredSelection) { + Object element = ((IStructuredSelection)selection).getFirstElement(); + if (element instanceof IFormattedValueVMContext) { + fFormattedValueVMC = ((IFormattedValueVMContext)element); + } + } + action.setEnabled(fFormattedValueVMC != null); + } + +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/AbstractExpressionLayoutNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/AbstractExpressionLayoutNode.java new file mode 100644 index 00000000000..ffacf21203f --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/AbstractExpressionLayoutNode.java @@ -0,0 +1,310 @@ +/******************************************************************************* + * Copyright (c) 2007 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.expression; + +import java.util.List; +import java.util.Map; + +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.CountingRequestMonitor; +import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; +import org.eclipse.dd.dsf.concurrent.MultiRequestMonitor; +import org.eclipse.dd.dsf.concurrent.RequestMonitor; +import org.eclipse.dd.dsf.datamodel.IDMContext; +import org.eclipse.dd.dsf.datamodel.IDMData; +import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin; +import org.eclipse.dd.dsf.service.DsfSession; +import org.eclipse.dd.dsf.service.IDsfService; +import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider; +import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode; +import org.eclipse.dd.dsf.ui.viewmodel.VMDelta; +import org.eclipse.dd.dsf.ui.viewmodel.VMElementsUpdate; +import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode; +import org.eclipse.debug.core.model.IExpression; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; +import org.eclipse.jface.viewers.TreePath; + +/** + * + */ +@SuppressWarnings("restriction") +public abstract class AbstractExpressionLayoutNode extends AbstractDMVMLayoutNode + implements IExpressionLayoutNode +{ + + public AbstractExpressionLayoutNode(AbstractVMProvider provider, DsfSession session, Class> dmcClassType) { + super(provider, session, dmcClassType); + } + + public void getElementForExpression(final IChildrenUpdate update, final String expressionText, final IExpression expression) { + final int exprLength = getExpressionLength(expressionText); + if (exprLength < 0) { + update.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Invalid expression", null)); //$NON-NLS-1$ + update.done(); + return; + } + + final String nodeExpressionText = exprLength > 0 ? expressionText.substring(0, exprLength) : expressionText; + + getElementForExpressionPart( + update, nodeExpressionText, + new DataRequestMonitor(getExecutor(), null) { + @Override + protected void handleOK() { + /** + * If the current expression is the whole expression from the argument, + * return the VMC. Otherwise, call the child nodes to continue evaluating + * the expression. + */ + if (exprLength == expressionText.length()) { + Object element = getData(); + associateExpression(element, expression); + update.setChild(element, 0); + update.done(); + } else { + getVMContextForExpressionFromChildNodes( + update, getData(), expressionText.substring(exprLength), expression); + } + } + + @Override + protected void handleErrorOrCancel() { + update.setStatus(getStatus()); + update.done(); + } + }); + } + + protected void getElementForExpressionPart(final IChildrenUpdate update, final String expressionPartText, final DataRequestMonitor rm) { + updateElements(new VMElementsUpdate( + update, -1, -1, + new DataRequestMonitor>(getSession().getExecutor(), rm) { + @Override + protected void handleOK() { + if (getData().size() == 0) { + rm.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "No contexts", null)); //$NON-NLS-1$ + rm.done(); + } else { + final List elements = getData(); + + final MultiRequestMonitor> multiRm = new MultiRequestMonitor>(getExecutor(), rm) { + @Override + protected void handleOK() { + boolean foundMatchingContext = false; + for (int i = 0; i < getRequestMonitors().size(); i++) { + if (getRequestMonitors().get(i).getData()) { + rm.setData(elements.get(i)); + foundMatchingContext = true; + break; + } + } + if (!foundMatchingContext) { + rm.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Context not found", null)); //$NON-NLS-1$ + } + rm.done(); + } + }; + + for (Object element : elements) { + testContextForExpression( + element, expressionPartText, + multiRm.add( + new DataRequestMonitor(getExecutor(), null) { + @Override + protected void handleCompleted() { + multiRm.requestMonitorDone(this); + } + })); + } + } + } + + @Override + protected void handleErrorOrCancel() { + update.setStatus(getStatus()); + update.done(); + } + }) + ); + } + + + @ConfinedToDsfExecutor("#getSession#getExecutor") + protected abstract void testContextForExpression(Object element, final String expression, final DataRequestMonitor rm); + protected abstract void associateExpression(Object element, IExpression expression); + + protected void getVMContextForExpressionFromChildNodes(final IChildrenUpdate update, Object parentElement, String childExpression, IExpression expression) { + IChildrenUpdate childUpdate = new ChildExpressionElementUpdate( + update, update.getElementPath().createChildPath(parentElement), + new DataRequestMonitor>(getExecutor(), null) { + @Override + protected void handleOK() { + update.setChild(getData().get(0), 0); + update.done(); + } + @Override + protected void handleErrorOrCancel() { + update.setStatus(getStatus()); + update.done(); + } + }); + + + for (int i = 0; i < getChildLayoutNodes().length; i++) { + if (getChildLayoutNodes()[i] instanceof IExpressionLayoutNode) { + IExpressionLayoutNode childNode = (IExpressionLayoutNode)getChildLayoutNodes()[i]; + if (childNode.getExpressionLength(childExpression) > 0) { + // The child node will call update.done(); + childNode.getElementForExpression(childUpdate, childExpression, expression); + return; + } + } + } + + // If we didn't find a matching child node in the for loop above, return an error. + update.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INTERNAL_ERROR, "Invalid expression", null)); //$NON-NLS-1$ + update.done(); + + } + + public int getDeltaFlagsForExpression(String expressionText, Object event) { + int exprLength = getExpressionLength(expressionText); + if (exprLength >= 0) { + if (exprLength == expressionText.length()) { + return getDeltaFlags(event); + } else { + int retVal = getDeltaFlagsForExpressionPart(event); + String childExpression = expressionText.substring(exprLength); + for (int i = 0; i < getChildLayoutNodes().length; i++) { + if (getChildLayoutNodes()[i] instanceof IExpressionLayoutNode) { + IExpressionLayoutNode exprNode = (IExpressionLayoutNode)getChildLayoutNodes()[i]; + if (exprNode.getExpressionLength(childExpression) > 0) { + // The child node will call update.done(); + retVal |= exprNode.getDeltaFlagsForExpression(childExpression, event); + } + } + } + return retVal; + } + } + + return IModelDelta.NO_CHANGE; + } + + protected abstract int getDeltaFlagsForExpressionPart(Object event); + + public void buildDeltaForExpression(final IExpression expression, final int elementIdx, final String expressionText, final Object event, final VMDelta parentDelta, final TreePath path, final RequestMonitor rm) + { + // Find the expression part that belong to this node. If expression + // is not recognized, do nothing. + final int exprLength = getExpressionLength(expressionText); + if (exprLength < 0) { + rm.done(); + return; + } + + final String nodeExpressionText = exprLength > 0 ? expressionText.substring(0, exprLength) : expressionText; + + getElementForExpressionPart( + new ElementsUpdate(new DataRequestMonitor>(getExecutor(), null), path), + nodeExpressionText, + new DataRequestMonitor(getExecutor(), null) { + @Override + protected void handleOK() { + if (exprLength == expressionText.length()) { + associateExpression(getData(), expression); + buildDeltaForExpressionElement(getData(), elementIdx, event, parentDelta, rm); + } else { + TreePath newPath = path.createChildPath(getData()); + callChildExpressionNodesToBuildDelta( + expression, elementIdx, expressionText.substring(exprLength), event, parentDelta, newPath, rm); + } + } + + @Override + protected void handleErrorOrCancel() { + // There is no matching element for given expression. That's OK, it just + // means that the expression is invalid. + rm.done(); + } + }); + } + + protected void buildDeltaForExpressionElement(Object element, int elementIdx, Object event, VMDelta parentDelta, final RequestMonitor rm) + { + // Find the child nodes that have deltas for the given event. + final Map childNodesWithDeltaFlags = getChildNodesWithDeltaFlags(event); + + // If no child layout nodes have deltas we can stop here. + if (childNodesWithDeltaFlags.size() == 0) { + rm.done(); + return; + } + + callChildNodesToBuildDelta( + childNodesWithDeltaFlags, parentDelta.addNode(element, elementIdx, IModelDelta.NO_CHANGE), event, rm); + } + + protected void callChildExpressionNodesToBuildDelta(IExpression expression, int elementIdx, String expressionRemainder, Object event, VMDelta parentDelta, TreePath path, final RequestMonitor rm) + { + final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), null) { + @Override + protected void handleCompleted() { + rm.done(); + } + }; + + int childRmCount = 0; + + for (int i = 0; i < getChildLayoutNodes().length; i++) { + if (getChildLayoutNodes()[i] instanceof IExpressionLayoutNode) { + IExpressionLayoutNode childNode = (IExpressionLayoutNode)getChildLayoutNodes()[i]; + if (childNode.getExpressionLength(expressionRemainder) > 0 && + childNode.getDeltaFlagsForExpression(expressionRemainder, event) != IModelDelta.NO_CHANGE) + { + childNode.buildDeltaForExpression( + expression, elementIdx, expressionRemainder, event, parentDelta, path, rm); + childRmCount++; + // The child node will call update.done(); + } + } + } + + if (childRmCount > 0) { + countingRm.setCount(childRmCount); + } else { + countingRm.done(); + } + } + + + class ChildExpressionElementUpdate extends VMElementsUpdate { + private final TreePath fPath; + + ChildExpressionElementUpdate(IChildrenUpdate clientUpdate, TreePath path, DataRequestMonitor> rm) { + super(clientUpdate, 0, 1, rm); + fPath = path; + } + + @Override + public Object getElement() { + return fPath.getLastSegment(); + } + + @Override + public TreePath getElementPath() { + return fPath; + } + } +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/ExpressionColumnPresentation.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/ExpressionColumnPresentation.java new file mode 100644 index 00000000000..b2945554a57 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/ExpressionColumnPresentation.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * 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.expression; + +import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin; +import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants; +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; + +/** + * + */ +@SuppressWarnings("restriction") +public class ExpressionColumnPresentation implements IColumnPresentation { + + public static final String ID = DsfDebugUIPlugin.PLUGIN_ID + ".REGISTERS_COLUMN_PRESENTATION_ID"; //$NON-NLS-1$ + + public void init(IPresentationContext context) { + } + + public void dispose() { + } + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getAvailableColumns() + public String[] getAvailableColumns() { + return new String[] { IDebugVMConstants.COLUMN_ID__EXPRESSION, IDebugVMConstants.COLUMN_ID__NAME, IDebugVMConstants.COLUMN_ID__TYPE, IDebugVMConstants.COLUMN_ID__VALUE, IDebugVMConstants.COLUMN_ID__DESCRIPTION, }; + } + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getHeader(java.lang.String) + public String getHeader(String id) { + if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(id)) { + return MessagesForExpressionVM.ExpressionColumnPresentation_expression; + } else if (IDebugVMConstants.COLUMN_ID__NAME.equals(id)) { + return MessagesForExpressionVM.ExpressionColumnPresentation_name; + } else if (IDebugVMConstants.COLUMN_ID__TYPE.equals(id)) { + return MessagesForExpressionVM.ExpressionColumnPresentation_type; + } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(id)) { + return MessagesForExpressionVM.ExpressionColumnPresentation_value; + } else if (IDebugVMConstants.COLUMN_ID__DESCRIPTION.equals(id)) { + return MessagesForExpressionVM.ExpressionColumnPresentation_description; + } + return null; + } + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getId() + public String getId() { + return ID; + } + + public ImageDescriptor getImageDescriptor(String id) { + return null; + } + + + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getInitialColumns() + public String[] getInitialColumns() { + return new String[] { IDebugVMConstants.COLUMN_ID__EXPRESSION, IDebugVMConstants.COLUMN_ID__VALUE }; + } + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#isOptional() + public boolean isOptional() { + return true; + } + +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/ExpressionManagerLayoutNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/ExpressionManagerLayoutNode.java new file mode 100644 index 00000000000..f8adf60a30b --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/ExpressionManagerLayoutNode.java @@ -0,0 +1,293 @@ +/******************************************************************************* + * 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.expression; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.dd.dsf.concurrent.CountingRequestMonitor; +import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; +import org.eclipse.dd.dsf.concurrent.RequestMonitor; +import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants; +import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.ExpressionVMProvider.ExpressionsChangedEvent; +import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMLayoutNode; +import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider; +import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode; +import org.eclipse.dd.dsf.ui.viewmodel.VMDelta; +import org.eclipse.dd.dsf.ui.viewmodel.VMElementsUpdate; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.IExpressionManager; +import org.eclipse.debug.core.model.IExpression; +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.IElementEditor; +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.IPresentationContext; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.IDebugUIConstants; +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.ICellModifier; +import org.eclipse.jface.viewers.TextCellEditor; +import org.eclipse.swt.widgets.Composite; + +@SuppressWarnings("restriction") +public class ExpressionManagerLayoutNode extends AbstractVMLayoutNode + implements IElementLabelProvider, IElementEditor +{ + + private class InvalidExpressionVMC extends AbstractVMContext { + final IExpression fExpression; + + public InvalidExpressionVMC(IExpression expression) { + super(getVMProvider().getVMAdapter(), ExpressionManagerLayoutNode.this); + fExpression = expression; + } + + @Override + @SuppressWarnings("unchecked") + public Object getAdapter(Class adapter) { + if (adapter.isAssignableFrom(fExpression.getClass())) { + return fExpression; + } else { + return super.getAdapter(adapter); + } + } + + @Override + public boolean equals(Object obj) { + return obj instanceof InvalidExpressionVMC && ((InvalidExpressionVMC)obj).fExpression.equals(fExpression); + } + + @Override + public int hashCode() { + return fExpression.hashCode(); + } + } + + private IExpressionLayoutNode[] fExpressionNodes = new IExpressionLayoutNode[0]; + private IExpressionManager fManager = DebugPlugin.getDefault().getExpressionManager(); + private WatchExpressionCellModifier fWatchExpressionCellModifier = new WatchExpressionCellModifier(); + + public ExpressionManagerLayoutNode(AbstractVMProvider provider) { + super(provider); + } + + public void updateHasElements(IHasChildrenUpdate[] updates) { + for (int i = 0; i < updates.length; i++) { + updates[i].setHasChilren(fManager.getExpressions().length != 0); + updates[i].done(); + } + } + + public void updateElementCount(IChildrenCountUpdate update) { + update.setChildCount(fManager.getExpressions().length); + update.done(); + } + + public void updateElements(final IChildrenUpdate update) { + final IExpression[] expressions = fManager.getExpressions(); + + final CountingRequestMonitor multiRm = new CountingRequestMonitor(getExecutor(), null) { + @Override + protected void handleCompleted() { + update.done(); + } + }; + + int expressionRmCount = 0; + + for (int i = update.getOffset(); i < update.getOffset() + update.getLength() && i < expressions.length; i++) { + + // Check the array boundries as the expression manager could change asynchronously. + // The expression manager change should lead to a refresh in the view. + if (i > expressions.length) { + continue; + } + + final String expressionText = expressions[i].getExpressionText(); + final int expressionIdx = i; + final IExpression expression = expressions[i]; + IExpressionLayoutNode expressionNode = findNodeForExpression(expressionText); + if (expressionNode == null) { + update.setChild(new InvalidExpressionVMC(expression), i); + } else { + expressionRmCount++; + VMElementsUpdate expressionElementUpdate = new VMElementsUpdate( + update, 0, 1, + new DataRequestMonitor>(getExecutor(), multiRm) { + @Override + protected void handleOK() { + update.setChild(getData().get(0), expressionIdx); + multiRm.done(); + } + + @Override + protected void handleError() { + update.setChild(new InvalidExpressionVMC(expression), expressionIdx); + multiRm.done(); + } + }); + expressionNode.getElementForExpression(expressionElementUpdate, expressionText, expression); + } + } + + if (expressionRmCount > 0) { + multiRm.setCount(expressionRmCount); + } else { + multiRm.done(); + } + } + + public void update(ILabelUpdate[] updates) { + for (ILabelUpdate update : updates) { + if (update.getElement() instanceof InvalidExpressionVMC) { + updateInvalidExpressionVMCLabel(update, (InvalidExpressionVMC) update.getElement()); + } else { + update.done(); + } + } + } + + private void updateInvalidExpressionVMCLabel(ILabelUpdate update, InvalidExpressionVMC vmc) { + String[] columnIds = update.getColumnIds() != null ? + update.getColumnIds() : new String[] { IDebugVMConstants.COLUMN_ID__NAME }; + + for (int i = 0; i < columnIds.length; i++) { + if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(columnIds[i])) { + update.setLabel(vmc.fExpression.getExpressionText(), i); + update.setImageDescriptor(DebugUITools.getImageDescriptor( IDebugUIConstants.IMG_OBJS_EXPRESSION ), i); + } else if (IDebugVMConstants.COLUMN_ID__NAME.equals(columnIds[i])) { + update.setLabel(vmc.fExpression.getExpressionText(), i); + update.setImageDescriptor(DebugUITools.getImageDescriptor( IDebugUIConstants.IMG_OBJS_EXPRESSION ), i); + } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(columnIds[i])) { + update.setLabel(MessagesForExpressionVM.ExpressionManagerLayoutNode__invalidExpression_valueColumn_label, i); + } else { + update.setLabel("", i); //$NON-NLS-1$ + } + } + + + update.done(); + } + + private IExpressionLayoutNode findNodeForExpression(String expressionText) { + for (IExpressionLayoutNode node : fExpressionNodes) { + if (node.getExpressionLength(expressionText) > 0) { + return node; + } + } + return null; + } + + @Override + public void setChildNodes(IVMLayoutNode[] childNodes) { + throw new UnsupportedOperationException("This node does not support children."); //$NON-NLS-1$ + } + + public void setExpressionLayoutNodes(IExpressionLayoutNode[] nodes) { + fExpressionNodes = nodes; + } + + @Override + public void dispose() { + + for (IExpressionLayoutNode exprNode : fExpressionNodes) { + exprNode.dispose(); + } + super.dispose(); + } + + /** + * If any of the children nodes have delta flags, that means that this + * node has to generate a delta as well. + */ + @Override + public int getDeltaFlags(Object event) { + int retVal = 0; + + // Add a flag if the list of expressions has changed. + if (event instanceof ExpressionsChangedEvent) { + retVal |= IModelDelta.CONTENT; + } + + for (IExpressionLayoutNode node : fExpressionNodes) { + retVal |= node.getDeltaFlags(event); + } + + return retVal; + } + + @Override + public void buildDelta(final Object event, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor requestMonitor) { + // Add a flag if the list of expressions has changed. + if (event instanceof ExpressionsChangedEvent) { + parentDelta.addFlags(IModelDelta.CONTENT); + } + + CountingRequestMonitor multiRm = new CountingRequestMonitor(getExecutor(), requestMonitor); + int buildDeltaForExpressionCallCount = 0; + + IExpression[] expressions = fManager.getExpressions(); + for (int i = 0; i < expressions.length; i++ ) { + String expressionText = expressions[i].getExpressionText(); + IExpressionLayoutNode node = findNodeForExpression(expressionText); + if (node == null) continue; + + int flags = node.getDeltaFlagsForExpression(expressionText, event); + + // If the given node has no delta flags, skip it. + if (flags == IModelDelta.NO_CHANGE) continue; + + node.buildDeltaForExpression(expressions[i], i + nodeOffset, expressionText, event, parentDelta, + getTreePathFromDelta(parentDelta), + new RequestMonitor(getExecutor(), multiRm)); + buildDeltaForExpressionCallCount++; + } + + if (buildDeltaForExpressionCallCount != 0) { + multiRm.setCount(buildDeltaForExpressionCallCount); + } else { + requestMonitor.done(); + } + } + + /** + * Convenience method that returns the child layout nodes which return + * true to the hasDeltaFlags() test for the given + * event. + */ + protected Map getExpressionsWithDeltaFlags(String expressionText, Object e) { + Map nodes = new HashMap(); + for (final IExpressionLayoutNode node : fExpressionNodes) { + int delta = node.getDeltaFlagsForExpression(expressionText, e); + if (delta != IModelDelta.NO_CHANGE) { + nodes.put(node, delta); + } + } + return nodes; + } + + + public CellEditor getCellEditor(IPresentationContext context, String columnId, Object element, Composite parent) { + if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(columnId)) { + return new TextCellEditor(parent); + } + return null; + } + + public ICellModifier getCellModifier(IPresentationContext context, Object element) { + return fWatchExpressionCellModifier; + } +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/ExpressionVMProvider.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/ExpressionVMProvider.java new file mode 100644 index 00000000000..2348cc3c41a --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/ExpressionVMProvider.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * 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.expression; + +import org.eclipse.dd.dsf.debug.ui.viewmodel.DebugViewSelectionRootLayoutNode; +import org.eclipse.dd.dsf.debug.ui.viewmodel.register.RegisterGroupLayoutNode; +import org.eclipse.dd.dsf.debug.ui.viewmodel.register.RegisterLayoutNode; +import org.eclipse.dd.dsf.debug.ui.viewmodel.register.SyncRegisterDataAccess; +import org.eclipse.dd.dsf.service.DsfSession; +import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMAdapter; +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.dm.AbstractDMVMProvider; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.IExpressionsListener; +import org.eclipse.debug.core.model.IExpression; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; + +/** + * + */ +@SuppressWarnings("restriction") +public class ExpressionVMProvider extends AbstractDMVMProvider + implements IExpressionsListener +{ + public static class ExpressionsChangedEvent { + enum Type {ADDED, CHANGED, REMOVED} + public final Type fType; + public final IExpression[] fExpressions; + public ExpressionsChangedEvent(Type type, IExpression[] expressions) { + fType = type; + fExpressions = expressions; + } + } + + public ExpressionVMProvider(AbstractVMAdapter adapter, IPresentationContext context, DsfSession session) { + super(adapter, context, session); + + // The VM provider has to handle all events that result in model deltas. + // Add the provider as listener to expression changes events. + DebugPlugin.getDefault().getExpressionManager().addExpressionListener(this); + + configureLayout(); + } + + protected void configureLayout() { + SyncRegisterDataAccess syncDataAccess = new SyncRegisterDataAccess(); + + // Configure the layout nodes + IVMRootLayoutNode debugViewSelectionNode = new DebugViewSelectionRootLayoutNode(this); + ExpressionManagerLayoutNode expressionManagerNode = new ExpressionManagerLayoutNode(this); + debugViewSelectionNode.setChildNodes(new IVMLayoutNode[] {expressionManagerNode}); + IExpressionLayoutNode registerGroupNode = new RegisterGroupLayoutNode(this, getSession(), syncDataAccess); + expressionManagerNode.setExpressionLayoutNodes(new IExpressionLayoutNode[] { registerGroupNode }); + IVMLayoutNode registerNode = new RegisterLayoutNode(this, getSession(), syncDataAccess); + registerGroupNode.setChildNodes(new IVMLayoutNode[] { registerNode }); + setRootLayoutNode(debugViewSelectionNode); + } + + @Override + public void dispose() { + DebugPlugin.getDefault().getExpressionManager().removeExpressionListener(this); + super.dispose(); + } + + @Override + public IColumnPresentation createColumnPresentation(IPresentationContext context, Object element) { + return new ExpressionColumnPresentation(); + } + + @Override + public String getColumnPresentationId(IPresentationContext context, Object element) { + return ExpressionColumnPresentation.ID; + } + + /** + * Override this operation to avoid the standard test of isOurLayoutNode(), + * which does not take into account {@link ExpressionManagerLayoutNode.setExpressionLayoutNodes} + * nodes. + */ + @Override + protected IVMLayoutNode getLayoutNodeForElement(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){ + return ((IVMContext)element).getLayoutNode(); + } + return null; + } + + public void expressionsAdded(IExpression[] expressions) { + handleEvent(new ExpressionsChangedEvent(ExpressionsChangedEvent.Type.ADDED, expressions)); + } + + public void expressionsChanged(IExpression[] expressions) { + handleEvent(new ExpressionsChangedEvent(ExpressionsChangedEvent.Type.CHANGED, expressions)); + } + + public void expressionsRemoved(IExpression[] expressions) { + handleEvent(new ExpressionsChangedEvent(ExpressionsChangedEvent.Type.REMOVED, expressions)); + } +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/IExpressionLayoutNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/IExpressionLayoutNode.java new file mode 100644 index 00000000000..ea30c602a42 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/IExpressionLayoutNode.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2007 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.expression; + +import org.eclipse.dd.dsf.concurrent.RequestMonitor; +import org.eclipse.dd.dsf.ui.viewmodel.IVMLayoutNode; +import org.eclipse.dd.dsf.ui.viewmodel.VMDelta; +import org.eclipse.debug.core.model.IExpression; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; +import org.eclipse.jface.viewers.TreePath; + +/** + * + */ +@SuppressWarnings("restriction") +public interface IExpressionLayoutNode extends IVMLayoutNode { + int getExpressionLength(String expression); + void getElementForExpression(IChildrenUpdate update, String expressionText, IExpression expression); + + int getDeltaFlagsForExpression(String expressionText, Object event); + void buildDeltaForExpression(IExpression expression, int elementIdx, String expressionText, Object event, + VMDelta parentDelta, TreePath path, RequestMonitor rm); +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/IExpressionVMContext.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/IExpressionVMContext.java new file mode 100644 index 00000000000..73d6a53f155 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/IExpressionVMContext.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2007 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.expression; + +import org.eclipse.dd.dsf.ui.viewmodel.IVMContext; + +/** + * + */ +public interface IExpressionVMContext extends IVMContext { +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/MessagesForExpressionVM.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/MessagesForExpressionVM.java new file mode 100644 index 00000000000..6b943864783 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/MessagesForExpressionVM.java @@ -0,0 +1,24 @@ +package org.eclipse.dd.dsf.debug.ui.viewmodel.expression; + +import org.eclipse.osgi.util.NLS; + +public class MessagesForExpressionVM extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.dd.dsf.debug.ui.viewmodel.expression.messages"; //$NON-NLS-1$ + + public static String ExpressionColumnPresentation_expression; + public static String ExpressionColumnPresentation_name; + public static String ExpressionColumnPresentation_type; + public static String ExpressionColumnPresentation_value; + public static String ExpressionColumnPresentation_description; + + public static String ExpressionManagerLayoutNode__invalidExpression_nameColumn_label; + public static String ExpressionManagerLayoutNode__invalidExpression_valueColumn_label; + + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, MessagesForExpressionVM.class); + } + + private MessagesForExpressionVM() { + } +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/WatchExpressionCellModifier.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/WatchExpressionCellModifier.java new file mode 100644 index 00000000000..a66ccef945f --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/WatchExpressionCellModifier.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * 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.expression; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.dd.dsf.concurrent.ThreadSafeAndProhibitedFromDsfExecutor; +import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants; +import org.eclipse.debug.core.model.IWatchExpression; +import org.eclipse.jface.viewers.ICellModifier; + +/** + * + */ +@SuppressWarnings("restriction") +@ThreadSafeAndProhibitedFromDsfExecutor("") +public class WatchExpressionCellModifier implements ICellModifier { + + /** + * Constructor for the modifier requires a valid DSF session in order to + * initialize the service tracker. + * @param session DSF session this modifier will use. + */ + public WatchExpressionCellModifier() { + } + + public boolean canModify(Object element, String property) { + return IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(property) && getWatchExpression(element) != null; + } + + public Object getValue(Object element, String property) { + if (!IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(property)) return ""; //$NON-NLS-1$ + + IWatchExpression expression = getWatchExpression(element); + + if (expression != null) { + return expression.getExpressionText(); + } + return ""; //$NON-NLS-1$ + } + + + public void modify(Object element, String property, Object value) { + if (!IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(property)) return; + + IWatchExpression expression = getWatchExpression(element); + if (expression != null && value instanceof String) { + expression.setExpressionText((String)value); + } + } + + private IWatchExpression getWatchExpression(Object element) { + if (element instanceof IAdaptable) { + return (IWatchExpression)((IAdaptable)element).getAdapter(IWatchExpression.class); + } + return null; + } + +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/WatchExpressionDelegate.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/WatchExpressionDelegate.java new file mode 100644 index 00000000000..0d0bd695dc7 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/WatchExpressionDelegate.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2007 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.expression; + +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.model.IDebugElement; +import org.eclipse.debug.core.model.IValue; +import org.eclipse.debug.core.model.IWatchExpressionDelegate; +import org.eclipse.debug.core.model.IWatchExpressionListener; +import org.eclipse.debug.core.model.IWatchExpressionResult; + +/** + * + */ +public class WatchExpressionDelegate implements IWatchExpressionDelegate { + public void evaluateExpression(final String expression, IDebugElement context, IWatchExpressionListener listener) { + listener.watchEvaluationFinished(new IWatchExpressionResult() { + public String[] getErrorMessages() { return new String[0]; } + public DebugException getException() { return null; } + public String getExpressionText() { return expression; } + public IValue getValue() { return null; } + public boolean hasErrors() { return false; } + }); + } +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/messages.properties b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/messages.properties new file mode 100644 index 00000000000..9c940b5d501 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/expression/messages.properties @@ -0,0 +1,7 @@ +ExpressionColumnPresentation_expression=Expression +ExpressionColumnPresentation_name=Name +ExpressionColumnPresentation_type=Type +ExpressionColumnPresentation_value=Value +ExpressionColumnPresentation_description=Description +ExpressionManagerLayoutNode__invalidExpression_nameColumn_label=Invalid expression +ExpressionManagerLayoutNode__invalidExpression_valueColumn_label=Invalid expression 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 d09e526a29b..6968cc8d6b6 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 @@ -12,8 +12,8 @@ package org.eclipse.dd.dsf.debug.ui.viewmodel.launch; import java.util.List; -import org.eclipse.dd.dsf.concurrent.RequestMonitor; import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; +import org.eclipse.dd.dsf.concurrent.RequestMonitor; import org.eclipse.dd.dsf.datamodel.IDMContext; import org.eclipse.dd.dsf.datamodel.IDMEvent; import org.eclipse.dd.dsf.debug.service.IRunControl; 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 e471686c7b4..38f3a669992 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 @@ -66,7 +66,7 @@ public class StandardLaunchRootLayoutNode extends AbstractVMRootLayoutNode return IModelDelta.NO_CHANGE; } else if (de.getSource() instanceof IDebugElement && - !((IDebugElement)de.getSource()).getLaunch().equals(fLaunch) ) + !fLaunch.equals(((IDebugElement)de.getSource()).getLaunch())) { return IModelDelta.NO_CHANGE; } 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 779980b0586..b7c15157661 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,6 +11,7 @@ package org.eclipse.dd.dsf.debug.ui.viewmodel.register; import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin; +import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants; 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; @@ -22,28 +23,25 @@ import org.eclipse.jface.resource.ImageDescriptor; public class RegisterColumnPresentation implements IColumnPresentation { public static final String ID = DsfDebugUIPlugin.PLUGIN_ID + ".REGISTERS_COLUMN_PRESENTATION_ID"; //$NON-NLS-1$ - public static final String COL_NAME = ID + ".COL_NAME"; //$NON-NLS-1$ - public static final String COL_VALUE = ID + ".COL_VALUE"; //$NON-NLS-1$ - public static final String COL_DESCRIPTION = ID + ".COL_DESCRIPTION"; //$NON-NLS-1$ - - // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#init(org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext) - public void init(IPresentationContext context) {} - // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#dispose() - public void dispose() {} + public void init(IPresentationContext context) { + } + + public void dispose() { + } // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getAvailableColumns() public String[] getAvailableColumns() { - return new String[] { COL_NAME, COL_VALUE, COL_DESCRIPTION }; + return new String[] { IDebugVMConstants.COLUMN_ID__NAME, IDebugVMConstants.COLUMN_ID__VALUE, IDebugVMConstants.COLUMN_ID__DESCRIPTION, }; } // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getHeader(java.lang.String) public String getHeader(String id) { - if (COL_NAME.equals(id)) { + if (IDebugVMConstants.COLUMN_ID__NAME.equals(id)) { return MessagesForRegisterVM.RegisterColumnPresentation_name; - } else if (COL_VALUE.equals(id)) { + } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(id)) { return MessagesForRegisterVM.RegisterColumnPresentation_value; - } else if (COL_DESCRIPTION.equals(id)) { + } else if (IDebugVMConstants.COLUMN_ID__DESCRIPTION.equals(id)) { return MessagesForRegisterVM.RegisterColumnPresentation_description; } return null; @@ -53,17 +51,18 @@ public class RegisterColumnPresentation implements IColumnPresentation { public String getId() { return ID; } - - // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getImageDescriptor(java.lang.String) + public ImageDescriptor getImageDescriptor(String id) { return null; - } + } + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getInitialColumns() public String[] getInitialColumns() { - return new String[] { COL_NAME, COL_VALUE }; + return new String[] { IDebugVMConstants.COLUMN_ID__NAME, IDebugVMConstants.COLUMN_ID__VALUE, IDebugVMConstants.COLUMN_ID__DESCRIPTION }; } - + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#isOptional() public boolean isOptional() { return true; 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 384e5fd7b69..2ad13d9885b 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,30 +10,144 @@ *******************************************************************************/ package org.eclipse.dd.dsf.debug.ui.viewmodel.register; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; import org.eclipse.dd.dsf.concurrent.RequestMonitor; +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.datamodel.IDMService; import org.eclipse.dd.dsf.debug.service.IRegisters; import org.eclipse.dd.dsf.debug.service.IRunControl; import org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterGroupDMContext; import org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterGroupDMData; import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin; +import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants; +import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.AbstractExpressionLayoutNode; +import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.WatchExpressionCellModifier; import org.eclipse.dd.dsf.service.DsfSession; +import org.eclipse.dd.dsf.service.IDsfService; 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.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.model.IDebugTarget; +import org.eclipse.debug.core.model.IExpression; +import org.eclipse.debug.core.model.IValue; +import org.eclipse.debug.core.model.IVariable; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementEditor; 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.IPresentationContext; +import org.eclipse.debug.ui.actions.IWatchExpressionFactoryAdapterExtension; +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.ICellModifier; +import org.eclipse.jface.viewers.TextCellEditor; +import org.eclipse.jface.viewers.TreePath; +import org.eclipse.swt.widgets.Composite; @SuppressWarnings("restriction") -public class RegisterGroupLayoutNode extends AbstractDMVMLayoutNode { +public class RegisterGroupLayoutNode extends AbstractExpressionLayoutNode + implements IElementEditor +{ - public RegisterGroupLayoutNode(AbstractVMProvider provider, DsfSession session) { - super(provider, session, IRegisters.IRegisterGroupDMContext.class); + protected class RegisterGroupVMC extends DMVMContext + implements IVariable + { + private IExpression fExpression; + public RegisterGroupVMC(IDMContext dmc) { + super(dmc); + } + + public void setExpression(IExpression expression) { + fExpression = expression; + } + + @Override + @SuppressWarnings("unchecked") + public Object getAdapter(Class adapter) { + if (fExpression != null && adapter.isAssignableFrom(fExpression.getClass())) { + return fExpression; + } else if (adapter.isAssignableFrom(IWatchExpressionFactoryAdapterExtension.class)) { + return fRegisterGroupExpressionFactory; + } else { + return super.getAdapter(adapter); + } + } + + @Override + public boolean equals(Object other) { + if (other instanceof RegisterGroupVMC && super.equals(other)) { + RegisterGroupVMC otherGroup = (RegisterGroupVMC)other; + return (otherGroup.fExpression == null && fExpression == null) || + (otherGroup.fExpression != null && otherGroup.fExpression.equals(fExpression)); + } + return false; + } + + @Override + public int hashCode() { + return super.hashCode() + (fExpression != null ? fExpression.hashCode() : 0); + } + + public String getName() throws DebugException { return toString(); } + public String getReferenceTypeName() throws DebugException { return ""; } //$NON-NLS-1$ + public IValue getValue() throws DebugException { return null; } + public boolean hasValueChanged() throws DebugException { return false; } + public void setValue(IValue value) throws DebugException {} + public void setValue(String expression) throws DebugException {} + public boolean supportsValueModification() { return false; } + public boolean verifyValue(IValue value) throws DebugException { return false; } + public boolean verifyValue(String expression) throws DebugException { return false; } + public IDebugTarget getDebugTarget() { return null;} + public ILaunch getLaunch() { return null; } + public String getModelIdentifier() { return DsfDebugUIPlugin.PLUGIN_ID; } } + protected class RegisterGroupExpressionFactory implements IWatchExpressionFactoryAdapterExtension { + + public boolean canCreateWatchExpression(IVariable variable) { + return variable instanceof RegisterGroupVMC; + } + + public String createWatchExpression(IVariable variable) throws CoreException { + RegisterGroupVMC registerVmc = ((RegisterGroupVMC)variable); + + StringBuffer exprBuf = new StringBuffer(); + IRegisterGroupDMContext groupDmc = + DMContexts.getAncestorOfType(registerVmc.getDMC(), IRegisterGroupDMContext.class); + IRegisterGroupDMData groupData = fSyncRegisterDataAccess.readRegisterGroup(groupDmc); + if (groupData != null) { + exprBuf.append("$$\""); //$NON-NLS-1$ + exprBuf.append(groupData.getName()); + exprBuf.append('"'); + return exprBuf.toString(); + } + + return null; + } + } + + final private SyncRegisterDataAccess fSyncRegisterDataAccess; + final protected RegisterGroupExpressionFactory fRegisterGroupExpressionFactory = new RegisterGroupExpressionFactory(); + private WatchExpressionCellModifier fWatchExpressionCellModifier = new WatchExpressionCellModifier(); + + public RegisterGroupLayoutNode(AbstractVMProvider provider, DsfSession session, SyncRegisterDataAccess syncDataAccess) { + super(provider, session, IRegisters.IRegisterGroupDMContext.class); + fSyncRegisterDataAccess = syncDataAccess; + } + + protected SyncRegisterDataAccess getSyncRegisterDataAccess() { + return fSyncRegisterDataAccess; + } + + @Override protected void updateElementsInSessionThread(final IChildrenUpdate update) { if (!checkService(IRegisters.class, null, update)) return; @@ -59,16 +173,30 @@ public class RegisterGroupLayoutNode extends AbstractDMVMLayoutNode dmc) { + return new RegisterGroupVMC(dmc); + } + + @Override protected void fillColumnLabel(IDMContext dmContext, IRegisterGroupDMData dmData, String columnId, int idx, ILabelUpdate update) { - if (RegisterColumnPresentation.COL_NAME.equals(columnId)) { + if (IDebugVMConstants.COLUMN_ID__NAME.equals(columnId)) { update.setLabel(dmData.getName(), idx); - } else if (RegisterColumnPresentation.COL_VALUE.equals(columnId)) { + } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(columnId)) { update.setLabel("", idx); //$NON-NLS-1$ - } else if (RegisterColumnPresentation.COL_DESCRIPTION.equals(columnId)) { + } else if (IDebugVMConstants.COLUMN_ID__DESCRIPTION.equals(columnId)) { update.setLabel(dmData.getDescription(), idx); + } else if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(columnId)) { + IVMContext vmc = (IVMContext)update.getElement(); + IExpression expression = (IExpression)vmc.getAdapter(IExpression.class); + if (expression != null) { + update.setLabel(expression.getExpressionText(), idx); + } else { + update.setLabel(dmData.getName(), idx); + } } } @@ -89,9 +217,100 @@ public class RegisterGroupLayoutNode extends AbstractDMVMLayoutNode 0) { + return secondQuoteIdx + 1; + } + } + return -1; + } + + @Override + protected int getDeltaFlagsForExpressionPart(Object event) { + if (event instanceof IRunControl.ISuspendedDMEvent) { + return IModelDelta.CONTENT; + } + + return IModelDelta.NO_CHANGE; + } + + @Override + public void buildDeltaForExpression(final IExpression expression, final int elementIdx, final String expressionText, final Object event, final VMDelta parentDelta, final TreePath path, final RequestMonitor rm) + { + if (event instanceof IRunControl.ISuspendedDMEvent) { + // Mark the partent delta indicating that elements were added and/or removed. + parentDelta.addFlags(IModelDelta.CONTENT); + } + + super.buildDeltaForExpression(expression, elementIdx, expressionText, event, parentDelta, path, rm); + } + + @Override + protected void buildDeltaForExpressionElement(Object element, int elementIdx, Object event, VMDelta parentDelta, final RequestMonitor rm) + { + if (event instanceof IRegisters.IRegistersChangedDMEvent) { + parentDelta.addNode(element, IModelDelta.STATE); + } + + super.buildDeltaForExpressionElement(element, elementIdx, event, parentDelta, rm); + } + + @Override + protected void testContextForExpression(Object element, final String expression, final DataRequestMonitor rm) { + if (!(element instanceof AbstractDMVMLayoutNode.DMVMContext)) { + rm.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + return; + } + final IRegisterGroupDMContext dmc = DMContexts.getAncestorOfType(((DMVMContext)element).getDMC(), IRegisterGroupDMContext.class); + if (dmc == null) { + rm.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + return; + } + + ((IDMService)getServicesTracker().getService(null, dmc.getServiceFilter())).getModelData( + dmc, + new DataRequestMonitor(getSession().getExecutor(), rm) { + @Override + protected void handleOK() { + int startIdx = "$$\"".length(); //$NON-NLS-1$ + int endIdx = expression.indexOf('"', startIdx); + String groupName = expression.substring(startIdx, endIdx); + if (groupName.equals(getData().getName())) { + rm.setData(Boolean.TRUE); + } else { + rm.setData(Boolean.FALSE); + } + rm.done(); + } + }); + } + + @Override + protected void associateExpression(Object element, IExpression expression) { + if (element instanceof RegisterGroupVMC) { + ((RegisterGroupVMC)element).setExpression(expression); + } + } + + public CellEditor getCellEditor(IPresentationContext context, String columnId, Object element, Composite parent) { + if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(columnId)) { + return new TextCellEditor(parent); + } + return null; + } + + public ICellModifier getCellModifier(IPresentationContext context, Object element) { + return fWatchExpressionCellModifier; + } + } 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 77c05d42d19..0f55510b8b0 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 @@ -10,8 +10,13 @@ *******************************************************************************/ package org.eclipse.dd.dsf.debug.ui.viewmodel.register; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; import org.eclipse.dd.dsf.concurrent.RequestMonitor; +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.datamodel.IDMService; import org.eclipse.dd.dsf.debug.service.IFormattedValues; @@ -23,20 +28,137 @@ import org.eclipse.dd.dsf.debug.service.IRegisters.IRegisterChangedDMEvent; 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.debug.service.IRegisters.IRegisterGroupDMData; +import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin; +import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants; +import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.AbstractExpressionLayoutNode; +import org.eclipse.dd.dsf.debug.ui.viewmodel.expression.WatchExpressionCellModifier; import org.eclipse.dd.dsf.service.DsfSession; import org.eclipse.dd.dsf.service.IDsfService; 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.dd.dsf.ui.viewmodel.dm.AbstractDMVMLayoutNode; +import org.eclipse.debug.core.DebugException; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.model.IDebugTarget; +import org.eclipse.debug.core.model.IExpression; +import org.eclipse.debug.core.model.IValue; +import org.eclipse.debug.core.model.IVariable; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementEditor; 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.IPresentationContext; +import org.eclipse.debug.ui.actions.IWatchExpressionFactoryAdapterExtension; +import org.eclipse.jface.viewers.CellEditor; +import org.eclipse.jface.viewers.ICellModifier; +import org.eclipse.jface.viewers.TextCellEditor; +import org.eclipse.jface.viewers.TreePath; +import org.eclipse.swt.widgets.Composite; @SuppressWarnings("restriction") -public class RegisterLayoutNode extends AbstractDMVMLayoutNode { +public class RegisterLayoutNode extends AbstractExpressionLayoutNode + implements IElementEditor +{ + protected class RegisterVMC extends DMVMContext + implements IVariable + { + private IExpression fExpression; + public RegisterVMC(IDMContext dmc) { + super(dmc); + } + + public void setExpression(IExpression expression) { + fExpression = expression; + } + + @Override + @SuppressWarnings("unchecked") + public Object getAdapter(Class adapter) { + if (fExpression != null && adapter.isAssignableFrom(fExpression.getClass())) { + return fExpression; + } else if (adapter.isAssignableFrom(IWatchExpressionFactoryAdapterExtension.class)) { + return fRegisterExpressionFactory; + } else { + return super.getAdapter(adapter); + } + } - public RegisterLayoutNode(AbstractVMProvider provider, DsfSession session) { + @Override + public boolean equals(Object other) { + if (other instanceof RegisterVMC && super.equals(other)) { + RegisterVMC otherReg = (RegisterVMC)other; + return (otherReg.fExpression == null && fExpression == null) || + (otherReg.fExpression != null && otherReg.fExpression.equals(fExpression)); + } + return false; + } + + @Override + public int hashCode() { + return super.hashCode() + (fExpression != null ? fExpression.hashCode() : 0); + } + + public String getName() throws DebugException { return toString(); } + public String getReferenceTypeName() throws DebugException { return ""; } //$NON-NLS-1$ + public IValue getValue() throws DebugException { return null; } + public boolean hasValueChanged() throws DebugException { return false; } + public void setValue(IValue value) throws DebugException {} + public void setValue(String expression) throws DebugException {} + public boolean supportsValueModification() { return false; } + public boolean verifyValue(IValue value) throws DebugException { return false; } + public boolean verifyValue(String expression) throws DebugException { return false; } + public IDebugTarget getDebugTarget() { return null;} + public ILaunch getLaunch() { return null; } + public String getModelIdentifier() { return DsfDebugUIPlugin.PLUGIN_ID; } + } + + protected class RegisterExpressionFactory implements IWatchExpressionFactoryAdapterExtension { + + public boolean canCreateWatchExpression(IVariable variable) { + return variable instanceof RegisterVMC; + } + + public String createWatchExpression(IVariable variable) throws CoreException { + RegisterVMC registerVmc = ((RegisterVMC)variable); + + StringBuffer exprBuf = new StringBuffer(); + IRegisterGroupDMContext groupDmc = + DMContexts.getAncestorOfType(registerVmc.getDMC(), IRegisterGroupDMContext.class); + if (groupDmc != null) { + IRegisterGroupDMData groupData = fSyncRegisterDataAccess.readRegisterGroup(groupDmc); + if (groupData != null) { + exprBuf.append("$$\""); //$NON-NLS-1$ + exprBuf.append(groupData.getName()); + exprBuf.append('"'); + } + } + + IRegisterDMContext registerDmc = + DMContexts.getAncestorOfType(registerVmc.getDMC(), IRegisterDMContext.class); + IRegisterDMData regData = fSyncRegisterDataAccess.readRegister(registerDmc); + if (regData != null) { + exprBuf.append('$'); + exprBuf.append(regData.getName()); + return exprBuf.toString(); + } + + return null; + } + } + + private WatchExpressionCellModifier fWatchExpressionCellModifier = new WatchExpressionCellModifier(); + final protected RegisterExpressionFactory fRegisterExpressionFactory = new RegisterExpressionFactory(); + final private SyncRegisterDataAccess fSyncRegisterDataAccess; + + public RegisterLayoutNode(AbstractVMProvider provider, DsfSession session, SyncRegisterDataAccess syncDataAccess) { super(provider, session, IRegisters.IRegisterDMContext.class); + fSyncRegisterDataAccess = syncDataAccess; + } + + protected SyncRegisterDataAccess getSyncRegisterDataAccess() { + return fSyncRegisterDataAccess; } /** @@ -177,12 +299,20 @@ public class RegisterLayoutNode extends AbstractDMVMLayoutNode boolean weAreExtractingFormattedData = false; for (int idx = 0; idx < localColumns.length; idx++) { - if (RegisterColumnPresentation.COL_NAME.equals(localColumns[idx])) { + if (IDebugVMConstants.COLUMN_ID__NAME.equals(localColumns[idx])) { update.setLabel(getData().getName(), idx); - } else if (RegisterColumnPresentation.COL_VALUE.equals(localColumns[idx])) { + } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(localColumns[idx])) { weAreExtractingFormattedData = true; - } else if (RegisterColumnPresentation.COL_DESCRIPTION.equals(localColumns[idx])) { + } else if (IDebugVMConstants.COLUMN_ID__DESCRIPTION.equals(localColumns[idx])) { update.setLabel(getData().getDescription(), idx); + } else if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(localColumns[idx])) { + IVMContext vmc = (IVMContext)update.getElement(); + IExpression expression = (IExpression)vmc.getAdapter(IExpression.class); + if (expression != null) { + update.setLabel(expression.getExpressionText(), idx); + } else { + update.setLabel(getData().getName(), idx); //$NON-NLS-1$ + } } } @@ -190,7 +320,7 @@ public class RegisterLayoutNode extends AbstractDMVMLayoutNode update.done(); } else { for (int idx = 0; idx < localColumns.length; idx++) { - if (RegisterColumnPresentation.COL_VALUE.equals(localColumns[idx])) { + if (IDebugVMConstants.COLUMN_ID__VALUE.equals(localColumns[idx])) { updateFormattedRegisterValue(update, idx, dmc); } } @@ -225,6 +355,11 @@ public class RegisterLayoutNode extends AbstractDMVMLayoutNode }); } + @Override + protected IVMContext createVMContext(IDMContext dmc) { + return new RegisterVMC(dmc); + } + @Override protected int getNodeDeltaFlagsForDMEvent(IDMEvent e) { if (e instanceof IRunControl.ISuspendedDMEvent) { @@ -247,4 +382,95 @@ public class RegisterLayoutNode extends AbstractDMVMLayoutNode super.buildDeltaForDMEvent(e, parent, nodeOffset, rm); } + + public int getExpressionLength(String expression) { + if (expression.charAt(0) == '$' && Character.isLetterOrDigit(expression.charAt(1))) { + int length = 1; + while( length < expression.length() && Character.isLetterOrDigit(expression.charAt(length)) ) { + length++; + } + return length; + } else { + return -1; + } + } + + @Override + protected void testContextForExpression(Object element, final String expression, final DataRequestMonitor rm) { + if (!(element instanceof AbstractDMVMLayoutNode.DMVMContext)) { + rm.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + return; + } + final IRegisterDMContext dmc = DMContexts.getAncestorOfType(((DMVMContext)element).getDMC(), IRegisterDMContext.class); + if (dmc == null) { + rm.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + return; + } + + ((IDMService)getServicesTracker().getService(null, dmc.getServiceFilter())).getModelData( + dmc, + new DataRequestMonitor(getSession().getExecutor(), rm) { + @Override + protected void handleOK() { + String regName = expression.substring(1); + if (regName.equals(getData().getName())) { + rm.setData(Boolean.TRUE); + } else { + rm.setData(Boolean.FALSE); + } + rm.done(); + } + }); + } + + @Override + protected void associateExpression(Object element, IExpression expression) { + if (element instanceof RegisterVMC) { + ((RegisterVMC)element).setExpression(expression); + } + } + + @Override + protected int getDeltaFlagsForExpressionPart(Object event) { + if (event instanceof IRunControl.ISuspendedDMEvent) { + return IModelDelta.CONTENT; + } + + return IModelDelta.NO_CHANGE; + } + + @Override + public void buildDeltaForExpression(final IExpression expression, final int elementIdx, final String expressionText, final Object event, final VMDelta parentDelta, final TreePath path, final RequestMonitor rm) + { + if (event instanceof IRunControl.ISuspendedDMEvent) { + // Mark the partent delta indicating that elements were added and/or removed. + parentDelta.addFlags(IModelDelta.CONTENT); + } + + super.buildDeltaForExpression(expression, elementIdx, expressionText, event, parentDelta, path, rm); + } + + @Override + protected void buildDeltaForExpressionElement(Object element, int elementIdx, Object event, VMDelta parentDelta, final RequestMonitor rm) + { + if (event instanceof IRegisters.IRegisterChangedDMEvent) { + parentDelta.addNode(element, IModelDelta.STATE); + } + + super.buildDeltaForExpressionElement(element, elementIdx, event, parentDelta, rm); + } + + + public CellEditor getCellEditor(IPresentationContext context, String columnId, Object element, Composite parent) { + if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(columnId)) { + return new TextCellEditor(parent); + } + return null; + } + + public ICellModifier getCellModifier(IPresentationContext context, Object element) { + return fWatchExpressionCellModifier; + } } 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 f40284a2fc2..11bad015335 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 @@ -23,13 +23,17 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationCont * */ @SuppressWarnings("restriction") -public class RegisterVMProvider extends AbstractDMVMProvider { +public class RegisterVMProvider extends AbstractDMVMProvider +{ public RegisterVMProvider(AbstractVMAdapter adapter, IPresentationContext context, DsfSession session) { super(adapter, context, session); + + SyncRegisterDataAccess syncDataAccess = new SyncRegisterDataAccess(); + IVMRootLayoutNode debugViewSelection = new DebugViewSelectionRootLayoutNode(this); - IVMLayoutNode registerGroupNode = new RegisterGroupLayoutNode(this, getSession()); + IVMLayoutNode registerGroupNode = new RegisterGroupLayoutNode(this, getSession(), syncDataAccess); debugViewSelection.setChildNodes(new IVMLayoutNode[] { registerGroupNode }); - IVMLayoutNode registerNode = new RegisterLayoutNode(this, getSession()); + IVMLayoutNode registerNode = new RegisterLayoutNode(this, getSession(), syncDataAccess); registerGroupNode.setChildNodes(new IVMLayoutNode[] { registerNode }); setRootLayoutNode(debugViewSelection); } diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/SyncRegisterDataAccess.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/SyncRegisterDataAccess.java index 0c2811fd097..63c901c1787 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/SyncRegisterDataAccess.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/register/SyncRegisterDataAccess.java @@ -29,6 +29,8 @@ import org.eclipse.dd.dsf.debug.service.IRegisters.IBitFieldDMData; import org.eclipse.dd.dsf.debug.service.IRegisters.IMnemonic; 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.debug.service.IRegisters.IRegisterGroupDMData; import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin; import org.eclipse.dd.dsf.service.DsfSession; import org.eclipse.dd.dsf.service.IDsfService; @@ -390,6 +392,13 @@ public class SyncRegisterDataAccess { } } + public IRegisterGroupDMContext getRegisterGroupDMC(Object element) { + if (element instanceof IAdaptable) { + return (IRegisterGroupDMContext) ((IAdaptable) element).getAdapter(IRegisterGroupDMContext.class); + } + return null; + } + public IRegisterDMContext getRegisterDMC(Object element) { if (element instanceof IAdaptable) { return (IRegisterDMContext) ((IAdaptable) element).getAdapter(IRegisterDMContext.class); @@ -399,10 +408,99 @@ public class SyncRegisterDataAccess { public IFormattedDataDMContext getFormattedDMC(Object element) { if (element instanceof IAdaptable) { - return (IFormattedDataDMContext) ((IAdaptable) element).getAdapter(IFormattedDataDMContext.class); + return (IFormattedDataDMContext) ((IAdaptable) element).getAdapter(IFormattedDataDMContext.class); } return null; } + + public class GetRegisterGroupValueQuery extends Query { + + IRegisterGroupDMContext fDmc; + + public GetRegisterGroupValueQuery(DsfExecutor executor, IRegisterGroupDMContext dmc) { + super(executor); + fDmc = dmc; + } + + @Override + protected void execute(final DataRequestMonitor rm) { + /* + * Guard agains the session being disposed. If session is disposed + * it could mean that the executor is shut-down, which in turn could + * mean that we can't complete the RequestMonitor argument. in that + * case, cancel to notify waiting thread. + */ + final DsfSession session = DsfSession.getSession(fDmc.getSessionId()); + if (session == null) { + cancel(false); + return; + } + + IRegisters service = getService(fDmc.getServiceFilter()); + if (service == null) { + rm.setStatus(new Status(IStatus.ERROR, DsfDebugUIPlugin.PLUGIN_ID, IDsfService.INVALID_STATE, "Service not available", null)); //$NON-NLS-1$ + rm.done(); + return; + } + + service.getModelData(fDmc, new DataRequestMonitor( session.getExecutor(), rm) { + @Override + protected void handleCompleted() { + /* + * We're in another dispatch, so we must guard against + * executor shutdown again. + */ + if (!DsfSession.isSessionActive(session.getId())) { + GetRegisterGroupValueQuery.this.cancel(false); + return; + } + super.handleCompleted(); + } + + @Override + protected void handleOK() { + /* + * All good set return value. + */ + rm.setData(getData()); + rm.done(); + } + }); + } + } + + public IRegisterGroupDMData readRegisterGroup(Object element) { + /* + * Get the DMC and the session. If element is not an register DMC, or + * session is stale, then bail out. + */ + IRegisterGroupDMContext dmc = getRegisterGroupDMC(element); + if (dmc == null) return null; + DsfSession session = DsfSession.getSession(dmc.getSessionId()); + if (session == null) return null; + + /* + * Create the query to request the value from service. Note: no need to + * guard agains RejectedExecutionException, because + * DsfSession.getSession() above would only return an active session. + */ + GetRegisterGroupValueQuery query = new GetRegisterGroupValueQuery(session.getExecutor(), dmc); + session.getExecutor().execute(query); + + /* + * Now we have the data, go and get it. Since the call is completed now + * the ".get()" will not suspend it will immediately return with the + * data. + */ + try { + return query.get(); + } catch (InterruptedException e) { + assert false; + return null; + } catch (ExecutionException e) { + return null; + } + } public class GetRegisterValueQuery extends Query { diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/LocalsLayoutNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/LocalsLayoutNode.java new file mode 100644 index 00000000000..4c171f3b0e4 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/LocalsLayoutNode.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * 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.variable; + +import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; +import org.eclipse.dd.dsf.concurrent.RequestMonitor; +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; +import org.eclipse.dd.dsf.debug.service.IStack; +import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext; +import org.eclipse.dd.dsf.debug.service.IStack.IVariableDMContext; +import org.eclipse.dd.dsf.debug.service.IStack.IVariableDMData; +import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants; +import org.eclipse.dd.dsf.service.DsfSession; +import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMProvider; +import org.eclipse.dd.dsf.ui.viewmodel.VMDelta; +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 LocalsLayoutNode extends AbstractDMVMLayoutNode { + + public LocalsLayoutNode(AbstractVMProvider provider, DsfSession session) { + super(provider, session, IStack.IVariableDMContext.class); + } + + @Override + protected void updateElementsInSessionThread(final IChildrenUpdate update) { + if (!checkService(IRegisters.class, null, update)) return; + + final IFrameDMContext frameDmc = findDmcInPath(update.getElementPath(), IFrameDMContext.class) ; + + if (frameDmc != null) { + getServicesTracker().getService(IStack.class).getArguments( + frameDmc, + new DataRequestMonitor(getSession().getExecutor(), null) { + @Override + public void handleCompleted() { + if (!getStatus().isOK()) { + update.done(); + return; + } + fillUpdateWithVMCs(update, getData()); + update.done(); + }}); + } else { + handleFailedUpdate(update); + } + + } + + @Override + protected void fillColumnLabel(IDMContext dmContext, IVariableDMData dmData, + String columnId, int idx, ILabelUpdate update) + { + if (IDebugVMConstants.COLUMN_ID__NAME.equals(columnId)) { + update.setLabel(dmData.getName(), idx); + } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(columnId)) { + update.setLabel(dmData.getValue(), idx); + } else { + update.setLabel("", idx); //$NON-NLS-1$ + } + } + + @Override + protected int getNodeDeltaFlagsForDMEvent(IDMEvent e) { + if (e instanceof IRunControl.ISuspendedDMEvent) { + return IModelDelta.CONTENT; + } + return IModelDelta.NO_CHANGE; + } + + @Override + protected void buildDeltaForDMEvent(IDMEvent e, VMDelta parent, int nodeOffset, RequestMonitor rm) { + if (e instanceof IRunControl.ISuspendedDMEvent) { + // Create a delta that the whole register group has changed. + parent.addFlags(IModelDelta.CONTENT); + } + + super.buildDeltaForDMEvent(e, parent, nodeOffset, rm); + } +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/MessagesForVariablesVM.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/MessagesForVariablesVM.java new file mode 100644 index 00000000000..9f2f0febf91 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/MessagesForVariablesVM.java @@ -0,0 +1,21 @@ +package org.eclipse.dd.dsf.debug.ui.viewmodel.variable; + +import org.eclipse.osgi.util.NLS; + +public class MessagesForVariablesVM extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.dd.dsf.debug.ui.viewmodel.variable.messages"; //$NON-NLS-1$ + + public static String VariableColumnPresentation_name; + + public static String VariableColumnPresentation_type; + + public static String VariableColumnPresentation_value; + + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, MessagesForVariablesVM.class); + } + + private MessagesForVariablesVM() { + } +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/VariableColumnPresentation.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/VariableColumnPresentation.java new file mode 100644 index 00000000000..fd5cfd52ccd --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/VariableColumnPresentation.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * 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.variable; + +import org.eclipse.dd.dsf.debug.ui.DsfDebugUIPlugin; +import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants; +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; + +/** + * + */ +@SuppressWarnings("restriction") +public class VariableColumnPresentation implements IColumnPresentation { + public static final String ID = DsfDebugUIPlugin.PLUGIN_ID + ".VARIABLES_COLUMN_PRESENTATION_ID"; //$NON-NLS-1$ + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#init(org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext) + public void init(IPresentationContext context) {} + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#dispose() + public void dispose() {} + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getAvailableColumns() + public String[] getAvailableColumns() { + return new String[] { IDebugVMConstants.COLUMN_ID__NAME, IDebugVMConstants.COLUMN_ID__TYPE, IDebugVMConstants.COLUMN_ID__VALUE }; + } + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getHeader(java.lang.String) + public String getHeader(String id) { + if (IDebugVMConstants.COLUMN_ID__NAME.equals(id)) { + return MessagesForVariablesVM.VariableColumnPresentation_name; + } else if (IDebugVMConstants.COLUMN_ID__TYPE.equals(id)) { + return MessagesForVariablesVM.VariableColumnPresentation_type; + } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(id)) { + return MessagesForVariablesVM.VariableColumnPresentation_value; + } + return null; + } + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getId() + public String getId() { + return ID; + } + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getImageDescriptor(java.lang.String) + public ImageDescriptor getImageDescriptor(String id) { + return null; + } + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getInitialColumns() + public String[] getInitialColumns() { + return new String[] { IDebugVMConstants.COLUMN_ID__NAME, IDebugVMConstants.COLUMN_ID__TYPE, IDebugVMConstants.COLUMN_ID__VALUE }; + } + + // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#isOptional() + public boolean isOptional() { + return true; + } + +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java new file mode 100644 index 00000000000..559ee8ba034 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/VariableVMProvider.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.debug.ui.viewmodel.variable; + +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.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 VariableVMProvider extends AbstractDMVMProvider { + public VariableVMProvider(AbstractVMAdapter adapter, IPresentationContext context, DsfSession session) { + super(adapter, context, session); + IVMRootLayoutNode debugViewSelectionNode = new DebugViewSelectionRootLayoutNode(this); + IVMLayoutNode localsNode = new LocalsLayoutNode(this, getSession()); + debugViewSelectionNode.setChildNodes(new IVMLayoutNode[] { localsNode }); + setRootLayoutNode(debugViewSelectionNode); + } + + @Override + public IColumnPresentation createColumnPresentation(IPresentationContext context, Object element) { + return new VariableColumnPresentation(); + } + + @Override + public String getColumnPresentationId(IPresentationContext context, Object element) { + return VariableColumnPresentation.ID; + } +} diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/messages.properties b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/messages.properties new file mode 100644 index 00000000000..d67d7e56fd7 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/messages.properties @@ -0,0 +1,3 @@ +VariableColumnPresentation_name=Name +VariableColumnPresentation_type=Type +VariableColumnPresentation_value=Value 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 a9b5463c5d6..09dc3ac517b 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 @@ -82,10 +82,19 @@ 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. + *

Note: If a child node has a IModelDelta.CONTENT delta + * flag, it means that this flag will be added to this node's element. + * To allow for optimization change the child's IModelDelta.CONTENT + * flag into a IModelDelta.STATE flag. */ public int getDeltaFlags(Object e) { int retVal = 0; for (IVMLayoutNode childNode : getChildLayoutNodes()) { + int childNodeDeltaFlags = childNode.getDeltaFlags(e); + if ((childNodeDeltaFlags | IModelDelta.CONTENT) != 0) { + childNodeDeltaFlags &= ~IModelDelta.CONTENT; + childNodeDeltaFlags |= IModelDelta.STATE; + } retVal |= childNode.getDeltaFlags(e); } return retVal; @@ -116,7 +125,7 @@ abstract public class AbstractVMLayoutNode implements IVMLayoutNode { // Similarly, the index argument is not necessary either. boolean mustGetElements = false; for (int childDelta : childNodesWithDeltaFlags.values()) { - if ((childDelta & ~IModelDelta.CONTENT & ~IModelDelta.STATE) != 0) { + if ((childDelta & ~IModelDelta.STATE) != 0) { mustGetElements = true; } } @@ -391,6 +400,17 @@ abstract public class AbstractVMLayoutNode implements IVMLayoutNode { abstract public int hashCode(); } + protected TreePath getTreePathFromDelta(IModelDelta delta) { + List elementList = new LinkedList(); + IModelDelta listDelta = delta; + elementList.add(0, listDelta.getElement()); + while (listDelta.getParentDelta() != null) { + elementList.add(0, listDelta.getElement()); + listDelta = listDelta.getParentDelta(); + } + return new TreePath(elementList.toArray()); + } + protected class ViewerUpdate implements IViewerUpdate { final private RequestMonitor fRequestMonitor; @@ -486,7 +506,7 @@ abstract public class AbstractVMLayoutNode implements IVMLayoutNode { @Override public String toString() { - return "ElementsUpdate for all elements under parent = " + getElement(); //$NON-NLS-1$ + return "VMElementsUpdate for all elements under parent = " + getElement(); //$NON-NLS-1$ } } 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 index 58a6fa3bbc6..d8ade10a314 100644 --- 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 @@ -42,8 +42,6 @@ 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.jface.viewers.TreePath; -import org.eclipse.jface.viewers.Viewer; /** * View model provider implements the asynchronous view model functionality for @@ -66,7 +64,7 @@ abstract public class AbstractVMProvider implements IVMProvider { private final AbstractVMAdapter fVMAdapter; private final IPresentationContext fPresentationContext; - private final ModelProxy fModelProxy = new ModelProxy(); + private ModelProxy fModelProxy = new ModelProxy(); private boolean fDisposed = false; /** @@ -106,7 +104,7 @@ abstract public class AbstractVMProvider implements IVMProvider } } - protected ModelProxy getModelProxy() { + protected synchronized ModelProxy getModelProxy() { return fModelProxy; } @@ -138,7 +136,7 @@ abstract public class AbstractVMProvider implements IVMProvider Map> nodeUpdatesMap = new HashMap>(); for (IHasChildrenUpdate update : updates) { // Get the VM Context for last element in path. - IVMLayoutNode layoutNode = getLayoutNodeObject(update.getElement()); + IVMLayoutNode layoutNode = getLayoutNodeForElement(update.getElement()); if (layoutNode == null) { // Stale update, most likely as a result of the layout nodes being // changed. Just ignore it. @@ -167,8 +165,8 @@ abstract public class AbstractVMProvider implements IVMProvider return; } - HasElementsUpdate[][] elementsUpdates = - new HasElementsUpdate[node.getChildLayoutNodes().length][updates.length]; + VMHasElementsUpdate[][] elementsUpdates = + new VMHasElementsUpdate[node.getChildLayoutNodes().length][updates.length]; for (int i = 0; i < updates.length; i ++) { final IHasChildrenUpdate update = updates[i]; @@ -181,7 +179,7 @@ abstract public class AbstractVMProvider implements IVMProvider // Status is OK, only if all request monitors are OK. if (getStatus().isOK()) { boolean isContainer = false; - for (DataRequestMonitor hasElementsDone : getRequestMonitors().keySet()) { + for (DataRequestMonitor hasElementsDone : getRequestMonitors()) { isContainer |= hasElementsDone.getStatus().isOK() && hasElementsDone.getData().booleanValue(); } @@ -191,7 +189,7 @@ abstract public class AbstractVMProvider implements IVMProvider } }; - elementsUpdates[j][i] = new HasElementsUpdate( + elementsUpdates[j][i] = new VMHasElementsUpdate( update, hasChildrenMultiRequestMon.add( new DataRequestMonitor(getExecutor(), null) { @@ -214,7 +212,7 @@ abstract public class AbstractVMProvider implements IVMProvider if (update.isCanceled()) continue; getChildrenCountsForNode( - update, update.getElementPath(), + update, new DataRequestMonitor(getExecutor(), null) { @Override protected void handleCompleted() { @@ -236,7 +234,7 @@ abstract public class AbstractVMProvider implements IVMProvider public void update(IChildrenUpdate[] updates) { for (final IChildrenUpdate update : updates) { getChildrenCountsForNode( - update, update.getElementPath(), + update, new DataRequestMonitor(getExecutor(), null) { @Override protected void handleCompleted() { @@ -251,11 +249,11 @@ abstract public class AbstractVMProvider implements IVMProvider } - private void getChildrenCountsForNode(IViewerUpdate update, TreePath elementPath, final DataRequestMonitor rm) { + private void getChildrenCountsForNode(IViewerUpdate update, final DataRequestMonitor rm) { if (isDisposed()) return; // Get the VM Context for last element in path. - final IVMLayoutNode layoutNode = getLayoutNodeObject(update.getElement()); + final IVMLayoutNode layoutNode = getLayoutNodeForElement(update.getElement()); if (layoutNode == null) { // Stale update. Just ignore. rm.setStatus(new Status( @@ -294,7 +292,7 @@ abstract public class AbstractVMProvider implements IVMProvider for (int i = 0; i < childNodes.length; i++) { final int nodeIndex = i; childNodes[i].updateElementCount( - new ElementsCountUpdate( + new VMElementsCountUpdate( update, childrenCountMultiReqMon.add( new DataRequestMonitor(getExecutor(), null) { @@ -308,14 +306,13 @@ abstract public class AbstractVMProvider implements IVMProvider super.handleCompleted(); childrenCountMultiReqMon.requestMonitorDone(this); } - }), - elementPath) + })) ); } } private void updateChildrenWithCounts(final IChildrenUpdate update, Integer[] nodeElementCounts) { - final IVMLayoutNode layoutNode = getLayoutNodeObject(update.getElement()); + final IVMLayoutNode layoutNode = getLayoutNodeForElement(update.getElement()); if (layoutNode == null) { // Stale update. Just ignore. if (!update.isCanceled()) update.done(); @@ -347,18 +344,22 @@ abstract public class AbstractVMProvider implements IVMProvider 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, - elementsMultiRequestMon.add(new RequestMonitor(getExecutor(), null) { - @Override - protected void handleCompleted() { - elementsMultiRequestMon.requestMonitorDone(this); - } - }), - nodeStartIdx, elementsStartIdx, elementsEndIdx - elementsStartIdx) - ); + final int elementsLength = elementsEndIdx - elementsStartIdx; + if (elementsLength > 0) { + layoutNodes[i].updateElements( + new VMElementsUpdate( + update, elementsStartIdx, elementsLength, + elementsMultiRequestMon.add(new DataRequestMonitor>(getExecutor(), null) { + @Override + protected void handleCompleted() { + for (int i = 0; i < elementsLength; i++) { + update.setChild(getData().get(i), elementsStartIdx + nodeStartIdx + i); + } + elementsMultiRequestMon.requestMonitorDone(this); + } + })) + ); + } } } @@ -378,6 +379,9 @@ abstract public class AbstractVMProvider implements IVMProvider if (getRootLayoutNode() != null && element.equals(getRootLayoutNode().getRootObject())) { + synchronized(this) { + fModelProxy = new ModelProxy(); + } return fModelProxy; } return null; @@ -429,7 +433,7 @@ abstract public class AbstractVMProvider implements IVMProvider * @return parent VMC, if null it indicates that the object did not originate * from this view or is stale. */ - private IVMLayoutNode getLayoutNodeObject(Object element) { + protected IVMLayoutNode getLayoutNodeForElement(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 @@ -474,14 +478,39 @@ abstract public class AbstractVMProvider implements IVMProvider } + protected void handleEvent(final Object event) { + // 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 DataRequestMonitor(getExecutor(), null) { + @Override + public void handleCompleted() { + if (getStatus().isOK()) { + getModelProxy().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$ + } + }); + } + }}); + } catch (RejectedExecutionException e) { + // Ignore. This exception could be thrown if the provider is being + // shut down. + } + } + @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. */ @@ -490,25 +519,12 @@ abstract public class AbstractVMProvider implements IVMProvider public boolean isConflicting(ISchedulingRule rule) { return rule == this; } }; - @Override - public void installed(Viewer viewer) { - fProxyActive++; - } - - @Override - public void dispose() { - fProxyActive--; - super.dispose(); - } - /** * 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$ @Override protected IStatus run(IProgressMonitor monitor) { @@ -522,125 +538,4 @@ abstract public class AbstractVMProvider implements IVMProvider } } - - class ViewerUpdate implements IViewerUpdate { - - private IStatus fStatus; - final private RequestMonitor fRequestMonitor; - final protected IViewerUpdate fClientUpdate; - - public ViewerUpdate(IViewerUpdate clientUpdate, RequestMonitor requestMonitor) { - fRequestMonitor = requestMonitor; - 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 boolean isCanceled() { return fClientUpdate.isCanceled(); } - public void cancel() { - fClientUpdate.cancel(); - } - - public void done() { - try { - fRequestMonitor.done(); - } catch (RejectedExecutionException e) { // Ignore - } - } - - } - - class HasElementsUpdate extends ViewerUpdate implements IHasChildrenUpdate { - - final private DataRequestMonitor fHasElemsRequestMonitor; - - HasElementsUpdate(IHasChildrenUpdate clientUpdate, DataRequestMonitor rm) { - super(clientUpdate, rm); - fHasElemsRequestMonitor = rm; - } - - @Override - public TreePath getElementPath() { - return ((IHasChildrenUpdate)fClientUpdate).getElementPath(); - } - - public void setHasChilren(boolean hasChildren) { - fHasElemsRequestMonitor.setData(hasChildren); - } - - @Override - public void done() { - assert fHasElemsRequestMonitor.getData() != null || !fHasElemsRequestMonitor.getStatus().isOK(); - super.done(); - } - } - - class ElementsCountUpdate extends ViewerUpdate implements IChildrenCountUpdate { - final private DataRequestMonitor fCountRequestMonitor; - final private TreePath fElementPath; - - ElementsCountUpdate(IViewerUpdate clientUpdate, DataRequestMonitor rm, TreePath elementPath) { - super(clientUpdate, rm); - fElementPath = elementPath; - fCountRequestMonitor = rm; - } - - @Override - public TreePath getElementPath() { - return fElementPath; - } - - public void setChildCount(int count) { - fCountRequestMonitor.setData(count); - } - - @Override - public void done() { - assert fCountRequestMonitor.getData() != null || !fCountRequestMonitor.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, RequestMonitor requestMonitor, int clientOffset, int offset, int length) { - super(clientUpdate, requestMonitor); - fClientOffset = clientOffset; - fOffset = offset; - fLength = length; - } - - public int getOffset() { - return fOffset; - } - - public int getLength() { - return fLength; - } - - @Override - 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); - } - } - - @Override - public String toString() { - return "ElementsUpdate for elements under parent = " + getElement() + ", in range " + getOffset() + " -> " + (getOffset() + getLength()); //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$ - } - - } } diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMElementsCountUpdate.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMElementsCountUpdate.java new file mode 100644 index 00000000000..8c599f90e10 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMElementsCountUpdate.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2007 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.dd.dsf.concurrent.DataRequestMonitor; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate; + +/** + * Helper class implementation of an update object to use with IElementContentProvider. + * @see IElementContentProvider + */ +@SuppressWarnings("restriction") +public class VMElementsCountUpdate extends VMViewerUpdate implements IChildrenCountUpdate { + final private DataRequestMonitor fCountRequestMonitor; + + public VMElementsCountUpdate(IViewerUpdate clientUpdate, DataRequestMonitor rm) { + super(clientUpdate, rm); + fCountRequestMonitor = rm; + } + + public void setChildCount(int count) { + fCountRequestMonitor.setData(count); + } + + @Override + public void done() { + assert fCountRequestMonitor.getData() != null || !fCountRequestMonitor.getStatus().isOK(); + super.done(); + } + +} diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMElementsUpdate.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMElementsUpdate.java new file mode 100644 index 00000000000..4966402314e --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMElementsUpdate.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2007 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.List; + +import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider; + +/** + * Helper class implementation of an update object to use with IElementContentProvider. + * @see IElementContentProvider + */ +@SuppressWarnings("restriction") +public class VMElementsUpdate extends VMViewerUpdate implements IChildrenUpdate { + private final int fOffset; + private final int fLength; + private final List fElements; + + public VMElementsUpdate(IChildrenUpdate clientUpdate, int offset, int length, DataRequestMonitor> requestMonitor) { + super(clientUpdate, requestMonitor); + fOffset = offset; + fLength = length; + fElements = length > 0 ? new ArrayList(length) : new ArrayList(); + } + + public int getOffset() { + return fOffset; + } + + public int getLength() { + return fLength; + } + + public void setChild(Object element, int offset) { + // Calculate the index in array based on configured offset. + int idx = offset - (fOffset > 0 ? fOffset : 0); + + // To make sure that index is in valid range. + if (idx < 0 || (fLength > 0 && idx >= fLength)) return; + + // Increase the list size if needed. + ensureElementsSize(idx + 1); + + // Finally set the element in elements list. + fElements.set(idx, element); + } + + private void ensureElementsSize(int size) { + while (fElements.size() < size) { + fElements.add(null); + } + } + + @Override + public String toString() { + return "VMElementsUpdate for elements under parent = " + getElement() + ", in range " + getOffset() + " -> " + (getOffset() + getLength()); //$NON-NLS-1$ //$NON-NLS-2$//$NON-NLS-3$ + } + + @Override + public void done() { + @SuppressWarnings("unchecked") + DataRequestMonitor> rm = (DataRequestMonitor>)fRequestMonitor; + rm.setData(fElements); + super.done(); + } +} diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMHasElementsUpdate.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMHasElementsUpdate.java new file mode 100644 index 00000000000..2153473ff11 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMHasElementsUpdate.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2007 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.dd.dsf.concurrent.DataRequestMonitor; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate; + +/** + * Helper class implementation of an update object to use with IElementContentProvider. + * @see IElementContentProvider + */ +@SuppressWarnings("restriction") +public class VMHasElementsUpdate extends VMViewerUpdate implements IHasChildrenUpdate { + + final private DataRequestMonitor fHasElemsRequestMonitor; + + public VMHasElementsUpdate(IHasChildrenUpdate clientUpdate, DataRequestMonitor rm) { + super(clientUpdate, rm); + fHasElemsRequestMonitor = rm; + } + + public void setHasChilren(boolean hasChildren) { + fHasElemsRequestMonitor.setData(hasChildren); + } + + @Override + public void done() { + assert fHasElemsRequestMonitor.getData() != null || !fHasElemsRequestMonitor.getStatus().isOK(); + super.done(); + } +} diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMViewerUpdate.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMViewerUpdate.java new file mode 100644 index 00000000000..6512fb3ec4d --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/VMViewerUpdate.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2007 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.RejectedExecutionException; + +import org.eclipse.core.runtime.IStatus; +import org.eclipse.dd.dsf.concurrent.RequestMonitor; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate; +import org.eclipse.jface.viewers.TreePath; + +/** + * Helper class implementation of an update object to use with IElementContentProvider. + * @see IElementContentProvider + */ +@SuppressWarnings("restriction") +public class VMViewerUpdate implements IViewerUpdate { + final protected RequestMonitor fRequestMonitor; + final protected IViewerUpdate fClientUpdate; + + public VMViewerUpdate(IViewerUpdate clientUpdate, RequestMonitor requestMonitor) { + fRequestMonitor = requestMonitor; + fClientUpdate = clientUpdate; + } + + public Object getElement() { return fClientUpdate.getElement(); } + public TreePath getElementPath() { return fClientUpdate.getElementPath(); } + public IPresentationContext getPresentationContext() { return fClientUpdate.getPresentationContext(); } + + public IStatus getStatus() { return fRequestMonitor.getStatus(); } + public void setStatus(IStatus status) { fRequestMonitor.setStatus(status); } + public boolean isCanceled() { return fClientUpdate.isCanceled(); } + public void cancel() { + fClientUpdate.cancel(); + } + + public void done() { + try { + fRequestMonitor.done(); + } catch (RejectedExecutionException e) { // Ignore + } + } + +} 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 index d85a0937d1d..250c5dabfa0 100644 --- 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 @@ -452,9 +452,9 @@ abstract public class AbstractDMVMLayoutNode extends Abstract callChildNodesToBuildDelta(childNodeDeltas, delta, event, requestMonitor); } } else { - // The for this node was not found in the event. Call the + // The DMC 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. + // delta for every element in this node. super.buildDelta(event, parentDelta, nodeOffset, requestMonitor); } } 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 index 990892a5d1a..2391170d2db 100644 --- 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 @@ -13,15 +13,12 @@ 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.DataRequestMonitor; 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; @@ -111,33 +108,6 @@ abstract public class AbstractDMVMProvider extends AbstractVMProvider 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 DataRequestMonitor(getExecutor(), null) { - @Override - public void handleCompleted() { - 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. - } + handleEvent(event); } } diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/CountingRequestMonitor.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/CountingRequestMonitor.java new file mode 100644 index 00000000000..6e6220f4a25 --- /dev/null +++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/CountingRequestMonitor.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * 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.concurrent; + +import org.eclipse.core.runtime.MultiStatus; +import org.eclipse.dd.dsf.DsfPlugin; + +/** + * Utility class to collect multiple request monitor results of commands + * that are initiated simultaneously. The usage is as follows: + *
+ *     final MultiRequestMonitor multiRequestMon = new MultiRequestMonitor(fExecutor, null) { 
+ *         public void handleCompleted() {
+ *             System.out.println("All complete, errors=" + !getStatus().isOK());
+ *         }
+ *     };
+ *     
+ *     for (int i = 0; i < 10; i++) {
+ *         service.call(i, multiRequestMon.addRequestMonitor(
+ *             new RequestMonitor(fExecutor, null) {
+ *                 public void handleCompleted() {
+ *                     System.out.println(Integer.toString(i) + " complete");
+ *                     multiRequestMon.requestMonitorDone(this);
+ *                }
+ *             }));
+ *     }
+ * 
+ */ +public class CountingRequestMonitor extends RequestMonitor { + private int fDoneCounter; + + public CountingRequestMonitor(DsfExecutor executor, RequestMonitor parentRequestMonitor) { + super(executor, parentRequestMonitor); + setStatus(new MultiStatus(DsfPlugin.PLUGIN_ID, 0, "Collective status for set of sub-operations.", null)); //$NON-NLS-1$ + } + + public void setCount(int count) { + fDoneCounter = count; + } + + @Override + public synchronized void done() { + fDoneCounter--; + if (fDoneCounter <= 0) { + super.done(); + } + } + + @Override + public String toString() { + return "Multi-RequestMonitor: " + getStatus().toString(); //$NON-NLS-1$ + } +} diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DataRequestMonitor.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DataRequestMonitor.java index 754e5dd4175..9cfe5a24e2f 100644 --- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DataRequestMonitor.java +++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/DataRequestMonitor.java @@ -16,7 +16,7 @@ package org.eclipse.dd.dsf.concurrent; * * @param V The type of the data object that this monitor handles. */ -public abstract class DataRequestMonitor extends RequestMonitor { +public class DataRequestMonitor extends RequestMonitor { /** Data object reference */ private V fData; diff --git a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/MultiRequestMonitor.java b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/MultiRequestMonitor.java index 37bb9fdbf9b..e084cdd3a5a 100644 --- a/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/MultiRequestMonitor.java +++ b/plugins/org.eclipse.dd.dsf/src/org/eclipse/dd/dsf/concurrent/MultiRequestMonitor.java @@ -11,6 +11,8 @@ package org.eclipse.dd.dsf.concurrent; import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; import java.util.Map; import org.eclipse.core.runtime.MultiStatus; @@ -37,8 +39,9 @@ import org.eclipse.dd.dsf.DsfPlugin; * } * */ -public abstract class MultiRequestMonitor extends RequestMonitor { - private Map fRequestMonitors = new HashMap(); +public class MultiRequestMonitor extends RequestMonitor { + private List fRequestMonitorList = new LinkedList(); + private Map fStatusMap = new HashMap(); private int fDoneCounter; public MultiRequestMonitor(DsfExecutor executor, RequestMonitor parentRequestMonitor) { @@ -55,8 +58,9 @@ public abstract class MultiRequestMonitor extends Requ * inlined in service method calls */ public T add(T rm) { - assert !fRequestMonitors.containsKey(rm); - fRequestMonitors.put(rm, false); + assert !fStatusMap.containsKey(rm); + fRequestMonitorList.add(rm); + fStatusMap.put(rm, false); fDoneCounter++; return rm; } @@ -70,23 +74,29 @@ public abstract class MultiRequestMonitor extends Requ */ public void requestMonitorDone(V requestMonitor) { ((MultiStatus)getStatus()).merge(requestMonitor.getStatus()); - assert fRequestMonitors.containsKey(requestMonitor); - fRequestMonitors.put(requestMonitor, true); + assert fStatusMap.containsKey(requestMonitor); + fStatusMap.put(requestMonitor, true); assert fDoneCounter > 0; fDoneCounter--; if (fDoneCounter == 0) { - assert !fRequestMonitors.containsValue(false); + assert !fStatusMap.containsValue(false); super.done(); } } - + /** - * Returns the map of RequestMonitor callbacks. Access to this data is provided - * in case overriding classes need access to the collected data in the - * request monitors. - * @return map of the request monitors + * Returns the list of requested monitors, sorted in order as they were added. */ - public Map getRequestMonitors() { return fRequestMonitors; } + public List getRequestMonitors() { + return fRequestMonitorList; + } + + /** + * Returns true if given monitor is finished. + */ + public boolean isRequestMonitorDone(V rm) { + return fStatusMap.get(rm); + } @Override public String toString() {