### Eclipse Workspace Patch 1.0 #P org.eclipse.dd.dsf.debug.ui Index: src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java =================================================================== RCS file: /cvsroot/dsdp/org.eclipse.dd.dsf/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java,v retrieving revision 1.1 diff -u -r1.1 VariableVMProvider.java --- src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java 5 May 2007 00:12:37 -0000 1.1 +++ src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java 9 May 2007 21:01:10 -0000 @@ -1,13 +1,11 @@ -/******************************************************************************* - * 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 +/** + * 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 - *******************************************************************************/ + * 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; @@ -17,19 +15,37 @@ 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.IColumnPresentationFactory; 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) { +public class VariableVMProvider extends AbstractDMVMProvider implements + IColumnPresentationFactory { + + 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); + + /* + * Create the top level node to deal with the root selection. + */ + IVMRootLayoutNode debugViewSelection = new DebugViewSelectionRootLayoutNode(this); + + /* + * Create the local variables nodes next. They represent the first level shown in the view. + */ + IVMLayoutNode localsNode = new VariableLocalsLayoutNode(this, getSession()); + debugViewSelection.setChildNodes(new IVMLayoutNode[] { localsNode }); + + /* + * Create the next level which represents members of structs/unions/enums and elements of arrays. + */ + IVMLayoutNode subExpressioNode = new VariableSubExpressionsLayoutNode(this, getSession()); + localsNode.setChildNodes(new IVMLayoutNode[] { subExpressioNode }); + + /* + * Now set this schema set as the layout set. + */ + setRootLayoutNode(debugViewSelection); } @Override Index: src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/LocalsLayoutNode.java =================================================================== RCS file: src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/LocalsLayoutNode.java diff -N src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/LocalsLayoutNode.java --- src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/LocalsLayoutNode.java 5 May 2007 00:12:37 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,94 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2006 Wind River Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Wind River Systems - initial API and implementation - *******************************************************************************/ -package org.eclipse.dd.dsf.debug.ui.viewmodel.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); - } -} Index: src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/VariableLocalsLayoutNode.java =================================================================== RCS file: src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/VariableLocalsLayoutNode.java diff -N src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/VariableLocalsLayoutNode.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/VariableLocalsLayoutNode.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,341 @@ +/** + * 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 java.util.ArrayList; +import java.util.List; + +import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; +import org.eclipse.dd.dsf.concurrent.DsfExecutor; +import org.eclipse.dd.dsf.concurrent.MultiRequestMonitor; +import org.eclipse.dd.dsf.concurrent.RequestMonitor; +import org.eclipse.dd.dsf.datamodel.IDMEvent; +import org.eclipse.dd.dsf.datamodel.IDMService; +import org.eclipse.dd.dsf.debug.service.IExpressions; +import org.eclipse.dd.dsf.debug.service.IFormattedValues; +import org.eclipse.dd.dsf.debug.service.IRunControl; +import org.eclipse.dd.dsf.debug.service.IStack; +import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext; +import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMData; +import org.eclipse.dd.dsf.debug.service.IFormattedValues.FormattedValueDMContext; +import org.eclipse.dd.dsf.debug.service.IFormattedValues.FormattedValueDMData; +import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; +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.service.IDsfService; +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 VariableLocalsLayoutNode extends AbstractDMVMLayoutNode { + + public VariableLocalsLayoutNode(AbstractVMProvider provider, DsfSession session) { + super(provider, session, IExpressions.IExpressionDMContext.class); + } + + /** + * We override this method because we now need to perform an extra level of data fetch to get the + * formatted value of the expression. + * + * @return void + */ + @Override + protected void updateLabelInSessionThread(ILabelUpdate[] updates) { + for (final ILabelUpdate update : updates) { + + final IExpressionDMContext dmc = findDmcInPath(update.getElementPath(), IExpressions.IExpressionDMContext.class); + + ((IDMService)getServicesTracker().getService(null, dmc.getServiceFilter())).getModelData( + dmc, + new DataRequestMonitor(getSession().getExecutor(), null) { + @Override + protected void handleCompleted() { + // Check that the request was evaluated and data is still valid. The request could + // fail if the state of the service changed during the request, but the view model + // has not been updated yet. + + if (!getStatus().isOK() || !getData().isValid()) { + assert getStatus().isOK() || + getStatus().getCode() != IDsfService.INTERNAL_ERROR || + getStatus().getCode() != IDsfService.NOT_SUPPORTED; + handleFailedUpdate(update); + return; + } + + // If columns are configured, extract the selected values for each understood column. + // First, we fill all of those columns which can be filled without extra data mining. + // We also note if we do have to do extra data mining. Any columns need to set the + // processing flag so we know we have further work to do. If there are more columns + // which need data extraction they need to be added in both "for" loops. + + String[] localColumns = update.getPresentationContext().getColumns(); + if (localColumns == null) + localColumns = new String[] { null }; + + boolean weAreExtractingFormattedData = false; + + for (int idx = 0; idx < localColumns.length; idx++) { + if (IDebugVMConstants.COLUMN_ID__NAME.equals(localColumns[idx])) { + update.setLabel(getData().getName(), idx); + } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(localColumns[idx])) { + weAreExtractingFormattedData = true; + } else if (IDebugVMConstants.COLUMN_ID__DESCRIPTION.equals(localColumns[idx])) { + update.setLabel("", idx); //$NON-NLS-1$ + } + } + + if ( ! weAreExtractingFormattedData ) { + update.done(); + } else { + for (int idx = 0; idx < localColumns.length; idx++) { + if (IDebugVMConstants.COLUMN_ID__VALUE.equals(localColumns[idx])) { + updateFormattedExpressionValue(update, idx, dmc); + } + } + } + } + } + ); + } + } + + + /** + * Private data access routine which performs the extra level of data access needed to + * get the formatted data value for a specific register. + */ + private void updateFormattedExpressionValue(final ILabelUpdate update, final int labelIndex, + final IExpressionDMContext dmc) + { + final IExpressions expressionService = getServicesTracker().getService(IExpressions.class); + /* + * PREFPAGE : We are using a default format until the preference page is created + * + * First select the format to be used. This involves checking so see that the preference + * page format is supported by the register service. If the format is not supported then + * we will pick the first available format. + */ + + final String preferencePageFormatId = IFormattedValues.NATURAL_FORMAT; + + expressionService.getAvailableFormattedValues( + dmc, + new DataRequestMonitor(getSession().getExecutor(), null) { + @Override + public void handleCompleted() { + if (!getStatus().isOK()) { + handleFailedUpdate(update); + return; + } + + /* + * See if the desired format is supported. + */ + String[] formatIds = getData(); + String finalFormatId = IFormattedValues.NATURAL_FORMAT; + boolean requestedFormatIsSupported = false; + + for ( String fId : formatIds ) { + if ( preferencePageFormatId.equals(fId) ) { + // The desired format is supported. + + finalFormatId = preferencePageFormatId; + requestedFormatIsSupported = true; + break; + } + } + + if ( ! requestedFormatIsSupported ) { + /* + * Desired format is not supported. If there are any formats supported + * then use the first available. + */ + if ( formatIds.length != 0 ) { + finalFormatId = formatIds[0]; + } + else { + // Expression service does not support any format. + + handleFailedUpdate(update); + return; + } + } + + /* + * Format has been validated. Get the formatted value. + */ + FormattedValueDMContext valueDmc = expressionService.getFormattedValue(dmc, finalFormatId); + + expressionService.getModelData( + valueDmc, + new DataRequestMonitor(getSession().getExecutor(), null) { + @Override + public void handleCompleted() { + if (!getStatus().isOK()) { + handleFailedUpdate(update); + return; + } + + /* + * Fill the label/column with the properly formatted data value. + */ + update.setLabel(getData().getFormattedValue(), labelIndex); + update.done(); + } + } + ); + } + } + ); + } + + + @Override + protected void updateElementsInSessionThread(final IChildrenUpdate update) { + + // ISSUE: Do we need to explicitly get the IExecutionDMContext and ISymbolDMContext since they + // should be in the parent chain of the IFrameDMContext object? + + final IExecutionDMContext execDmc = + findDmcInPath(update.getElementPath(), IExecutionDMContext.class); + final IFrameDMContext frameDmc = + findDmcInPath(update.getElementPath(), IFrameDMContext.class); + //final ISymbolDMContext symbolDmc = + // findDmcInPath(update.getElementPath(), ISymbolDMContext.class); + + // Get the services we need to use. + + final IExpressions expressionService = getServicesTracker().getService(IExpressions.class); + final IStack stackFrameService = getServicesTracker().getService(IStack.class); + + if (execDmc == null || frameDmc == null || expressionService == null || stackFrameService == null) { + handleFailedUpdate(update); + return; + } + + final DsfExecutor dsfExecutor = getSession().getExecutor(); + + // Call IStack.getLocals() to get an array of IVariableDMContext objects representing the local + // variables in the stack frame represented by frameDmc. + + final DataRequestMonitor rm = + new DataRequestMonitor(dsfExecutor, null) { + @Override + public void handleCompleted() { + if (!getStatus().isOK()) { + handleFailedUpdate(update); + return; + } + + // For each IVariableDMContext object returned by IStack.getLocals(), call + // MIStackFrameService.getModelData() to get the IVariableDMData object. This requires + // a MultiRequestMonitor object. + + // First, get the data model context objects for the local variables. + + IVariableDMContext[] localsDMCs = getData(); + + if (localsDMCs == null) { + handleFailedUpdate(update); + return; + } + + // Create a List in which we store the DM data objects for the local variables. This is + // necessary because there is no MultiDataRequestMonitor. :) + + final List localsDMData = new ArrayList(); + + // Create the MultiRequestMonitor to handle completion of the set of getModelData() calls. + + final MultiRequestMonitor> mrm = + new MultiRequestMonitor>(dsfExecutor, null) { + @Override + public void handleCompleted() { + // Now that all the calls to getModelData() are complete, we create an + // IExpressionDMContext object for each local variable name, saving them all + // in an array. + + IExpressionDMContext[] expressionDMCs = new IExpressionDMContext[localsDMData.size()]; + + int i = 0; + + for (IVariableDMData localDMData : localsDMData) { + expressionDMCs[i++] = expressionService.createExpression(frameDmc, localDMData.getName()); + } + + // Lastly, we fill the update from the array of view model context objects + // that reference the ExpressionDMC objects for the local variables. This is + // the last code to run for a given call to updateElementsInSessionThread(). + // We can now leave anonymous-inner-class hell. + + fillUpdateWithVMCs(update, expressionDMCs); + update.done(); + } + }; + + // Perform a set of getModelData() calls, one for each local variable's data model + // context object. In the handleCompleted() method of the DataRequestMonitor, add the + // IVariableDMData object to the localsDMData List for later processing (see above). + + for (IVariableDMContext localDMC : localsDMCs) { + DataRequestMonitor rm = + new DataRequestMonitor(dsfExecutor, null) { + @Override + public void handleCompleted() { + localsDMData.add(getData()); + mrm.requestMonitorDone(this); + } + }; + + mrm.add(rm); + + stackFrameService.getModelData(localDMC, rm); + } + } + }; + + // Make the asynchronous call to IStack.getLocals(). The results are processed in the + // DataRequestMonitor.handleCompleted() above. + + stackFrameService.getLocals(frameDmc, rm); + } + + @Override + protected int getNodeDeltaFlagsForDMEvent(IDMEvent e) { + if (e instanceof IRunControl.ISuspendedDMEvent) { + return IModelDelta.CONTENT; + // } else if (e instanceof IRegisters.IRegisterChangedDMEvent) { + // return IModelDelta.STATE; + } + return IModelDelta.NO_CHANGE; + } + + @Override + protected void buildDeltaForDMEvent(IDMEvent e, VMDelta parent, + int nodeOffset, RequestMonitor requestMonitor) { + if (e instanceof IRunControl.ISuspendedDMEvent) { + // Create a delta that the whole register group has changed. + parent.addFlags(IModelDelta.CONTENT); + } + // if (e instanceof IRegisters.IRegisterChangedDMEvent) { + // parent.addNode(new + // DMVMContext(((IRegisters.IRegisterChangedDMEvent)e).getDMContext()), + // IModelDelta.STATE); + // } + super.buildDeltaForDMEvent(e, parent, nodeOffset, requestMonitor); + } +} Index: src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/VariableSubExpressionsLayoutNode.java =================================================================== RCS file: src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/VariableSubExpressionsLayoutNode.java diff -N src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/VariableSubExpressionsLayoutNode.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/dd/dsf/debug/ui/viewmodel/variable/VariableSubExpressionsLayoutNode.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,297 @@ +/******************************************************************************* + * 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 java.util.Iterator; +import java.util.List; + +import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; +import org.eclipse.dd.dsf.concurrent.DsfExecutor; +import org.eclipse.dd.dsf.concurrent.RequestMonitor; +import org.eclipse.dd.dsf.datamodel.IDMEvent; +import org.eclipse.dd.dsf.datamodel.IDMService; +import org.eclipse.dd.dsf.debug.service.IExpressions; +import org.eclipse.dd.dsf.debug.service.IFormattedValues; +import org.eclipse.dd.dsf.debug.service.IRunControl; +import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMContext; +import org.eclipse.dd.dsf.debug.service.IExpressions.IExpressionDMData; +import org.eclipse.dd.dsf.debug.service.IFormattedValues.FormattedValueDMContext; +import org.eclipse.dd.dsf.debug.service.IFormattedValues.FormattedValueDMData; +import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMContext; +import org.eclipse.dd.dsf.debug.ui.viewmodel.IDebugVMConstants; +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.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 VariableSubExpressionsLayoutNode extends AbstractDMVMLayoutNode { + + public VariableSubExpressionsLayoutNode(AbstractVMProvider provider, DsfSession session) { + super(provider, session, IExpressions.IExpressionDMContext.class); + } + + /** + * List of child nodes containing only a reference to this. This is what enables the view model + * provider to know about the recursive nature of subexpression nodes. + */ + private final IVMLayoutNode[] fChildLayoutNodes = { this }; + + @Override + public IVMLayoutNode[] getChildLayoutNodes() { + return fChildLayoutNodes; + } + + + /** + * We override this method because we now need to perform an extra level of data fetch to get the + * formatted value of the expression. + * + * @return void + */ + @Override + protected void updateLabelInSessionThread(ILabelUpdate[] updates) { + for (final ILabelUpdate update : updates) { + + final IExpressionDMContext dmc = findDmcInPath(update.getElementPath(), IExpressions.IExpressionDMContext.class); + + ((IDMService)getServicesTracker().getService(null, dmc.getServiceFilter())).getModelData( + dmc, + new DataRequestMonitor(getSession().getExecutor(), null) { + @Override + protected void handleCompleted() { + // Check that the request was evaluated and data is still valid. The request could + // fail if the state of the service changed during the request, but the view model + // has not been updated yet. + + if (!getStatus().isOK() || !getData().isValid()) { + assert getStatus().isOK() || + getStatus().getCode() != IDsfService.INTERNAL_ERROR || + getStatus().getCode() != IDsfService.NOT_SUPPORTED; + handleFailedUpdate(update); + return; + } + + // If columns are configured, extract the selected values for each understood column. + // First, we fill all of those columns which can be filled without extra data mining. + // We also note if we do have to do extra data mining. Any columns need to set the + // processing flag so we know we have further work to do. If there are more columns + // which need data extraction they need to be added in both "for" loops. + + String[] localColumns = update.getPresentationContext().getColumns(); + if (localColumns == null) + localColumns = new String[] { null }; + + boolean weAreExtractingFormattedData = false; + + for (int idx = 0; idx < localColumns.length; idx++) { + if (IDebugVMConstants.COLUMN_ID__NAME.equals(localColumns[idx])) { + update.setLabel(getData().getName(), idx); + } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(localColumns[idx])) { + weAreExtractingFormattedData = true; + } else if (IDebugVMConstants.COLUMN_ID__DESCRIPTION.equals(localColumns[idx])) { + update.setLabel("", idx); //$NON-NLS-1$ + } + } + + if ( ! weAreExtractingFormattedData ) { + update.done(); + } else { + for (int idx = 0; idx < localColumns.length; idx++) { + if (IDebugVMConstants.COLUMN_ID__VALUE.equals(localColumns[idx])) { + updateFormattedExpressionValue(update, idx, dmc); + } + } + } + } + } + ); + } + } + + + /** + * Private data access routine which performs the extra level of data access needed to + * get the formatted data value for a specific register. + */ + private void updateFormattedExpressionValue(final ILabelUpdate update, final int labelIndex, + final IExpressionDMContext dmc) + { + final IExpressions expressionService = getServicesTracker().getService(IExpressions.class); + /* + * PREFPAGE : We are using a default format until the preference page is created + * + * First select the format to be used. This involves checking so see that the preference + * page format is supported by the register service. If the format is not supported then + * we will pick the first available format. + */ + + final String preferencePageFormatId = IFormattedValues.NATURAL_FORMAT; + + expressionService.getAvailableFormattedValues( + dmc, + new DataRequestMonitor(getSession().getExecutor(), null) { + @Override + public void handleCompleted() { + if (!getStatus().isOK()) { + handleFailedUpdate(update); + return; + } + + /* + * See if the desired format is supported. + */ + String[] formatIds = getData(); + String finalFormatId = IFormattedValues.NATURAL_FORMAT; + boolean requestedFormatIsSupported = false; + + for ( String fId : formatIds ) { + if ( preferencePageFormatId.equals(fId) ) { + // The desired format is supported. + + finalFormatId = preferencePageFormatId; + requestedFormatIsSupported = true; + break; + } + } + + if ( ! requestedFormatIsSupported ) { + /* + * Desired format is not supported. If there are any formats supported + * then use the first available. + */ + if ( formatIds.length != 0 ) { + finalFormatId = formatIds[0]; + } + else { + // Expression service does not support any format. + + handleFailedUpdate(update); + return; + } + } + + /* + * Format has been validated. Get the formatted value. + */ + FormattedValueDMContext valueDmc = expressionService.getFormattedValue(dmc, finalFormatId); + + expressionService.getModelData( + valueDmc, + new DataRequestMonitor(getSession().getExecutor(), null) { + @Override + public void handleCompleted() { + if (!getStatus().isOK()) { + handleFailedUpdate(update); + return; + } + + /* + * Fill the label/column with the properly formatted data value. + */ + update.setLabel(getData().getFormattedValue(), labelIndex); + update.done(); + } + } + ); + } + } + ); + } + + + @Override + protected void updateElementsInSessionThread(final IChildrenUpdate update) { + // Get the data model context object for the current node in the hierarchy. + + final IExpressionDMContext expressionDMC = findDmcInPath(update.getElementPath(), IExpressionDMContext.class); + + // ISSUE: Do we need to explicitly get the IExecutionDMContext and ISymbolDMContext since they + // should be in the parent chain of the IFrameDMContext object? + + final IExecutionDMContext execDmc = findDmcInPath(update.getElementPath(), IExecutionDMContext.class); + final IFrameDMContext frameDmc = findDmcInPath(update.getElementPath(), IFrameDMContext.class); + //final ISymbolDMContext symbolDmc = findDmcInPath(update.getElementPath(), ISymbolDMContext.class); + + // Get the services we need to use. + + final IExpressions expressionService = getServicesTracker().getService(IExpressions.class); + + if (execDmc == null || frameDmc == null || expressionService == null) { + handleFailedUpdate(update); + return; + } + + final DsfExecutor dsfExecutor = getSession().getExecutor(); + + // Call IExpressions.getSubExpressions() to get an Iterable of IExpressionDMContext objects representing + // the sub-expressions of the expression represented by the current expression node. + + final DataRequestMonitor> rm = + new DataRequestMonitor>(dsfExecutor, null) { + @Override + public void handleCompleted() { + if (!getStatus().isOK()) { + handleFailedUpdate(update); + return; + } + + // Fill the update with the the IExpressionDMContext objects returned by + // IExpressions.getSubExpressions(). + + List subExpressionDMCList = (List)getData(); + IExpressionDMContext[] subExpressionDMCArray = new IExpressionDMContext[subExpressionDMCList.size()]; + Iterator iter = subExpressionDMCList.iterator(); + + int i = 0; + while (iter.hasNext()) { + subExpressionDMCArray[i++] = iter.next(); + } + + fillUpdateWithVMCs(update, subExpressionDMCArray); + update.done(); + } + }; + + // Make the asynchronous call to IExpressions.getSubExpressions(). The results are processed in the + // DataRequestMonitor.handleCompleted() above. + + expressionService.getSubExpressions(expressionDMC, rm); + } + + @Override + protected int getNodeDeltaFlagsForDMEvent(IDMEvent e) { + if (e instanceof IRunControl.ISuspendedDMEvent) { + return IModelDelta.CONTENT; +// } else if (e instanceof IRegisters.IExpressionsChangedDMEvent) { +// return IModelDelta.STATE; + } + return IModelDelta.NO_CHANGE; + } + + @Override + protected void buildDeltaForDMEvent(IDMEvent e, VMDelta parent, int nodeOffset, RequestMonitor requestMonitor) { + if (e instanceof IRunControl.ISuspendedDMEvent) { + // Create a delta that the whole register group has changed. + parent.addFlags(IModelDelta.CONTENT); + } +// if (e instanceof IRegisters.IRegisterChangedDMEvent) { +// parent.addNode( new DMVMContext(((IRegisters.IRegisterChangedDMEvent)e).getDMContext()), IModelDelta.STATE ); +// } + super.buildDeltaForDMEvent(e, parent, nodeOffset, requestMonitor); + } +}