diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ContainerVMNode.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ContainerVMNode.java index bff2b7d7dbd..82b729d0a6d 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ContainerVMNode.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ContainerVMNode.java @@ -16,29 +16,32 @@ package org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel.launch; import java.util.concurrent.RejectedExecutionException; import org.eclipse.cdt.dsf.concurrent.DsfRunnable; +import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; +import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.debug.service.IProcesses; -import org.eclipse.cdt.dsf.debug.service.IRunControl; import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext; import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMData; import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent; import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.AbstractContainerVMNode; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.ILaunchVMConstants; +import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.cdt.dsf.ui.concurrent.ViewerCountingRequestMonitor; import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor; import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.VMDelegatingPropertiesUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest; -import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; -import org.eclipse.debug.ui.DebugUITools; -import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.ui.IMemento; @@ -79,50 +82,56 @@ public class ContainerVMNode extends AbstractContainerVMNode }); } - - @Override - protected void updateLabelInSessionThread(final ILabelUpdate update) { - IProcesses processService = getServicesTracker().getService(IProcesses.class); - IRunControl runControl = getServicesTracker().getService(IRunControl.class); - if (processService == null || runControl == null) { - handleFailedUpdate(update); - return; - } - - final IProcessDMContext procDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IProcessDMContext.class); - final IContainerDMContext contDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IContainerDMContext.class); - - String imageKey = null; - if (runControl.isSuspended(contDmc)) { - imageKey = IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED; - } else { - imageKey = IDebugUIConstants.IMG_OBJS_THREAD_RUNNING; - } - update.setImageDescriptor(DebugUITools.getImageDescriptor(imageKey), 0); - - processService.getExecutionData( - procDmc, - new ViewerDataRequestMonitor(getExecutor(), update) { - @Override - public void handleCompleted() { - if (!isSuccess()) { - update.setLabel("", 0); //$NON-NLS-1$ - update.done(); - return; - } - - // Create Labels of type Name[PID] if the pid is available - final StringBuilder builder = new StringBuilder(); - builder.append(getData().getName()); - if (getData().getId() != null && getData().getId().length() > 0) { - builder.append("[" + getData().getId()+ "]"); //$NON-NLS-1$//$NON-NLS-2$ - } - update.setLabel(builder.toString(), 0); - update.done(); - } - }); - } + @Override + protected void updatePropertiesInSessionThread(IPropertiesUpdate[] updates) { + IPropertiesUpdate[] parentUpdates = new IPropertiesUpdate[updates.length]; + + for (int i = 0; i < updates.length; i++) { + final IPropertiesUpdate update = updates[i]; + + final ViewerCountingRequestMonitor countringRm = + new ViewerCountingRequestMonitor(ImmediateExecutor.getInstance(), updates[i]); + int count = 0; + + // Create a delegating update which will let the super-class fill in the + // standard container properties. + parentUpdates[i] = new VMDelegatingPropertiesUpdate(updates[i], countringRm); + count++; + + IProcesses processService = getServicesTracker().getService(IProcesses.class); + final IProcessDMContext procDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IProcessDMContext.class); + + if (processService == null || procDmc == null) { + update.setStatus(DsfUIPlugin.newErrorStatus(IDsfStatusConstants.INVALID_HANDLE, "Service or handle invalid", null)); //$NON-NLS-1$ + } else { + processService.getExecutionData( + procDmc, + new ViewerDataRequestMonitor(getExecutor(), update) { + @Override + public void handleCompleted() { + if (isSuccess()) { + fillThreadDataProperties(update, getData()); + } else { + update.setStatus(getStatus()); + } + countringRm.done(); + } + }); + count++; + } + + countringRm.setDoneCount(count); + } + + super.updatePropertiesInSessionThread(parentUpdates); + } + + protected void fillThreadDataProperties(IPropertiesUpdate update, IThreadDMData data) { + update.setProperty(PROP_NAME, data.getName()); + update.setProperty(ILaunchVMConstants.PROP_ID, data.getId()); + } + @Override public int getDeltaFlags(Object e) { if (e instanceof ICommandControlShutdownDMEvent) { diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ThreadVMNode.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ThreadVMNode.java index 1942e2e8a63..1dfc629c5ac 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ThreadVMNode.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/ThreadVMNode.java @@ -11,26 +11,27 @@ *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel.launch; +import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; +import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.debug.service.IProcesses; -import org.eclipse.cdt.dsf.debug.service.IRunControl; -import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext; +import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext; import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMData; -import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMData; -import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason; import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.AbstractThreadVMNode; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.ILaunchVMConstants; +import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext; import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.cdt.dsf.ui.concurrent.ViewerCountingRequestMonitor; import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.VMDelegatingPropertiesUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest; -import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; -import org.eclipse.debug.ui.DebugUITools; -import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.ui.IMemento; @@ -48,84 +49,57 @@ public class ThreadVMNode extends AbstractThreadVMNode } @Override - protected void updateLabelInSessionThread(ILabelUpdate[] updates) { - for (final ILabelUpdate update : updates) { - final IRunControl runControl = getServicesTracker().getService(IRunControl.class); - if (runControl == null) { - handleFailedUpdate(update); - continue; - } + protected void updatePropertiesInSessionThread(IPropertiesUpdate[] updates) { + IPropertiesUpdate[] parentUpdates = new IPropertiesUpdate[updates.length]; + + for (int i = 0; i < updates.length; i++) { + final IPropertiesUpdate update = updates[i]; - final IMIExecutionDMContext execDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IMIExecutionDMContext.class); - - String imageKey = null; - final boolean threadSuspended; - if (runControl.isSuspended(execDmc)) { - threadSuspended = true; - imageKey = IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED; + final ViewerCountingRequestMonitor countringRm = + new ViewerCountingRequestMonitor(ImmediateExecutor.getInstance(), updates[i]); + int count = 0; + + // Create a delegating update which will let the super-class fill in the + // standard container properties. + parentUpdates[i] = new VMDelegatingPropertiesUpdate(updates[i], countringRm); + count++; + + IProcesses processService = getServicesTracker().getService(IProcesses.class); + final IProcessDMContext procDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IProcessDMContext.class); + + if (processService == null || procDmc == null) { + update.setStatus(DsfUIPlugin.newErrorStatus(IDsfStatusConstants.INVALID_HANDLE, "Service or handle invalid", null)); //$NON-NLS-1$ } else { - threadSuspended = false; - imageKey = IDebugUIConstants.IMG_OBJS_THREAD_RUNNING; - } - update.setImageDescriptor(DebugUITools.getImageDescriptor(imageKey), 0); - - // Find the Reason for the State - runControl.getExecutionData(execDmc, - new ViewerDataRequestMonitor(getSession().getExecutor(), update) { - @Override - public void handleCompleted(){ - if (!isSuccess()) { - update.setLabel("", 0); //$NON-NLS-1$ - update.done(); - return; - } - - final IProcesses procService = getServicesTracker().getService(IProcesses.class); - if ( procService == null ) { - handleFailedUpdate(update); - return; - } - - final StateChangeReason reason = getData().getStateChangeReason(); - - // Retrieve the rest of the thread information - final IThreadDMContext threadDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IThreadDMContext.class); - - procService.getExecutionData( - threadDmc, - new ViewerDataRequestMonitor(getSession().getExecutor(), update) { - @Override - public void handleCompleted() { - // We can still generate a good enough label even if this call fails - // so continue and check if we should use getData() or not. - - // Create Labels of type Thread[GDBthreadId]RealThreadID/Name (State: Reason) - // Thread[1] 3457 (Suspended:BREAKPOINT) - final StringBuilder builder = new StringBuilder("Thread["); //$NON-NLS-1$ - builder.append(execDmc.getThreadId()); - builder.append("] "); //$NON-NLS-1$ - if (isSuccess()) { - builder.append(getData().getId()); - builder.append(getData().getName()); + processService.getExecutionData( + procDmc, + new ViewerDataRequestMonitor(getExecutor(), update) { + @Override + public void handleCompleted() { + if (isSuccess()) { + fillThreadDataProperties(update, getData()); + } else { + final IMIExecutionDMContext execDmc = findDmcInPath( + update.getViewerInput(), update.getElementPath(), IMIExecutionDMContext.class); + if (execDmc != null) { + update.setProperty(ILaunchVMConstants.PROP_ID, Integer.toString(execDmc.getThreadId())); + } else { + update.setStatus(getStatus()); } - if(threadSuspended) - builder.append(" (Suspended"); //$NON-NLS-1$ - else - builder.append(" (Running"); //$NON-NLS-1$ - // Reason will be null before ContainerSuspendEvent is fired - if(reason != null) { - builder.append(" : "); //$NON-NLS-1$ - builder.append(reason); - } - builder.append(")"); //$NON-NLS-1$ - update.setLabel(builder.toString(), 0); - update.done(); } - }); - } - }); + countringRm.done(); + } + }); + count++; + } + countringRm.setDoneCount(count); } + super.updatePropertiesInSessionThread(parentUpdates); + } + + protected void fillThreadDataProperties(IPropertiesUpdate update, IThreadDMData data) { + update.setProperty(PROP_NAME, data.getName()); + update.setProperty(ILaunchVMConstants.PROP_ID, data.getId()); } private String produceThreadElementName(String viewName, IMIExecutionDMContext execCtx) { diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_0.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_0.java index cffccb78d99..2b583b3229c 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_0.java @@ -469,26 +469,6 @@ public class GDBProcesses_7_0 extends AbstractDsfService return execDmcList.toArray(new IMIExecutionDMContext[0]); } - /** - * This method obtains the model data for a given IThreadDMContext object - * which can represent a thread or a process. - * - * @param dmc - * The context for which we are requesting the data - * @param rm - * The request monitor that will contain the requested data - */ - @SuppressWarnings("unchecked") - public void getModelData(IDMContext dmc, DataRequestMonitor rm) { - if (dmc instanceof IThreadDMContext) { - getExecutionData((IThreadDMContext) dmc, - (DataRequestMonitor) rm); - } else { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid DMC type", null)); //$NON-NLS-1$ - rm.done(); - } - } - public void getExecutionData(IThreadDMContext dmc, final DataRequestMonitor rm) { if (dmc instanceof IMIProcessDMContext) { final String id = ((IMIProcessDMContext)dmc).getProcId(); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java index 8e728b2de03..f2e38630626 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java @@ -244,20 +244,6 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IRunCont return GdbPlugin.getBundleContext(); } - /////////////////////////////////////////////////////////////////////////// - // IDMService - /////////////////////////////////////////////////////////////////////////// - - @SuppressWarnings("unchecked") - public void getModelData(IDMContext dmc, DataRequestMonitor rm) { - if (dmc instanceof IExecutionDMContext) { - getExecutionData((IExecutionDMContext) dmc, (DataRequestMonitor) rm); - } else { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ - rm.done(); - } - } - /////////////////////////////////////////////////////////////////////////// // IRunControl /////////////////////////////////////////////////////////////////////////// diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIExpressions.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIExpressions.java index 7536654de27..bc01af2fc03 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIExpressions.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIExpressions.java @@ -562,29 +562,6 @@ public class MIExpressions extends AbstractDsfService implements IExpressions, I IFormattedValues.OCTAL_FORMAT, IFormattedValues.DECIMAL_FORMAT }); rm.done(); } - - /** - * This method obtains the model data for a given ExpressionDMC object or - * for a FormattedValueDMC, or for this DSF service. - * - * @param dmc - * The context for which we are requesting the data - * @param rm - * The request monitor that will contain the requested data - */ - @SuppressWarnings("unchecked") - public void getModelData(IDMContext dmc, DataRequestMonitor rm) { - if (dmc instanceof MIExpressionDMC) { - getExpressionData((MIExpressionDMC) dmc, - (DataRequestMonitor) rm); - } else if (dmc instanceof FormattedValueDMContext) { - getFormattedExpressionValue((FormattedValueDMContext) dmc, - (DataRequestMonitor) rm); - } else { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ - rm.done(); - } - } /** * Obtains the static data of an expression represented diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIProcesses.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIProcesses.java index 49d8f1c0144..fe4abf424aa 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIProcesses.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIProcesses.java @@ -399,26 +399,6 @@ public class MIProcesses extends AbstractDsfService implements IMIProcesses, ICa return createContainerContext(processDmc, groupId); } - /** - * This method obtains the model data for a given IThreadDMContext object - * which can represent a thread or a process. - * - * @param dmc - * The context for which we are requesting the data - * @param rm - * The request monitor that will contain the requested data - */ - @SuppressWarnings("unchecked") - public void getModelData(IDMContext dmc, DataRequestMonitor rm) { - if (dmc instanceof IThreadDMContext) { - getExecutionData((IThreadDMContext) dmc, - (DataRequestMonitor) rm); - } else { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid DMC type", null)); //$NON-NLS-1$ - rm.done(); - } - } - public void getExecutionData(IThreadDMContext dmc, final DataRequestMonitor rm) { if (dmc instanceof MIProcessDMC) { rm.setData(new MIThreadDMData("", ((MIProcessDMC)dmc).getProcId())); //$NON-NLS-1$ diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRegisters.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRegisters.java index 8a958d59eb1..39e8d7b9589 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRegisters.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRegisters.java @@ -202,27 +202,6 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach public boolean isValid() { return true; } - @SuppressWarnings("unchecked") - public void getModelData(IDMContext dmc, DataRequestMonitor rm) { - /* - * This is the method which is called when actual results need to be returned. We - * can be called either with a service DMC for which we return ourselves or we can - * be called with the DMC's we have handed out. If the latter is the case then we - * data mine by talking to the Debug Engine. - */ - - if (dmc instanceof MIRegisterGroupDMC) { - getRegisterGroupData((MIRegisterGroupDMC)dmc, (DataRequestMonitor)rm); - } else if (dmc instanceof MIRegisterDMC) { - getRegisterData((MIRegisterDMC)dmc, (DataRequestMonitor)rm); - } else if (dmc instanceof FormattedValueDMContext) { - getFormattedExpressionValue((FormattedValueDMContext)dmc, (DataRequestMonitor)rm); - } else { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Unknown DMC type", null)); //$NON-NLS-1$ - rm.done(); - } - } - public void getFormattedExpressionValue(FormattedValueDMContext dmc, DataRequestMonitor rm) { if (dmc.getParents().length == 1 && dmc.getParents()[0] instanceof MIRegisterDMC) { getRegisterDataValue( (MIRegisterDMC) dmc.getParents()[0], dmc.getFormatID(), rm); @@ -534,12 +513,12 @@ public class MIRegisters extends AbstractDsfService implements IRegisters, ICach final MIExpressions exprService = getServicesTracker().getService(MIExpressions.class); String regName = regDmc.getName(); final IExpressionDMContext exprCtxt = exprService.createExpression(regCtx, "$" + regName); //$NON-NLS-1$ - exprService.getModelData(exprCtxt, new DataRequestMonitor(getExecutor(), rm) { + exprService.getExpressionData(exprCtxt, new DataRequestMonitor(getExecutor(), rm) { @Override protected void handleSuccess() { // Evaluate the expression - request HEX since it works in every case final FormattedValueDMContext valueDmc = exprService.getFormattedValueContext(exprCtxt, formatId); - exprService.getModelData( + exprService.getFormattedExpressionValue( valueDmc, new DataRequestMonitor(getExecutor(), rm) { @Override diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRunControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRunControl.java index db8c1b74af4..e2c9b799a77 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRunControl.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIRunControl.java @@ -314,16 +314,6 @@ public class MIRunControl extends AbstractDsfService implements IRunControl, ICa /** @since 2.0 */ protected void setTerminated(boolean terminated) { fTerminated = terminated; } - @SuppressWarnings("unchecked") - public void getModelData(IDMContext dmc, DataRequestMonitor rm) { - if (dmc instanceof IExecutionDMContext) { - getExecutionData((IExecutionDMContext)dmc, (DataRequestMonitor)rm); - } else { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ - rm.done(); - } - } - public CommandCache getCache() { return fMICommandCache; } /** @since 2.0 */ protected ICommandControlService getConnection() { return fConnection; } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIStack.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIStack.java index a7a3c57b031..b163bba7bba 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIStack.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIStack.java @@ -208,20 +208,6 @@ public class MIStack extends AbstractDsfService super.shutdown(rm); } - @SuppressWarnings("unchecked") - public void getModelData(IDMContext dmc, DataRequestMonitor rm) { - if (dmc instanceof MIFrameDMC) { - getFrameData((MIFrameDMC)dmc, (DataRequestMonitor)rm); - // getFrameData invokes rm - } else if (dmc instanceof MIVariableDMC) { - getVariableData((MIVariableDMC)dmc, (DataRequestMonitor)rm); - // getVariablesData invokes rm - } else { - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Unknown DMC type", null)); //$NON-NLS-1$ - rm.done(); - } - } - /** * Creates a frame context. This method is intended to be used by other MI * services and sub-classes which need to create a frame context directly. diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/viewmodel/numberformat/detail/MessagesForNumberFormatDetailPane.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/viewmodel/numberformat/detail/MessagesForNumberFormatDetailPane.java index 8d758797f43..337c267e2dc 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/viewmodel/numberformat/detail/MessagesForNumberFormatDetailPane.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/viewmodel/numberformat/detail/MessagesForNumberFormatDetailPane.java @@ -20,13 +20,7 @@ public class MessagesForNumberFormatDetailPane extends NLS { private static final String BUNDLE_NAME = "org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.numberformat.detail.messages"; //$NON-NLS-1$ - public static String NumberFormatDetailPane_Natural_label; - public static String NumberFormatDetailPane_Decimal_label; - public static String NumberFormatDetailPane_Hex_label; - public static String NumberFormatDetailPane_Octal_label; - public static String NumberFormatDetailPane_Binary_label; - public static String NumberFormatDetailPane_String_label; - public static String NumberFormatDetailPane_Other_label; + public static String NumberFormatDetailPane_format_separator__label; public static String NumberFormatDetailPane_Name_label; public static String NumberFormatDetailPane_Spaces_label; public static String NumberFormatDetailPane_CarriageReturn_label; diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/viewmodel/numberformat/detail/NumberFormatDetailPane.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/viewmodel/numberformat/detail/NumberFormatDetailPane.java index 22156dfee53..b11b9949b40 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/viewmodel/numberformat/detail/NumberFormatDetailPane.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/viewmodel/numberformat/detail/NumberFormatDetailPane.java @@ -12,44 +12,38 @@ package org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.numberformat.detail; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.concurrent.Executor; -import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; -import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.detailsupport.DetailPaneMaxLengthAction; import org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.detailsupport.DetailPaneWordWrapAction; import org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.detailsupport.MessagesForDetailPane; import org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.detailsupport.TextViewerAction; -import org.eclipse.cdt.dsf.debug.service.IExpressions; -import org.eclipse.cdt.dsf.debug.service.IFormattedValues; -import org.eclipse.cdt.dsf.debug.service.IRegisters; -import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext; -import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext; -import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMData; -import org.eclipse.cdt.dsf.debug.service.IFormattedValues.IFormattedDataDMContext; -import org.eclipse.cdt.dsf.debug.service.IRegisters.IBitFieldDMContext; -import org.eclipse.cdt.dsf.debug.service.IRegisters.IBitFieldDMData; -import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext; -import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData; import org.eclipse.cdt.dsf.debug.ui.IDsfDebugUIConstants; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueVMUtil; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; -import org.eclipse.cdt.dsf.service.DsfServicesTracker; -import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode; -import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; -import org.eclipse.cdt.dsf.ui.viewmodel.update.AbstractCachingVMProvider; +import org.eclipse.cdt.dsf.ui.concurrent.SimpleDisplayExecutor; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.VMPropertiesUpdate; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.model.IDebugModelProvider; import org.eclipse.debug.core.model.IValue; import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; -import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer; import org.eclipse.debug.ui.IDebugModelPresentation; import org.eclipse.debug.ui.IDebugUIConstants; @@ -249,35 +243,12 @@ public class NumberFormatDetailPane implements IDetailPane, IAdaptable, IPropert /** * Useful shortened names for the internationalized strings. */ - public static String HEX = MessagesForNumberFormatDetailPane.NumberFormatDetailPane_Hex_label; - public static String NATURAL = MessagesForNumberFormatDetailPane.NumberFormatDetailPane_Natural_label; - public static String DECIMAL = MessagesForNumberFormatDetailPane.NumberFormatDetailPane_Decimal_label; - public static String OCTAL = MessagesForNumberFormatDetailPane.NumberFormatDetailPane_Octal_label; - public static String BINARY = MessagesForNumberFormatDetailPane.NumberFormatDetailPane_Binary_label; - public static String STRING = MessagesForNumberFormatDetailPane.NumberFormatDetailPane_String_label; - public static String OTHER = MessagesForNumberFormatDetailPane.NumberFormatDetailPane_String_label; + public static String FORMAT_SEPARATOR = MessagesForNumberFormatDetailPane.NumberFormatDetailPane_format_separator__label; public static String NAME = MessagesForNumberFormatDetailPane.NumberFormatDetailPane_Name_label; public static String SPACES = MessagesForNumberFormatDetailPane.NumberFormatDetailPane_Spaces_label; public static String CRLF = MessagesForNumberFormatDetailPane.NumberFormatDetailPane_CarriageReturn_label; public static String DOTS = MessagesForNumberFormatDetailPane.NumberFormatDetailPane_DotDotDot_label; - /* - * Returns a formatted combination of format label and its corresponding value. - */ - private String formatNumericResult(String format, String value) { - - /* - * Select the proper string format and create the total value to be displayed. - */ - if ( format == IFormattedValues.HEX_FORMAT) { return(HEX + value); } - else if ( format == IFormattedValues.OCTAL_FORMAT) { return(OCTAL + value); } - else if ( format == IFormattedValues.NATURAL_FORMAT) { return(NATURAL + value); } - else if ( format == IFormattedValues.BINARY_FORMAT) { return(BINARY + value); } - else if ( format == IFormattedValues.DECIMAL_FORMAT) { return(DECIMAL + value); } - else if ( format == IFormattedValues.STRING_FORMAT) { return(STRING + value); } - else { return(OTHER + value); } - } - /** * Job to compute the details for a selection */ @@ -299,142 +270,11 @@ public class NumberFormatDetailPane implements IDetailPane, IAdaptable, IPropert fElements = elements; } - /* - * This is the routine which will actually process the various format requests - * for a given element. It is expected and required that this routine will be - * called from within a DSF executor. - */ - private void putInformationIntoDetailPane( final AbstractCachingVMProvider provider, - final IVMNode node, - final TreePath path, - final IFormattedDataDMContext finalDmc , - final IFormattedValues service, - final IProgressMonitor monitor, - final String name ) { - - /* - * Now that we can process this one. Find out how many formats we can - * show this in. We will choose to show all of the supported formats. - * Since we are doing this in the background and the debug engines do - * typically cache the results so producing multiple formats will not - * typically be a burden. We should probably consider perhaps doing a - * preference where they can select what formats they want to show. - */ - final DataRequestMonitor getAvailableFormatsDone = - new DataRequestMonitor(service.getExecutor(), null) { - @Override - protected void handleSuccess() { - if (monitor.isCanceled()) { - notifyAll(); - return; - } - - /* - * Now we have a set of formats for each one fire up an independent - * asynchronous request to get the data in that format. We do not - * go through the cache manager here because when the values are - * edited and written the cache is bypassed. - */ - String[] formats = getData(); - - final List completedFormatStrings = new ArrayList(); - - final CountingRequestMonitor countingRm = new CountingRequestMonitor(service.getExecutor(), null) { - @Override - protected void handleCompleted() { - - if (monitor.isCanceled()) { - notifyAll(); - return; - } - - /* - * We sort the array to make the strings appear always in the same order. - */ - java.util.Collections.sort( completedFormatStrings ); - - int len = completedFormatStrings.size() ; - - if ( len == 0 ) { - detailComputed(null,""); //$NON-NLS-1$ - } - else { - /* - * Add the HEADER which identifies what is being represented. When there - * are multiple selections in the view the detail pane contains multiple - * entries. They would be all compressed together and even though the - * order of the entries is the order of the selections in the view and - * it is very hard to know what goes with what. This makes it easy. - */ - String finalResult = NAME + name + CRLF; - int cnt = 0 ; - - for (String str : completedFormatStrings) { - - finalResult += SPACES + str ; - - if ( ( ++ cnt ) < len ) { - finalResult += CRLF; - } - } - - detailComputed(null,finalResult); - } - } - }; - - countingRm.setDoneCount(formats.length); - - for ( final String str : formats ) { - /* - * Format has been validated. Get the formatted value. - */ - final FormattedValueDMContext valueDmc = service.getFormattedValueContext(finalDmc, str); - - provider.getModelData( - node, - new IViewerUpdate() { - public void cancel() {} - public void done() {} - public Object getViewerInput() { return fViewerInput; } - public TreePath getElementPath() { return path; } - public Object getElement() { return path.getLastSegment(); } - public IPresentationContext getPresentationContext() { return fPresentationContext; } - public boolean isCanceled() { return monitor.isCanceled(); } - public void setStatus(IStatus status) {} - public IStatus getStatus() { return null; } - }, - service, valueDmc, - new DataRequestMonitor(service.getExecutor(), null) { - @Override - public void handleCompleted() { - if (getStatus().isOK()) { - /* - * Show the information indicating the format. - */ - completedFormatStrings.add( formatNumericResult( str, getData().getFormattedValue() ) ); - } - countingRm.done(); - } - }, - provider.getExecutor()); - } - } - }; - - /* - * Get the supported formats. - */ - service.getAvailableFormats(finalDmc, getAvailableFormatsDone); - } - /* (non-Javadoc) * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor) */ @Override protected IStatus run(final IProgressMonitor monitor) { - - String message = null; if ( fMonitor != null && ! fMonitor.isCanceled() ) { fMonitor.setCanceled(true); } @@ -447,158 +287,62 @@ public class NumberFormatDetailPane implements IDetailPane, IAdaptable, IPropert final TreePath path = paths[i]; Object element = paths[i].getLastSegment(); - /* - * Make sure this is an element we want to deal with. - */ - if ( element instanceof IDMVMContext) { - IDMVMContext vmc = (IDMVMContext)element; - /* - * We are specifically looking to support the following Data Model Contexts - * - * IRegisterDMContext - * IBitFieldDMContext - * IExpressionDMContext - * - * At first you might think that we should just use the service which is - * associated with the dmc. But there are implementations where the data - * model contexts are extended but the services do not extend each other - * ( this is the case with the WindRiver OCD extensions for example ). - * - * So here we specifically look for the service which knows how to deal - * with the formatted data. - * - * Please note that the order or searching for the ancestor is important. - * A BitField Data Model Context will have a Register Data Model Context - * as its parent so if we search for a Register DMC first when we actually - * have a BitField DMC we will get the register and show the value of the - * register not the bit field. - */ - - DsfServicesTracker tracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), vmc.getDMContext().getSessionId()); - - final AbstractCachingVMProvider provider = (AbstractCachingVMProvider)vmc.getAdapter(AbstractCachingVMProvider.class); - final IVMNode node = (IVMNode)vmc.getAdapter(IVMNode.class); - - final IBitFieldDMContext bitfieldDmc = DMContexts.getAncestorOfType(((IDMVMContext) element).getDMContext(), IBitFieldDMContext.class); - if ( bitfieldDmc != null ) { - /* - * Get the name so we can construct the header which identifies the detail - * set of values. - */ - final IRegisters regService = tracker.getService(IRegisters.class); - - regService.getExecutor().submit( - new Runnable() { - public void run() { - regService.getBitFieldData( - bitfieldDmc, - new DataRequestMonitor(regService.getExecutor(), null) { - @Override - public void handleCompleted() { - if (getStatus().isOK()) { - putInformationIntoDetailPane(provider, node, path, bitfieldDmc , regService, monitor, getData().getName()); - } - } - } - ); - } - } - ); - } - else { - final IRegisterDMContext regDmc = DMContexts.getAncestorOfType(((IDMVMContext) element).getDMContext(), IRegisterDMContext.class); - - if ( regDmc != null ) { - /* - * Get the name so we can construct the header which identifies the detail - * set of values. - */ - final IRegisters regService = tracker.getService(IRegisters.class); - - regService.getExecutor().submit( - new Runnable() { - public void run() { - regService.getRegisterData( - regDmc, - new DataRequestMonitor(regService.getExecutor(), null) { - @Override - public void handleCompleted() { - if (getStatus().isOK()) { - putInformationIntoDetailPane(provider, node, path, regDmc , regService, monitor, getData().getName()); - } - } - } - ); - } - } - ); - } - else { - final IExpressionDMContext exprDmc = DMContexts.getAncestorOfType(((IDMVMContext) element).getDMContext(), IExpressionDMContext.class); - - if ( exprDmc != null ) { - final IExpressions exprService = tracker.getService(IExpressions.class);; - - exprService.getExecutor().submit( - new Runnable() { - public void run() { - putInformationIntoDetailPane(provider, node, path, exprDmc , exprService, monitor, exprDmc.getExpression()); - } - } - ); - } - else { - /* - * For whatever reason we are seeing some form of context we do not handle. So we - * will skip this one and try and process any remaining ones. At least this way - * we can fill the detail pane with those we do understand. - */ - continue; - } - } - } - - tracker.dispose(); - - /* - * We need to wait until all the values are in. This causes the work - * to in effect be synchronous, but if we do not wait then when we - * are stepping fast if we exit before the job is finished then we - * will enter and start to update the pane before the previous work - * is actually done. This causes the data to be screwed up in an - * overlapped way. It should be the case that most of the jobs that - * occur in the middle will be cancelled, so there is not a lot of - * waste actually going on. - */ - synchronized (this) { - try { - // wait for a max of 30 seconds for result, then cancel - wait(30000); - if (!fComputed) { - fMonitor.setCanceled(true); - } - } catch (InterruptedException e) { - break; - } - } - } - else { - if (element instanceof String) { message = (String) element; } - else { message = element.toString(); } - fComputed = true; - } + final IElementPropertiesProvider propertiesProvider = + (IElementPropertiesProvider)DebugPlugin.getAdapter(element, IElementPropertiesProvider.class); - /* - * If no details were computed for the selected variable, clear the pane - * or use the message. - */ - if (!fComputed){ - if (message == null) { - detailComputed(null,""); //$NON-NLS-1$ - } else { - detailComputed(null, message); - } - } + final Executor executor = SimpleDisplayExecutor.getSimpleDisplayExecutor( + fWorkbenchPartSite.getShell().getDisplay()); + Set properties = new HashSet(1); + properties.add(IDebugVMConstants.PROP_FORMATTED_VALUE_AVAILABLE_FORMATS); + propertiesProvider.update(new IPropertiesUpdate[] { new VMPropertiesUpdate( + properties, path, fViewerInput, fPresentationContext, + new DataRequestMonitor>(executor, null) { + @Override + protected void handleCompleted() { + Set properties = new HashSet(1); + properties.add(IElementPropertiesProvider.PROP_NAME); + final String[] formats = (String[])getData().get( + IDebugVMConstants.PROP_FORMATTED_VALUE_AVAILABLE_FORMATS); + if (formats != null) { + for (String format : formats) { + properties.add(FormattedValueVMUtil.getPropertyForFormatId(format)); + } + } + + propertiesProvider.update(new IPropertiesUpdate[] { new VMPropertiesUpdate( + properties, path, fViewerInput, fPresentationContext, + new DataRequestMonitor>(executor, null) { + @Override + protected void handleSuccess() { + StringBuffer finalResult = new StringBuffer(); + finalResult.append(NAME).append(getData().get(IElementPropertiesProvider.PROP_NAME)).append(CRLF); + + List formatsList = new ArrayList(Arrays.asList(formats)); + Collections.sort(formatsList); + + for (int i = 0; i < formatsList.size(); i++) { + String formatId = formatsList.get(i); + finalResult.append(SPACES); + finalResult.append( FormattedValueVMUtil.getFormatLabel(formatId) ); + finalResult.append(FORMAT_SEPARATOR); + finalResult.append( getData().get(FormattedValueVMUtil.getPropertyForFormatId(formatId)) ); + if ( i < formatsList.size() + 1 ) { + finalResult.append(CRLF); + } + } + detailComputed(null, finalResult.toString()); + } + + @Override + protected void handleErrorOrWarning() { + detailComputed(null, getStatus().getMessage()); + }; + }) + }); + } + }) + }); + continue; } return Status.OK_STATUS; diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/viewmodel/numberformat/detail/messages.properties b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/viewmodel/numberformat/detail/messages.properties index 270ebe2a2e1..8f8aec8b0fc 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/viewmodel/numberformat/detail/messages.properties +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/viewmodel/numberformat/detail/messages.properties @@ -9,13 +9,7 @@ # Wind River Systems Inc - copied for non-restricted version for DSDP/DD/DSF ############################################################################### -NumberFormatDetailPane_Natural_label=Default : -NumberFormatDetailPane_Decimal_label=Decimal : -NumberFormatDetailPane_Hex_label=Hex.... : -NumberFormatDetailPane_Octal_label=Octal.. : -NumberFormatDetailPane_Binary_label=Binary. : -NumberFormatDetailPane_String_label=String : -NumberFormatDetailPane_Other_label=Other.. : +NumberFormatDetailPane_format_separator__label= : NumberFormatDetailPane_Name_label=Name : NumberFormatDetailPane_Spaces_label=\t NumberFormatDetailPane_CarriageReturn_label=\n diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/ErrorLabelText.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/ErrorLabelText.java new file mode 100644 index 00000000000..5b9d521ad7f --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/ErrorLabelText.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.debug.ui.viewmodel; + +import java.util.Map; + +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelText; +import org.eclipse.core.runtime.IStatus; + +/** + * @since 2.0 + */ +public class ErrorLabelText extends LabelText { + + protected final static String PROP_ERROR_MESSAGE = "error_message"; //$NON-NLS-1$ + + public ErrorLabelText() { + this( + MessagesForDebugVM.ErrorLabelText__text_format, + new String[] { PROP_ERROR_MESSAGE }); + } + + public ErrorLabelText(String formatPattern, String[] propertyNames) { + super(formatPattern, addActiveFormatPropertyNames(propertyNames)); + } + + private static String[] addActiveFormatPropertyNames(String[] propertyNames) { + String[] newPropertyNames = new String[propertyNames.length + 1]; + System.arraycopy(propertyNames, 0, newPropertyNames, 0, propertyNames.length); + newPropertyNames[propertyNames.length + 0] = PROP_ERROR_MESSAGE; + return newPropertyNames; + } + + @Override + protected Object getPropertyValue(String propertyName, IStatus status, Map properties) { + if (PROP_ERROR_MESSAGE.equals(propertyName)) { + return status.getMessage().replaceAll( + "\n", MessagesForDebugVM.ErrorLabelText_Error_message__text_page_break_delimiter); //$NON-NLS-1$ + } + return super.getPropertyValue(propertyName, status, properties); + } + + @Override + public boolean checkProperty(String propertyName, IStatus status, Map properties) { + if (PROP_ERROR_MESSAGE.equals(propertyName)) { + return !status.isOK(); + } + return super.checkProperty(propertyName, status, properties); + }; +} diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/IDebugVMConstants.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/IDebugVMConstants.java index 36aa45bf221..751cc62f2ce 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/IDebugVMConstants.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/IDebugVMConstants.java @@ -10,7 +10,10 @@ *******************************************************************************/ package org.eclipse.cdt.dsf.debug.ui.viewmodel; +import org.eclipse.cdt.dsf.debug.service.IFormattedValues; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueVMUtil; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; +import org.eclipse.cdt.dsf.ui.viewmodel.update.ICachingVMProvider; /** * @@ -30,6 +33,38 @@ public interface IDebugVMConstants { /** * Location of the current format in the IPresentationContext data store. + * + * @since 2.0 */ - public final static String CURRENT_FORMAT_STORAGE = "CurrentNumericStyle" ; //$NON-NLS-1$ + public final static String PROP_FORMATTED_VALUE_FORMAT_PREFERENCE = "CurrentNumericStyle" ; //$NON-NLS-1$ + + /** + * @since 2.0 + */ + public static final String PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE = "formatted_value_active_format_value"; //$NON-NLS-1$ + + /** + * @since 2.0 + */ + public static final String PROP_FORMATTED_VALUE_AVAILABLE_FORMATS = "formatted_value_available_formats"; //$NON-NLS-1$ + + /** + * @since 2.0 + */ + public static final String PROP_FORMATTED_VALUE_ACTIVE_FORMAT = "formatted_value_active_format"; //$NON-NLS-1$ + + /** + * @since 2.0 + */ + public static final String PROP_FORMATTED_VALUE_BASE = "formatted_value_base"; //$NON-NLS-1$ + + /** + * @since 2.0 + */ + public static final String PROP_IS_STRING_FORMAT_VALUE_CHANGED = ICachingVMProvider.PROP_IS_CHANGED_PREFIX + FormattedValueVMUtil.getPropertyForFormatId(IFormattedValues.STRING_FORMAT); + + /** + * @since 2.0 + */ + public static final String PROP_IS_ACTIVE_FORMATTED_VALUE_CHANGED = ICachingVMProvider.PROP_IS_CHANGED_PREFIX + FormattedValueVMUtil.getPropertyForFormatId(IFormattedValues.NATURAL_FORMAT); } diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/MessagesForDebugVM.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/MessagesForDebugVM.java new file mode 100644 index 00000000000..4baeafb3f19 --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/MessagesForDebugVM.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2006, 2008 IBM Corporation 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, Inc. - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.dsf.debug.ui.viewmodel; + +import org.eclipse.osgi.util.NLS; + +/** + * @noinstantiate This class is not intended to be instantiated by clients. + */ +public class MessagesForDebugVM extends NLS { + + private static final String BUNDLE_NAME = "org.eclipse.cdt.dsf.debug.ui.viewmodel.messages"; //$NON-NLS-1$ + + public static String ErrorLabelText__text_format; + public static String ErrorLabelText_Error_message__text_page_break_delimiter; + + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, MessagesForDebugVM.class); + } + + private MessagesForDebugVM() {} +} diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/AbstractExpressionVMNode.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/AbstractExpressionVMNode.java index 6e2a34f3e4c..51a32d02772 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/AbstractExpressionVMNode.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/AbstractExpressionVMNode.java @@ -43,6 +43,12 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; public abstract class AbstractExpressionVMNode extends AbstractDMVMNode implements IExpressionVMNode { + /** + * @since 2.0 + */ + protected static final String PROP_ELEMENT_EXPRESSION = "element_expression"; //$NON-NLS-1$ + + public AbstractExpressionVMNode(AbstractDMVMProvider provider, DsfSession session, Class dmcClassType) { super(provider, session, dmcClassType); } diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProvider.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProvider.java index 3f608a9dc0a..1f419e7b4eb 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProvider.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProvider.java @@ -22,8 +22,6 @@ import org.eclipse.cdt.dsf.debug.service.IRegisters; import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent; import org.eclipse.cdt.dsf.debug.ui.DsfDebugUITools; import org.eclipse.cdt.dsf.debug.ui.IDsfDebugUIConstants; -import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValuePreferenceStore; -import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.IFormattedValuePreferenceStore; import org.eclipse.cdt.dsf.debug.ui.viewmodel.register.RegisterBitFieldVMNode; import org.eclipse.cdt.dsf.debug.ui.viewmodel.register.RegisterGroupVMNode; import org.eclipse.cdt.dsf.debug.ui.viewmodel.register.RegisterVMNode; @@ -198,8 +196,6 @@ public class ExpressionVMProvider extends AbstractDMVMProvider */ protected void configureLayout() { - IFormattedValuePreferenceStore prefStore = FormattedValuePreferenceStore.getDefault(); - /* * Allocate the synchronous data providers. */ @@ -222,13 +218,13 @@ public class ExpressionVMProvider extends AbstractDMVMProvider */ IExpressionVMNode registerGroupNode = new RegisterGroupVMNode(this, getSession(), syncRegDataAccess); - IExpressionVMNode registerNode = new RegisterVMNode(prefStore, this, getSession(), syncRegDataAccess); + IExpressionVMNode registerNode = new RegisterVMNode(this, getSession(), syncRegDataAccess); addChildNodes(registerGroupNode, new IExpressionVMNode[] {registerNode}); /* * Create the next level which is the bit-field level. */ - IVMNode bitFieldNode = new RegisterBitFieldVMNode(prefStore, this, getSession(), syncRegDataAccess); + IVMNode bitFieldNode = new RegisterBitFieldVMNode(this, getSession(), syncRegDataAccess); addChildNodes(registerNode, new IVMNode[] { bitFieldNode }); /* @@ -236,7 +232,7 @@ public class ExpressionVMProvider extends AbstractDMVMProvider * view comes in as a fully qualified expression so we go directly to the SubExpression layout * node. */ - IExpressionVMNode variableNode = new VariableVMNode(prefStore, this, getSession(), syncvarDataAccess); + IExpressionVMNode variableNode = new VariableVMNode(this, getSession(), syncvarDataAccess); addChildNodes(variableNode, new IExpressionVMNode[] {variableNode}); /* diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/AbstractContainerVMNode.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/AbstractContainerVMNode.java index 9b7ebf9b15d..deed098a511 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/AbstractContainerVMNode.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/AbstractContainerVMNode.java @@ -12,6 +12,7 @@ package org.eclipse.cdt.dsf.debug.ui.viewmodel.launch; import java.util.concurrent.RejectedExecutionException; +import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DsfRunnable; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; @@ -22,17 +23,30 @@ import org.eclipse.cdt.dsf.debug.service.IRunControl; import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerResumedDMEvent; import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerSuspendedDMEvent; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMData; import org.eclipse.cdt.dsf.debug.service.IRunControl.IExitedDMEvent; import org.eclipse.cdt.dsf.debug.service.IRunControl.IStartedDMEvent; import org.eclipse.cdt.dsf.debug.ui.viewmodel.SteppingController.SteppingTimedOutEvent; import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor; import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext; import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMNode; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelAttribute; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelColumnInfo; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelImage; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelText; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.PropertiesBasedLabelProvider; +import org.eclipse.core.runtime.IStatus; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider; import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.IDebugUIConstants; /** * Abstract implementation of a container view model node. @@ -40,35 +54,118 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; * * @since 1.1 */ -@SuppressWarnings("restriction") -public abstract class AbstractContainerVMNode extends AbstractDMVMNode implements IElementLabelProvider { - +public abstract class AbstractContainerVMNode extends AbstractDMVMNode + implements IElementLabelProvider, IElementPropertiesProvider + { + /** + * The label provider delegate. This VM node will delegate label updates to this provider + * which can be created by sub-classes. + * + * @since 2.0 + */ + private IElementLabelProvider fLabelProvider; + public AbstractContainerVMNode(AbstractDMVMProvider provider, DsfSession session) { super(provider, session, IRunControl.IContainerDMContext.class); - } - - public void update(final ILabelUpdate[] updates) { - try { - getSession().getExecutor().execute(new DsfRunnable() { - public void run() { - for (final ILabelUpdate update : updates) { - updateLabelInSessionThread(update); - } - }}); - } catch (RejectedExecutionException e) { - for (ILabelUpdate update : updates) { - handleFailedUpdate(update); - } - } + fLabelProvider = createLabelProvider(); } /** - * Perform the given label updates in the session executor thread. + * Creates the label provider delegate. This VM node will delegate label + * updates to this provider which can be created by sub-classes. + * + * @return Returns the label provider for this node. + * + * @since 2.0 + */ + protected IElementLabelProvider createLabelProvider() { + PropertiesBasedLabelProvider provider = new PropertiesBasedLabelProvider(); + + provider.setColumnInfo( + PropertiesBasedLabelProvider.ID_COLUMN_NO_COLUMNS, + new LabelColumnInfo(new LabelAttribute[] { + new ExecutionContextLabelText( + MessagesForLaunchVM.AbstractContainerVMNode_No_columns__text_format, + new String[] { + ExecutionContextLabelText.PROP_NAME_KNOWN, + PROP_NAME, + ExecutionContextLabelText.PROP_ID_KNOWN, + ILaunchVMConstants.PROP_ID }), + new LabelText(MessagesForLaunchVM.AbstractContainerVMNode_No_columns__Error__label, new String[0]), + new LabelImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_DEBUG_TARGET_SUSPENDED)) { + { setPropertyNames(new String[] { ILaunchVMConstants.PROP_IS_SUSPENDED }); } + + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + return !Boolean.TRUE.equals(properties.get(ILaunchVMConstants.PROP_IS_SUSPENDED)); + }; + }, + new LabelImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_DEBUG_TARGET)), + })); + + return provider; + } + + + public void update(final ILabelUpdate[] updates) { + fLabelProvider.update(updates); + } + + /** + * @see IElementPropertiesProvider#update(IPropertiesUpdate[]) * - * @param updates the pending label updates - * @see {@link #update(ILabelUpdate[]) + * @since 2.0 + */ + public void update(final IPropertiesUpdate[] updates) { + try { + getSession().getExecutor().execute(new DsfRunnable() { + public void run() { + updatePropertiesInSessionThread(updates); + }}); + } catch (RejectedExecutionException e) { + for (IPropertiesUpdate update : updates) { + handleFailedUpdate(update); + } + } + } + + /** + * @since 2.0 */ - protected abstract void updateLabelInSessionThread(ILabelUpdate update); + @ConfinedToDsfExecutor("getSession().getExecutor()") + protected void updatePropertiesInSessionThread(final IPropertiesUpdate[] updates) { + IRunControl service = getServicesTracker().getService(IRunControl.class); + + for (final IPropertiesUpdate update : updates) { + if (service == null) { + handleFailedUpdate(update); + continue; + } + + IExecutionDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IExecutionDMContext.class); + if (dmc == null) { + handleFailedUpdate(update); + continue; + } + + update.setProperty(ILaunchVMConstants.PROP_IS_SUSPENDED, service.isSuspended(dmc)); + update.setProperty(ILaunchVMConstants.PROP_IS_STEPPING, service.isStepping(dmc)); + + service.getExecutionData( + dmc, + new ViewerDataRequestMonitor(getSession().getExecutor(), update) { + @Override + protected void handleSuccess() { + fillExecutionDataProperties(update, getData()); + update.done(); + } + }); + } + } + + protected void fillExecutionDataProperties(IPropertiesUpdate update, IExecutionDMData data) { + update.setProperty(ILaunchVMConstants.PROP_STATE_CHANGE_REASON, data.getStateChangeReason().name()); + } @Override public void getContextsForEvent(VMDelta parentDelta, Object e, final DataRequestMonitor rm) { diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/AbstractThreadVMNode.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/AbstractThreadVMNode.java index 3c0c7190c15..9662893f3c2 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/AbstractThreadVMNode.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/AbstractThreadVMNode.java @@ -12,8 +12,10 @@ package org.eclipse.cdt.dsf.debug.ui.viewmodel.launch; import java.util.List; +import java.util.Map; import java.util.concurrent.RejectedExecutionException; +import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DsfRunnable; import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; @@ -26,8 +28,10 @@ import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerResumedDMEvent; import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerSuspendedDMEvent; import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; +import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMData; import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent; import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent; +import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason; import org.eclipse.cdt.dsf.debug.ui.viewmodel.SteppingController.SteppingTimedOutEvent; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.service.DsfSession; @@ -39,12 +43,21 @@ import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMNode; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelAttribute; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelColumnInfo; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelImage; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelText; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.PropertiesBasedLabelProvider; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider; import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.IDebugUIConstants; /** @@ -53,14 +66,78 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; * * @since 1.1 */ -@SuppressWarnings("restriction") public abstract class AbstractThreadVMNode extends AbstractDMVMNode - implements IElementLabelProvider + implements IElementLabelProvider, IElementPropertiesProvider { + /** + * The label provider delegate. This VM node will delegate label updates to this provider + * which can be created by sub-classes. + * + * @since 2.0 + */ + private IElementLabelProvider fLabelProvider; + public AbstractThreadVMNode(AbstractDMVMProvider provider, DsfSession session) { super(provider, session, IExecutionDMContext.class); + fLabelProvider = createLabelProvider(); } + + /** + * Creates the label provider delegate. This VM node will delegate label + * updates to this provider which can be created by sub-classes. + * + * @return Returns the label provider for this node. + * + * @since 2.0 + */ + protected IElementLabelProvider createLabelProvider() { + PropertiesBasedLabelProvider provider = new PropertiesBasedLabelProvider(); + + provider.setColumnInfo( + PropertiesBasedLabelProvider.ID_COLUMN_NO_COLUMNS, + new LabelColumnInfo(new LabelAttribute[] { + // Text is made of the thread name followed by its state and state change reason. + new ExecutionContextLabelText( + MessagesForLaunchVM.AbstractThreadVMNode_No_columns__text_format, + new String[] { + ExecutionContextLabelText.PROP_NAME_KNOWN, + PROP_NAME, + ExecutionContextLabelText.PROP_ID_KNOWN, + ILaunchVMConstants.PROP_ID, + ILaunchVMConstants.PROP_IS_SUSPENDED, + ILaunchVMConstants.PROP_STATE_CHANGE_REASON }) + { + @Override + public boolean isEnabled(IStatus status, Map properties) { + String reason = (String)properties.get(ILaunchVMConstants.PROP_STATE_CHANGE_REASON); + return + reason != null && reason.length() != 0 && + !StateChangeReason.UNKNOWN.equals(reason); + } + }, + // If no state change reason is available compose a string without it. + new ExecutionContextLabelText( + MessagesForLaunchVM.AbstractThreadVMNode_No_columns__No_reason__text_format, + new String[] { + ExecutionContextLabelText.PROP_NAME_KNOWN, + PROP_NAME, + ExecutionContextLabelText.PROP_ID_KNOWN, + ILaunchVMConstants.PROP_ID}), + new LabelText(MessagesForLaunchVM.AbstractThreadVMNode_No_columns__Error__label, new String[0]), + new LabelImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_THREAD_RUNNING)) { + { setPropertyNames(new String[] { ILaunchVMConstants.PROP_IS_SUSPENDED }); } + + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + return !((Boolean)properties.get(ILaunchVMConstants.PROP_IS_SUSPENDED)).booleanValue(); + }; + }, + new LabelImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED)), + })); + return provider; + } + @Override protected void updateElementsInSessionThread(final IChildrenUpdate update) { IRunControl runControl = getServicesTracker().getService(IRunControl.class); @@ -85,19 +162,67 @@ public abstract class AbstractThreadVMNode extends AbstractDMVMNode } + public void update(final ILabelUpdate[] updates) { + fLabelProvider.update(updates); + } + + /** + * @see IElementPropertiesProvider#update(IPropertiesUpdate[]) + * + * @since 2.0 + */ + public void update(final IPropertiesUpdate[] updates) { try { getSession().getExecutor().execute(new DsfRunnable() { public void run() { - updateLabelInSessionThread(updates); + updatePropertiesInSessionThread(updates); }}); } catch (RejectedExecutionException e) { - for (ILabelUpdate update : updates) { + for (IPropertiesUpdate update : updates) { handleFailedUpdate(update); } } } + /** + * @since 2.0 + */ + @ConfinedToDsfExecutor("getSession().getExecutor()") + protected void updatePropertiesInSessionThread(final IPropertiesUpdate[] updates) { + IRunControl service = getServicesTracker().getService(IRunControl.class); + + for (final IPropertiesUpdate update : updates) { + if (service == null) { + handleFailedUpdate(update); + continue; + } + + IExecutionDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IExecutionDMContext.class); + if (dmc == null) { + handleFailedUpdate(update); + continue; + } + + update.setProperty(ILaunchVMConstants.PROP_IS_SUSPENDED, service.isSuspended(dmc)); + update.setProperty(ILaunchVMConstants.PROP_IS_STEPPING, service.isStepping(dmc)); + + service.getExecutionData( + dmc, + new ViewerDataRequestMonitor(getSession().getExecutor(), update) { + @Override + protected void handleSuccess() { + fillExecutionDataProperties(update, getData()); + update.done(); + } + }); + } + } + + protected void fillExecutionDataProperties(IPropertiesUpdate update, IExecutionDMData data) { + update.setProperty(ILaunchVMConstants.PROP_STATE_CHANGE_REASON, data.getStateChangeReason().name()); + } + @Override public void getContextsForEvent(VMDelta parentDelta, Object e, final DataRequestMonitor rm) { if(e instanceof IContainerResumedDMEvent) { @@ -212,14 +337,6 @@ public abstract class AbstractThreadVMNode extends AbstractDMVMNode })); } - /** - * Perform the given label updates in the session executor thread. - * - * @param updates the pending label updates - * @see {@link #update(ILabelUpdate[]) - */ - protected abstract void updateLabelInSessionThread(ILabelUpdate[] updates); - public int getDeltaFlags(Object e) { IDMContext dmc = e instanceof IDMEvent ? ((IDMEvent)e).getDMContext() : null; diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/ExecutionContextLabelText.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/ExecutionContextLabelText.java new file mode 100644 index 00000000000..9d378c1be22 --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/ExecutionContextLabelText.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.debug.ui.viewmodel.launch; + +import java.util.Map; + +import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelText; +import org.eclipse.core.runtime.IStatus; + +class ExecutionContextLabelText extends LabelText { + + /** + * Value 0 means it's not known. Value 1, means it's known. + */ + public static final String PROP_ID_KNOWN = "id_known"; //$NON-NLS-1$ + + /** + * Value 0 means it's not known. Value 1, means it's known. + */ + public static final String PROP_NAME_KNOWN = "name_known"; //$NON-NLS-1$ + + protected ExecutionContextLabelText(String formatPattern, String[] propertyNames) { + super(formatPattern, propertyNames); + } + + @Override + protected Object getPropertyValue(String propertyName, IStatus status, Map properties) { + if ( ILaunchVMConstants.PROP_STATE_CHANGE_REASON.equals(propertyName) ) { + String reason = (String)properties.get(propertyName); + String reasonLabel = "invalid reason"; //$NON-NLS-1$ + if (StateChangeReason.BREAKPOINT.name().equals(reason)) { + reasonLabel = MessagesForLaunchVM.State_change_reason__Breakpoint__label; + } else if (StateChangeReason.CONTAINER.name().equals(reason)) { + reasonLabel = MessagesForLaunchVM.State_change_reason__Container__label; + } else if (StateChangeReason.ERROR.name().equals(reason)) { + reasonLabel = MessagesForLaunchVM.State_change_reason__Error__label; + } else if (StateChangeReason.EVALUATION.name().equals(reason)) { + reasonLabel = MessagesForLaunchVM.State_change_reason__Evaluation__label; + } else if (StateChangeReason.EXCEPTION.name().equals(reason)) { + reasonLabel = MessagesForLaunchVM.State_change_reason__Exception__label; + } else if (StateChangeReason.SHAREDLIB.name().equals(reason)) { + reasonLabel = MessagesForLaunchVM.State_change_reason__Shared_lib__label; + } else if (StateChangeReason.SIGNAL.name().equals(reason)) { + reasonLabel = MessagesForLaunchVM.State_change_reason__Signal__label; + } else if (StateChangeReason.STEP.name().equals(reason)) { + reasonLabel = MessagesForLaunchVM.State_change_reason__Step__label; + } else if (StateChangeReason.USER_REQUEST.name().equals(reason)) { + reasonLabel = MessagesForLaunchVM.State_change_reason__User_request__label; + } else if (StateChangeReason.WATCHPOINT.name().equals(reason)) { + reasonLabel = MessagesForLaunchVM.State_change_reason__Watchpoint__label; + } + return reasonLabel; + } else if ( ILaunchVMConstants.PROP_IS_SUSPENDED.equals(propertyName) ) { + Boolean suspended = (Boolean)properties.get(propertyName); + return suspended ? 1 : 0; + } else if (PROP_NAME_KNOWN.equals(propertyName)) { + return properties.get(IElementPropertiesProvider.PROP_NAME) != null ? 1 : 0; + } else if (IElementPropertiesProvider.PROP_NAME.equals(propertyName)) { + Object val = properties.get(IElementPropertiesProvider.PROP_NAME); + return val != null ? val : ""; //$NON-NLS-1$ + } else if (PROP_ID_KNOWN.equals(propertyName)) { + return properties.get(ILaunchVMConstants.PROP_ID) != null ? 1 : 0; + } else if (ILaunchVMConstants.PROP_ID.equals(propertyName)) { + Object val = properties.get(ILaunchVMConstants.PROP_ID); + return val != null ? val : ""; //$NON-NLS-1$ + } + return super.getPropertyValue(propertyName, status, properties); + } + + @Override + protected boolean checkProperty(String propertyName, IStatus status, Map properties) { + if (PROP_NAME_KNOWN.equals(propertyName) || + IElementPropertiesProvider.PROP_NAME.equals(propertyName) || + PROP_ID_KNOWN.equals(propertyName) || + ILaunchVMConstants.PROP_ID.equals(propertyName)) + { + return true; + } + return super.checkProperty(propertyName, status, properties); + } +} \ No newline at end of file diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/ILaunchVMConstants.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/ILaunchVMConstants.java new file mode 100644 index 00000000000..9b43a6346c2 --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/ILaunchVMConstants.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.debug.ui.viewmodel.launch; + + +/** + * @since 2.0 + */ +public interface ILaunchVMConstants { + + public static final String PROP_ID = "id"; //$NON-NLS-1$ + + public static final String PROP_IS_SUSPENDED = "is_suspended"; //$NON-NLS-1$ + + public static final String PROP_IS_STEPPING = "is_stepping"; //$NON-NLS-1$ + + public static final String PROP_FRAME_ADDRESS = "frame_address"; //$NON-NLS-1$ + + public static final String PROP_FRAME_FUNCTION = "frame_function"; //$NON-NLS-1$ + + public static final String PROP_FRAME_FILE = "frame_file"; //$NON-NLS-1$ + + public static final String PROP_FRAME_LINE = "frame_line"; //$NON-NLS-1$ + + public static final String PROP_FRAME_COLUMN = "frame_column"; //$NON-NLS-1$ + + public static final String PROP_FRAME_MODULE = "frame_module"; //$NON-NLS-1$ + + public static final String PROP_STATE_CHANGE_REASON = "state_change_reason"; //$NON-NLS-1$ + +} diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/MessagesForLaunchVM.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/MessagesForLaunchVM.java new file mode 100644 index 00000000000..a1f9a05687d --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/MessagesForLaunchVM.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.dsf.debug.ui.viewmodel.launch; + +import org.eclipse.osgi.util.NLS; + +/** + * @noinstantiate This class is not intended to be instantiated by clients. + */ +public class MessagesForLaunchVM extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.messages"; //$NON-NLS-1$ + + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, MessagesForLaunchVM.class); + } + + private MessagesForLaunchVM() { + } + + public static String StackFramesVMNode_No_columns__Incomplete_stack_marker__text_format; + public static String StackFramesVMNode_No_columns__text_format; + public static String StackFramesVMNode_No_columns__No_line__text_format; + public static String StackFramesVMNode_No_columns__No_function__text_format; + public static String StackFramesVMNode_No_columns__No_module__text_format; + public static String StackFramesVMNode_No_columns__Address_only__text_format; + + public static String AbstractContainerVMNode_No_columns__text_format; + public static String AbstractContainerVMNode_No_columns__Error__label; + + public static String AbstractThreadVMNode_No_columns__text_format; + public static String AbstractThreadVMNode_No_columns__No_reason__text_format; + public static String AbstractThreadVMNode_No_columns__Error__label; + + public static String State_change_reason__Unknown__label; + public static String State_change_reason__User_request__label; + public static String State_change_reason__Step__label; + public static String State_change_reason__Breakpoint__label; + public static String State_change_reason__Exception__label; + public static String State_change_reason__Container__label; + public static String State_change_reason__Watchpoint__label; + public static String State_change_reason__Signal__label; + public static String State_change_reason__Shared_lib__label; + public static String State_change_reason__Error__label; + public static String State_change_reason__Evaluation__label; +} diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/StackFramesVMNode.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/StackFramesVMNode.java index e5d952e04b5..71368c7453a 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/StackFramesVMNode.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/StackFramesVMNode.java @@ -16,6 +16,8 @@ import java.util.List; import java.util.Map; import java.util.concurrent.RejectedExecutionException; +import org.eclipse.cdt.core.IAddress; +import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DsfRunnable; import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; @@ -34,6 +36,7 @@ import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMData; import org.eclipse.cdt.dsf.debug.ui.IDsfDebugUIConstants; import org.eclipse.cdt.dsf.debug.ui.viewmodel.SteppingController; import org.eclipse.cdt.dsf.debug.ui.viewmodel.SteppingController.SteppingTimedOutEvent; +import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor; import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMContext; @@ -44,6 +47,14 @@ import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMNode; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelAttribute; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelColumnInfo; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelImage; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelText; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.PropertiesBasedLabelProvider; +import org.eclipse.core.runtime.IStatus; 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.IElementCompareRequest; @@ -58,10 +69,13 @@ import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.ui.IMemento; -@SuppressWarnings("restriction") public class StackFramesVMNode extends AbstractDMVMNode - implements IElementLabelProvider, IElementMementoProvider + implements IElementLabelProvider, IElementMementoProvider, IElementPropertiesProvider { + /** + * @since 2.0 + */ + public static final String PROP_IS_INCOMPLETE_STACK_MARKER = "is_incomplete_stack_marker"; //$NON-NLS-1$ /** * View model context representing the end of an incomplete stack. @@ -100,8 +114,17 @@ public class StackFramesVMNode extends AbstractDMVMNode */ private Map fTemporaryLimits = new HashMap(); + /** + * The label provider delegate. This VM node will delegate label updates to this provider + * which can be created by sub-classes. + * + * @since 2.0 + */ + private IElementLabelProvider fLabelProvider; + public StackFramesVMNode(AbstractDMVMProvider provider, DsfSession session) { super(provider, session, IStack.IFrameDMContext.class); + fLabelProvider = createLabelProvider(); } @Override @@ -109,6 +132,102 @@ public class StackFramesVMNode extends AbstractDMVMNode return "StackFramesVMNode(" + getSession().getId() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } + /** + * Creates the label provider delegate. This VM node will delegate label + * updates to this provider which can be created by sub-classes. + * + * @return Returns the label provider for this node. + * + * @since 2.0 + */ + protected IElementLabelProvider createLabelProvider() { + PropertiesBasedLabelProvider provider = new PropertiesBasedLabelProvider(); + + provider.setColumnInfo( + PropertiesBasedLabelProvider.ID_COLUMN_NO_COLUMNS, + new LabelColumnInfo(new LabelAttribute[] { + new LabelText( + MessagesForLaunchVM.StackFramesVMNode_No_columns__Incomplete_stack_marker__text_format, + new String[] { PROP_NAME }) + { + @Override + public boolean isEnabled(IStatus status, Map properties) { + return Boolean.TRUE.equals(properties.get(PROP_IS_INCOMPLETE_STACK_MARKER)); + } + + }, + new LabelText( + MessagesForLaunchVM.StackFramesVMNode_No_columns__text_format, + new String[] { + ILaunchVMConstants.PROP_FRAME_ADDRESS, + ILaunchVMConstants.PROP_FRAME_FUNCTION, + ILaunchVMConstants.PROP_FRAME_FILE, + ILaunchVMConstants.PROP_FRAME_LINE, + ILaunchVMConstants.PROP_FRAME_COLUMN, + ILaunchVMConstants.PROP_FRAME_MODULE}) + { + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + Integer line = (Integer)properties.get(ILaunchVMConstants.PROP_FRAME_LINE); + String file = (String)properties.get(ILaunchVMConstants.PROP_FRAME_FILE); + return line != null && line >= 0 && file != null && file.length() > 0; + }; + }, + new LabelText( + MessagesForLaunchVM.StackFramesVMNode_No_columns__No_line__text_format, + new String[] { + ILaunchVMConstants.PROP_FRAME_ADDRESS, + ILaunchVMConstants.PROP_FRAME_FUNCTION, + ILaunchVMConstants.PROP_FRAME_MODULE}) + { + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + String function = (String)properties.get(ILaunchVMConstants.PROP_FRAME_FUNCTION); + String module = (String)properties.get(ILaunchVMConstants.PROP_FRAME_MODULE); + return function != null && function.length() > 0 && module != null && module.length() > 0; + }; + }, + new LabelText( + MessagesForLaunchVM.StackFramesVMNode_No_columns__No_function__text_format, + new String[] { + ILaunchVMConstants.PROP_FRAME_ADDRESS, + ILaunchVMConstants.PROP_FRAME_MODULE}) + { + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + String module = (String)properties.get(ILaunchVMConstants.PROP_FRAME_MODULE); + return module != null && module.length() > 0; + }; + }, + new LabelText( + MessagesForLaunchVM.StackFramesVMNode_No_columns__No_module__text_format, + new String[] { + ILaunchVMConstants.PROP_FRAME_ADDRESS, + ILaunchVMConstants.PROP_FRAME_FUNCTION}) + { + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + String function = (String)properties.get(ILaunchVMConstants.PROP_FRAME_FUNCTION); + return function != null && function.length() > 0; + }; + }, + new LabelText( + MessagesForLaunchVM.StackFramesVMNode_No_columns__Address_only__text_format, + new String[] { ILaunchVMConstants.PROP_FRAME_ADDRESS }), + new LabelImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_STACKFRAME_RUNNING)) { + { setPropertyNames(new String[] { ILaunchVMConstants.PROP_IS_SUSPENDED }); } + + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + return Boolean.FALSE.equals( properties.get(ILaunchVMConstants.PROP_IS_SUSPENDED) ); + }; + }, + new LabelImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_STACKFRAME)) + })); + + return provider; + } + /* * (non-Javadoc) * @see org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMNode#updateHasElementsInSessionThread(org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate) @@ -239,83 +358,86 @@ public class StackFramesVMNode extends AbstractDMVMNode } } - /* - * (non-Javadoc) - * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider#update(org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate[]) - */ public void update(final ILabelUpdate[] updates) { + fLabelProvider.update(updates); + } + + /** + * @see IElementPropertiesProvider#update(IPropertiesUpdate[]) + * + * @since 2.0 + */ + public void update(final IPropertiesUpdate[] updates) { try { getSession().getExecutor().execute(new DsfRunnable() { public void run() { - updateLabelInSessionThread(updates); + updatePropertiesInSessionThread(updates); }}); } catch (RejectedExecutionException e) { - for (ILabelUpdate update : updates) { + for (IPropertiesUpdate update : updates) { handleFailedUpdate(update); } } } - - protected void updateLabelInSessionThread(ILabelUpdate[] updates) { - for (final ILabelUpdate update : updates) { - IStack stackService = getServicesTracker().getService(IStack.class); - - if (stackService == null) { + + /** + * @since 2.0 + */ + @ConfinedToDsfExecutor("getSession().getExecutor()") + protected void updatePropertiesInSessionThread(final IPropertiesUpdate[] updates) { + IStack service = getServicesTracker().getService(IStack.class); + + for (final IPropertiesUpdate update : updates) { + if (service == null) { handleFailedUpdate(update); continue; } if (update.getElement() instanceof IncompleteStackVMContext) { - update.setLabel("<...more frames...>", 0); //$NON-NLS-1$ - update.setImageDescriptor(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_STACKFRAME), 0); + update.setProperty(PROP_IS_INCOMPLETE_STACK_MARKER, Boolean.TRUE); update.done(); continue; } - final IFrameDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IFrameDMContext.class); + IFrameDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IFrameDMContext.class); if (dmc == null) { handleFailedUpdate(update); continue; } - getDMVMProvider().getModelData( - this, update, - getServicesTracker().getService(IStack.class, null), + IRunControl runControlService = getServicesTracker().getService(IRunControl.class); + IExecutionDMContext execDmc = DMContexts.getAncestorOfType(dmc, IExecutionDMContext.class); + if (execDmc != null && runControlService != null) { + update.setProperty(ILaunchVMConstants.PROP_IS_SUSPENDED, runControlService.isSuspended(execDmc)); + update.setProperty(ILaunchVMConstants.PROP_IS_STEPPING, runControlService.isStepping(execDmc)); + } else { + update.setStatus(DsfUIPlugin.newErrorStatus(IDsfStatusConstants.INVALID_HANDLE, "Invalid context or service not available", null)); //$NON-NLS-1$ + } + + service.getFrameData( dmc, new ViewerDataRequestMonitor(getSession().getExecutor(), update) { @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 (!isSuccess()) { - assert getStatus().isOK() || - getStatus().getCode() != IDsfStatusConstants.INTERNAL_ERROR || - getStatus().getCode() != IDsfStatusConstants.NOT_SUPPORTED; - handleFailedUpdate(update); - return; - } - - /* - * If columns are configured, call the protected methods to - * fill in column values. - */ - String[] localColumns = update.getColumnIds(); - if (localColumns == null) localColumns = new String[] { null }; - - for (int i = 0; i < localColumns.length; i++) { - fillColumnLabel(dmc, getData(), localColumns[i], i, update); - } + protected void handleSuccess() { + fillFrameDataProperties(update, getData()); update.done(); } - }, - getExecutor()); + }); } } + protected void fillFrameDataProperties(IPropertiesUpdate update, IFrameDMData data) { + IAddress address = data.getAddress(); + if (address != null) { + update.setProperty(ILaunchVMConstants.PROP_FRAME_ADDRESS, "0x" + address.toString(16)); //$NON-NLS-1$ + } + update.setProperty(ILaunchVMConstants.PROP_FRAME_FILE, data.getFile()); + update.setProperty(ILaunchVMConstants.PROP_FRAME_FUNCTION, data.getFunction()); + update.setProperty(ILaunchVMConstants.PROP_FRAME_LINE, data.getLine()); + update.setProperty(ILaunchVMConstants.PROP_FRAME_COLUMN, data.getColumn()); + update.setProperty(ILaunchVMConstants.PROP_FRAME_MODULE, data.getModule()); + } + protected void fillColumnLabel(IFrameDMContext dmContext, IFrameDMData dmData, String columnId, int idx, ILabelUpdate update) { if (idx != 0) return; diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/messages.properties b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/messages.properties new file mode 100644 index 00000000000..ae27589a968 --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/messages.properties @@ -0,0 +1,73 @@ +############################################################################### +# Copyright (c) 2007, 2009 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 +############################################################################### + +StackFramesVMNode_No_columns__Incomplete_stack_marker__text_format=<...more frames...> + +# {0} - address, +# {1} - function, +# {2} - file (path or just name, depending on preference) +# {3} - line +# {4} - column +# {5} - module +StackFramesVMNode_No_columns__text_format={1}() at {2}:{3}{4,choice,0#|1#:{4}} + +# {0} - address +# {1} - function +# {2} - module +StackFramesVMNode_No_columns__No_line__text_format={1}() [{2}] at {0} + +# {0} - address +# {1} - module +StackFramesVMNode_No_columns__No_function__text_format=[{2}] at {0} + +# {0} - address +# {1} - function +StackFramesVMNode_No_columns__No_module__text_format={1}() at {0} + +# {0} - address +StackFramesVMNode_No_columns__Address_only__text_format={0} + +# {0} - name +# {1} - name available, 0=not available/1=available +# {2} - ID +# {3} - ID available, 0=not available/1=available +AbstractContainerVMNode_No_columns__text_format={0,choice,0#Process|1#{1}}{2,choice,0#|1# [{3}]} + +AbstractContainerVMNode_No_columns__Error__label= + +# {0} - name +# {1} - name available, 0=not available/1=available +# {2} - ID +# {3} - ID available, 0=not available/1=available +# {4} - 0=running/1=suspended +# {5} - state change reason +AbstractThreadVMNode_No_columns__text_format={0,choice,0#Thread|1#{1}}{2,choice,0#|1# [{3}]} ({4,choice,0#Running|1#Suspended} : {5}) + +# {0} - name +# {1} - name available, 0=not available/1=available +# {2} - ID +# {3} - ID available, 0=not available/1=available +# {4} - 0=running/1=suspended +AbstractThreadVMNode_No_columns__No_reason__text_format={0,choice,0#Thread|1#{1}}{2,choice,0#|1# [{3}]} ({4,choice,0#Running|1#Suspended}) + +AbstractThreadVMNode_No_columns__Error__label= + +State_change_reason__Unknown__label = Unknown +State_change_reason__User_request__label = User Request +State_change_reason__Step__label = Step +State_change_reason__Breakpoint__label = Breakpoint +State_change_reason__Exception__label = Exception +State_change_reason__Container__label = Container +State_change_reason__Watchpoint__label = Watchpoint +State_change_reason__Signal__label = Signal +State_change_reason__Shared_lib__label = Shared Library +State_change_reason__Error__label = Error +State_change_reason__Evaluation__label = Evaluation \ No newline at end of file diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/messages.properties b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/messages.properties new file mode 100644 index 00000000000..d043fac2d3e --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/messages.properties @@ -0,0 +1,17 @@ +############################################################################### +# Copyright (c) 2009 Wind River Corporation 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 Inc - Initial API and implementation +############################################################################### + +# {0} - Error message +ErrorLabelText__text_format=Error: {0} + +# If multiple errors are shown in the combined error message, this +# string is used as a separator between them. +ErrorLabelText_Error_message__text_page_break_delimiter= \ \ No newline at end of file diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/MessagesForModulesVM.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/MessagesForModulesVM.java new file mode 100644 index 00000000000..a3ffeae9ccd --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/MessagesForModulesVM.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ + +package org.eclipse.cdt.dsf.debug.ui.viewmodel.modules; + +import org.eclipse.osgi.util.NLS; + +/** + * @noinstantiate This class is not intended to be instantiated by clients. + */ +public class MessagesForModulesVM extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.cdt.dsf.debug.ui.viewmodel.modules.messages"; //$NON-NLS-1$ + + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, MessagesForModulesVM.class); + } + + private MessagesForModulesVM() { + } + + public static String ModulesVMNode_No_columns__text_format; +} diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/ModulesVMNode.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/ModulesVMNode.java index 83c9bbe2e4c..ec939cb692e 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/ModulesVMNode.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/ModulesVMNode.java @@ -11,10 +11,11 @@ *******************************************************************************/ package org.eclipse.cdt.dsf.debug.ui.viewmodel.modules; +import java.util.Map; import java.util.concurrent.RejectedExecutionException; +import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor; import org.eclipse.cdt.dsf.concurrent.DsfRunnable; -import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.debug.service.IModules; @@ -23,21 +24,33 @@ import org.eclipse.cdt.dsf.debug.service.IModules.IModuleDMContext; import org.eclipse.cdt.dsf.debug.service.IModules.IModuleDMData; import org.eclipse.cdt.dsf.debug.service.IModules.ISymbolDMContext; import org.eclipse.cdt.dsf.debug.ui.IDsfDebugUIConstants; -import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; +import org.eclipse.cdt.dsf.internal.ui.DsfUILabelImage; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor; import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMNode; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelAttribute; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelColumnInfo; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelFont; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelText; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.PropertiesBasedLabelProvider; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.debug.internal.ui.IInternalDebugUIConstants; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider; import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; +import org.eclipse.jface.resource.JFaceResources; -@SuppressWarnings("restriction") +/** + * @since 1.0 + */ public class ModulesVMNode extends AbstractDMVMNode - implements IElementLabelProvider + implements IElementLabelProvider, IElementPropertiesProvider { /** * Marker type for the modules VM context. It allows action enablement @@ -49,9 +62,57 @@ public class ModulesVMNode extends AbstractDMVMNode } } + /** + * @since 2.0 + */ + public static final String PROP_IS_LOADED = "is_loaded"; //$NON-NLS-1$ + + /** + * The label provider delegate. This VM node will delegate label updates to this provider + * which can be created by sub-classes. + * + * @since 2.0 + */ + private IElementLabelProvider fLabelProvider; + + /** + * Creates the label provider delegate. This VM node will delegate label + * updates to this provider which can be created by sub-classes. + * + * @return Returns the label provider for this node. + * + * @since 2.0 + */ + protected IElementLabelProvider createLabelProvider() { + PropertiesBasedLabelProvider provider = new PropertiesBasedLabelProvider(); + + provider.setColumnInfo( + PropertiesBasedLabelProvider.ID_COLUMN_NO_COLUMNS, + new LabelColumnInfo(new LabelAttribute[] { + new LabelText(MessagesForModulesVM.ModulesVMNode_No_columns__text_format, new String[] { PROP_NAME }), + new DsfUILabelImage(IDsfDebugUIConstants.IMG_OBJS_SHARED_LIBRARY_SYMBOLS_LOADED) { + { setPropertyNames(new String[] { PROP_IS_LOADED }); } + + @Override + public boolean checkProperty(String propertyName, IStatus status, Map properties) { + if (PROP_IS_LOADED.equals(propertyName)) { + return Boolean.TRUE.equals( properties.get(propertyName) ); + } + return super.checkProperty(propertyName, status, properties); + }; + }, + new DsfUILabelImage(IDsfDebugUIConstants.IMG_OBJS_SHARED_LIBRARY_SYMBOLS_UNLOADED), + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + return provider; + } + public ModulesVMNode(AbstractDMVMProvider provider, DsfSession session) { super(provider, session, IModuleDMContext.class); + + fLabelProvider = createLabelProvider(); } @Override @@ -88,80 +149,60 @@ public class ModulesVMNode extends AbstractDMVMNode return new ModuleVMContext(dmc); } - public void update(final ILabelUpdate[] updates) { + /* + * @since 2.0 + */ + public void update(final IPropertiesUpdate[] updates) { try { getSession().getExecutor().execute(new DsfRunnable() { public void run() { - updateLabelInSessionThread(updates); + updatePropertiesInSessionThread(updates); }}); } catch (RejectedExecutionException e) { - for (ILabelUpdate update : updates) { + for (IPropertiesUpdate update : updates) { handleFailedUpdate(update); } } } - - protected void updateLabelInSessionThread(ILabelUpdate[] updates) { - for (final ILabelUpdate update : updates) { - IModules modulesService = getServicesTracker().getService(IModules.class); + public void update(final ILabelUpdate[] updates) { + fLabelProvider.update(updates); + } + + /** + * @since 2.0 + */ + @ConfinedToDsfExecutor("getSession().getExecutor()") + protected void updatePropertiesInSessionThread(final IPropertiesUpdate[] updates) { + IModules modulesService = getServicesTracker().getService(IModules.class); + for (final IPropertiesUpdate update : updates) { final IModuleDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IModuleDMContext.class); // If either update or service are not valid, fail the update and exit. if ( modulesService == null || dmc == null ) { handleFailedUpdate(update); - continue; + return; } - // Use different image for loaded and unloaded symbols when event to report loading of symbols is implemented. - update.setImageDescriptor(DsfUIPlugin.getImageDescriptor(IDsfDebugUIConstants.IMG_OBJS_SHARED_LIBRARY_SYMBOLS_LOADED), 0); - modulesService.getModuleData( dmc, new ViewerDataRequestMonitor(getSession().getExecutor(), update) { @Override - protected void handleCompleted() { - /* - * The request could fail if the state of the service - * changed during the request, but the view model - * has not been updated yet. - */ - if (!isSuccess()) { - assert getStatus().isOK() || - getStatus().getCode() != IDsfStatusConstants.INTERNAL_ERROR || - getStatus().getCode() != IDsfStatusConstants.NOT_SUPPORTED; - handleFailedUpdate(update); - return; - } - - /* - * If columns are configured, call the protected methods to - * fill in column values. - */ - String[] localColumns = update.getColumnIds(); - if (localColumns == null) localColumns = new String[] { null }; - - for (int i = 0; i < localColumns.length; i++) { - fillColumnLabel(dmc, getData(), localColumns[i], i, update); - } + protected void handleSuccess() { + fillModuleDataProperties(update, getData()); update.done(); } }); } } - protected void fillColumnLabel(IModuleDMContext dmContext, IModuleDMData dmData, - String columnId, int idx, ILabelUpdate update) - { - if ( columnId == null ) { - /* - * If the Column ID comes in as "null" then this is the case where the user has decided - * to not have any columns. So we need a default action which makes the most sense and - * is doable. In this case we elect to simply display the name. - */ - update.setLabel(dmData.getName(), idx); - } - } - + /** + * @since 2.0 + */ + protected void fillModuleDataProperties(IPropertiesUpdate update, IModuleDMData data) { + update.setProperty(PROP_NAME, data.getName()); + update.setProperty(PROP_IS_LOADED, data.isSymbolsLoaded()); + } + public int getDeltaFlags(Object e) { if (e instanceof IRunControl.ISuspendedDMEvent) { return IModelDelta.CONTENT; diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/ModulesVMProvider.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/ModulesVMProvider.java index fc713683cdc..46cc5a01366 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/ModulesVMProvider.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/ModulesVMProvider.java @@ -27,9 +27,8 @@ import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.RootDMVMNode; import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; /** - * + * @since 1.0 */ -@SuppressWarnings("restriction") public class ModulesVMProvider extends AbstractDMVMProvider { /* * Current default for register formatting. diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/messages.properties b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/messages.properties new file mode 100644 index 00000000000..867515f5fc4 --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/messages.properties @@ -0,0 +1,13 @@ +############################################################################### +# Copyright (c) 2007, 2009 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 +# Wind River Systems - added Address +############################################################################### + +ModulesVMNode_No_columns__text_format={0} diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/FormattedValueLabelText.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/FormattedValueLabelText.java new file mode 100644 index 00000000000..62c628bc184 --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/FormattedValueLabelText.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat; + +import java.text.MessageFormat; +import java.util.Map; + +import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelText; +import org.eclipse.core.runtime.IStatus; + +/** + * + * + * @since 2.0 + */ +public class FormattedValueLabelText extends LabelText { + + public FormattedValueLabelText() { + this( + MessagesForNumberFormat.FormattedValueLabelText__text_format, + new String[] { IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE }); + } + + public FormattedValueLabelText(String formatPattern, String[] propertyNames) { + super(formatPattern, addActiveFormatPropertyNames(propertyNames)); + } + + private static String[] addActiveFormatPropertyNames(String[] propertyNames) { + String[] newPropertyNames = new String[propertyNames.length + 2]; + System.arraycopy(propertyNames, 0, newPropertyNames, 0, propertyNames.length); + newPropertyNames[propertyNames.length + 0] = IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT; + newPropertyNames[propertyNames.length + 1] = IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE; + return newPropertyNames; + } + + @Override + protected Object getPropertyValue(String propertyName, IStatus status, Map properties) { + // If the format is not the same as the preferred format, include it in the value string. + if ( IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE.equals(propertyName) ) { + Object activeFormat = properties.get(IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT); + Object preferredFormat = properties.get(IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE); + Object value = properties.get(IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE); + if (value != null && activeFormat != null && !activeFormat.equals(preferredFormat)) { + return MessageFormat.format( + MessagesForNumberFormat.FormattedValueLabelText__Value__text_format, + new Object[] { + value, + FormattedValueVMUtil.getFormatLabel((String)activeFormat) }); + } + } + return properties.get(propertyName); + } + + @Override + public boolean isEnabled(IStatus status, Map properties) { + for (String property : getPropertyNames()) { + if ( IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT.equals(property) || + IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE.equals(property) ) + { + continue; + } + if (properties.get(property) == null) { + return false; + } + } + return true; + } +} \ No newline at end of file diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/FormattedValuePreferenceStore.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/FormattedValuePreferenceStore.java deleted file mode 100644 index ac02e59a06d..00000000000 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/FormattedValuePreferenceStore.java +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2006, 2008 Wind River Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Wind River Systems - initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat; - -import org.eclipse.cdt.dsf.debug.service.IFormattedValues; -import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants; -import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; - -/** - * Provides default implementation of preference storage. - * - * @since 1.0 - */ -@SuppressWarnings("restriction") -public class FormattedValuePreferenceStore implements IFormattedValuePreferenceStore { - - private static IFormattedValuePreferenceStore fgSingletonReference; - - public static IFormattedValuePreferenceStore getDefault() { - if (fgSingletonReference == null) { - fgSingletonReference = new FormattedValuePreferenceStore(); - } - return fgSingletonReference; - } - - public String getCurrentNumericFormat( IPresentationContext context ) { - - Object prop = context.getProperty( IDebugVMConstants.CURRENT_FORMAT_STORAGE ); - - if ( prop != null ) { - return (String) prop; - } - return IFormattedValues.NATURAL_FORMAT; - } -} diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/FormattedValueVMUtil.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/FormattedValueVMUtil.java new file mode 100644 index 00000000000..ad5cad4e3dd --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/FormattedValueVMUtil.java @@ -0,0 +1,255 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat; + +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor; +import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; +import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; +import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.datamodel.DMContexts; +import org.eclipse.cdt.dsf.debug.service.IFormattedValues; +import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext; +import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMData; +import org.eclipse.cdt.dsf.debug.service.IFormattedValues.IFormattedDataDMContext; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants; +import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; +import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor; +import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; + +/** + * + * @since 2.0 + */ +public class FormattedValueVMUtil { + + /** + * Common map of user-readable labels for format IDs. UI components for + */ + private static Map fFormatLabels = new HashMap(8); + + static { + setFormatLabel(IFormattedValues.NATURAL_FORMAT, MessagesForNumberFormat.FormattedValueVMUtil_Natural_format__label); + setFormatLabel(IFormattedValues.HEX_FORMAT, MessagesForNumberFormat.FormattedValueVMUtil_Hex_format__label); + setFormatLabel(IFormattedValues.DECIMAL_FORMAT, MessagesForNumberFormat.FormattedValueVMUtil_Decimal_format__label); + setFormatLabel(IFormattedValues.OCTAL_FORMAT, MessagesForNumberFormat.FormattedValueVMUtil_Octal_format__label); + setFormatLabel(IFormattedValues.BINARY_FORMAT, MessagesForNumberFormat.FormattedValueVMUtil_Binary_format__label); + setFormatLabel(IFormattedValues.STRING_FORMAT, MessagesForNumberFormat.FormattedValueVMUtil_String_format__label); + } + + public static void setFormatLabel(String formatId, String label) { + fFormatLabels.put(formatId, label); + } + + public static String getFormatLabel(String formatId) { + String label = fFormatLabels.get(formatId); + if (label != null) { + return label; + } else { + return MessageFormat.format( + MessagesForNumberFormat.FormattedValueVMUtil_Other_format__format_text, new Object[] { formatId }); + } + } + + public static String getPropertyForFormatId(String formatId) { + if (formatId == null) { + return null; + } + return IDebugVMConstants.PROP_FORMATTED_VALUE_BASE + "." + formatId; //$NON-NLS-1$ + } + + public static String getFormatFromProperty(String property) { + return property.substring(IDebugVMConstants.PROP_FORMATTED_VALUE_BASE.length() + 1); + } + + + public static String getPreferredFormat(IPresentationContext context) { + Object prop = context.getProperty( IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE ); + if ( prop != null ) { + return (String) prop; + } + return IFormattedValues.NATURAL_FORMAT; + } + + @ConfinedToDsfExecutor("service.getExecutor()") + public static void updateFormattedValues( + final IPropertiesUpdate updates[], + final IFormattedValues service, + final Class dmcType, + final RequestMonitor monitor) + { + // First retrieve the available formats for all the updates, and store it in a map (as well as the updates). + // After that is completed call another method to retrieve the formatted values. + final Map availableFormats = new HashMap(updates.length * 4/3); + final CountingRequestMonitor countingRm = new CountingRequestMonitor( + service.getExecutor(), + new RequestMonitor(service.getExecutor(), monitor) { + @Override + protected void handleCompleted() { + updateFormattedValuesWithAvailableFormats(updates, service, dmcType, availableFormats, monitor); + } + }); + int count = 0; + + for (final IPropertiesUpdate update : updates) { + if (!update.getProperties().contains(IDebugVMConstants.PROP_FORMATTED_VALUE_AVAILABLE_FORMATS) && + !update.getProperties().contains(IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT) && + !update.getProperties().contains(IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE)) + { + // Update is not requesting any formatted value information, so just skip it. If specitic formats were + // requested for this update, they will still be retrieved by updateFormattedValuesWithAvailableFormats. + continue; + } + + IFormattedDataDMContext dmc = null; + if (update.getElement() instanceof IDMVMContext) { + dmc = DMContexts.getAncestorOfType(((IDMVMContext)update.getElement()).getDMContext(), dmcType); + } + + if (dmc == null) { + update.setStatus(DsfUIPlugin.newErrorStatus(IDsfStatusConstants.INVALID_HANDLE, "Update element did not contain a valid context: " + dmcType, null)); //$NON-NLS-1$ + continue; + } + + service.getAvailableFormats( + dmc, + // Use the ViewerDataRequestMonitor in order to propagate the update's cancel request. But this means that + // we have to override the handleRequestedExecutionException() to guarantee that the caller's RM gets + // completed even when the service session has been shut down. + new ViewerDataRequestMonitor(service.getExecutor(), update) { + @Override + protected void handleCompleted() { + if (isSuccess()) { + update.setProperty(IDebugVMConstants.PROP_FORMATTED_VALUE_AVAILABLE_FORMATS, getData()); + availableFormats.put(update, getData()); + } else { + update.setStatus(getStatus()); + } + countingRm.done(); + } + + @Override + protected void handleRejectedExecutionException() { + countingRm.setStatus(DsfUIPlugin.newErrorStatus(IDsfStatusConstants.INVALID_STATE, "Request for monitor: '" + toString() + "' resulted in a rejected execution exception.", null)); //$NON-NLS-1$//$NON-NLS-2$ + countingRm.done(); + } + }); + count++; + } + countingRm.setDoneCount(count); + } + + @ConfinedToDsfExecutor("service.getExecutor()") + private static void updateFormattedValuesWithAvailableFormats( + IPropertiesUpdate updates[], + IFormattedValues service, + Class dmcType, + Map availableFormatsMap, + final RequestMonitor monitor) + { + // Use a single counting RM for all the requested formats for each update. + final CountingRequestMonitor countingRm = new CountingRequestMonitor(ImmediateExecutor.getInstance(), monitor); + int count = 0; + + for (final IPropertiesUpdate update : updates) { + IFormattedDataDMContext dmc = null; + if (update.getElement() instanceof IDMVMContext) { + dmc = DMContexts.getAncestorOfType(((IDMVMContext)update.getElement()).getDMContext(), dmcType); + } + if (dmc == null) { + // The error status should already be set by the calling method. + continue; + } + + // Calculate the active value format based on view preference and available formats. + String[] availableFormats = availableFormatsMap.get(update); + String _activeFormat = null; + if (availableFormats != null && availableFormats.length != 0) { + _activeFormat = getPreferredFormat(update.getPresentationContext()); + update.setProperty(IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE, _activeFormat); + if (!isFormatAvailable(_activeFormat, availableFormats)) { + _activeFormat = availableFormats[0]; + } + } + final String activeFormat = _activeFormat; + + update.setProperty(IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT, activeFormat); + + // Loop through all the requested properties and check if any of them are for the formatted value. In the + // same loop, try to see if the active format is already requested and if it's not request it at the end. + boolean activeFormatRequested = activeFormat == null; + for (Iterator itr = update.getProperties().iterator(); itr.hasNext() || !activeFormatRequested;) { + String nextFormat; + if (itr.hasNext()) { + String propertyName = itr.next(); + if (propertyName.startsWith(IDebugVMConstants.PROP_FORMATTED_VALUE_BASE)) { + nextFormat = FormattedValueVMUtil.getFormatFromProperty(propertyName); + if (nextFormat.equals(activeFormat)) { + activeFormatRequested = true; + } + if (availableFormats != null && !isFormatAvailable(nextFormat, availableFormats)) { + continue; + } + } else { + continue; + } + } else { + nextFormat = activeFormat; + activeFormatRequested = true; + } + + final FormattedValueDMContext formattedValueDmc = service.getFormattedValueContext(dmc, nextFormat); + service.getFormattedExpressionValue( + formattedValueDmc, + // Here also use the ViewerDataRequestMonitor in order to propagate the update's cancel request. + // Use an immediate executor to avoid the possibility of a rejected execution exception. + new ViewerDataRequestMonitor(ImmediateExecutor.getInstance(), update) { + @Override + protected void handleCompleted() { + if (isSuccess()) { + String format = formattedValueDmc.getFormatID(); + update.setProperty( + FormattedValueVMUtil.getPropertyForFormatId(format), + getData().getFormattedValue()); + if (format.equals(activeFormat)) { + update.setProperty( + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE, + getData().getFormattedValue()); + } + } else { + update.setStatus(getStatus()); + } + countingRm.done(); + }; + }); + count++; + } + } + countingRm.setDoneCount(count); + } + + private static boolean isFormatAvailable(String format, String[] availableFormats) { + for (String availableFormat : availableFormats) { + if (availableFormat.equals(format)) { + return true; + } + } + return false; + } + +} diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/IFormattedValuePreferenceStore.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/IFormattedValuePreferenceStore.java deleted file mode 100644 index 63525cf933e..00000000000 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/IFormattedValuePreferenceStore.java +++ /dev/null @@ -1,28 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2006, 2008 Wind River Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Wind River Systems - initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat; - -import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; - -/** - * - * @since 1.0 - */ -@SuppressWarnings("restriction") -public interface IFormattedValuePreferenceStore { - /* - * Retrieves for the specified Presentation Context the configured format. - * - * @param context Specified Presentation Context - * @return Format ID. - */ - public String getCurrentNumericFormat( IPresentationContext context ); -} diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/IFormattedValueVMContext.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/IFormattedValueVMContext.java index 9c145770365..f6e45d6996f 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/IFormattedValueVMContext.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/IFormattedValueVMContext.java @@ -16,5 +16,4 @@ import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext; * @since 1.0 */ public interface IFormattedValueVMContext extends IVMContext { - IFormattedValuePreferenceStore getPreferenceStore(); } diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/MessagesForNumberFormat.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/MessagesForNumberFormat.java index 893759fbd9a..89098009aee 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/MessagesForNumberFormat.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/MessagesForNumberFormat.java @@ -20,15 +20,19 @@ public class MessagesForNumberFormat extends NLS { private static final String BUNDLE_NAME = "org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.messages"; //$NON-NLS-1$ - public static String NumberFormatContribution_Natural_label; - public static String NumberFormatContribution_Decimal_label; - public static String NumberFormatContribution_Hex_label; - public static String NumberFormatContribution_Octal_label; - public static String NumberFormatContribution_Binary_label; - public static String NumberFormatContribution_String_label; + public static String FormattedValueVMUtil_Natural_format__label; + public static String FormattedValueVMUtil_Decimal_format__label; + public static String FormattedValueVMUtil_Hex_format__label; + public static String FormattedValueVMUtil_Octal_format__label; + public static String FormattedValueVMUtil_Binary_format__label; + public static String FormattedValueVMUtil_String_format__label; + public static String FormattedValueVMUtil_Other_format__format_text; public static String NumberFormatContribution_EmptyFormatsList_label; + public static String FormattedValueLabelText__Value__text_format; + public static String FormattedValueLabelText__text_format; + static { // initialize resource bundle NLS.initializeMessages(BUNDLE_NAME, MessagesForNumberFormat.class); diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/NumberFormatsContribution.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/NumberFormatsContribution.java index bda57b093c4..9b9c2c50d74 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/NumberFormatsContribution.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/NumberFormatsContribution.java @@ -11,9 +11,8 @@ package org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat; import java.util.ArrayList; -import java.util.LinkedHashMap; +import java.util.LinkedList; import java.util.List; -import java.util.Map; import org.eclipse.cdt.dsf.debug.service.IFormattedValues; import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants; @@ -37,24 +36,23 @@ import org.eclipse.ui.services.IServiceLocator; * * @since 1.1 */ -@SuppressWarnings("restriction") public class NumberFormatsContribution extends CompoundContributionItem implements IWorkbenchContribution { - private static final Map FORMATS = new LinkedHashMap(); + private static final List FORMATS = new LinkedList(); static { - FORMATS.put(IFormattedValues.NATURAL_FORMAT, MessagesForNumberFormat.NumberFormatContribution_Natural_label); - FORMATS.put(IFormattedValues.HEX_FORMAT, MessagesForNumberFormat.NumberFormatContribution_Hex_label); - FORMATS.put(IFormattedValues.DECIMAL_FORMAT, MessagesForNumberFormat.NumberFormatContribution_Decimal_label); - FORMATS.put(IFormattedValues.OCTAL_FORMAT, MessagesForNumberFormat.NumberFormatContribution_Octal_label); - FORMATS.put(IFormattedValues.BINARY_FORMAT, MessagesForNumberFormat.NumberFormatContribution_Binary_label); - FORMATS.put(IFormattedValues.STRING_FORMAT, MessagesForNumberFormat.NumberFormatContribution_String_label); + FORMATS.add(IFormattedValues.NATURAL_FORMAT); + FORMATS.add(IFormattedValues.HEX_FORMAT); + FORMATS.add(IFormattedValues.DECIMAL_FORMAT); + FORMATS.add(IFormattedValues.OCTAL_FORMAT); + FORMATS.add(IFormattedValues.BINARY_FORMAT); + FORMATS.add(IFormattedValues.STRING_FORMAT); } private class SelectNumberFormatAction extends Action { private final IPresentationContext fContext; private final String fFormatId; SelectNumberFormatAction(IPresentationContext context, String formatId) { - super(FORMATS.get(formatId), AS_RADIO_BUTTON); + super(FormattedValueVMUtil.getFormatLabel(formatId), AS_RADIO_BUTTON); fContext = context; fFormatId = formatId; } @@ -62,7 +60,7 @@ public class NumberFormatsContribution extends CompoundContributionItem implemen @Override public void run() { if (isChecked()) { - fContext.setProperty(IDebugVMConstants.CURRENT_FORMAT_STORAGE, fFormatId); + fContext.setProperty(IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE, fFormatId); } } } @@ -95,13 +93,13 @@ public class NumberFormatsContribution extends CompoundContributionItem implemen } IPresentationContext context = provider.getPresentationContext(); - Object activeId = context.getProperty(IDebugVMConstants.CURRENT_FORMAT_STORAGE); + Object activeId = context.getProperty(IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE); if (activeId == null) { activeId = IFormattedValues.NATURAL_FORMAT; } List actions = new ArrayList(FORMATS.size()); - for (String formatId : FORMATS.keySet()) { + for (String formatId : FORMATS) { Action action = new SelectNumberFormatAction(context, formatId); if (formatId.equals(activeId)) { action.setChecked(true); diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/NumberFormatsPropertyTester.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/NumberFormatsPropertyTester.java index d16abb0fb6c..fde73af243b 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/NumberFormatsPropertyTester.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/NumberFormatsPropertyTester.java @@ -81,7 +81,7 @@ public class NumberFormatsPropertyTester extends PropertyTester { } else if (AVAILABLE.equals(property)) { return AVAILABLE_FORMATS.contains(expectedValue); } else if (ACTIVE.equals(property)) { - Object activeId = provider.getPresentationContext().getProperty(IDebugVMConstants.CURRENT_FORMAT_STORAGE); + Object activeId = provider.getPresentationContext().getProperty(IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE); return expectedValue != null && expectedValue.equals(activeId); } return false; diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/messages.properties b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/messages.properties index cbd76844508..63487f9f6e8 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/messages.properties +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/messages.properties @@ -9,11 +9,21 @@ # Wind River Systems Inc - copied for non-restricted version for DSDP/DD/DSF ############################################################################### -NumberFormatContribution_Natural_label=Default -NumberFormatContribution_Decimal_label=Decimal -NumberFormatContribution_Hex_label=Hex -NumberFormatContribution_Octal_label=Octal -NumberFormatContribution_Binary_label=Binary -NumberFormatContribution_String_label=String +FormattedValueVMUtil_Natural_format__label=Default +FormattedValueVMUtil_Decimal_format__label=Decimal +FormattedValueVMUtil_Hex_format__label=Hex +FormattedValueVMUtil_Octal_format__label=Octal +FormattedValueVMUtil_Binary_format__label=Binary +FormattedValueVMUtil_String_format__label=String +FormattedValueVMUtil_Other_format__format_text=Other ({0}) -NumberFormatContribution_EmptyFormatsList_label=Number formats not available \ No newline at end of file +NumberFormatContribution_EmptyFormatsList_label=Number formats not available + +# Message format used for cases where the value is formatted in a format that +# is not configured as the preferred format for the view or item. +# {0} - formatted value +# {1} - name of the format used to format the value +FormattedValueLabelText__Value__text_format={0} ({1}) + +# {0} - Value string as formatted by ValueLabelText__Value__text_format. +FormattedValueLabelText__text_format={0} diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/IRegisterVMConstants.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/IRegisterVMConstants.java new file mode 100644 index 00000000000..0ed834cb41d --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/IRegisterVMConstants.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2008 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.debug.ui.viewmodel.register; + +/** + * @since 2.0 + */ +public interface IRegisterVMConstants { + + public static final String PROP_DESCRIPTION = "description"; //$NON-NLS-1$ + + public static final String PROP_IS_FLOAT = "is_float"; //$NON-NLS-1$ + + public static final String PROP_IS_READABLE = "is_readable"; //$NON-NLS-1$ + + public static final String PROP_IS_READONCE = "is_readonce"; //$NON-NLS-1$ + + public static final String PROP_IS_WRITEABLE = "is_writeable"; //$NON-NLS-1$ + + public static final String PROP_IS_WRITEONCE = "is_writeonce"; //$NON-NLS-1$ + + public static final String PROP_HAS_SIDE_EFFECTS = "has_side_effects"; //$NON-NLS-1$ + + public static final String PROP_IS_ZERO_BASED_NUMBERING = "is_zero_based_numbering"; //$NON-NLS-1$ + + public static final String PROP_IS_ZERO_BIT_LEFT_MOST = "is_zero_bit_left_most"; //$NON-NLS-1$ + + public static final String PROP_CURRENT_MNEMONIC_LONG_NAME = "mnemonic_long_name"; //$NON-NLS-1$ + + public static final String PROP_CURRENT_MNEMONIC_SHORT_NAME = "mnemonic_short_name"; //$NON-NLS-1$ +} diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/MessagesForRegisterVM.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/MessagesForRegisterVM.java index b66c181f134..9a53f5439a8 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/MessagesForRegisterVM.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/MessagesForRegisterVM.java @@ -19,12 +19,34 @@ public class MessagesForRegisterVM extends NLS { private static final String BUNDLE_NAME = "org.eclipse.cdt.dsf.debug.ui.viewmodel.register.messages"; //$NON-NLS-1$ public static String RegisterColumnPresentation_description; - public static String RegisterColumnPresentation_name; - public static String RegisterColumnPresentation_type; - public static String RegisterColumnPresentation_value; + + public static String RegisterGroupVMNode_Name_column__text_format; + public static String RegisterGroupVMNode_Description_column__text_format; + public static String RegisterGroupVMNode_Expression_column__text_format; + public static String RegisterGroupVMNode_No_columns__text_format; + public static String RegisterGroupVMNode_No_columns__Error__text_format; + + public static String RegisterVMNode_Description_column__text_format; + public static String RegisterVMNode_Name_column__text_format; + public static String RegisterVMNode_Expression_column__text_format; + public static String RegisterVMNode_Type_column__text_format; + public static String RegisterVMNode_No_columns__text_format; + public static String RegisterVMNode_No_columns__Error__text_format; + + public static String RegisterBitFieldVMNode_Name_column__text_format; + public static String RegisterBitFieldVMNode_Description_column__text_format; + public static String RegisterBitFieldVMNode_Type_column__text_format; + public static String RegisterBitFieldVMNode_Value_column__With_mnemonic__text_format; + public static String RegisterBitFieldVMNode_Expression_column__text_format; + public static String RegisterBitFieldVMNode_No_columns__text_format; + public static String RegisterBitFieldVMNode_No_columns__With_mnemonic__text_format; + public static String RegisterBitFieldVMNode_No_columns__Error__text_format; + + + static { // initialize resource bundle NLS.initializeMessages(BUNDLE_NAME, MessagesForRegisterVM.class); diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterBitFieldCellModifier.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterBitFieldCellModifier.java index 48c8d7b471c..247be83c710 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterBitFieldCellModifier.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterBitFieldCellModifier.java @@ -18,7 +18,7 @@ import org.eclipse.cdt.dsf.debug.service.IRegisters.IBitFieldDMData; import org.eclipse.cdt.dsf.debug.service.IRegisters.IMnemonic; import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants; import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.WatchExpressionCellModifier; -import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.IFormattedValuePreferenceStore; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueVMUtil; import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; import org.eclipse.cdt.dsf.ui.viewmodel.update.AbstractCachingVMProvider; @@ -35,15 +35,16 @@ public class RegisterBitFieldCellModifier extends WatchExpressionCellModifier { private IBitFieldDMData fBitFieldData = null; private Object fElement = null; private SyncRegisterDataAccess fDataAccess = null; - private IFormattedValuePreferenceStore fFormatPrefStore; + /** + * @since 2.0 + */ public RegisterBitFieldCellModifier(AbstractCachingVMProvider provider, - IFormattedValuePreferenceStore formatPrefStore, BitFieldEditorStyle style, SyncRegisterDataAccess access ) + BitFieldEditorStyle style, SyncRegisterDataAccess access ) { fProvider = provider; fStyle = style; fDataAccess = access; - fFormatPrefStore = formatPrefStore; } /* @@ -109,8 +110,7 @@ public class RegisterBitFieldCellModifier extends WatchExpressionCellModifier { */ IVMContext ctx = (IVMContext) element; IPresentationContext presCtx = ctx.getVMNode().getVMProvider().getPresentationContext(); - - formatId = fFormatPrefStore.getCurrentNumericFormat(presCtx); + formatId = FormattedValueVMUtil.getPreferredFormat(presCtx); } else { formatId = IFormattedValues.NATURAL_FORMAT; @@ -167,8 +167,7 @@ public class RegisterBitFieldCellModifier extends WatchExpressionCellModifier { */ IVMContext ctx = (IVMContext) element; IPresentationContext presCtx = ctx.getVMNode().getVMProvider().getPresentationContext(); - - formatId = fFormatPrefStore.getCurrentNumericFormat(presCtx); + formatId = FormattedValueVMUtil.getPreferredFormat(presCtx); } else { formatId = IFormattedValues.NATURAL_FORMAT; diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterBitFieldVMNode.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterBitFieldVMNode.java index 0e96bf90d8a..1f40f4ac48b 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterBitFieldVMNode.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterBitFieldVMNode.java @@ -10,8 +10,11 @@ *******************************************************************************/ package org.eclipse.cdt.dsf.debug.ui.viewmodel.register; +import java.util.Map; import java.util.concurrent.RejectedExecutionException; +import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor; +import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DsfRunnable; import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; @@ -19,10 +22,7 @@ import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.datamodel.IDMContext; -import org.eclipse.cdt.dsf.debug.service.IFormattedValues; import org.eclipse.cdt.dsf.debug.service.IRegisters; -import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext; -import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMData; import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryChangedEvent; import org.eclipse.cdt.dsf.debug.service.IRegisters.IBitFieldChangedDMEvent; import org.eclipse.cdt.dsf.debug.service.IRegisters.IBitFieldDMContext; @@ -33,24 +33,34 @@ import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext; import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData; import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMData; import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.ErrorLabelText; import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants; import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.AbstractExpressionVMNode; -import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.IFormattedValuePreferenceStore; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueLabelText; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueVMUtil; import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.IFormattedValueVMContext; import org.eclipse.cdt.dsf.debug.ui.viewmodel.register.RegisterBitFieldCellModifier.BitFieldEditorStyle; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor; -import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext; import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelAttribute; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelColor; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelColumnInfo; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelFont; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelImage; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelText; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.PropertiesBasedLabelProvider; +import org.eclipse.cdt.dsf.ui.viewmodel.update.ICachingVMProvider; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.model.IExpression; -import org.eclipse.debug.internal.ui.DebugPluginImages; -import org.eclipse.debug.internal.ui.DebugUIPlugin; import org.eclipse.debug.internal.ui.IInternalDebugUIConstants; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest; @@ -61,6 +71,7 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRe 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.debug.ui.actions.IWatchExpressionFactoryAdapter2; import org.eclipse.jface.resource.JFaceResources; @@ -70,11 +81,11 @@ import org.eclipse.jface.viewers.ComboBoxCellEditor; import org.eclipse.jface.viewers.ICellModifier; import org.eclipse.jface.viewers.TextCellEditor; import org.eclipse.jface.viewers.TreePath; +import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Composite; -@SuppressWarnings("restriction") public class RegisterBitFieldVMNode extends AbstractExpressionVMNode - implements IElementEditor, IElementLabelProvider, IElementMementoProvider + implements IElementEditor, IElementLabelProvider, IElementMementoProvider, IElementPropertiesProvider { protected class BitFieldVMC extends DMVMContext implements IFormattedValueVMContext @@ -84,10 +95,6 @@ public class RegisterBitFieldVMNode extends AbstractExpressionVMNode super(dmc); } - public IFormattedValuePreferenceStore getPreferenceStore() { - return fFormattedPrefStore; - } - public void setExpression(IExpression expression) { fExpression = expression; } @@ -150,12 +157,19 @@ public class RegisterBitFieldVMNode extends AbstractExpressionVMNode private SyncRegisterDataAccess fSyncRegisterDataAccess = null; protected IWatchExpressionFactoryAdapter2 fBitFieldExpressionFactory = null; - private final IFormattedValuePreferenceStore fFormattedPrefStore; - public RegisterBitFieldVMNode(IFormattedValuePreferenceStore prefStore, AbstractDMVMProvider provider, DsfSession session, SyncRegisterDataAccess access) { + /** + * The label provider delegate. This VM node will delegate label updates to this provider + * which can be created by sub-classes. + * + * @since 2.0 + */ + private IElementLabelProvider fLabelProvider; + + public RegisterBitFieldVMNode(AbstractDMVMProvider provider, DsfSession session, SyncRegisterDataAccess access) { super(provider, session, IBitFieldDMContext.class); fSyncRegisterDataAccess = access; - fFormattedPrefStore = prefStore; + fLabelProvider = createLabelProvider(); } @@ -164,10 +178,185 @@ public class RegisterBitFieldVMNode extends AbstractExpressionVMNode return "RegisterBitFieldVMNode(" + getSession().getId() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } - public IFormattedValuePreferenceStore getPreferenceStore() { - return fFormattedPrefStore; - } + /** + * Creates the label provider delegate. This VM node will delegate label + * updates to this provider which can be created by sub-classes. + * + * @return Returns the label provider for this node. + * + * @since 2.0 + */ + protected IElementLabelProvider createLabelProvider() { + PropertiesBasedLabelProvider provider = new PropertiesBasedLabelProvider(); + + // The name column consists of the bit field name. + provider.setColumnInfo( + IDebugVMConstants.COLUMN_ID__NAME, + new LabelColumnInfo(new LabelAttribute[] { + new LabelText( + MessagesForRegisterVM.RegisterBitFieldVMNode_Name_column__text_format, + new String[] { PROP_NAME }), + new LabelImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_REGISTER)), + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + // The description column contains a brief description of the bit field. + provider.setColumnInfo( + IDebugVMConstants.COLUMN_ID__DESCRIPTION, + new LabelColumnInfo(new LabelAttribute[] { + new LabelText( + MessagesForRegisterVM.RegisterBitFieldVMNode_Description_column__text_format, + new String[] { IRegisterVMConstants.PROP_DESCRIPTION }), + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + // In the type column add information about bit field read/write/fload flags. + provider.setColumnInfo( + IDebugVMConstants.COLUMN_ID__TYPE, + new LabelColumnInfo(new LabelAttribute[] { + new LabelText( + MessagesForRegisterVM.RegisterBitFieldVMNode_Type_column__text_format, + new String[] { + IRegisterVMConstants.PROP_IS_READABLE, IRegisterVMConstants.PROP_IS_READONCE, + IRegisterVMConstants.PROP_IS_WRITEABLE, IRegisterVMConstants.PROP_IS_WRITEONCE + }) + { + @Override + public void updateAttribute(ILabelUpdate update, int columnIndex, IStatus status, Map properties) { + int readAttr = 0; + if ( Boolean.TRUE.equals(properties.get(IRegisterVMConstants.PROP_IS_READABLE)) ) { + readAttr = 1; + } else if ( Boolean.TRUE.equals(properties.get(IRegisterVMConstants.PROP_IS_READONCE)) ) { + readAttr = 2; + } + + int writeAttr = 0; + if ( Boolean.TRUE.equals(properties.get(IRegisterVMConstants.PROP_IS_WRITEABLE)) ) { + writeAttr = 1; + } else if ( Boolean.TRUE.equals(properties.get(IRegisterVMConstants.PROP_IS_WRITEONCE)) ) { + writeAttr = 2; + } + + Object[] messageAttrs = new Object[] { readAttr, writeAttr }; + try { + update.setLabel(getMessageFormat().format( + messageAttrs, new StringBuffer(), null).toString(), columnIndex); + } catch (IllegalArgumentException e) { + update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, 0, "Failed formatting a message for column " + columnIndex + ", for update " + update, e)); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + }, + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + // Value column shows the value in the active value format, followed by the active mnemonic if one is + // available. + // + // In case of error, show the error message in the value column (instead of the usual "...". This is needed + // for the expressions view, where an invalid expression entered by the user is a normal use case. + // + // For changed value high-lighting check the value in the active format. But if the format itself has changed, + // ignore the value change. + provider.setColumnInfo( + IDebugVMConstants.COLUMN_ID__VALUE, + new LabelColumnInfo(new LabelAttribute[] { + new FormattedValueLabelText( + MessagesForRegisterVM.RegisterBitFieldVMNode_Value_column__With_mnemonic__text_format, + new String[] { + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE, + IRegisterVMConstants.PROP_CURRENT_MNEMONIC_LONG_NAME}), + new FormattedValueLabelText(), + new ErrorLabelText(), + new LabelColor(new RGB(255, 0, 0), null) // TODO: replace with preference error color + { + { setPropertyNames(new String[] { PROP_NAME }); } + + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + return !status.isOK(); + } + }, + new LabelColor( + null, + DebugUITools.getPreferenceColor(IInternalDebugUIConstants.PREF_CHANGED_VALUE_BACKGROUND).getRGB()) + { + { + setPropertyNames(new String[] { + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE, + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE, + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT, + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT}); + } + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + Boolean activeFormatChanged = (Boolean)properties.get( + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT); + Boolean activeChanged = (Boolean)properties.get( + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE); + return Boolean.TRUE.equals(activeChanged) && !Boolean.TRUE.equals(activeFormatChanged); + } + }, + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + // Expression column is visible only in the expressions view. It shows the expression string that the user + // entered. Expression column images are the same as for the name column. + provider.setColumnInfo( + IDebugVMConstants.COLUMN_ID__EXPRESSION, + new LabelColumnInfo(new LabelAttribute[] { + new LabelText( + MessagesForRegisterVM.RegisterBitFieldVMNode_Expression_column__text_format, + new String[] { PROP_ELEMENT_EXPRESSION }), + new LabelImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_REGISTER)), + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + provider.setColumnInfo( + PropertiesBasedLabelProvider.ID_COLUMN_NO_COLUMNS, + new LabelColumnInfo(new LabelAttribute[] { + new FormattedValueLabelText( + MessagesForRegisterVM.RegisterBitFieldVMNode_No_columns__With_mnemonic__text_format, + new String[] { + PROP_NAME, + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE, + IRegisterVMConstants.PROP_CURRENT_MNEMONIC_LONG_NAME}), + new FormattedValueLabelText( + MessagesForRegisterVM.RegisterBitFieldVMNode_No_columns__With_mnemonic__text_format, + new String[] { + PROP_NAME, + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE}), + new ErrorLabelText( + MessagesForRegisterVM.RegisterBitFieldVMNode_No_columns__Error__text_format, + new String[] { PROP_NAME }), + new LabelImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_REGISTER)), + new LabelColor( + DebugUITools.getPreferenceColor(IDebugUIConstants.PREF_CHANGED_DEBUG_ELEMENT_COLOR).getRGB(), + null) + { + { + setPropertyNames(new String[] { + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE, + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE, + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT, + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT}); + } + + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + Boolean activeFormatChanged = (Boolean)properties.get( + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT); + Boolean activeChanged = (Boolean)properties.get( + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE); + return Boolean.TRUE.equals(activeChanged) && !Boolean.TRUE.equals(activeFormatChanged); + } + }, + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + return provider; + } + /** * @since 1.1 */ @@ -185,286 +374,103 @@ public class RegisterBitFieldVMNode extends AbstractExpressionVMNode return fBitFieldExpressionFactory; } - /** - * 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 updateFormattedRegisterValue(final ILabelUpdate update, final int labelIndex, final IBitFieldDMContext dmc, final IBitFieldDMData data) - { - final IRegisters regService = getServicesTracker().getService(IRegisters.class); - - /* - * 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 IPresentationContext context = update.getPresentationContext(); - final String preferencePageFormatId = fFormattedPrefStore.getCurrentNumericFormat(context) ; - - regService.getAvailableFormats( - dmc, - new ViewerDataRequestMonitor(getSession().getExecutor(), update) { - @Override - public void handleCompleted() { - if (!isSuccess()) { - handleFailedUpdate(update); - return; - } - - /* - * See if the desired format is supported. - */ - String[] formatIds = getData(); - String finalFormatId = IFormattedValues.HEX_FORMAT; - boolean requestedFormatIsSupported = false; - - for ( String fId : formatIds ) { - if ( preferencePageFormatId.equals(fId) ) { - /* - * 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 { - /* - * Register service does not support any format. - */ - handleFailedUpdate(update); - return; - } - } - - /* - * Format has been validated. Get the formatted value. - */ - final FormattedValueDMContext valueDmc = regService.getFormattedValueContext(dmc, finalFormatId); - - getDMVMProvider().getModelData( - RegisterBitFieldVMNode.this, update, regService, valueDmc, - new ViewerDataRequestMonitor(getSession().getExecutor(), update) { - @Override - public void handleCompleted() { - if (!isSuccess()) { - if (getStatus().getCode() == IDsfStatusConstants.INVALID_STATE) { - update.setLabel("...", labelIndex); //$NON-NLS-1$ - } else { - update.setLabel("Error: " + getStatus().getMessage(), labelIndex); //$NON-NLS-1$ - } - update.setFontData(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0], labelIndex); - update.done(); - return; - } - - /* - * Fill the label/column with the properly formatted data value. - */ - IMnemonic mnemonic = data.getCurrentMnemonicValue(); - if ( mnemonic != null ) { - String mnemstr = mnemonic.getLongName() + " - " + getData().getFormattedValue(); //$NON-NLS-1$ - update.setLabel(mnemstr , labelIndex); - } - else { - update.setLabel(getData().getFormattedValue() , labelIndex); - } - - update.setFontData(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0], labelIndex); - - // color based on change history - - FormattedValueDMData oldData = (FormattedValueDMData) getDMVMProvider().getArchivedModelData( - RegisterBitFieldVMNode.this, update, valueDmc); - if(oldData != null && !oldData.getFormattedValue().equals(getData().getFormattedValue())) { - update.setBackground( - DebugUIPlugin.getPreferenceColor(IInternalDebugUIConstants.PREF_CHANGED_VALUE_BACKGROUND).getRGB(), labelIndex); - } - update.done(); - } - }, - getExecutor() - ); - } - } - ); - } - - /* - * (non-Javadoc) - * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider#update(org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate[]) - */ public void update(final ILabelUpdate[] updates) { + fLabelProvider.update(updates); + } + + /** + * @see IElementPropertiesProvider#update(IPropertiesUpdate[]) + * + * @since 2.0 + */ + public void update(final IPropertiesUpdate[] updates) { try { getSession().getExecutor().execute(new DsfRunnable() { public void run() { - updateLabelInSessionThread(updates); + updatePropertiesInSessionThread(updates); }}); } catch (RejectedExecutionException e) { - for (ILabelUpdate update : updates) { + for (IPropertiesUpdate update : updates) { handleFailedUpdate(update); } } } - /* - * Updates the requested label based on the specified column. + /** + * @since 2.0 */ - protected void updateLabelInSessionThread(ILabelUpdate[] updates) { - for (final ILabelUpdate update : updates) { - - final IRegisters regService = getServicesTracker().getService(IRegisters.class); - - if ( regService == null ) { - handleFailedUpdate(update); + @ConfinedToDsfExecutor("getSession().getExecutor()") + protected void updatePropertiesInSessionThread(final IPropertiesUpdate[] updates) { + IRegisters service = getServicesTracker().getService(IRegisters.class, null); + + final CountingRequestMonitor countingRm = new CountingRequestMonitor(ImmediateExecutor.getInstance(), null) { + @Override + protected void handleCompleted() { + for (final IPropertiesUpdate update : updates) { + update.done(); + } + }; + }; + int count = 0; + + if (service != null) { + FormattedValueVMUtil.updateFormattedValues(updates, service, IBitFieldDMContext.class, countingRm); + count++; + } + + for (final IPropertiesUpdate update : updates) { + IExpression expression = (IExpression)DebugPlugin.getAdapter(update.getElement(), IExpression.class); + if (expression != null) { + update.setProperty(AbstractExpressionVMNode.PROP_ELEMENT_EXPRESSION, expression.getExpressionText()); + } + + IBitFieldDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IBitFieldDMContext.class); + if (dmc == null || service == null) { + handleFailedUpdate(update); continue; } - final IBitFieldDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IBitFieldDMContext.class); - - getDMVMProvider().getModelData( - this, - update, - regService, - dmc, + service.getBitFieldData( + dmc, + // Use the ViewerDataRequestMonitor in order to propagate the update's cancel request. Use an immediate + // executor to avoid the possibility of a rejected execution exception. new ViewerDataRequestMonitor(getSession().getExecutor(), update) { @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 (!isSuccess()) { - assert getStatus().isOK() || - getStatus().getCode() != IDsfStatusConstants.INTERNAL_ERROR || - getStatus().getCode() != IDsfStatusConstants.NOT_SUPPORTED; - /* - * Instead of just failing this outright we are going to attempt to do more here. - * Failing it outright causes the view to display ... for all columns in the line - * and this is uninformative about what is happening. We may be trying to show a - * register whos retrieval has been cancelled by the lower level. Perhaps because - * we are stepping extremely fast and state changes cause the register service to - * return these requests without ever sending them to the debug engine. - * - */ - String[] localColumns = update.getColumnIds(); - if (localColumns == null) - localColumns = new String[] { IDebugVMConstants.COLUMN_ID__NAME }; - - for (int idx = 0; idx < localColumns.length; idx++) { - if (IDebugVMConstants.COLUMN_ID__NAME.equals(localColumns[idx])) { - /* - * This used to be easy in that the DMC contained the name. Which allowed us - * to display the register name and an error message across from it. Now that - * name must come from the data and we could not retrieve the data we do not - * have anything intelligent to show here. I think this is going to look very - * ugly and will need to be worked on. We know the service has the name with - * it, it is just the dynamic part which cannot be obtained ( as explained in - * comments above ). - */ - update.setLabel("Unknown name", idx); //$NON-NLS-1$ - update.setImageDescriptor(DebugPluginImages.getImageDescriptor(IDebugUIConstants.IMG_OBJS_REGISTER), idx); - } else if (IDebugVMConstants.COLUMN_ID__TYPE.equals(localColumns[idx])) { - update.setLabel("", idx); //$NON-NLS-1$ - } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(localColumns[idx])) { - if (getStatus().getCode() == IDsfStatusConstants.INVALID_STATE) { - update.setLabel("...", idx); //$NON-NLS-1$ - } else { - update.setLabel("Error: " + getStatus().getMessage(), idx); //$NON-NLS-1$ - } - } else if (IDebugVMConstants.COLUMN_ID__DESCRIPTION.equals(localColumns[idx])) { - update.setLabel("...", idx); //$NON-NLS-1$ - } else if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(localColumns[idx])) { - update.setLabel("", idx); //$NON-NLS-1$ - } - - update.setFontData(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0], idx); - } - - update.done(); - 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 the extra data mining. We also note if we do - * have to datamine. 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.getColumnIds(); - if (localColumns == null) localColumns = new String[] { IDebugVMConstants.COLUMN_ID__NAME }; - - 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__TYPE.equals(localColumns[idx])) { - IBitFieldDMData data = getData(); - String typeStr = "Unsigned"; //$NON-NLS-1$ - String ReadAttrStr = "ReadNone"; //$NON-NLS-1$ - String WriteAddrStr = "WriteNone"; //$NON-NLS-1$ - - if ( data.isReadOnce() ) { ReadAttrStr = "ReadOnce"; } //$NON-NLS-1$ - else if ( data.isReadable() ) { ReadAttrStr = "Readable"; } //$NON-NLS-1$ - - if ( data.isReadOnce() ) { WriteAddrStr = "WriteOnce"; } //$NON-NLS-1$ - else if ( data.isReadable() ) { WriteAddrStr = "Writeable"; } //$NON-NLS-1$ - - typeStr += " - " + ReadAttrStr + "/" + WriteAddrStr; //$NON-NLS-1$ //$NON-NLS-2$ - update.setLabel(typeStr, 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); - } - } - - update.setFontData(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0], idx); - } - - if ( ! weAreExtractingFormattedData ) { - update.done(); + if (isSuccess()) { + fillBitFieldDataProperties(update, getData()); } else { - for (int idx = 0; idx < localColumns.length; idx++) { - if (IDebugVMConstants.COLUMN_ID__VALUE.equals(localColumns[idx])) { - updateFormattedRegisterValue(update, idx, dmc, getData() ); - } - update.setFontData(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0], idx); - } + update.setStatus(getStatus()); } + countingRm.done(); } - }, - getExecutor() - ); + }); + count++; + } + countingRm.setDoneCount(count); + } + + /** + * @since 2.0 + */ + @ConfinedToDsfExecutor("getSession().getExecutor()") + protected void fillBitFieldDataProperties(IPropertiesUpdate update, IBitFieldDMData data) { + update.setProperty(PROP_NAME, data.getName()); + update.setProperty(IRegisterVMConstants.PROP_DESCRIPTION, data.getDescription()); + update.setProperty(IRegisterVMConstants.PROP_IS_READABLE, data.isReadable()); + update.setProperty(IRegisterVMConstants.PROP_IS_READONCE, data.isReadOnce()); + update.setProperty(IRegisterVMConstants.PROP_IS_WRITEABLE, data.isWriteable()); + update.setProperty(IRegisterVMConstants.PROP_IS_WRITEONCE, data.isWriteOnce()); + update.setProperty(IRegisterVMConstants.PROP_HAS_SIDE_EFFECTS, data.hasSideEffects()); + update.setProperty(IRegisterVMConstants.PROP_IS_ZERO_BIT_LEFT_MOST, data.isZeroBitLeftMost()); + update.setProperty(IRegisterVMConstants.PROP_IS_ZERO_BASED_NUMBERING, data.isZeroBasedNumbering()); + IMnemonic mnemonic = data.getCurrentMnemonicValue(); + if (mnemonic != null) { + update.setProperty(IRegisterVMConstants.PROP_CURRENT_MNEMONIC_LONG_NAME, mnemonic.getLongName()); + update.setProperty(IRegisterVMConstants.PROP_CURRENT_MNEMONIC_SHORT_NAME, mnemonic.getShortName()); } } - /* - * (non-Javadoc) - * @see org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMNode#updateElementsInSessionThread(org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate) - */ @Override protected void updateElementsInSessionThread(final IChildrenUpdate update) { final IRegisterDMContext regDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IRegisterDMContext.class); @@ -516,7 +522,7 @@ public class RegisterBitFieldVMNode extends AbstractExpressionVMNode e instanceof IMemoryChangedEvent || e instanceof IRegisterChangedDMEvent || (e instanceof PropertyChangeEvent && - ((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) ) + ((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE) ) { return IModelDelta.CONTENT; } @@ -539,7 +545,7 @@ public class RegisterBitFieldVMNode extends AbstractExpressionVMNode e instanceof IMemoryChangedEvent || e instanceof IRegisterChangedDMEvent || (e instanceof PropertyChangeEvent && - ((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) ) + ((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE) ) { parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT); } @@ -623,14 +629,14 @@ public class RegisterBitFieldVMNode extends AbstractExpressionVMNode * Note we are complex COMBO and return the right editor. */ return new RegisterBitFieldCellModifier( - getDMVMProvider(), fFormattedPrefStore, BitFieldEditorStyle.BITFIELDCOMBO, getSyncRegisterDataAccess() ); + getDMVMProvider(), BitFieldEditorStyle.BITFIELDCOMBO, getSyncRegisterDataAccess() ); } else { /* * Text editor even if we need to clamp the value entered. */ return new RegisterBitFieldCellModifier( - getDMVMProvider(), fFormattedPrefStore, BitFieldEditorStyle.BITFIELDTEXT, getSyncRegisterDataAccess() ); + getDMVMProvider(), BitFieldEditorStyle.BITFIELDTEXT, getSyncRegisterDataAccess() ); } } else { @@ -769,7 +775,7 @@ public class RegisterBitFieldVMNode extends AbstractExpressionVMNode } if (event instanceof PropertyChangeEvent && - ((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) { + ((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE) { return IModelDelta.CONTENT; } @@ -805,7 +811,7 @@ public class RegisterBitFieldVMNode extends AbstractExpressionVMNode if ( event instanceof IRegisterChangedDMEvent || event instanceof IMemoryChangedEvent || (event instanceof PropertyChangeEvent && - ((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) ) + ((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE) ) { parentDelta.addNode(element, IModelDelta.STATE); } diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterCellModifier.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterCellModifier.java index 60b6e8d92f6..cc065cb46b6 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterCellModifier.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterCellModifier.java @@ -17,7 +17,7 @@ import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext; import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData; import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants; import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.WatchExpressionCellModifier; -import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.IFormattedValuePreferenceStore; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueVMUtil; import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; import org.eclipse.cdt.dsf.ui.viewmodel.update.AbstractCachingVMProvider; @@ -29,23 +29,17 @@ public class RegisterCellModifier extends WatchExpressionCellModifier { private AbstractCachingVMProvider fProvider; private SyncRegisterDataAccess fDataAccess = null; - private IFormattedValuePreferenceStore fFormattedValuePreferenceStore; - public RegisterCellModifier(AbstractCachingVMProvider provider, - IFormattedValuePreferenceStore formattedValuePreferenceStore, SyncRegisterDataAccess access) + public RegisterCellModifier(AbstractCachingVMProvider provider, SyncRegisterDataAccess access) { fProvider = provider; fDataAccess = access; - fFormattedValuePreferenceStore = formattedValuePreferenceStore; } public SyncRegisterDataAccess getRegisterDataAccess() { return fDataAccess; } - public IFormattedValuePreferenceStore getPreferenceStore() { - return fFormattedValuePreferenceStore; - } /* * Used to make sure we are dealing with a valid register. */ @@ -102,8 +96,7 @@ public class RegisterCellModifier extends WatchExpressionCellModifier { */ IVMContext ctx = (IVMContext) element; IPresentationContext presCtx = ctx.getVMNode().getVMProvider().getPresentationContext(); - - formatId = fFormattedValuePreferenceStore.getCurrentNumericFormat(presCtx); + formatId = FormattedValueVMUtil.getPreferredFormat(presCtx); } else { formatId = IFormattedValues.NATURAL_FORMAT; @@ -141,8 +134,7 @@ public class RegisterCellModifier extends WatchExpressionCellModifier { */ IVMContext ctx = (IVMContext) element; IPresentationContext presCtx = ctx.getVMNode().getVMProvider().getPresentationContext(); - - formatId = fFormattedValuePreferenceStore.getCurrentNumericFormat(presCtx); + formatId = FormattedValueVMUtil.getPreferredFormat(presCtx); } else { formatId = IFormattedValues.NATURAL_FORMAT; diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterGroupVMNode.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterGroupVMNode.java index 0d6fc7b2c9e..a133172fee4 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterGroupVMNode.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterGroupVMNode.java @@ -12,6 +12,7 @@ package org.eclipse.cdt.dsf.debug.ui.viewmodel.register; import java.util.concurrent.RejectedExecutionException; +import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DsfRunnable; import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; @@ -31,15 +32,22 @@ import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.WatchExpressionCellModi import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor; -import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext; import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelAttribute; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelColumnInfo; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelFont; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelImage; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelText; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.PropertiesBasedLabelProvider; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.model.IExpression; -import org.eclipse.debug.internal.ui.DebugPluginImages; import org.eclipse.debug.internal.ui.IInternalDebugUIConstants; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest; @@ -50,6 +58,7 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRe 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.debug.ui.actions.IWatchExpressionFactoryAdapter2; import org.eclipse.jface.resource.JFaceResources; @@ -59,10 +68,14 @@ import org.eclipse.jface.viewers.TextCellEditor; import org.eclipse.jface.viewers.TreePath; import org.eclipse.swt.widgets.Composite; -@SuppressWarnings("restriction") public class RegisterGroupVMNode extends AbstractExpressionVMNode - implements IElementEditor, IElementLabelProvider, IElementMementoProvider + implements IElementEditor, IElementLabelProvider, IElementMementoProvider, IElementPropertiesProvider { + /** + * @since 2.0 + */ + private static final String PROP_REGISTER_GROUP_DESCRIPTION = "register_group_description"; //$NON-NLS-1$ + protected class RegisterGroupVMC extends DMVMContext { private IExpression fExpression; @@ -129,8 +142,17 @@ public class RegisterGroupVMNode extends AbstractExpressionVMNode private IWatchExpressionFactoryAdapter2 fRegisterGroupExpressionFactory = null; private WatchExpressionCellModifier fWatchExpressionCellModifier = new WatchExpressionCellModifier(); + /** + * The label provider delegate. This VM node will delegate label updates to this provider + * which can be created by sub-classes. + * + * @since 2.0 + */ + private IElementLabelProvider fLabelProvider; + public RegisterGroupVMNode(AbstractDMVMProvider provider, DsfSession session, SyncRegisterDataAccess syncDataAccess) { super(provider, session, IRegisterGroupDMContext.class); + fLabelProvider = createLabelProvider(); fSyncRegisterDataAccess = syncDataAccess; } @@ -152,11 +174,7 @@ public class RegisterGroupVMNode extends AbstractExpressionVMNode } return fRegisterGroupExpressionFactory; } - - /* - * (non-Javadoc) - * @see org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMNode#updateElementsInSessionThread(org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate) - */ + @Override protected void updateElementsInSessionThread(final IChildrenUpdate update) { @@ -180,131 +198,131 @@ public class RegisterGroupVMNode extends AbstractExpressionVMNode update.done(); }}); } - - /* - * (non-Javadoc) - * @see org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMNode#createVMContext(org.eclipse.cdt.dsf.datamodel.IDMContext) - */ + @Override protected IDMVMContext createVMContext(IDMContext dmc) { return new RegisterGroupVMC(dmc); } - /* - * (non-Javadoc) - * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider#update(org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate[]) - */ + /** + * Creates the label provider delegate. This VM node will delegate label + * updates to this provider which can be created by sub-classes. + * + * @return Returns the label provider for this node. + * + * @since 2.0 + */ + protected IElementLabelProvider createLabelProvider() { + PropertiesBasedLabelProvider provider = new PropertiesBasedLabelProvider(); + + // The name column consists of the group name. + provider.setColumnInfo( + IDebugVMConstants.COLUMN_ID__NAME, + new LabelColumnInfo(new LabelAttribute[] { + new LabelText( + MessagesForRegisterVM.RegisterGroupVMNode_Name_column__text_format, + new String[] { PROP_NAME }), + new LabelImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_REGISTER_GROUP)), + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + // The description column contains a brief description of the register group. + provider.setColumnInfo( + IDebugVMConstants.COLUMN_ID__DESCRIPTION, + new LabelColumnInfo(new LabelAttribute[] { + new LabelText(MessagesForRegisterVM.RegisterGroupVMNode_Description_column__text_format, + new String[] { PROP_REGISTER_GROUP_DESCRIPTION }), + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + // Expression column is visible only in the expressions view. It shows the expression string that the user + // entered. Expression column images are the same as for the name column. + provider.setColumnInfo( + IDebugVMConstants.COLUMN_ID__EXPRESSION, + new LabelColumnInfo(new LabelAttribute[] { + new LabelText( + MessagesForRegisterVM.RegisterGroupVMNode_Expression_column__text_format, + new String[] { PROP_ELEMENT_EXPRESSION }), + new LabelImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_REGISTER_GROUP)), + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + provider.setColumnInfo( + PropertiesBasedLabelProvider.ID_COLUMN_NO_COLUMNS, + new LabelColumnInfo(new LabelAttribute[] { + new LabelText(MessagesForRegisterVM.RegisterGroupVMNode_No_columns__text_format, + new String[] { PROP_NAME, PROP_REGISTER_GROUP_DESCRIPTION}), + new LabelImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_REGISTER_GROUP)), + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + return provider; + } + public void update(final ILabelUpdate[] updates) { + fLabelProvider.update(updates); + } + + /** + * @see IElementPropertiesProvider#update(IPropertiesUpdate[]) + * + * @since 2.0 + */ + public void update(final IPropertiesUpdate[] updates) { try { getSession().getExecutor().execute(new DsfRunnable() { public void run() { - updateLabelInSessionThread(updates); + updatePropertiesInSessionThread(updates); }}); } catch (RejectedExecutionException e) { - for (ILabelUpdate update : updates) { + for (IPropertiesUpdate update : updates) { handleFailedUpdate(update); } } } - /* - * Updates the labels with the required information for each visible column. + /** + * @since 2.0 */ - protected void updateLabelInSessionThread(ILabelUpdate[] updates) { - for (final ILabelUpdate update : updates) { - - final IRegisterGroupDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IRegisterGroupDMContext.class); - if ( dmc == null ) { - handleFailedUpdate(update); - continue; + @ConfinedToDsfExecutor("getSession().getExecutor()") + protected void updatePropertiesInSessionThread(IPropertiesUpdate[] updates) { + IRegisters service = getServicesTracker().getService(IRegisters.class, null); + + for (final IPropertiesUpdate update : updates) { + IExpression expression = (IExpression)DebugPlugin.getAdapter(update.getElement(), IExpression.class); + if (expression != null) { + update.setProperty(AbstractExpressionVMNode.PROP_ELEMENT_EXPRESSION, expression.getExpressionText()); } + IRegisterGroupDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IRegisterGroupDMContext.class); IRegisters regService = getServicesTracker().getService(IRegisters.class); - if ( regService == null ) { + + if ( dmc == null || regService == null) { handleFailedUpdate(update); - continue; + return; } - getDMVMProvider().getModelData( - this, - update, - regService, + service.getRegisterGroupData( dmc, new ViewerDataRequestMonitor(getSession().getExecutor(), update) { @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 (!isSuccess()) { - assert getStatus().isOK() || - getStatus().getCode() != IDsfStatusConstants.INTERNAL_ERROR || - getStatus().getCode() != IDsfStatusConstants.NOT_SUPPORTED; - handleFailedUpdate(update); - return; - } - - /* - * If columns are configured, call the protected methods to - * fill in column values. - */ - String[] localColumns = update.getColumnIds(); - if (localColumns == null) localColumns = new String[] { null }; - - for (int i = 0; i < localColumns.length; i++) { - fillColumnLabel(dmc, getData(), localColumns[i], i, update); - } + protected void handleSuccess() { + fillRegisterGroupDataProperties(update, getData()); update.done(); } - }, - getExecutor()); + }); } } + + /** + * @since 2.0 + */ + @ConfinedToDsfExecutor("getSession().getExecutor()") + protected void fillRegisterGroupDataProperties(IPropertiesUpdate update, IRegisterGroupDMData data) { + update.setProperty(PROP_NAME, data.getName()); + update.setProperty(PROP_REGISTER_GROUP_DESCRIPTION, data.getName()); + } - /* - * Based on the specified visible column, provide the appropriate value/label. - */ - protected void fillColumnLabel(IRegisterGroupDMContext dmContext, IRegisterGroupDMData dmData, - String columnId, int idx, ILabelUpdate update) - { - update.setFontData(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0], idx); - - if (IDebugVMConstants.COLUMN_ID__NAME.equals(columnId)) { - update.setLabel(dmData.getName(), idx); - update.setImageDescriptor(DebugPluginImages.getImageDescriptor(IDebugUIConstants.IMG_OBJS_REGISTER_GROUP), idx); - } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(columnId)) { - update.setLabel("", idx); //$NON-NLS-1$ - } else if (IDebugVMConstants.COLUMN_ID__DESCRIPTION.equals(columnId)) { - update.setLabel(dmData.getDescription(), idx); - } else if (IDebugVMConstants.COLUMN_ID__TYPE.equals(columnId)) { - update.setLabel("", idx); //$NON-NLS-1$ - } 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); - } - } - else if ( columnId == null ) { - /* - * If the Column ID comes in as "null" then this is the case where the user has decided - * to not have any columns. So we need a default action which makes the most sense and - * is doable. In this case we elect to simply display the name. - */ - update.setLabel(dmData.getName(), idx); - update.setImageDescriptor(DebugPluginImages.getImageDescriptor(IDebugUIConstants.IMG_OBJS_REGISTER_GROUP), idx); - } - } - - /* - * (non-Javadoc) - * @see org.eclipse.cdt.dsf.ui.viewmodel.IVMNode#getDeltaFlags(java.lang.Object) - */ public int getDeltaFlags(Object e) { if (e instanceof ISuspendedDMEvent) { return IModelDelta.CONTENT; @@ -318,10 +336,6 @@ public class RegisterGroupVMNode extends AbstractExpressionVMNode return IModelDelta.NO_CHANGE; } - /* - * (non-Javadoc) - * @see org.eclipse.cdt.dsf.ui.viewmodel.IVMNode#buildDelta(java.lang.Object, org.eclipse.cdt.dsf.ui.viewmodel.VMDelta, int, org.eclipse.cdt.dsf.concurrent.RequestMonitor) - */ public void buildDelta(Object e, VMDelta parentDelta, int nodeOffset, RequestMonitor rm) { // Although the register groups themselves are not affected by the // suspended event, typically all the registers are. Add a CONTENT changed @@ -341,10 +355,6 @@ public class RegisterGroupVMNode extends AbstractExpressionVMNode rm.done(); } - /* - * (non-Javadoc) - * @see org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.IExpressionVMNode#canParseExpression(org.eclipse.debug.core.model.IExpression) - */ public boolean canParseExpression(IExpression expression) { return parseExpressionForGroupName(expression.getExpressionText()) != null; } diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMNode.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMNode.java index c48ec9590b9..f375b386d13 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMNode.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMNode.java @@ -10,22 +10,19 @@ *******************************************************************************/ package org.eclipse.cdt.dsf.debug.ui.viewmodel.register; -import java.util.ArrayList; +import java.util.Map; import java.util.concurrent.RejectedExecutionException; +import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor; import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; -import org.eclipse.cdt.dsf.concurrent.DsfExecutor; import org.eclipse.cdt.dsf.concurrent.DsfRunnable; import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.datamodel.DMContexts; import org.eclipse.cdt.dsf.datamodel.IDMContext; -import org.eclipse.cdt.dsf.debug.service.IFormattedValues; import org.eclipse.cdt.dsf.debug.service.IRegisters; -import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext; -import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMData; import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryChangedEvent; import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterChangedDMEvent; import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMContext; @@ -33,23 +30,33 @@ import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterDMData; import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMData; import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegistersChangedDMEvent; import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.ErrorLabelText; import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants; import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.AbstractExpressionVMNode; -import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.IFormattedValuePreferenceStore; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueLabelText; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueVMUtil; import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.IFormattedValueVMContext; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor; -import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext; import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelAttribute; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelColor; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelColumnInfo; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelFont; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelImage; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelText; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.PropertiesBasedLabelProvider; +import org.eclipse.cdt.dsf.ui.viewmodel.update.ICachingVMProvider; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.model.IExpression; -import org.eclipse.debug.internal.ui.DebugPluginImages; -import org.eclipse.debug.internal.ui.DebugUIPlugin; import org.eclipse.debug.internal.ui.IInternalDebugUIConstants; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest; @@ -61,6 +68,7 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdat 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.debug.ui.actions.IWatchExpressionFactoryAdapter2; import org.eclipse.jface.resource.JFaceResources; @@ -69,11 +77,14 @@ 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.graphics.RGB; import org.eclipse.swt.widgets.Composite; -@SuppressWarnings("restriction") +/** + * @since 1.0 + */ public class RegisterVMNode extends AbstractExpressionVMNode - implements IElementEditor, IElementLabelProvider, IElementMementoProvider + implements IElementEditor, IElementLabelProvider, IElementMementoProvider, IElementPropertiesProvider { protected class RegisterVMC extends DMVMContext implements IFormattedValueVMContext @@ -113,10 +124,6 @@ public class RegisterVMNode extends AbstractExpressionVMNode public int hashCode() { return super.hashCode() + (fExpression != null ? fExpression.hashCode() : 0); } - - public IFormattedValuePreferenceStore getPreferenceStore() { - return fFormattedPrefStore; - } } protected class RegisterExpressionFactory implements IWatchExpressionFactoryAdapter2 { @@ -147,14 +154,192 @@ public class RegisterVMNode extends AbstractExpressionVMNode private IWatchExpressionFactoryAdapter2 fRegisterExpressionFactory = null; final private SyncRegisterDataAccess fSyncRegisterDataAccess; - private final IFormattedValuePreferenceStore fFormattedPrefStore; - public RegisterVMNode(IFormattedValuePreferenceStore prefStore, AbstractDMVMProvider provider, DsfSession session, SyncRegisterDataAccess syncDataAccess) { + /** + * The label provider delegate. This VM node will delegate label updates to this provider + * which can be created by sub-classes. + * + * @since 2.0 + */ + private IElementLabelProvider fLabelProvider; + + public RegisterVMNode(AbstractDMVMProvider provider, DsfSession session, SyncRegisterDataAccess syncDataAccess) { super(provider, session, IRegisterDMContext.class); fSyncRegisterDataAccess = syncDataAccess; - fFormattedPrefStore = prefStore; + fLabelProvider = createLabelProvider(); } + /** + * Creates the label provider delegate. This VM node will delegate label + * updates to this provider which can be created by sub-classes. + * + * @return Returns the label provider for this node. + * + * @since 2.0 + */ + protected IElementLabelProvider createLabelProvider() { + PropertiesBasedLabelProvider provider = new PropertiesBasedLabelProvider(); + + // The name column consists of the register name. + provider.setColumnInfo( + IDebugVMConstants.COLUMN_ID__NAME, + new LabelColumnInfo(new LabelAttribute[] { + new LabelText( + MessagesForRegisterVM.RegisterVMNode_Name_column__text_format, + new String[] { PROP_NAME }), + new LabelImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_REGISTER)), + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + // The description column contains a brief description of the register. + provider.setColumnInfo( + IDebugVMConstants.COLUMN_ID__DESCRIPTION, + new LabelColumnInfo(new LabelAttribute[] { + new LabelText( + MessagesForRegisterVM.RegisterVMNode_Description_column__text_format, + new String[] { IRegisterVMConstants.PROP_DESCRIPTION }), + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + // In the type column add information about register read/write/fload flags. + provider.setColumnInfo( + IDebugVMConstants.COLUMN_ID__TYPE, + new LabelColumnInfo(new LabelAttribute[] { + new LabelText( + MessagesForRegisterVM.RegisterVMNode_Type_column__text_format, + new String[] { + IRegisterVMConstants.PROP_IS_FLOAT, IRegisterVMConstants.PROP_IS_READABLE, IRegisterVMConstants.PROP_IS_READONCE, + IRegisterVMConstants.PROP_IS_WRITEABLE, IRegisterVMConstants.PROP_IS_WRITEONCE + }) + { + @Override + public void updateAttribute(ILabelUpdate update, int columnIndex, IStatus status, Map properties) { + int type = 0; + if ( Boolean.TRUE.equals(properties.get(IRegisterVMConstants.PROP_IS_FLOAT)) ) { + type = 1; + } + + int readAttr = 0; + if ( Boolean.TRUE.equals(properties.get(IRegisterVMConstants.PROP_IS_READABLE)) ) { + readAttr = 1; + } else if ( Boolean.TRUE.equals(properties.get(IRegisterVMConstants.PROP_IS_READONCE)) ) { + readAttr = 2; + } + + int writeAttr = 0; + if ( Boolean.TRUE.equals(properties.get(IRegisterVMConstants.PROP_IS_WRITEABLE)) ) { + writeAttr = 1; + } else if ( Boolean.TRUE.equals(properties.get(IRegisterVMConstants.PROP_IS_WRITEONCE)) ) { + writeAttr = 2; + } + + Object[] messageAttrs = new Object[] { type, readAttr, writeAttr }; + try { + update.setLabel(getMessageFormat().format( + messageAttrs, new StringBuffer(), null).toString(), columnIndex); + } catch (IllegalArgumentException e) { + update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, 0, "Failed formatting a message for column " + columnIndex + ", for update " + update, e)); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + }, + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + // Value column shows the value in the active value format. + // + // In case of error, show the error message in the value column (instead of the usual "...". This is needed + // for the expressions view, where an invalid expression entered by the user is a normal use case. + // + // For changed value high-lighting check the value in the active format. But if the format itself has changed, + // ignore the value change. + provider.setColumnInfo( + IDebugVMConstants.COLUMN_ID__VALUE, + new LabelColumnInfo(new LabelAttribute[] { + new FormattedValueLabelText(), + new ErrorLabelText(), + new LabelColor(new RGB(255, 0, 0), null) // TODO: replace with preference error color + { + { setPropertyNames(new String[] { PROP_NAME }); } + + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + return !status.isOK(); + } + }, + new LabelColor( + null, + DebugUITools.getPreferenceColor(IInternalDebugUIConstants.PREF_CHANGED_VALUE_BACKGROUND).getRGB()) + { + { + setPropertyNames(new String[] { + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE, + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE, + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT, + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT}); + } + + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + Boolean activeFormatChanged = (Boolean)properties.get( + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT); + Boolean activeChanged = (Boolean)properties.get( + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE); + return Boolean.TRUE.equals(activeChanged) && !Boolean.TRUE.equals(activeFormatChanged); + } + }, + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + // Expression column is visible only in the expressions view. It shows the expression string that the user + // entered. Expression column images are the same as for the name column. + provider.setColumnInfo( + IDebugVMConstants.COLUMN_ID__EXPRESSION, + new LabelColumnInfo(new LabelAttribute[] { + new LabelText( + MessagesForRegisterVM.RegisterVMNode_Expression_column__text_format, + new String[] { PROP_ELEMENT_EXPRESSION }), + new LabelImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_REGISTER)), + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + provider.setColumnInfo( + PropertiesBasedLabelProvider.ID_COLUMN_NO_COLUMNS, + new LabelColumnInfo(new LabelAttribute[] { + new FormattedValueLabelText( + MessagesForRegisterVM.RegisterVMNode_No_columns__text_format, + new String[] { PROP_NAME, IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE }), + new ErrorLabelText( + MessagesForRegisterVM.RegisterVMNode_No_columns__Error__text_format, + new String[] { PROP_NAME }), + new LabelImage(DebugUITools.getImageDescriptor(IDebugUIConstants.IMG_OBJS_REGISTER)), + new LabelColor( + DebugUITools.getPreferenceColor(IDebugUIConstants.PREF_CHANGED_DEBUG_ELEMENT_COLOR).getRGB(), + null) + { + { + setPropertyNames(new String[] { + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE, + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE, + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT, + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT}); + } + + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + Boolean activeFormatChanged = (Boolean)properties.get( + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT); + Boolean activeChanged = (Boolean)properties.get( + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE); + return Boolean.TRUE.equals(activeChanged) && !Boolean.TRUE.equals(activeFormatChanged); + } + }, + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + return provider; + } + + @Override public String toString() { return "RegisterVMNode(" + getSession().getId() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ @@ -164,10 +349,6 @@ public class RegisterVMNode extends AbstractExpressionVMNode return fSyncRegisterDataAccess; } - public IFormattedValuePreferenceStore getPreferenceStore() { - return fFormattedPrefStore; - } - /** * @since 1.1 */ @@ -177,398 +358,105 @@ public class RegisterVMNode extends AbstractExpressionVMNode } return fRegisterExpressionFactory; } - - /* - * This class is used to hold the associated information needed to finally get the - * formatted value for a register DMC. It starts out with the basic set sans the - * actual formatted register DMC. Once found this is added to the information. - */ - private class QueuedValueUpdate { - - ILabelUpdate fUpdate; - int fIndex ; - IRegisterDMContext fDmc; - FormattedValueDMContext fValueDmc = null; - - public QueuedValueUpdate( ILabelUpdate update, int index , IRegisterDMContext dmc ) { - fUpdate = update; - fIndex = index; - fDmc = dmc; - } - - public ILabelUpdate getUpdate() { return fUpdate; } - public int getIndex() { return fIndex; } - public IRegisterDMContext getDmc() { return fDmc; } - - public void setValueDmc( FormattedValueDMContext dmc ) { fValueDmc = dmc; } - public FormattedValueDMContext getValueDmc() { return fValueDmc; } - } - - private void retrieveAllFormattedDataValues( final ArrayList updates ) { - - final IRegisters regService = getServicesTracker().getService(IRegisters.class); - if ( regService == null ) { - for ( final QueuedValueUpdate up : updates ) { - handleFailedUpdate(up.getUpdate()); - } - return; - } - for ( final QueuedValueUpdate up : updates ) { - - final ILabelUpdate update = up.getUpdate(); - final FormattedValueDMContext valueDmc = up.getValueDmc(); - - /* - * It is possible that we could not get a formatted DMC. In this case the setup - * logic puts a null as the value. So in this case we just complete this one - * with nothing. - */ - if ( valueDmc == null ) { - update.done(); - continue; - } - - final int idx = up.getIndex(); - - getDMVMProvider().getModelData( - RegisterVMNode.this, - update, - regService, - valueDmc, - new ViewerDataRequestMonitor(getSession().getExecutor(), update) { - @Override - public void handleCompleted() { - if (!isSuccess()) { - if (getStatus().getCode() == IDsfStatusConstants.INVALID_STATE) { - update.setLabel("...", idx); //$NON-NLS-1$ - } else { - update.setLabel("Error: " + getStatus().getMessage(), idx); //$NON-NLS-1$ - } - update.setFontData(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0], idx); - update.done(); - return; - } - /* - * Fill the label/column with the properly formatted data value. - */ - update.setLabel(getData().getFormattedValue(), idx); - - // color based on change history - FormattedValueDMData oldData = (FormattedValueDMData) getDMVMProvider().getArchivedModelData(RegisterVMNode.this, update, valueDmc); - if(oldData != null && !oldData.getFormattedValue().equals(getData().getFormattedValue())) { - update.setBackground(DebugUIPlugin.getPreferenceColor(IInternalDebugUIConstants.PREF_CHANGED_VALUE_BACKGROUND).getRGB(), idx); - } - update.setFontData(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0], idx); - update.done(); - } - }, - getSession().getExecutor() - ); - } - } - - /** - * 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 getFormattedDmcForReqister( final ILabelUpdate update, final IRegisterDMContext dmc, final DataRequestMonitor rm) - { - final IRegisters regService = getServicesTracker().getService(IRegisters.class); - if ( regService == null ) { - rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "", null)); //$NON-NLS-1$ - rm.done(); - return; - } - - /* - * 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 IPresentationContext context = update.getPresentationContext(); - final String preferencePageFormatId = getPreferenceStore().getCurrentNumericFormat(context) ; - - regService.getAvailableFormats( - dmc, - new DataRequestMonitor(getSession().getExecutor(), rm) { - @Override - public void handleSuccess() { - /* - * 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) ) { - /* - * 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 { - /* - * Register service does not support any format. - */ - handleFailure(); - return; - } - } - - /* - * Format has been validated. Return it. - */ - rm.setData(regService.getFormattedValueContext(dmc, finalFormatId)); - rm.done(); - } - } - ); - } - - /* - * (non-Javadoc) - * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider#update(org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate[]) - */ public void update(final ILabelUpdate[] updates) { + fLabelProvider.update(updates); + } + + /** + * @see IElementPropertiesProvider#update(IPropertiesUpdate[]) + * + * @since 2.0 + */ + public void update(final IPropertiesUpdate[] updates) { try { getSession().getExecutor().execute(new DsfRunnable() { public void run() { - updateLabelInSessionThread(updates); + updatePropertiesInSessionThread(updates); }}); } catch (RejectedExecutionException e) { - for (ILabelUpdate update : updates) { + for (IPropertiesUpdate update : updates) { handleFailedUpdate(update); } } } - - /* - * Updates the labels which are controlled by the column being requested. + + /** + * @since 2.0 */ - protected void updateLabelInSessionThread(final ILabelUpdate[] updates) { - - /* - * This list represents all the QUEUED requests for formatted DMCs. This allows us to issue the - * requests for the data in the same dispatch cycle. Thus the lower level services is given its - * best chance to coalesce the registers in to a single request. - */ - final ArrayList valueUpdatesToProcess = new ArrayList(); - - final DsfExecutor dsfExecutor = getSession().getExecutor(); - final CountingRequestMonitor crm = - new CountingRequestMonitor(dsfExecutor, null) { - @Override - public void handleCompleted() { - if (!isSuccess()) { - for ( ILabelUpdate up : updates ) { - handleFailedUpdate(up); - } - return; - } - - /* - * We have all of the formatted DMCs. Go issue the requests for the formatted data - * in a single dispatch cycle. - */ - retrieveAllFormattedDataValues( valueUpdatesToProcess ); + @ConfinedToDsfExecutor("getSession().getExecutor()") + protected void updatePropertiesInSessionThread(final IPropertiesUpdate[] updates) { + IRegisters service = getServicesTracker().getService(IRegisters.class, null); + + final CountingRequestMonitor countingRm = new CountingRequestMonitor(ImmediateExecutor.getInstance(), null) { + @Override + protected void handleCompleted() { + for (final IPropertiesUpdate update : updates) { + update.done(); } }; - - crm.setDoneCount( calculateTheNumberOfRowsWithValueColumns(updates) ); + }; + int count = 0; - /* - * Process each update request, creating a QUEUE of requests which need further processing - * for the formatted values. - */ - for (final ILabelUpdate update : updates) { - - final IRegisterDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IRegisterDMContext.class); - if ( dmc == null ) { - handleFailedUpdate(update); - continue; - } - - IRegisters regService = getServicesTracker().getService(IRegisters.class); - if ( regService == null ) { - handleFailedUpdate(update); - continue; - } - - getDMVMProvider().getModelData( - this, - update, - regService, - dmc, - new ViewerDataRequestMonitor(getSession().getExecutor(), update) { - @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 (!isSuccess()) { - assert getStatus().isOK() || - getStatus().getCode() != IDsfStatusConstants.INTERNAL_ERROR || - getStatus().getCode() != IDsfStatusConstants.NOT_SUPPORTED; - /* - * Instead of just failing this outright we are going to attempt to do more here. - * Failing it outright causes the view to display ... for all columns in the line - * and this is uninformative about what is happening. We may be trying to show a - * register whos retrieval has been cancelled by the lower level. Perhaps because - * we are stepping extremely fast and state changes cause the register service to - * return these requests without ever sending them to the debug engine. - * - */ - String[] localColumns = update.getColumnIds(); - if (localColumns == null) - localColumns = new String[] { IDebugVMConstants.COLUMN_ID__NAME }; - - for (int idx = 0; idx < localColumns.length; idx++) { - if (IDebugVMConstants.COLUMN_ID__NAME.equals(localColumns[idx])) { - /* - * This used to be easy in that the DMC contained the name. Which allowed us - * to display the register name and an error message across from it. Now that - * name must come from the data and we could not retrieve the data we do not - * have anything intelligent to show here. I think this is going to look very - * ugly and will need to be worked on. We know the service has the name with - * it, it is just the dynamic part which cannot be obtained ( as explained in - * comments above ). - */ - update.setLabel("Unknown name", idx); //$NON-NLS-1$ - update.setImageDescriptor(DebugPluginImages.getImageDescriptor(IDebugUIConstants.IMG_OBJS_REGISTER), idx); - } else if (IDebugVMConstants.COLUMN_ID__TYPE.equals(localColumns[idx])) { - update.setLabel("", idx); //$NON-NLS-1$ - } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(localColumns[idx])) { - if (getStatus().getCode() == IDsfStatusConstants.INVALID_STATE) { - update.setLabel("...", idx); //$NON-NLS-1$ - } else { - update.setLabel("Error: " + getStatus().getMessage(), idx); //$NON-NLS-1$ - } - } else if (IDebugVMConstants.COLUMN_ID__DESCRIPTION.equals(localColumns[idx])) { - update.setLabel("...", idx); //$NON-NLS-1$ - } else if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(localColumns[idx])) { - update.setLabel("", idx); //$NON-NLS-1$ - } - - update.setFontData(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0], idx); - } - - update.done(); - 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 the extra data mining. We also note, if we do have to - * datamine. 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.getColumnIds(); - if (localColumns == null) localColumns = new String[] { IDebugVMConstants.COLUMN_ID__NAME }; - - boolean allFieldsProcessed = true; - - for (int idx = 0; idx < localColumns.length; idx++) { - update.setFontData(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0], idx); - if (IDebugVMConstants.COLUMN_ID__NAME.equals(localColumns[idx])) { - update.setLabel(getData().getName(), idx); - update.setImageDescriptor(DebugPluginImages.getImageDescriptor(IDebugUIConstants.IMG_OBJS_REGISTER), idx); - } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(localColumns[idx])) { - allFieldsProcessed = false; - /* - * Create an entry which holds all related data and add it to the list to process - * when all the formatted DMCs are gathered. - */ - final QueuedValueUpdate valueUpdate = new QueuedValueUpdate(update,idx,dmc); - valueUpdatesToProcess.add(valueUpdate); - - /* - * Fetch the associated formatted DMC for this field. Note that every time we - * complete the request for a Formatted DMC we tell the Counting Request Monitor - * we have completed one in the list. - */ - getFormattedDmcForReqister( - update, dmc, - new ViewerDataRequestMonitor(dsfExecutor, update) { - @Override - public void handleCompleted() { - if ( getStatus().isOK() ) { - valueUpdate.setValueDmc(getData()); - } - else { - valueUpdate.setValueDmc(null); - } - crm.done(); - } - }); - } else if (IDebugVMConstants.COLUMN_ID__TYPE.equals(localColumns[idx])) { - IRegisterDMData data = getData(); - String typeStr = "Unsigned"; //$NON-NLS-1$ - String ReadAttrStr = "ReadNone"; //$NON-NLS-1$ - String WriteAddrStr = "WriteNone"; //$NON-NLS-1$ - - if ( data.isFloat() ) { typeStr = "Floating Point"; } //$NON-NLS-1$ - - if ( data.isReadOnce() ) { ReadAttrStr = "ReadOnce"; } //$NON-NLS-1$ - else if ( data.isReadable() ) { ReadAttrStr = "Readable"; } //$NON-NLS-1$ - - if ( data.isReadOnce() ) { WriteAddrStr = "WriteOnce"; } //$NON-NLS-1$ - else if ( data.isReadable() ) { WriteAddrStr = "Writeable"; } //$NON-NLS-1$ - - typeStr += " - " + ReadAttrStr + "/" + WriteAddrStr; //$NON-NLS-1$ //$NON-NLS-2$ - update.setLabel(typeStr, 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); - } - } - } - - if ( allFieldsProcessed ) { - update.done(); - } - } - }, - getSession().getExecutor()); + if (service != null) { + FormattedValueVMUtil.updateFormattedValues(updates, service, IRegisterDMContext.class, countingRm); + count++; } + + for (final IPropertiesUpdate update : updates) { + IExpression expression = (IExpression)DebugPlugin.getAdapter(update.getElement(), IExpression.class); + if (expression != null) { + update.setProperty(AbstractExpressionVMNode.PROP_ELEMENT_EXPRESSION, expression.getExpressionText()); + } + + final IRegisterDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IRegisterDMContext.class); + if (dmc == null || service == null) { + handleFailedUpdate(update); + continue; + } + + service.getRegisterData( + dmc, + // Use the ViewerDataRequestMonitor in order to propagate the update's cancel request. Use an immediate + // executor to avoid the possibility of a rejected execution exception. + new ViewerDataRequestMonitor(getSession().getExecutor(), update) { + @Override + protected void handleCompleted() { + if (isSuccess()) { + fillRegisterDataProperties(update, getData()); + update.setProperty(PROP_NAME, getData().getName()); + update.setProperty(IRegisterVMConstants.PROP_DESCRIPTION, getData().getDescription()); + update.setProperty(IRegisterVMConstants.PROP_IS_FLOAT, getData().isFloat()); + update.setProperty(IRegisterVMConstants.PROP_IS_READABLE, getData().isReadable()); + update.setProperty(IRegisterVMConstants.PROP_IS_READONCE, getData().isReadOnce()); + update.setProperty(IRegisterVMConstants.PROP_IS_WRITEABLE, getData().isWriteable()); + update.setProperty(IRegisterVMConstants.PROP_IS_WRITEONCE, getData().isWriteOnce()); + } else { + update.setStatus(getStatus()); + } + countingRm.done(); + } + }); + count++; + } + countingRm.setDoneCount(count); } - private int calculateTheNumberOfRowsWithValueColumns( ILabelUpdate updates[] ) { - int count = 0; - for (final ILabelUpdate update : updates) { - String[] columns = update.getColumnIds(); - if (columns == null) columns = new String[] { IDebugVMConstants.COLUMN_ID__NAME }; - - for (int idx = 0; idx < columns.length; idx++) { - if (IDebugVMConstants.COLUMN_ID__VALUE.equals(columns[idx])) { - count ++; - } - } - } - return count; + /** + * @since 2.0 + */ + @ConfinedToDsfExecutor("getSession().getExecutor()") + protected void fillRegisterDataProperties(IPropertiesUpdate update, IRegisterDMData data) + { + update.setProperty(PROP_NAME, data.getName()); + update.setProperty(IRegisterVMConstants.PROP_DESCRIPTION, data.getDescription()); + update.setProperty(IRegisterVMConstants.PROP_IS_FLOAT, data.isFloat()); + update.setProperty(IRegisterVMConstants.PROP_IS_READABLE, data.isReadable()); + update.setProperty(IRegisterVMConstants.PROP_IS_READONCE, data.isReadOnce()); + update.setProperty(IRegisterVMConstants.PROP_IS_WRITEABLE, data.isWriteable()); + update.setProperty(IRegisterVMConstants.PROP_IS_WRITEONCE, data.isWriteOnce()); } + /* * (non-Javadoc) @@ -631,7 +519,7 @@ public class RegisterVMNode extends AbstractExpressionVMNode e instanceof IMemoryChangedEvent || e instanceof IRegistersChangedDMEvent || (e instanceof PropertyChangeEvent && - ((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) ) + ((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE) ) { return IModelDelta.CONTENT; } @@ -654,7 +542,7 @@ public class RegisterVMNode extends AbstractExpressionVMNode e instanceof IMemoryChangedEvent || e instanceof IRegistersChangedDMEvent || (e instanceof PropertyChangeEvent && - ((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) ) + ((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE) ) { // Create a delta that the whole register group has changed. parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT); @@ -786,7 +674,7 @@ public class RegisterVMNode extends AbstractExpressionVMNode if ( event instanceof IRegisterChangedDMEvent || event instanceof IMemoryChangedEvent || (event instanceof PropertyChangeEvent && - ((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) ) + ((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE) ) { return IModelDelta.STATE; } @@ -834,7 +722,7 @@ public class RegisterVMNode extends AbstractExpressionVMNode if ( event instanceof IRegisterChangedDMEvent || event instanceof IMemoryChangedEvent || (event instanceof PropertyChangeEvent && - ((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) ) + ((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE) ) { parentDelta.addNode(element, IModelDelta.STATE); } @@ -869,8 +757,7 @@ public class RegisterVMNode extends AbstractExpressionVMNode * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementEditor#getCellModifier(org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext, java.lang.Object) */ public ICellModifier getCellModifier(IPresentationContext context, Object element) { - return new RegisterCellModifier( - getDMVMProvider(), fFormattedPrefStore, getSyncRegisterDataAccess() ); + return new RegisterCellModifier( getDMVMProvider(), getSyncRegisterDataAccess() ); } /* diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMProvider.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMProvider.java index 01badb93297..4e2a3e4d359 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMProvider.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMProvider.java @@ -21,7 +21,6 @@ import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent; import org.eclipse.cdt.dsf.debug.ui.DsfDebugUITools; import org.eclipse.cdt.dsf.debug.ui.IDsfDebugUIConstants; -import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValuePreferenceStore; import org.eclipse.cdt.dsf.debug.ui.viewmodel.update.BreakpointHitUpdatePolicy; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.service.DsfServicesTracker; @@ -95,13 +94,13 @@ public class RegisterVMProvider extends AbstractDMVMProvider /* * Create the next level which is the registers themselves. */ - IVMNode registerNode = new RegisterVMNode(FormattedValuePreferenceStore.getDefault(), this, getSession(), regAccess); + IVMNode registerNode = new RegisterVMNode(this, getSession(), regAccess); addChildNodes(registerGroupNode, new IVMNode[] { registerNode }); /* * Create the next level which is the bitfield level. */ - IVMNode bitFieldNode = new RegisterBitFieldVMNode(FormattedValuePreferenceStore.getDefault(), this, getSession(), regAccess); + IVMNode bitFieldNode = new RegisterBitFieldVMNode(this, getSession(), regAccess); addChildNodes(registerNode, new IVMNode[] { bitFieldNode }); /* diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/messages.properties b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/messages.properties index a5bb472ba12..02a25e17151 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/messages.properties +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/messages.properties @@ -13,3 +13,74 @@ RegisterColumnPresentation_name=Name RegisterColumnPresentation_type=Type RegisterColumnPresentation_value=Value RegisterColumnPresentation_description=Description + +# Message format used for cases where the value is formatted in a format that +# is not configured as the preferred format for the view or item. +# {0} - formatted value +# {1} - name of the format used to format the value +Value_column__Value__text_format={0} ({1}) + +RegisterGroupVMNode_Name_column__text_format={0} +RegisterGroupVMNode_Description_column__text_format={0} +RegisterGroupVMNode_Expression_column__text_format={0} +RegisterGroupVMNode_No_columns__text_format={0} - {1} + +# {0} - register group name +# {1} - error message +RegisterGroupVMNode_No_columns__Error__text_format={0} - Error:{1} + + +RegisterVMNode_Name_column__text_format={0} +RegisterVMNode_Description_column__text_format={0} + +# {0} floating point, 0=integer/1=float +# {1} readability, 0=not readable/1=readable/2=readonce +# {2} write-ability, 0=not write-able/1=write-able/2=write once +RegisterVMNode_Type_column__text_format={0,choice,0#Unsigned|1#Floating Point} / {1,choice,0#ReadNone|1#Readable|2#ReadOnce},{2,choice,0#WriteNone|1#Writeable|2#WriteOnce} + +RegisterVMNode_Expression_column__text_format={0} + +# {0} - register name +# {1} - value formatted in the active format. If the preferred format was +# available, then this is just the value. Otherwise, it's the string formatted +# by the FormattedValueLabelText. +RegisterVMNode_No_columns__text_format={0} = {1} + +# {0} - register name +# {1} - error message +RegisterVMNode_No_columns__Error__text_format={0} - Error:{1} + + +RegisterBitFieldVMNode_Name_column__text_format={0} +RegisterBitFieldVMNode_Description_column__text_format={0} + +# {0} readability, 0=not readable/1=readable/2=readonce +# {1} write-ability, 0=not write-able/1=write-able/2=write once +RegisterBitFieldVMNode_Type_column__text_format={0,choice,0#ReadNone|1#Readable|2#ReadOnce},{1,choice,0#WriteNone|1#Writeable|2#WriteOnce} + +# Message format for the value column text +# {0} - value formatted in the active format. If the preferred format was +# available, then this is just the value. Otherwise, it's the string formatted +# by FormattedValueLabelText. +# {1} - bit field mnemonic +RegisterBitFieldVMNode_Value_column__With_mnemonic__text_format={0} - {1} + +RegisterBitFieldVMNode_Expression_column__text_format={0} + + +# {0} - bit field name +# {1} - error message +RegisterBitFieldVMNode_No_columns__text_format={0} = {1} + +# {0} - bit field name +# {1} - error message +RegisterBitFieldVMNode_No_columns__text_format={0} = {1} + +# {0} - bit field name +# {1} - error message +# {2} - bit field mnemonic +RegisterBitFieldVMNode_No_columns__With_mnemonic__text_format={0} = {1} - {2} + +# {0} - bit field name +# {1} - error message +RegisterBitFieldVMNode_No_columns__Error__text_format={0} - Error:{1} diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/MessagesForVariablesVM.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/MessagesForVariablesVM.java index d452aec9206..8293590c00d 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/MessagesForVariablesVM.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/MessagesForVariablesVM.java @@ -20,13 +20,24 @@ public class MessagesForVariablesVM extends NLS { private static final String BUNDLE_NAME = "org.eclipse.cdt.dsf.debug.ui.viewmodel.variable.messages"; //$NON-NLS-1$ public static String VariableColumnPresentation_name; - public static String VariableColumnPresentation_type; - public static String VariableColumnPresentation_value; - public static String VariableColumnPresentation_address; + public static String VariableVMNode_Address_column__Error__text_format; + public static String VariableVMNode_Address_column__text_format; + public static String VariableVMNode_Description_column__text_format; + public static String VariableVMNode_Expression_column__text_format; + public static String VariableVMNode_Name_column__text_format; + public static String VariableVMNode_NoColumns_column__Error__text_format; + public static String VariableVMNode_NoColumns_column__text_format; + public static String VariableVMNode_NoColumns_column__No_string__text_format; + public static String VariableVMNode_Type_column__Error__text_format; + public static String VariableVMNode_Type_column__text_format; + public static String VariableVMNode_Value_column__text_format; + public static String VariableVMNode_Value_column___No_string__text_format; + public static String VariableVMNode_Value_column___No_string__Value__text_format; + static { // initialize resource bundle NLS.initializeMessages(BUNDLE_NAME, MessagesForVariablesVM.class); diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableCellModifier.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableCellModifier.java index 7d558cbbd5e..d18ac1ae65b 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableCellModifier.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableCellModifier.java @@ -14,7 +14,7 @@ import org.eclipse.cdt.dsf.debug.service.IFormattedValues; import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext; import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants; import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.WatchExpressionCellModifier; -import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.IFormattedValuePreferenceStore; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueVMUtil; import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext; import org.eclipse.cdt.dsf.ui.viewmodel.update.AbstractCachingVMProvider; import org.eclipse.cdt.dsf.ui.viewmodel.update.UserEditEvent; @@ -26,14 +26,11 @@ public class VariableCellModifier extends WatchExpressionCellModifier { private AbstractCachingVMProvider fProvider; private SyncVariableDataAccess fDataAccess = null; - private IFormattedValuePreferenceStore fPrefStore; - public VariableCellModifier(AbstractCachingVMProvider provider, - IFormattedValuePreferenceStore formattedValuePreferenceStore, SyncVariableDataAccess access) + public VariableCellModifier(AbstractCachingVMProvider provider, SyncVariableDataAccess access) { fProvider = provider; fDataAccess = access; - fPrefStore = formattedValuePreferenceStore; } /* @@ -81,8 +78,7 @@ public class VariableCellModifier extends WatchExpressionCellModifier { */ IVMContext ctx = (IVMContext) element; IPresentationContext presCtx = ctx.getVMNode().getVMProvider().getPresentationContext(); - - formatId = fPrefStore.getCurrentNumericFormat(presCtx); + formatId = FormattedValueVMUtil.getPreferredFormat(presCtx); } else { formatId = IFormattedValues.NATURAL_FORMAT; @@ -119,8 +115,7 @@ public class VariableCellModifier extends WatchExpressionCellModifier { */ IVMContext ctx = (IVMContext) element; IPresentationContext presCtx = ctx.getVMNode().getVMProvider().getPresentationContext(); - - formatId = fPrefStore.getCurrentNumericFormat(presCtx); + formatId = FormattedValueVMUtil.getPreferredFormat(presCtx); } else { formatId = IFormattedValues.NATURAL_FORMAT; diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMNode.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMNode.java index bed8ab511e7..91eb9b5bb71 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMNode.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMNode.java @@ -12,14 +12,20 @@ package org.eclipse.cdt.dsf.debug.ui.viewmodel.variable; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.concurrent.RejectedExecutionException; import org.eclipse.cdt.core.IAddress; +import org.eclipse.cdt.debug.internal.ui.CDebugImages; +import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor; +import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DsfExecutor; import org.eclipse.cdt.dsf.concurrent.DsfRunnable; import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; +import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; import org.eclipse.cdt.dsf.concurrent.MultiRequestMonitor; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.datamodel.DMContexts; @@ -31,32 +37,39 @@ import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionChangedDMEvent; import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMAddress; import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext; import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMData; -import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext; -import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMData; import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryChangedEvent; import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent; import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext; import org.eclipse.cdt.dsf.debug.service.IStack.IVariableDMContext; import org.eclipse.cdt.dsf.debug.service.IStack.IVariableDMData; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.ErrorLabelText; import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants; import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.AbstractExpressionVMNode; import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.IExpressionUpdate; -import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.IFormattedValuePreferenceStore; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueLabelText; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueVMUtil; import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.IFormattedValueVMContext; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor; -import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext; import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; -import org.eclipse.cdt.utils.Addr32; -import org.eclipse.cdt.utils.Addr64; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelAttribute; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelColor; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelColumnInfo; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelFont; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelImage; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelText; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.PropertiesBasedLabelProvider; +import org.eclipse.cdt.dsf.ui.viewmodel.update.ICachingVMProvider; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.model.IExpression; -import org.eclipse.debug.internal.ui.DebugUIPlugin; import org.eclipse.debug.internal.ui.IInternalDebugUIConstants; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest; @@ -68,6 +81,8 @@ 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.internal.ui.viewers.model.provisional.IViewerUpdate; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.debug.ui.actions.IWatchExpressionFactoryAdapter2; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.util.PropertyChangeEvent; @@ -79,15 +94,39 @@ import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.IMemento; -@SuppressWarnings({"restriction", "nls"}) public class VariableVMNode extends AbstractExpressionVMNode - implements IElementEditor, IElementLabelProvider, IElementMementoProvider + implements IElementEditor, IElementLabelProvider, IElementPropertiesProvider, IElementMementoProvider { + /** + * @since 2.0 + */ + private static final String PROP_VARIABLE_TYPE_NAME = "variable_type_name"; //$NON-NLS-1$ + + /** + * @since 2.0 + */ + private static final String PROP_VARIABLE_BASIC_TYPE = "variable_basic_type"; //$NON-NLS-1$ + + /** + * @since 2.0 + */ + private static final String PROP_VARIABLE_ADDRESS = "variable_address"; //$NON-NLS-1$ - private final IFormattedValuePreferenceStore fFormattedPrefStore; - + /** + * @since 2.0 + */ + private static final String PROP_VARIABLE_ADDRESS_CHANGED = ICachingVMProvider.PROP_IS_CHANGED_PREFIX + PROP_VARIABLE_ADDRESS; + private final SyncVariableDataAccess fSyncVariableDataAccess; + /** + * The label provider delegate. This VM node will delegate label updates to this provider + * which can be created by sub-classes. + * + * @since 2.0 + */ + private IElementLabelProvider fLabelProvider; + public class VariableExpressionVMC extends DMVMContext implements IFormattedValueVMContext { private IExpression fExpression; @@ -96,10 +135,6 @@ public class VariableVMNode extends AbstractExpressionVMNode super(dmc); } - public IFormattedValuePreferenceStore getPreferenceStore() { - return fFormattedPrefStore; - } - public void setExpression(IExpression expression) { fExpression = expression; } @@ -153,14 +188,287 @@ public class VariableVMNode extends AbstractExpressionVMNode final protected VariableExpressionFactory fVariableExpressionFactory = new VariableExpressionFactory(); - public VariableVMNode(IFormattedValuePreferenceStore prefStore, AbstractDMVMProvider provider, - DsfSession session, SyncVariableDataAccess syncVariableDataAccess) + public VariableVMNode(AbstractDMVMProvider provider, DsfSession session, + SyncVariableDataAccess syncVariableDataAccess) { super(provider, session, IExpressions.IExpressionDMContext.class); - fFormattedPrefStore = prefStore; fSyncVariableDataAccess = syncVariableDataAccess; + fLabelProvider = createLabelProvider(); } + /** + * Creates the label provider delegate. This VM node will delegate label + * updates to this provider which can be created by sub-classes. + * + * @return Returns the label provider for this node. + * + * @since 2.0 + */ + protected IElementLabelProvider createLabelProvider() { + PropertiesBasedLabelProvider provider = new PropertiesBasedLabelProvider(); + + // + // Create label image objects which are used in more than one column. + // + + // Pointer image is used for variable and function pointers. + LabelImage pointerLabelImage = new LabelImage(CDebugImages.DESC_OBJS_VARIABLE_POINTER) { + { setPropertyNames(new String[] { PROP_VARIABLE_BASIC_TYPE }); } + + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + String type = (String)properties.get(PROP_VARIABLE_BASIC_TYPE); + return IExpressionDMData.BasicType.pointer.name().equals(type) || + IExpressionDMData.BasicType.function.name().equals(type); + }; + }; + + // Aggregate image is used for array, struct, etc. + LabelImage aggregateLabelImage = new LabelImage(CDebugImages.DESC_OBJS_VARIABLE_AGGREGATE) { + { setPropertyNames(new String[] { PROP_VARIABLE_BASIC_TYPE }); } + + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + String type = (String)properties.get(PROP_VARIABLE_BASIC_TYPE); + return IExpressionDMData.BasicType.array.name().equals(type) || + IExpressionDMData.BasicType.composite.name().equals(type); + }; + }; + + // Simple variable image is used for all other types, except when there is no type specified. + LabelImage simpleLabelImage = new LabelImage(CDebugImages.DESC_OBJS_VARIABLE_SIMPLE) { + { setPropertyNames(new String[] { PROP_VARIABLE_BASIC_TYPE }); } + + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + String type = (String)properties.get(PROP_VARIABLE_BASIC_TYPE); + return type != null; + }; + }; + + // The name column consists of the expression name. The name column image depends on the variable type. + provider.setColumnInfo( + IDebugVMConstants.COLUMN_ID__NAME, + new LabelColumnInfo(new LabelAttribute[] { + new LabelText( + MessagesForVariablesVM.VariableVMNode_Name_column__text_format, + new String[] { PROP_NAME }), + pointerLabelImage, + aggregateLabelImage, + simpleLabelImage, + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + // Expression column is visible only in the expressions view. It shows the expression string that the user + // entered. Expression column images are the same as for the name column. + provider.setColumnInfo( + IDebugVMConstants.COLUMN_ID__EXPRESSION, + new LabelColumnInfo(new LabelAttribute[] { + new LabelText( + MessagesForVariablesVM.VariableVMNode_Expression_column__text_format, + new String[] { PROP_ELEMENT_EXPRESSION }), + pointerLabelImage, + aggregateLabelImage, + simpleLabelImage, + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + // Type column only contains the type name. + provider.setColumnInfo( + IDebugVMConstants.COLUMN_ID__TYPE, + new LabelColumnInfo(new LabelAttribute[] { + new LabelText( + MessagesForVariablesVM.VariableVMNode_Type_column__text_format, + new String[] { PROP_VARIABLE_TYPE_NAME }), + new LabelText( MessagesForVariablesVM.VariableVMNode_Type_column__Error__text_format, new String[] {}), + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + // Value column is more complicated: + // - If a STRING value format is supported. Then the value label consists of the active format label followed + // by the string format. + // - If the STRIGN value format is not supported. Then only show the active value format. The GDB reference + // implementation currently does not support the string format, but by default it does append extra + // information to the value label itself. + // + // In case of error, show the error message in the value column (instead of the usual "...". This is needed + // for the expressions view, where an invalid expression entered by the user is a normal use case. + // + // For changed value high-lighting check both the string value and the value in the active format. But, + // ignore the active format value change if the format itself has changed. + provider.setColumnInfo( + IDebugVMConstants.COLUMN_ID__VALUE, + new LabelColumnInfo(new LabelAttribute[] { + new FormattedValueLabelText( + MessagesForVariablesVM.VariableVMNode_Value_column__text_format, + new String[] { + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE, + FormattedValueVMUtil.getPropertyForFormatId(IFormattedValues.STRING_FORMAT), + IDebugVMConstants.PROP_FORMATTED_VALUE_AVAILABLE_FORMATS}) + { + @Override + public boolean isEnabled(IStatus status, Map properties) { + String[] formatIds = + (String[])properties.get(IDebugVMConstants.PROP_FORMATTED_VALUE_AVAILABLE_FORMATS); + String activeFormat = (String)properties.get(IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT); + return + !IFormattedValues.STRING_FORMAT.equals(activeFormat) && + formatIds != null && + Arrays.asList(formatIds).contains(IFormattedValues.STRING_FORMAT) && + super.isEnabled(status, properties); + } + }, + new FormattedValueLabelText(), + new ErrorLabelText(), + new LabelColor(new RGB(255, 0, 0), null) // TODO: replace with preference error color + { + { setPropertyNames(new String[] { PROP_NAME }); } + + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + return !status.isOK(); + } + }, + // + new LabelColor( + null, + DebugUITools.getPreferenceColor(IInternalDebugUIConstants.PREF_CHANGED_VALUE_BACKGROUND).getRGB()) + { + { + setPropertyNames(new String[] { + FormattedValueVMUtil.getPropertyForFormatId(IFormattedValues.STRING_FORMAT), + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + FormattedValueVMUtil.getPropertyForFormatId(IFormattedValues.STRING_FORMAT), + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE, + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE, + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT, + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT}); + } + + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + Boolean activeFormatChanged = (Boolean)properties.get( + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT); + Boolean activeChanged = (Boolean)properties.get( + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE); + Boolean stringChanged = (Boolean)properties.get( + ICachingVMProvider.PROP_IS_CHANGED_PREFIX + FormattedValueVMUtil.getPropertyForFormatId(IFormattedValues.STRING_FORMAT)); + return Boolean.TRUE.equals(stringChanged) || + ( Boolean.TRUE.equals(activeChanged) && !Boolean.TRUE.equals(activeFormatChanged)); + }; + }, + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + // Address column shows the variable's address. It is highlighted with the change background color when the + // address value changes. + provider.setColumnInfo( + IDebugVMConstants.COLUMN_ID__ADDRESS, + new LabelColumnInfo(new LabelAttribute[] { + new LabelText( + MessagesForVariablesVM.VariableVMNode_Address_column__text_format, + new String[] { PROP_VARIABLE_ADDRESS }), + new LabelText(MessagesForVariablesVM.VariableVMNode_Address_column__Error__text_format, new String[] {}), + new LabelColor( + null, + DebugUITools.getPreferenceColor(IInternalDebugUIConstants.PREF_CHANGED_VALUE_BACKGROUND).getRGB()) + { + { setPropertyNames(new String[] { PROP_VARIABLE_ADDRESS, PROP_VARIABLE_ADDRESS_CHANGED}); } + + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + Boolean changed = (Boolean)properties.get(PROP_VARIABLE_ADDRESS_CHANGED); + return Boolean.TRUE.equals(changed); + }; + }, + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]), + })); + + // Description column is shown in the expression view, but is not supported for variables. + provider.setColumnInfo( + IDebugVMConstants.COLUMN_ID__DESCRIPTION, + + new LabelColumnInfo(new LabelAttribute[] { + new LabelText(MessagesForVariablesVM.VariableVMNode_Description_column__text_format, new String[] {}) { + }, + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + // Configure the case where there are no columns visible. It basically combines the name and the value columns only. + provider.setColumnInfo( + PropertiesBasedLabelProvider.ID_COLUMN_NO_COLUMNS, + new LabelColumnInfo(new LabelAttribute[] { + new FormattedValueLabelText( + MessagesForVariablesVM.VariableVMNode_NoColumns_column__text_format, + new String[] { + PROP_NAME, + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE, + FormattedValueVMUtil.getPropertyForFormatId(IFormattedValues.STRING_FORMAT), + IDebugVMConstants.PROP_FORMATTED_VALUE_AVAILABLE_FORMATS, + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT, + IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE}) + { + @Override + public boolean isEnabled(IStatus status, Map properties) { + String[] formatIds = + (String[])properties.get(IDebugVMConstants.PROP_FORMATTED_VALUE_AVAILABLE_FORMATS); + String activeFormat = (String)properties.get(IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT); + return + !IFormattedValues.STRING_FORMAT.equals(activeFormat) && + formatIds != null && + Arrays.asList(formatIds).contains(IFormattedValues.STRING_FORMAT) && + super.isEnabled(status, properties); + } + }, + + new FormattedValueLabelText( + MessagesForVariablesVM.VariableVMNode_NoColumns_column__No_string__text_format, + new String[] { + PROP_NAME, + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE, + IDebugVMConstants.PROP_FORMATTED_VALUE_AVAILABLE_FORMATS, + IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT, + IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE}), + new ErrorLabelText( + MessagesForVariablesVM.VariableVMNode_NoColumns_column__Error__text_format, + new String[] { PROP_NAME }), + pointerLabelImage, + aggregateLabelImage, + simpleLabelImage, + new LabelColor(new RGB(255, 0, 0), null) // TODO: replace with preference error color + { + { setPropertyNames(new String[] { PROP_NAME }); } + + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + return !status.isOK(); + } + }, + new LabelColor( + DebugUITools.getPreferenceColor(IDebugUIConstants.PREF_CHANGED_DEBUG_ELEMENT_COLOR).getRGB(), + null) + { + { + setPropertyNames(new String[] { + FormattedValueVMUtil.getPropertyForFormatId(IFormattedValues.STRING_FORMAT), + IDebugVMConstants.PROP_IS_STRING_FORMAT_VALUE_CHANGED, + IDebugVMConstants.PROP_IS_ACTIVE_FORMATTED_VALUE_CHANGED}); + } + + @Override + public boolean isEnabled(IStatus status, java.util.Map properties) { + Boolean stringChanged = + (Boolean)properties.get(IDebugVMConstants.PROP_IS_STRING_FORMAT_VALUE_CHANGED); + Boolean activeChanged = + (Boolean)properties.get(IDebugVMConstants.PROP_IS_ACTIVE_FORMATTED_VALUE_CHANGED); + return Boolean.TRUE.equals(stringChanged) || Boolean.TRUE.equals(activeChanged); + }; + }, + new LabelFont(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0]) + })); + + return provider; + } + @Override public String toString() { return "VariableVMNode(" + getSession().getId() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ @@ -173,449 +481,137 @@ public class VariableVMNode extends AbstractExpressionVMNode public void update(final ILabelUpdate[] updates) { + fLabelProvider.update(updates); + } + + /** + * @see IElementPropertiesProvider#update(IPropertiesUpdate[]) + * + * @since 2.0 + */ + public void update(final IPropertiesUpdate[] updates) { try { getSession().getExecutor().execute(new DsfRunnable() { public void run() { - updateLabelInSessionThread(updates); + updatePropertiesInSessionThread(updates); }}); } catch (RejectedExecutionException e) { - for (ILabelUpdate update : updates) { + for (IPropertiesUpdate update : updates) { handleFailedUpdate(update); } } } + + /** + * @since 2.0 + */ + @ConfinedToDsfExecutor("getSession().getExecutor()") + protected void updatePropertiesInSessionThread(final IPropertiesUpdate[] updates) { + IExpressions service = getServicesTracker().getService(IExpressions.class, null); - private void fillInExpressionErrorInfo( ILabelUpdate update, IExpressionDMContext dmc, IStatus status ) { - /* - * Instead of just failing this outright we are going to attempt to do more here. - * Failing it outright causes the view to display ... for all columns in the line - * and this is uninformative about what is happening. It will be very common that - * one or more variables at that given instance in time are not evaluatable. They - * may be out of scope and will come back into scope later. - */ - String[] localColumns = update.getColumnIds(); - if (localColumns == null) - localColumns = new String[] { IDebugVMConstants.COLUMN_ID__NAME }; - - for (int idx = 0; idx < localColumns.length; idx++) { - if (IDebugVMConstants.COLUMN_ID__NAME.equals(localColumns[idx])) { - update.setLabel(dmc.getExpression(), idx); - } else if (IDebugVMConstants.COLUMN_ID__TYPE.equals(localColumns[idx])) { - update.setLabel("", idx); - } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(localColumns[idx])) { - update.setLabel("Error : " + status.getMessage(), idx); - } else if (IDebugVMConstants.COLUMN_ID__ADDRESS.equals(localColumns[idx])) { - update.setLabel("", idx); - } else if (IDebugVMConstants.COLUMN_ID__DESCRIPTION.equals(localColumns[idx])) { - update.setLabel("", idx); - } else if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(localColumns[idx])) { - update.setLabel(dmc.getExpression(), idx); - } else { - update.setLabel("", idx); - } - update.setFontData(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0], idx); - } - } - - protected void updateLabelInSessionThread(ILabelUpdate[] updates) { - for (final ILabelUpdate update : updates) { + final CountingRequestMonitor countingRm = new CountingRequestMonitor(ImmediateExecutor.getInstance(), null) { + @Override + protected void handleCompleted() { + for (final IPropertiesUpdate update : updates) { + update.done(); + } + }; + }; + int count = 0; + + if (service != null) { + FormattedValueVMUtil.updateFormattedValues(updates, service, IExpressionDMContext.class, countingRm); + count++; + } + + for (final IPropertiesUpdate update : updates) { + IExpression expression = (IExpression)DebugPlugin.getAdapter(update.getElement(), IExpression.class); + if (expression != null) { + update.setProperty(AbstractExpressionVMNode.PROP_ELEMENT_EXPRESSION, expression.getExpressionText()); + } - final IExpressionDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IExpressions.IExpressionDMContext.class); - - if ( dmc == null ) { - // Workaround for a bug in platform, where the find operation may use wrong label provider. - // See bug 246618. - update.done(); + IExpressionDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IExpressions.IExpressionDMContext.class); + if ( dmc == null || service == null) { + update.setStatus(DsfUIPlugin.newErrorStatus(IDsfStatusConstants.INVALID_STATE, "Invalid context or service not available.", null)); //$NON-NLS-1$ continue; } - - getDMVMProvider().getModelData( - this, update, - getServicesTracker().getService(IExpressions.class, null), - dmc, - new ViewerDataRequestMonitor(getSession().getExecutor(), update) { - @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 (!isSuccess()) { - assert getStatus().isOK() || - getStatus().getCode() != IDsfStatusConstants.INTERNAL_ERROR || - getStatus().getCode() != IDsfStatusConstants.NOT_SUPPORTED; - - fillInExpressionErrorInfo( update, dmc, getStatus() ); - - update.done(); - 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.getColumnIds(); - if (localColumns == null) - localColumns = new String[] { IDebugVMConstants.COLUMN_ID__NAME }; - - int extractingFormattedDataIndex = -1; - int extractingAddressDataIndex = -1; - - 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__TYPE.equals(localColumns[idx])) { - update.setLabel(getData().getTypeName(), idx); - } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(localColumns[idx])) { - extractingFormattedDataIndex = idx; - } else if (IDebugVMConstants.COLUMN_ID__ADDRESS.equals(localColumns[idx])) { - extractingAddressDataIndex = idx; - } else if (IDebugVMConstants.COLUMN_ID__DESCRIPTION.equals(localColumns[idx])) { - update.setLabel("", 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); - } - } - update.setFontData(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0], idx); - } - - if ( ( extractingFormattedDataIndex == -1 ) && ( extractingAddressDataIndex == -1 ) ) { - update.done(); - } else { - /* - * We are either updating the value or the address or possibly both. - * We will create a overarching monitor to handle completing the update - * when either/both of the lower level updates are done. - */ - final DsfExecutor dsfExecutor = getSession().getExecutor(); - - final MultiRequestMonitor mrm = - new MultiRequestMonitor(dsfExecutor, null) { - @Override - public void handleCompleted() { - if (!isSuccess()) { - handleFailedUpdate(update); - return; - } - update.done(); - } - }; - - /* - * Deal with the value. - */ - if ( extractingFormattedDataIndex != -1 ) { - RequestMonitor rm = new RequestMonitor(dsfExecutor, null) { - @Override - public void handleCompleted() { - mrm.requestMonitorDone(this); - } - }; - - mrm.add(rm); - updateFormattedExpressionValue(update, extractingFormattedDataIndex, dmc, getData(),rm); - } - - /* - * Deal with the address. - */ - if ( extractingAddressDataIndex != -1 ) { - RequestMonitor rm = new RequestMonitor(dsfExecutor, null) { - @Override - public void handleCompleted() { - mrm.requestMonitorDone(this); - } - }; - - mrm.add(rm); - updateAddressData(update, extractingAddressDataIndex, dmc, rm); - } - } - } - }, - getExecutor() - ); - } - } - - /** - * 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 updateAddressData(final ILabelUpdate update, - final int labelIndex, - final IExpressionDMContext dmc, - final RequestMonitor monitor) - { - /* - * 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 IExpressions expressionService = getServicesTracker().getService(IExpressions.class); - - // Get the variable information and update the corresponding memory locations - if (expressionService != null) { - expressionService.getExpressionAddressData(dmc, - new DataRequestMonitor(getExecutor(), monitor) { - @Override - protected void handleCompleted() { - if ( isSuccess() ) { - // Figure out which memory area was modified - IExpressionDMAddress expression = getData(); - IAddress expAddress = expression.getAddress(); - if (expAddress instanceof Addr64) { - update.setLabel( "0x" + ((Addr64) expAddress).toString(16), labelIndex); - } - else if (expAddress instanceof Addr32) { - update.setLabel( "0x" + ((Addr32) expAddress).toString(16), labelIndex); - } - else { - update.setLabel( "Unknown address format", labelIndex); - } - } - else { - /* - * We could not get the format. Currently GDB does not handle getting the address of - * a constant for example. We could put the error message in, but that would not be - * all that helpful top the user. The interface is a new one and perhaps failing to - * return a valid set of information is just saying it does not exist. Anyway, for - * now we will just put nothing in. - */ - update.setLabel( "", labelIndex); - } - - update.setFontData(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0], labelIndex); - monitor.done(); - } - } - ); - } - } - - /** - * 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 IExpressionDMData expressionDMData, - final RequestMonitor monitor) - { - final IExpressions expressionService = getServicesTracker().getService(IExpressions.class); - /* - * 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 IPresentationContext context = update.getPresentationContext(); - final String preferencePageFormatId = fFormattedPrefStore.getCurrentNumericFormat(context) ; - - expressionService.getAvailableFormats( - dmc, - new DataRequestMonitor(getSession().getExecutor(), monitor) { - @Override - public void handleCompleted() { - if (!isSuccess()) { - monitor.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Format information not available", null)); - monitor.done(); - return; - } - - /* - * See if the desired format is supported. - */ - final 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 (update.getProperties().contains(PROP_NAME) || + update.getProperties().contains(PROP_VARIABLE_TYPE_NAME) || + update.getProperties().contains(PROP_VARIABLE_BASIC_TYPE)) + { + service.getExpressionData( + dmc, + // Use the ViewerDataRequestMonitor in order to propagate the update's cancel request. Use an immediate + // executor to avoid the possibility of a rejected execution exception. + new ViewerDataRequestMonitor(ImmediateExecutor.getInstance(), update) { + @Override + protected void handleCompleted() { + if (isSuccess()) { + fillExpressionDataProperties(update, getData()); + } else { + // In case of an error fill in the expression next in the name column. + IExpressionDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IExpressions.IExpressionDMContext.class); + if (dmc != null && dmc.getExpression() != null) { + update.setProperty(PROP_NAME, dmc.getExpression()); + } + update.setStatus(getStatus()); + } + countingRm.done(); } - } - - 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. - - monitor.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Service does not support any formats", null)); - monitor.done(); - return; - } - } - - /* - * Format has been validated. Get the formatted value. - */ - final FormattedValueDMContext valueDmc = expressionService.getFormattedValueContext(dmc, finalFormatId); - - getDMVMProvider().getModelData( - VariableVMNode.this, - update, - expressionService, - valueDmc, - new DataRequestMonitor(getSession().getExecutor(), monitor) { - @Override - public void handleCompleted() { - if (!isSuccess()) { - monitor.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, getStatus().getMessage(), null)); - monitor.done(); - return; - } + }); - final String formattedValue = getData().getFormattedValue(); - final String formattedStringId = valueDmc.getFormatID(); - - if ( formattedStringId.equals(IFormattedValues.STRING_FORMAT) ) { - /* - * In this case we are being asked to fill in the value information with STRING_FORMAT. - * So we do not need to append it to the value as we did in the past. - */ - completeFillinInUpdateWithValue(update, labelIndex, valueDmc, formattedValue, null, null, monitor); - } - else { - /* - * The format specified is not STRING_FORMAT and as we did before we need to append - * the string information to the value ( if it exists ). So first see if STRING_FORMAT - * is supported by the service. - */ - boolean foundStringFormat = false; - - for ( String format : formatIds ) { - if ( format.equals(IFormattedValues.STRING_FORMAT) ) { - foundStringFormat = true; - } - } - - if ( foundStringFormat ) { - /* - * So STRING_FORMAT is supported so we can go get it and append it to the value. - * - * Note : Currently the Reference Model MI Expression Service does not support the - * STRING_FORMAT. The view still pretty much looks the same however, to one - * where the STRING_FORMAT is supplied. This is because when GDB is ask to - * evaluate a variable it will return the STRING_FORMAT information appended - * to the address so it looks good. GDB appends all kinds of usefull info to - * requests for data values, based on the value types. So the expressions do - * look good. If the Reference Model Expression Service ever does implement - * STRING_FORMAT this will need to be revisited. There would be duplicate - * information displayed and the view would look broken. However this needs - * to be put back in to satisfy Bugzilla defect "225612", which represents a - * regression in the display of data from 0.9 to 1.x. - */ - final FormattedValueDMContext stringDmc = expressionService.getFormattedValueContext(dmc, IFormattedValues.STRING_FORMAT); - - getDMVMProvider().getModelData( - VariableVMNode.this, - update, - expressionService, - stringDmc, - new DataRequestMonitor(getSession().getExecutor(), monitor) { - @Override - public void handleCompleted() { - if (!isSuccess()) { - monitor.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, getStatus().getMessage(), null)); - monitor.done(); - return; - } - - String stringValue = getData().getFormattedValue(); - - completeFillinInUpdateWithValue(update, labelIndex, valueDmc, formattedValue, stringDmc, stringValue, monitor); - } - }, - getExecutor() - ); - } - else { - /* - * The STRING_FORMAT is not supported. So all we can do is fill it in without it. - */ - completeFillinInUpdateWithValue(update, labelIndex, valueDmc, formattedValue, null, null, monitor); - } - } - } - }, - getExecutor() - ); - } + count++; } - ); + + if (update.getProperties().contains(PROP_VARIABLE_ADDRESS)) { + service.getExpressionAddressData( + dmc, + // Use the ViewerDataRequestMonitor in order to propagate the update's cancel request. Use an immediate + // executor to avoid the possibility of a rejected execution exception. + new ViewerDataRequestMonitor(ImmediateExecutor.getInstance(), update) { + @Override + protected void handleCompleted() { + if (isSuccess()) { + fillAddressDataProperties(update, getData()); + } else { + update.setStatus(getStatus()); + } + countingRm.done(); + } + }); + count++; + } + } + countingRm.setDoneCount(count); } - private void completeFillinInUpdateWithValue(ILabelUpdate update, - int labelIndex, - FormattedValueDMContext valueDmc, - String value, - FormattedValueDMContext stringFormatDmc, - String stringFormatValue, - RequestMonitor monitor) + /** + * @since 2.0 + */ + @ConfinedToDsfExecutor("getSession().getExecutor()") + protected void fillExpressionDataProperties(IPropertiesUpdate update, IExpressionDMData data) { - /* - * Complete filling in the VALUE. The form is - * - * "Numerical value" "STRING_FORMAT value" - * - * This makes it so if the value is a pointer to something else we conveniently - * fill in the something else ( typically a string ). - */ - - StringBuffer stringValueBuf = new StringBuffer(value); - if(stringFormatValue != null && stringFormatValue.length() > 0) - { - stringValueBuf.append(" "); - stringValueBuf.append(stringFormatValue); - } - update.setLabel(stringValueBuf.toString(), labelIndex); - update.setFontData(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0], labelIndex); - - /* - * Get old values for comparison ( if available ). - */ - FormattedValueDMData oldStringData = null; - FormattedValueDMData oldData = - - (FormattedValueDMData) getDMVMProvider().getArchivedModelData(VariableVMNode.this, update, valueDmc); - - if ( stringFormatDmc != null) { - oldStringData = (FormattedValueDMData) getDMVMProvider().getArchivedModelData(VariableVMNode.this, update, stringFormatDmc); - } - - /* - * Highlight the value if either the value (address) has changed or the string (memory at the value) has changed - */ - if ( ( oldData != null && ! oldData.getFormattedValue().equals(value) ) || - ( oldStringData != null && ! oldStringData.getFormattedValue().equals(stringFormatValue) ) - ) { - RGB rgb = DebugUIPlugin.getPreferenceColor(IInternalDebugUIConstants.PREF_CHANGED_VALUE_BACKGROUND).getRGB(); - update.setBackground(rgb, labelIndex); - } - - /* - * Now we finally can complete this one. - */ - monitor.done(); + update.setProperty(PROP_NAME, data.getName()); + update.setProperty(PROP_VARIABLE_TYPE_NAME, data.getTypeName()); + IExpressionDMData.BasicType type = data.getBasicType(); + if (type != null) { + update.setProperty(PROP_VARIABLE_BASIC_TYPE, type.name()); + } } + /** + * Private data access routine which performs the extra level of data access needed to + * get the formatted data value for a specific register. + */ + @ConfinedToDsfExecutor("getSession().getExecutor()") + protected void fillAddressDataProperties(IPropertiesUpdate update, IExpressionDMAddress address) + { + IExpressionDMAddress expression = address; + IAddress expAddress = expression.getAddress(); + update.setProperty(PROP_VARIABLE_ADDRESS, "0x" + expAddress.toString(16)); //$NON-NLS-1$ + } + public CellEditor getCellEditor(IPresentationContext context, String columnId, Object element, Composite parent) { if (IDebugVMConstants.COLUMN_ID__VALUE.equals(columnId)) { return new TextCellEditor(parent); @@ -628,7 +624,7 @@ public class VariableVMNode extends AbstractExpressionVMNode } public ICellModifier getCellModifier(IPresentationContext context, Object element) { - return new VariableCellModifier(getDMVMProvider(), fFormattedPrefStore, fSyncVariableDataAccess); + return new VariableCellModifier(getDMVMProvider(), fSyncVariableDataAccess); } public boolean canParseExpression(IExpression expression) { @@ -843,7 +839,7 @@ public class VariableVMNode extends AbstractExpressionVMNode mrm.add(rm); - getDMVMProvider().getModelData(VariableVMNode.this, update, stackFrameService, localDMC, rm, getExecutor()); + stackFrameService.getVariableData(localDMC, rm); } } }; @@ -861,7 +857,7 @@ public class VariableVMNode extends AbstractExpressionVMNode e instanceof IMemoryChangedEvent || e instanceof IExpressionChangedDMEvent || (e instanceof PropertyChangeEvent && - ((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) ) + ((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE) ) { // Create a delta that the whole register group has changed. return IModelDelta.CONTENT; @@ -878,7 +874,7 @@ public class VariableVMNode extends AbstractExpressionVMNode e instanceof IMemoryChangedEvent || e instanceof IExpressionChangedDMEvent || (e instanceof PropertyChangeEvent && - ((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) ) + ((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE) ) { // Create a delta that the whole register group has changed. parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT); @@ -891,7 +887,7 @@ public class VariableVMNode extends AbstractExpressionVMNode if ( event instanceof IExpressionChangedDMEvent || event instanceof IMemoryChangedEvent || (event instanceof PropertyChangeEvent && - ((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) ) + ((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE) ) { return IModelDelta.CONTENT; } @@ -923,7 +919,7 @@ public class VariableVMNode extends AbstractExpressionVMNode if ( event instanceof IExpressionChangedDMEvent || event instanceof IMemoryChangedEvent || (event instanceof PropertyChangeEvent && - ((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) ) + ((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.PROP_FORMATTED_VALUE_FORMAT_PREFERENCE) ) { parentDelta.addNode(element, IModelDelta.CONTENT); } @@ -933,10 +929,6 @@ public class VariableVMNode extends AbstractExpressionVMNode - /* - * (non-Javadoc) - * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider#compareElements(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest[]) - */ private String produceExpressionElementName( String viewName , IExpressionDMContext expression ) { return "Variable." + expression.getExpression(); //$NON-NLS-1$ @@ -950,7 +942,7 @@ public class VariableVMNode extends AbstractExpressionVMNode Object element = request.getElement(); IMemento memento = request.getMemento(); - String mementoName = memento.getString(MEMENTO_NAME); //$NON-NLS-1$ + String mementoName = memento.getString(MEMENTO_NAME); if (mementoName != null) { if (element instanceof IDMVMContext) { @@ -968,10 +960,6 @@ public class VariableVMNode extends AbstractExpressionVMNode } } - /* - * (non-Javadoc) - * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider#encodeElements(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest[]) - */ public void encodeElements(IElementMementoRequest[] requests) { for ( IElementMementoRequest request : requests ) { diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java index b6424ae75cf..46b4d36909f 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java @@ -18,7 +18,6 @@ import org.eclipse.cdt.dsf.debug.service.IExpressions; import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent; import org.eclipse.cdt.dsf.debug.ui.DsfDebugUITools; import org.eclipse.cdt.dsf.debug.ui.IDsfDebugUIConstants; -import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValuePreferenceStore; import org.eclipse.cdt.dsf.debug.ui.viewmodel.update.BreakpointHitUpdatePolicy; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.service.DsfServicesTracker; @@ -38,7 +37,6 @@ import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; -@SuppressWarnings("restriction") public class VariableVMProvider extends AbstractDMVMProvider implements IColumnPresentationFactory { @@ -81,7 +79,7 @@ public class VariableVMProvider extends AbstractDMVMProvider /* * Create the next level which represents members of structs/unions/enums and elements of arrays. */ - IVMNode subExpressioNode = new VariableVMNode(FormattedValuePreferenceStore.getDefault(), this, getSession(), varAccess); + IVMNode subExpressioNode = new VariableVMNode(this, getSession(), varAccess); addChildNodes(rootNode, new IVMNode[] { subExpressioNode }); // Configure the sub-expression node to be a child of itself. This way the content diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/messages.properties b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/messages.properties index 0b40d097c33..65fe07dc7db 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/messages.properties +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/messages.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2007, 2008 Wind River Systems and others. +# Copyright (c) 2007, 2009 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 @@ -14,3 +14,42 @@ VariableColumnPresentation_name=Name VariableColumnPresentation_type=Type VariableColumnPresentation_value=Value VariableColumnPresentation_address=Address + +VariableVMNode_Address_column__Error__text_format= +VariableVMNode_Address_column__text_format={0} +VariableVMNode_Description_column__text_format= +VariableVMNode_Expression_column__text_format={0} +VariableVMNode_Name_column__text_format={0} +VariableVMNode_Type_column__Error__text_format= +VariableVMNode_Type_column__text_format={0} + +# Message format for the value column text +# {0} - value formatted in the active format. If the preferred format was +# available, then this is just the value. Otherwise, it's the string formatted +# by the format in VariableVMNode_Value_column__Value__text_format. +# {1} - value in STRING format. +VariableVMNode_Value_column__text_format={0} {1} + +# Message format for the value column text +# {0} - value formatted in the active format. If the preferred format was +# available, then this is just the value. Otherwise, it's the string formatted +# by the format in VariableVMNode_Value_column__Value__text_format. +VariableVMNode_Value_column___No_string__text_format={0} + +# {0} - variable name +# {1} - value formatted in the active format. If the preferred format was +# available, then this is just the value. Otherwise, it's the string formatted +# by the format in VariableVMNode_Value_column__Value__text_format. +# {2} - value in STRING format. +VariableVMNode_NoColumns_column__text_format={0} = {1} {2} + +# {0} - variable name +# {1} - value formatted in the active format. If the preferred format was +# available, then this is just the value. Otherwise, it's the string formatted +# by the format in VariableVMNode_Value_column__Value__text_format. +VariableVMNode_NoColumns_column__No_string__text_format={0} = {1} + +# {0} - variable name +# {1} - error message +VariableVMNode_NoColumns_column__Error__text_format={0} - Error: {1} + diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/ILabelAttributeChangedListener.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/internal/ui/DsfUILabelImage.java similarity index 60% rename from dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/ILabelAttributeChangedListener.java rename to dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/internal/ui/DsfUILabelImage.java index bd9ca6cf995..660af4465d9 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/ILabelAttributeChangedListener.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/internal/ui/DsfUILabelImage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007 Wind River Systems and others. + * Copyright (c) 2008 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 @@ -8,13 +8,15 @@ * Contributors: * Wind River Systems - initial API and implementation *******************************************************************************/ -package org.eclipse.cdt.dsf.ui.viewmodel.properties; +package org.eclipse.cdt.dsf.internal.ui; + +import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelImage; /** - * - * @since 1.0 + * @since 2.0 */ -public interface ILabelAttributeChangedListener { - - public void attributesChanged(); +public class DsfUILabelImage extends LabelImage { + public DsfUILabelImage(String imageId) { + super(DsfUIPlugin.getImageDescriptor(imageId)); + } } diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/internal/ui/DsfUIPlugin.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/internal/ui/DsfUIPlugin.java index 5a2b1e24de3..17714f11099 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/internal/ui/DsfUIPlugin.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/internal/ui/DsfUIPlugin.java @@ -10,11 +10,11 @@ *******************************************************************************/ package org.eclipse.cdt.dsf.internal.ui; +import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; import org.eclipse.cdt.dsf.debug.internal.ui.disassembly.model.SourceDocumentProvider; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; -import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.osgi.framework.BundleContext; @@ -124,7 +124,7 @@ public class DsfUIPlugin extends AbstractUIPlugin { * @param t throwable to log */ public static void log(Throwable t) { - log(newErrorStatus("Error logged from Debug UI: ", t)); //$NON-NLS-1$ + log(newErrorStatus(IDsfStatusConstants.INTERNAL_ERROR, "Error logged from Debug UI: ", t)); //$NON-NLS-1$ } /** @@ -135,17 +135,21 @@ public class DsfUIPlugin extends AbstractUIPlugin { public static void logErrorMessage(String message) { // this message is intentionally not internationalized, as an exception may // be due to the resource bundle itself - log(newErrorStatus("Internal message logged from Debug UI: " + message, null)); //$NON-NLS-1$ + log(newErrorStatus(IDsfStatusConstants.INTERNAL_ERROR, "Internal message logged from Debug UI: " + message, null)); //$NON-NLS-1$ } /** * Returns a new error status for this plug-in with the given message + * * @param message the message to be included in the status + * @param error code * @param exception the exception to be included in the status or null if none * @return a new error status + * + * @since 2.0 */ - public static IStatus newErrorStatus(String message, Throwable exception) { - return new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDebugUIConstants.INTERNAL_ERROR, message, exception); + public static IStatus newErrorStatus(int code, String message, Throwable exception) { + return new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, code, message, exception); } } diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/concurrent/ViewerDataRequestMonitor.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/concurrent/ViewerDataRequestMonitor.java index 244280b8e11..3face45f3df 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/concurrent/ViewerDataRequestMonitor.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/concurrent/ViewerDataRequestMonitor.java @@ -16,13 +16,12 @@ import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate; /** - * Data Request monitor that takean IViewerUpdate as a parent. + * Data Request monitor that takes IViewerUpdate as a parent. * If the IViewerUpdate is canceled, this request monitor becomes canceled as well. * @see IViewerUpdate * * @since 1.0 */ -@SuppressWarnings("restriction") public class ViewerDataRequestMonitor extends DataRequestMonitor { private final IViewerUpdate fUpdate; diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/concurrent/ViewerRequestMonitor.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/concurrent/ViewerRequestMonitor.java new file mode 100644 index 00000000000..24835614cc3 --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/concurrent/ViewerRequestMonitor.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.ui.concurrent; + +import java.util.concurrent.Executor; + +import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate; + +/** + * Data Request monitor that takes IViewerUpdate as a parent. + * If the IViewerUpdate is canceled, this request monitor becomes canceled as well. + * @see IViewerUpdate + * + * @since 2.0 + */ +public class ViewerRequestMonitor extends RequestMonitor { + + private final IViewerUpdate fUpdate; + public ViewerRequestMonitor(Executor executor, IViewerUpdate update) { + super(executor, null); + fUpdate = update; + } + + @Override + public synchronized boolean isCanceled() { + return fUpdate.isCanceled() || super.isCanceled(); + } + + @Override + protected void handleSuccess() { + fUpdate.done(); + } + + @Override + protected void handleErrorOrWarning() { + fUpdate.setStatus(getStatus()); + fUpdate.done(); + } + + @Override + protected void handleCancel() { + fUpdate.setStatus(getStatus()); + fUpdate.done(); + } +} diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/DefaultVMContentProviderStrategy.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/DefaultVMContentProviderStrategy.java index 547eebc874c..f5a455e4f15 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/DefaultVMContentProviderStrategy.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/DefaultVMContentProviderStrategy.java @@ -29,24 +29,24 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdat import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate; /** - * The default strategy for implementing the IElementContentProvider - * functionality for an IVMProvider. It implements an algorithm to populate - * contents of the view in accordance with the tree structure of the - * view model nodes configured in the view model provider. + * The default strategy for implementing the IElementContentProvider + * functionality for an IVMProvider. It implements an algorithm to populate + * contents of the view in accordance with the tree structure of the view model + * nodes configured in the view model provider. *

- * This class may be used by an IVMProvider directly, or it - * may be be extended to customize for the provider's needs. + * This class may be used by an IVMProvider directly, or it may be + * be extended to customize for the provider's needs. *

- * This class is closely linked with a view model provider which is required - * for the constructor. The view model provider is used to access the correct - * executor and the node hierarchy. + * This class is closely linked with a view model provider which is required for + * the constructor. The view model provider is used to access the correct + * executor and the node hierarchy. * * @since 1.0 */ @ConfinedToDsfExecutor("#getExecutor()") @SuppressWarnings("restriction") public class DefaultVMContentProviderStrategy implements IElementContentProvider { - + private final AbstractVMProvider fVMProvider; public DefaultVMContentProviderStrategy(AbstractVMProvider provider) { @@ -55,14 +55,19 @@ public class DefaultVMContentProviderStrategy implements IElementContentProvider /** * Returns the view model provider that this strategy is configured for. + * * @return */ - protected AbstractVMProvider getVMProvider() { return fVMProvider; } - + protected AbstractVMProvider getVMProvider() { + return fVMProvider; + } + public void update(final IHasChildrenUpdate[] updates) { - if (updates.length == 0) return; - - // Optimization: if all the updates belong to the same node, avoid creating any new lists/arrays. + if (updates.length == 0) + return; + + // Optimization: if all the updates belong to the same node, avoid + // creating any new lists/arrays. boolean allNodesTheSame = true; IVMNode firstNode = getNodeForElement(updates[0].getElement()); for (int i = 1; i < updates.length; i++) { @@ -71,70 +76,74 @@ public class DefaultVMContentProviderStrategy implements IElementContentProvider break; } } - + if (allNodesTheSame) { updateNode(firstNode, updates); } else { // Sort the updates by the node. - Map> nodeUpdatesMap = new HashMap>(); + Map> nodeUpdatesMap = new HashMap>(); for (IHasChildrenUpdate update : updates) { - // Get the VM Context for last element in path. + // Get the VM Context for last element in path. IVMNode node = getNodeForElement(update.getElement()); if (node == null) { // Stale update, most likely as a result of the nodes being - // changed. Just ignore it. + // changed. Just ignore it. update.done(); continue; - } + } if (!nodeUpdatesMap.containsKey(node)) { nodeUpdatesMap.put(node, new ArrayList()); } nodeUpdatesMap.get(node).add(update); } - + // Iterate through the nodes in the sorted map. - for (IVMNode node : nodeUpdatesMap.keySet()) { - updateNode(node, nodeUpdatesMap.get(node).toArray(new IHasChildrenUpdate[nodeUpdatesMap.get(node).size()])); + for (IVMNode node : nodeUpdatesMap.keySet()) { + updateNode(node, nodeUpdatesMap.get(node).toArray( + new IHasChildrenUpdate[nodeUpdatesMap.get(node).size()])); } } } private void updateNode(IVMNode node, final IHasChildrenUpdate[] updates) { - // If parent element's node has no children, just set the - // result and continue to next element. final IVMNode[] childNodes = getVMProvider().getChildVMNodes(node); if (childNodes.length == 0) { + // If parent element's node has no children, just set the + // result and continue to next element. for (IHasChildrenUpdate update : updates) { update.setHasChilren(false); update.done(); } - return; - } - - // Create a matrix of element updates: - // The first dimension "i" is the list of children updates that came from the viewer. - // For each of these updates, there are "j" number of elment updates corresponding - // to the number of child nodes in this node. - // Each children update from the viewer is complete when all the child nodes - // fill in their elements update. - // Once the matrix is constructed, the child nodes are given the list of updates - // equal to the updates requested by the viewer. - VMHasChildrenUpdate[][] elementsUpdates = - new VMHasChildrenUpdate[childNodes.length][updates.length]; - for (int i = 0; i < updates.length; i ++) - { - final IHasChildrenUpdate update = updates[i]; - - final MultiRequestMonitor> hasChildrenMultiRequestMon = - new MultiRequestMonitor>(getVMProvider().getExecutor(), null) { + } else if (childNodes.length == 1) { + // Optimization: if there is only one child node, just pass on the + // update to the child node. + getVMProvider().updateNode(childNodes[0], updates); + } else { + // Create a matrix of element updates: + // The first dimension "i" is the list of children updates that came + // from the viewer. + // For each of these updates, there are "j" number of elment updates + // corresponding + // to the number of child nodes in this node. + // Each children update from the viewer is complete when all the child + // nodes + // fill in their elements update. + // Once the matrix is constructed, the child nodes are given the list of + // updates + // equal to the updates requested by the viewer. + VMHasChildrenUpdate[][] elementsUpdates = new VMHasChildrenUpdate[childNodes.length][updates.length]; + for (int i = 0; i < updates.length; i++) { + final IHasChildrenUpdate update = updates[i]; + + final MultiRequestMonitor> hasChildrenMultiRequestMon = new MultiRequestMonitor>( + getVMProvider().getExecutor(), null) { @Override protected void handleCompleted() { - // Status is OK, only if all request monitors are OK. - if (isSuccess()) { + // Status is OK, only if all request monitors are OK. + if (isSuccess()) { boolean isContainer = false; for (DataRequestMonitor hasElementsDone : getRequestMonitors()) { - isContainer |= hasElementsDone.isSuccess() && - hasElementsDone.getData().booleanValue(); + isContainer |= hasElementsDone.isSuccess() && hasElementsDone.getData().booleanValue(); } update.setHasChilren(isContainer); } else { @@ -143,26 +152,23 @@ public class DefaultVMContentProviderStrategy implements IElementContentProvider update.done(); } }; - - for (int j = 0; j < childNodes.length; j++) - { - elementsUpdates[j][i] = new VMHasChildrenUpdate( - update, - hasChildrenMultiRequestMon.add( - new ViewerDataRequestMonitor(getVMProvider().getExecutor(), update) { + + for (int j = 0; j < childNodes.length; j++) { + elementsUpdates[j][i] = new VMHasChildrenUpdate(update, hasChildrenMultiRequestMon + .add(new ViewerDataRequestMonitor(getVMProvider().getExecutor(), update) { @Override protected void handleCompleted() { hasChildrenMultiRequestMon.requestMonitorDone(this); } })); + } + } + + for (int j = 0; j < childNodes.length; j++) { + getVMProvider().updateNode(childNodes[j], elementsUpdates[j]); } } - - for (int j = 0; j < childNodes.length; j++) { - getVMProvider().updateNode(childNodes[j], elementsUpdates[j]); - } } - public void update(final IChildrenCountUpdate[] updates) { for (final IChildrenCountUpdate update : updates) { @@ -172,29 +178,29 @@ public class DefaultVMContentProviderStrategy implements IElementContentProvider IVMNode[] childNodes = getVMProvider().getChildVMNodes(node); if (childNodes.length == 0) { + // If there is no child nodes, logically the child count is 0. update.setChildCount(0); update.done(); } else if (childNodes.length == 1) { + // Optimization: there is only one child node, just pass on the child count to it. getVMProvider().updateNode(childNodes[0], update); } else { - getChildrenCountsForNode( - update, - node, - new ViewerDataRequestMonitor(getVMProvider().getExecutor(), update) { - @Override - protected void handleCompleted() { - if (isSuccess()) { - int numChildren = 0; - for (Integer count : getData()) { - numChildren += count.intValue(); - } - update.setChildCount(numChildren); - } else { - update.setChildCount(0); + getChildrenCountsForNode(update, node, new ViewerDataRequestMonitor(getVMProvider() + .getExecutor(), update) { + @Override + protected void handleCompleted() { + if (isSuccess()) { + int numChildren = 0; + for (Integer count : getData()) { + numChildren += count.intValue(); } - update.done(); + update.setChildCount(numChildren); + } else { + update.setChildCount(0); } - }); + update.done(); + } + }); } } else { update.done(); @@ -205,7 +211,7 @@ public class DefaultVMContentProviderStrategy implements IElementContentProvider public void update(final IChildrenUpdate[] updates) { for (final IChildrenUpdate update : updates) { - // Get the VM Context for last element in path. + // Get the VM Context for last element in path. final IVMNode node = getNodeForElement(update.getElement()); if (node != null && !update.isCanceled()) { IVMNode[] childNodes = getVMProvider().getChildVMNodes(node); @@ -213,84 +219,80 @@ public class DefaultVMContentProviderStrategy implements IElementContentProvider // Invalid update, just mark done. update.done(); } else if (childNodes.length == 1) { + // Optimization: there is only one child node, pass the updates to it. getVMProvider().updateNode(childNodes[0], update); } else { - getChildrenCountsForNode( - update, - node, - new ViewerDataRequestMonitor(getVMProvider().getExecutor(), update) { - @Override - protected void handleCompleted() { - if (!isSuccess()) { - update.done(); - return; - } - - updateChildrenWithCounts(update, node, getData()); + getChildrenCountsForNode(update, node, new ViewerDataRequestMonitor(getVMProvider() + .getExecutor(), update) { + @Override + protected void handleCompleted() { + if (!isSuccess()) { + update.done(); + return; } - }); + + updateChildrenWithCounts(update, node, getData()); + } + }); } } else { // Stale update. Just ignore. update.done(); - } + } - } + } } - /** - * Calculates the number of elements in each child node for the element in - * update. These counts are then used to delegate the children update to - * the correct nodes. + * Calculates the number of elements in each child node for the element in + * update. These counts are then used to delegate the children update to the + * correct nodes. */ - private void getChildrenCountsForNode(IViewerUpdate update, IVMNode updateNode, final DataRequestMonitor rm) { - + private void getChildrenCountsForNode(IViewerUpdate update, IVMNode updateNode, + final DataRequestMonitor rm) { + IVMNode[] childNodes = getVMProvider().getChildVMNodes(updateNode); // Check for an invalid call assert childNodes.length != 0; - + // Get the mapping of all the counts. - final Integer[] counts = new Integer[childNodes.length]; - final MultiRequestMonitor childrenCountMultiReqMon = - new MultiRequestMonitor(getVMProvider().getExecutor(), rm) { - @Override - protected void handleSuccess() { - rm.setData(counts); - rm.done(); - } - }; - + final Integer[] counts = new Integer[childNodes.length]; + final MultiRequestMonitor childrenCountMultiReqMon = new MultiRequestMonitor( + getVMProvider().getExecutor(), rm) { + @Override + protected void handleSuccess() { + rm.setData(counts); + rm.done(); + } + }; + for (int i = 0; i < childNodes.length; i++) { final int nodeIndex = i; getVMProvider().updateNode( - childNodes[i], - new VMChildrenCountUpdate( - update, - childrenCountMultiReqMon.add( - new ViewerDataRequestMonitor(getVMProvider().getExecutor(), update) { - @Override - protected void handleSuccess() { - counts[nodeIndex] = getData(); - } - - @Override - protected void handleCompleted() { - super.handleCompleted(); - childrenCountMultiReqMon.requestMonitorDone(this); - } - })) - ); + childNodes[i], + new VMChildrenCountUpdate(update, childrenCountMultiReqMon.add(new ViewerDataRequestMonitor( + getVMProvider().getExecutor(), update) { + @Override + protected void handleSuccess() { + counts[nodeIndex] = getData(); + } + + @Override + protected void handleCompleted() { + super.handleCompleted(); + childrenCountMultiReqMon.requestMonitorDone(this); + } + }))); } } - + /** - * Splits the given children update among the configured child nodes. Then calls - * each child node to complete the update. + * Splits the given children update among the configured child nodes. Then + * calls each child node to complete the update. */ private void updateChildrenWithCounts(final IChildrenUpdate update, IVMNode node, Integer[] nodeElementCounts) { - // Create the multi request monitor to mark update when querying all + // Create the multi request monitor to mark update when querying all // children nodes is finished. CountingRequestMonitor multiRm = new ViewerCountingRequestMonitor(getVMProvider().getExecutor(), update) { @Override @@ -300,7 +302,8 @@ public class DefaultVMContentProviderStrategy implements IElementContentProvider }; int multiRmCount = 0; - // Iterate through all child nodes and if requested range matches, call them to + // Iterate through all child nodes and if requested range matches, call + // them to // get their elements. int updateStartIdx = update.getOffset(); int updateEndIdx = update.getOffset() + update.getLength(); @@ -319,16 +322,20 @@ public class DefaultVMContentProviderStrategy implements IElementContentProvider if (elementsLength > 0) { getVMProvider().updateNode( nodes[i], - new VMChildrenUpdate( - update, elementsStartIdx, elementsLength, - new DataRequestMonitor>(getVMProvider().getExecutor(), multiRm) { + new VMChildrenUpdate(update, elementsStartIdx, elementsLength, + new DataRequestMonitor>(getVMProvider().getExecutor(), multiRm) { @Override protected void handleCompleted() { - // Workaround for a bug caused by an optimization in the viewer: - // The viewer may request more children then there are at a given level. - // This causes the update to return with an error. - // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=202109 - // Instead of checking isSuccess(), check getData() != null. + // Workaround for a bug caused by an + // optimization in the viewer: + // The viewer may request more children then + // there are at a given level. + // This causes the update to return with an + // error. + // See + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=202109 + // Instead of checking isSuccess(), check + // getData() != null. if (getData() != null) { for (int i = 0; i < elementsLength && i < getData().size(); i++) { Object child = getData().get(i); @@ -339,41 +346,42 @@ public class DefaultVMContentProviderStrategy implements IElementContentProvider } super.handleCompleted(); } - }) - ); + })); multiRmCount++; } } } - + // Guard against invalid queries. multiRm.setDoneCount(multiRmCount); } /** - * Convenience method that finds the VMC corresponding to given parent - * argument given to isContainer() or retrieveChildren(). - * @param object Object to find the VMC for. - * @return parent VMC, if null it indicates that the object did not originate - * from this view or is stale. + * Convenience method that finds the VM node corresponding to given element. + * It returns the root node if the element is not a VM Context or if it was + * created by another view. + * + * @param element Element to find the VM Node for. + * @return View Model Node that this element was created by. */ protected IVMNode getNodeForElement(Object element) { if (element instanceof IVMContext) { - IVMNode node = ((IVMContext)element).getVMNode(); - if (isOurNode(((IVMContext)element).getVMNode())) { + IVMNode node = ((IVMContext) element).getVMNode(); + if (isOurNode(((IVMContext) element).getVMNode())) { return node; } - } + } return getVMProvider().getRootVMNode(); } - + /** - * Convenience method which checks whether given layout node is a node - * that is configured in this ViewModelProvider. + * Convenience method which checks whether given layout node is a node that + * is configured in this ViewModelProvider. */ private boolean isOurNode(IVMNode node) { for (IVMNode nodeToSearch : getVMProvider().getAllVMNodes()) { - if (nodeToSearch.equals(node)) return true; + if (nodeToSearch.equals(node)) + return true; } return false; } diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/IVMAdapter.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/IVMAdapter.java index 69ca0d1bbe1..dacadcf3048 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/IVMAdapter.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/IVMAdapter.java @@ -26,7 +26,6 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerInputProvi * @since 1.0 */ @ThreadSafe -@SuppressWarnings("restriction") public interface IVMAdapter extends IElementContentProvider, IModelProxyFactory, IColumnPresentationFactory, IViewerInputProvider { diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/IElementPropertiesProvider.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/IElementPropertiesProvider.java index 5122fc7f7f2..3f8f103873a 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/IElementPropertiesProvider.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/IElementPropertiesProvider.java @@ -19,6 +19,14 @@ package org.eclipse.cdt.dsf.ui.viewmodel.properties; */ public interface IElementPropertiesProvider { + /** + * Common property representing an element's name. This property can be + * used in future extensions for filtering and sorting. + * + * @since 2.0 + */ + public static final String PROP_NAME = "name"; //$NON-NLS-1$ + /** * Updates the specified property sets. * diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/IPropertiesUpdate.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/IPropertiesUpdate.java index f01f7eded53..d3752ddc3f3 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/IPropertiesUpdate.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/IPropertiesUpdate.java @@ -10,6 +10,9 @@ *******************************************************************************/ package org.eclipse.cdt.dsf.ui.viewmodel.properties; +import java.util.Map; +import java.util.Set; + import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate; /** @@ -20,15 +23,22 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate; @SuppressWarnings("restriction") public interface IPropertiesUpdate extends IViewerUpdate { /** - * Returns the list of element properties that the provider should set. - * If null, all available properties should be set. + * Returns the set of element properties that the provider should update. */ - public String[] getProperties(); + public Set getProperties(); /** * Sets the given property to update. + * * @param property Property ID. * @param value Property value. */ public void setProperty(String property, Object value); + + /** + * Sets the given map as the complete property map for this update. + * + * @param properties Full properties map. + */ + public void setAllProperties(Map properties); } diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelAttribute.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelAttribute.java index 8c370d9b737..1812f2ff531 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelAttribute.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelAttribute.java @@ -12,7 +12,7 @@ package org.eclipse.cdt.dsf.ui.viewmodel.properties; import java.util.Map; -import org.eclipse.core.runtime.ListenerList; +import org.eclipse.core.runtime.IStatus; import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; /** @@ -28,7 +28,7 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; * also override how the attribute settings are stored, for example in * order to use a preference. * - * @see PropertyBasedLabelProvider + * @see PropertiesBasedLabelProvider * @see LabelColumnInfo * * @since 1.0 @@ -38,74 +38,84 @@ abstract public class LabelAttribute { public static final String[] EMPTY_PROPERTY_NAMES_ARRAY = new String[0]; /** - * Listeners for when this attribute is modified. + * @since 2.0 */ - private ListenerList fListeners = new ListenerList(); + private String[] fPropertyNames = EMPTY_PROPERTY_NAMES_ARRAY; public LabelAttribute() { + this(EMPTY_PROPERTY_NAMES_ARRAY); } /** - * Disposes this attribute. + * @since 2.0 */ - public void dispose() { + public LabelAttribute(String[] propertyNames) { + setPropertyNames(propertyNames); + } + + protected void setPropertyNames(String[] propertyNames) { + fPropertyNames = propertyNames; } /** - * Registers the given listener for changes in this attribute. A change in - * the attributes of a label should cause a view to repaint. - * @param listener Listener to register. - */ - public void addChangedListener(ILabelAttributeChangedListener listener) { - fListeners.add(listener); - } - - /** - * Unregisters the given listener. - * @param listener Listener to unregister. - */ - public void removeChangedListener(ILabelAttributeChangedListener listener) { - fListeners.remove(listener); - } - - /** - * Calls the listeners to notify them that this attribute has changed. - */ - protected void fireAttributeChanged() { - Object[] listeners = fListeners.getListeners(); - for (Object listener : listeners) { - ((ILabelAttributeChangedListener)listener).attributesChanged(); - } - } - - /** - * Returns the propertis that are needed by this attribute in order to + * Returns the properties that are needed by this attribute in order to * determine whether this attribute is enabled and/or for the actual * attribute itself. * @return Array of names of properties for the element properties provider. */ public String[] getPropertyNames() { - return EMPTY_PROPERTY_NAMES_ARRAY; + return fPropertyNames; } /** * Returns whether this attribute is enabled for an element which has - * the given properties. - * @param properties Map or element properties. The client should ensure - * that all properties specified by {@link #getPropertyNames()} are - * supplied in this map. + * the given properties. The default implementation checks if all the + * label's attributes are present in the properties map. + * + * @param status Result of the properties update. + * @param properties Properties supplied by a property update. * @return true if this attribute is enabled. + * + * @since 2.0 */ - public boolean isEnabled(Map properties) { + public boolean isEnabled(IStatus status, Map properties) { + for (String propertyName : getPropertyNames()) { + if (!checkProperty(propertyName, status, properties)) { + return false; + } + } return true; } - + + /** - * Updates the label with this attribute. + * Checks the status of the given property in the given properties map. The + * default implementation returns true if the given property + * exists and is not null. + * + * @param propertyName Name of the property to check. + * @param status Result of the properties update. + * @param properties Properties map following an update. + * @return true if the property exists in the given map and + * its value is not null. + * + * @since 2.0 + */ + protected boolean checkProperty(String propertyName, IStatus status, Map properties) { + return properties.get(propertyName) != null; + } + + /** + * Updates the label with this attribute. * * @param update Label update object to write to. - * @param columnIndex Colum index to write at. - * @param properties Element properties to use. + * @param columnIndex Column index to write at. + * @param status Result of the property update. + * @param properties Property values map. It is guaranteed to contain all + * the properties that this attribute requested through + * {@link getPropertyNames()}. + * + * @since 2.0 */ - abstract public void updateAttribute(ILabelUpdate update, int columnIndex, Map properties); + abstract public void updateAttribute(ILabelUpdate update, int columnIndex, IStatus status, Map properties); } \ No newline at end of file diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelColor.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelColor.java index 976acb59e64..3b6dfcd0e16 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelColor.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelColor.java @@ -12,6 +12,7 @@ package org.eclipse.cdt.dsf.ui.viewmodel.properties; import java.util.Map; +import org.eclipse.core.runtime.IStatus; import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; import org.eclipse.swt.graphics.RGB; @@ -21,7 +22,7 @@ import org.eclipse.swt.graphics.RGB; * * @see LabelAttribute * @see LabelColumnInfo - * @see PropertyBasedLabelProvider + * @see PropertiesBasedLabelProvider * * @since 1.0 */ @@ -50,16 +51,14 @@ public class LabelColor extends LabelAttribute { public void setForeground(RGB foreground) { fForeground = foreground; - fireAttributeChanged(); } public void setBackground(RGB background) { fBackground = background; - fireAttributeChanged(); } @Override - public void updateAttribute(ILabelUpdate update, int columnIndex, Map properties) { + public void updateAttribute(ILabelUpdate update, int columnIndex, IStatus status, Map properties) { RGB foreground = getForeground(); if (foreground != null) { update.setForeground(foreground, columnIndex); diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelColumnInfo.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelColumnInfo.java index 541df11b876..495f25c23c6 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelColumnInfo.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelColumnInfo.java @@ -15,11 +15,12 @@ import java.util.List; import java.util.Map; import org.eclipse.cdt.dsf.concurrent.ThreadSafe; +import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.ListenerList; import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; /** - * Class used by the PropertyBasedLabelProvider to generate store + * Class used by the PropertiesBasedLabelProvider to generate store * label attributes related to a single column. Each column info is * configured with an array of attributes (there are currently four * types of attributes: text, image, font, and color), which are @@ -27,15 +28,24 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; *

* Clients are not intended to extend this class. * - * @see PropertyBasedLabelProvider + * @see PropertiesBasedLabelProvider * * @since 1.0 */ -@SuppressWarnings("restriction") @ThreadSafe -public class LabelColumnInfo implements ILabelAttributeChangedListener { +public class LabelColumnInfo { + + /** + * @since 2.0 + */ + private static final LabelAttribute[] DEFAULT_FAILED_UPDATE_ATTRIBUTES = new LabelAttribute[] { + new LabelText("...", new String[0]) + }; - private static final LabelAttribute[] EMPTY_ATTRIBUTES_ARRAY = new LabelAttribute[0]; + /** + * @since 2.0 + */ + private static final LabelAttribute[] EMPTY_ATTRIBUTES = new LabelAttribute[0]; /** * Calculated list of property names that need to be retrieved to @@ -47,7 +57,7 @@ public class LabelColumnInfo implements ILabelAttributeChangedListener { * Array of label attribute objects. */ private LabelAttribute[] fLabelAttributes; - + /** * Listeners for when column attributes are modified. */ @@ -63,7 +73,6 @@ public class LabelColumnInfo implements ILabelAttributeChangedListener { List names = new LinkedList(); for (LabelAttribute attr : attributes) { - attr.addChangedListener(this); for (String name : attr.getPropertyNames()) { names.add(name); } @@ -71,19 +80,6 @@ public class LabelColumnInfo implements ILabelAttributeChangedListener { fPropertyNames = names.toArray(new String[names.size()]); } - - /** - * Disposes this column info object and the attribute objects - * within it. - */ - public void dispose() { - for (LabelAttribute attr : fLabelAttributes) { - attr.dispose(); - attr.removeChangedListener(this); - } - fLabelAttributes = EMPTY_ATTRIBUTES_ARRAY; - fPropertyNames = null; - } /** * Returns the property names that need to be retrieved in order @@ -97,43 +93,27 @@ public class LabelColumnInfo implements ILabelAttributeChangedListener { public LabelAttribute[] getLabelAttributes() { return fLabelAttributes; } /** - * Registers the given listener for changes in the attributes of this - * column. A change in the attributes of a label should cause - * a view to repaint. - * @param listener Listener to register. + * Returns the list of configured label attributes for this column. + * + * @since 2.0 */ - public void addChangedListener(ILabelAttributeChangedListener listener) { - fListeners.add(listener); - } - - /** - * Unregisters the given listener. - * @param listener Listener to unregister. - */ - public void removeChangedListener(ILabelAttributeChangedListener listener) { - fListeners.remove(listener); - } + protected LabelAttribute[] setLabelAttributes(LabelAttribute attributes) { + return fLabelAttributes; + } - /** - * Listener method called by the attribute objects. - * @see ILabelAttributeChangedListener - */ - public void attributesChanged() { - Object[] listeners = fListeners.getListeners(); - for (Object listener : listeners) { - ((ILabelAttributeChangedListener)listener).attributesChanged(); - } - } - /** * Updates the label parameters for this column based on the provided * properties. The label information is written to the givne label * update under the given column index. + * * @param update Update to write to. * @param columnIndex Column to write label information under. + * @param status Result of the properties update * @param properties Map of properties to use to generate the label. + * + * @since 2.0 */ - public void updateColumn(ILabelUpdate update, int columnIndex, Map properties) { + public void updateColumn(ILabelUpdate update, int columnIndex, IStatus status, Map properties) { boolean textSet = false; boolean imageSet = false; boolean fontSet = false; @@ -146,10 +126,9 @@ public class LabelColumnInfo implements ILabelAttributeChangedListener { !(info instanceof LabelImage && imageSet) && !(info instanceof LabelFont && fontSet) && !(info instanceof LabelColor && colorSet) && - info.isEnabled(properties)) + info.isEnabled(status, properties)) { - info.updateAttribute(update, columnIndex, properties); - + info.updateAttribute(update, columnIndex, status, properties); textSet = textSet || info instanceof LabelText; imageSet = imageSet || info instanceof LabelImage; fontSet = fontSet || info instanceof LabelFont; diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelFont.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelFont.java index 224eb1d86b7..b3650dfe7a1 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelFont.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelFont.java @@ -12,6 +12,7 @@ package org.eclipse.cdt.dsf.ui.viewmodel.properties; import java.util.Map; +import org.eclipse.core.runtime.IStatus; import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.swt.graphics.FontData; @@ -21,7 +22,7 @@ import org.eclipse.swt.graphics.FontData; * * @see LabelAttribute * @see LabelColumnInfo - * @see PropertyBasedLabelProvider + * @see PropertiesBasedLabelProvider * * @since 1.0 */ @@ -48,11 +49,10 @@ public class LabelFont extends LabelAttribute { public void setFontData(FontData fontData) { fFontData = fontData; - fireAttributeChanged(); } @Override - public void updateAttribute(ILabelUpdate update, int columnIndex, Map properties) { + public void updateAttribute(ILabelUpdate update, int columnIndex, IStatus status, Map properties) { update.setFontData(getFontData(), columnIndex); } diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelImage.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelImage.java index d658e64edc3..09a2569900e 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelImage.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelImage.java @@ -12,6 +12,7 @@ package org.eclipse.cdt.dsf.ui.viewmodel.properties; import java.util.Map; +import org.eclipse.core.runtime.IStatus; import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; import org.eclipse.jface.resource.ImageDescriptor; @@ -20,7 +21,7 @@ import org.eclipse.jface.resource.ImageDescriptor; * * @see LabelAttribute * @see LabelColumnInfo - * @see PropertyBasedLabelProvider + * @see PropertiesBasedLabelProvider * * @since 1.0 */ @@ -42,11 +43,10 @@ public class LabelImage extends LabelAttribute { public void setImageDescriptor(ImageDescriptor image) { fImageDescriptor = image; - fireAttributeChanged(); } @Override - public void updateAttribute(ILabelUpdate update, int columnIndex, Map properties) { + public void updateAttribute(ILabelUpdate update, int columnIndex, IStatus status, Map properties) { ImageDescriptor descriptor = getImageDescriptor(); if (descriptor != null) { update.setImageDescriptor(descriptor, columnIndex); diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelText.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelText.java index 8dcb06b544c..8b57d6699bf 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelText.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/LabelText.java @@ -26,7 +26,7 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; * @see MessageFormat#format(Object[], StringBuffer, java.text.FieldPosition) * @see LabelAttribute * @see LabelColumnInfo - * @see PropertyBasedLabelProvider + * @see PropertiesBasedLabelProvider * * @since 1.0 */ @@ -52,6 +52,15 @@ public class LabelText extends LabelAttribute { this(DEFAULT_MESSAGE, EMPTY_PROPERTY_NAMES_ARRAY); } + /** + * @since 2.0 + * @param formatPattern + * @param propertyNames + */ + public LabelText(String formatPattern, String[] propertyNames) { + this (new MessageFormat(formatPattern), propertyNames); + } + public LabelText(MessageFormat format, String[] propertyNames) { fMessageFormat = format; fPropertyNames = propertyNames; @@ -68,15 +77,14 @@ public class LabelText extends LabelAttribute { public void setMessageFormat(MessageFormat messageFormat) { fMessageFormat = messageFormat; - fireAttributeChanged(); } @Override - public void updateAttribute(ILabelUpdate update, int columnIndex, Map properties) { + public void updateAttribute(ILabelUpdate update, int columnIndex, IStatus status, Map properties) { String[] propertyNames = getPropertyNames(); Object[] propertyValues = new Object[propertyNames.length]; for (int i = 0; i < propertyNames.length; i++) { - propertyValues[i] = properties.get(propertyNames[i]); + propertyValues[i] = getPropertyValue(propertyNames[i], status, properties); } try { @@ -85,4 +93,8 @@ public class LabelText extends LabelAttribute { update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, 0, "Failed formatting a message for column " + columnIndex + ", for update " + update, e)); //$NON-NLS-1$ //$NON-NLS-2$ } } + + protected Object getPropertyValue(String propertyName, IStatus status, Map properties) { + return properties.get(propertyName); + } } \ No newline at end of file diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/PropertyBasedLabelProvider.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/PropertiesBasedLabelProvider.java similarity index 56% rename from dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/PropertyBasedLabelProvider.java rename to dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/PropertiesBasedLabelProvider.java index 161526b25ac..662e616fb29 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/PropertyBasedLabelProvider.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/PropertiesBasedLabelProvider.java @@ -12,20 +12,16 @@ package org.eclipse.cdt.dsf.ui.viewmodel.properties; import java.util.Collections; import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; +import java.util.HashSet; import java.util.Map; +import java.util.Set; -import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; -import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; import org.eclipse.cdt.dsf.concurrent.ThreadSafe; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor; -import org.eclipse.cdt.dsf.ui.viewmodel.VMViewerUpdate; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.Status; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider; import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; @@ -40,139 +36,52 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; * values are retrieved, they are processed in order to produce correct label text, * images, fonts, and colors, for the given element. * - * @since 1.0 + * @since 2.0 - Renamed from PropertyBasedLabelProvider */ @SuppressWarnings("restriction") @ThreadSafe -public class PropertyBasedLabelProvider - implements IElementLabelProvider, ILabelAttributeChangedListener +public class PropertiesBasedLabelProvider + implements IElementLabelProvider { - private static final String[] EMPTY_PROPERTY_NAMES_ARRAY = new String[0]; + public static final String ID_COLUMN_NO_COLUMNS = "ID_COLUMN_NO_COLUMNS"; //$NON-NLS-1$ - /** - * Properties update used as to collect property data from the provider. - */ - private class PropertiesUpdate extends VMViewerUpdate implements IPropertiesUpdate { - - private final String[] fProperties; - private final Map fValues; - - public PropertiesUpdate(String[] properties, ILabelUpdate labelUpdate, DataRequestMonitor> rm) { - super(labelUpdate, rm); - fProperties = properties; - fValues = fProperties != null - ? new HashMap(properties.length * 4 / 3, 0.75f) - : new HashMap(); - } - - public String[] getProperties() { - return fProperties; - } - - public void setProperty(String property, Object value) { - fValues.put(property, value); - } - - /** - * Overrides the standard done in order to store the retrieved values - * in the client's request monitor. - */ - @Override - public void done() { - @SuppressWarnings("unchecked") - DataRequestMonitor> rm = (DataRequestMonitor>)getRequestMonitor(); - if (fProperties == null || fValues.size() >= fProperties.length) { - rm.setData(fValues); - } else { - rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Incomplete properties updated", null)); //$NON-NLS-1$ - } - super.done(); - } - } - /** * Attribute information for each column by column ID. */ private Map fColumnInfos = Collections.synchronizedMap(new HashMap()); - private ListenerList fListeners = new ListenerList(); - /** * Standard constructor. A property based label constructor does not * initialize column attribute information {@link #setColumnInfo(String, LabelColumnInfo)} * must be called to configure each column. */ - public PropertyBasedLabelProvider() { - } - - /** - * Disposes this label provider and its configured column info objects. - */ - public void dispose() { - LabelColumnInfo[] infos = null; - synchronized (fColumnInfos) { - infos = fColumnInfos.values().toArray(new LabelColumnInfo[fColumnInfos.size()]); - fColumnInfos.clear(); - } - for (LabelColumnInfo info : infos) { - info.dispose(); - } + public PropertiesBasedLabelProvider() { } /** * Sets the given column info object for the given column ID. This column * info will be used to generate the label when the given column is visibile. + * * @param columnId Column ID that the given column info is being registered for. * @param info Column 'info' object containing column attributes. * @return The previous column info object configured for this ID. */ public LabelColumnInfo setColumnInfo(String columnId, LabelColumnInfo info) { LabelColumnInfo oldInfo = fColumnInfos.put(columnId, info); - info.addChangedListener(this); - if (oldInfo != null) { - info.removeChangedListener(this); - } return oldInfo; } /** * Returns the given column info object for the given column ID. * @param columnId Column ID to retrieve the column info for. + * + * @param columnId Column ID that the given column info is being registered for. * @@return Column 'info' object containing column attributes. */ - public LabelColumnInfo getColumnInfo(String column) { - return fColumnInfos.get(column); + public LabelColumnInfo getColumnInfo(String columnId) { + return fColumnInfos.get(columnId); } - /** - * Registers the given listener for changes in the attributes of this - * label provider. A change in the attributes of a label should cause - * a view to repaint. - * @param listener Listener to register. - */ - public void addChangedListener(ILabelAttributeChangedListener listener) { - fListeners.add(listener); - } - - /** - * Unregisters the given listener. - * @param listener Listener to unregister. - */ - public void removeChangedListener(ILabelAttributeChangedListener listener) { - fListeners.remove(listener); - } - - /** - * Listener method called by label provider's column info objects. - * @see ILabelAttributeChangedListener - */ - public void attributesChanged() { - Object[] listeners = fListeners.getListeners(); - for (Object listener : listeners) { - ((ILabelAttributeChangedListener)listener).attributesChanged(); - } - } - public void update(ILabelUpdate[] labelUpdates) { IElementPropertiesProvider propertiesProvider = getElementPropertiesProvider(labelUpdates[0].getElement()); if (propertiesProvider == null) { @@ -184,7 +93,7 @@ public class PropertyBasedLabelProvider } String[] columnIds = labelUpdates[0].getColumnIds(); - String[] propertyNames = calcPropertyNamesForColumns(columnIds); + Set propertyNames = calcPropertyNamesForColumns(columnIds); // Call the properties provider. Create a request monitor for each label update. // We can use an immediate executor for the request monitor because the label provider @@ -192,14 +101,12 @@ public class PropertyBasedLabelProvider IPropertiesUpdate[] propertiesUpdates = new IPropertiesUpdate[labelUpdates.length]; for (int i = 0; i < labelUpdates.length; i++) { final ILabelUpdate labelUpdate = labelUpdates[i]; - propertiesUpdates[i] = new PropertiesUpdate( + propertiesUpdates[i] = new VMPropertiesUpdate( propertyNames, labelUpdates[i], new ViewerDataRequestMonitor>(ImmediateExecutor.getInstance(), labelUpdates[i]) { @Override protected void handleCompleted() { - if (isSuccess()) { - updateLabel(labelUpdate, getData()); - } + updateLabel(labelUpdate, getStatus(), getData()); labelUpdate.done(); } }); @@ -213,39 +120,43 @@ public class PropertyBasedLabelProvider * @param columnIds Column IDs to check. * @return Array of property names. */ - private String[] calcPropertyNamesForColumns(String[] columnIds) { + private Set calcPropertyNamesForColumns(String[] columnIds) { + Set propertyNames = new HashSet(); if (columnIds == null) { - LabelColumnInfo columnInfo = getColumnInfo(null); + LabelColumnInfo columnInfo = getColumnInfo(ID_COLUMN_NO_COLUMNS); if (columnInfo != null) { - return columnInfo.getPropertyNames(); - } else { - return EMPTY_PROPERTY_NAMES_ARRAY; - } + for (String propertyName : columnInfo.getPropertyNames()) { + propertyNames.add(propertyName); + } + } } else { - List properties = new LinkedList(); for (String columnId : columnIds) { LabelColumnInfo info = getColumnInfo(columnId); if (info != null) { String[] infoPropertyNames = info.getPropertyNames(); for (int i = 0; i < infoPropertyNames.length; i++) { - properties.add(infoPropertyNames[i]); + propertyNames.add(infoPropertyNames[i]); } } } - return properties.toArray(new String[properties.size()]); } + return propertyNames; } /** * Updates the label information based on given map of properties. + * * @param update Label update to write to. + * @param status Result of the properties update * @param properties Properties retrieved from the element properties provider. + * + * @since 2.0 */ - protected void updateLabel(ILabelUpdate update, Map properties) { + protected void updateLabel(ILabelUpdate update, IStatus status, Map properties) { if (update.getColumnIds() == null) { - LabelColumnInfo info = getColumnInfo(null); + LabelColumnInfo info = getColumnInfo(ID_COLUMN_NO_COLUMNS); if (info != null) { - info.updateColumn(update, 0, properties); + info.updateColumn(update, 0, status, properties); } } else { String[] columnIds = update.getColumnIds(); @@ -253,7 +164,7 @@ public class PropertyBasedLabelProvider for (int i = 0; i < columnIds.length; i++) { LabelColumnInfo info = getColumnInfo(columnIds[i]); if (info != null) { - info.updateColumn(update, i, properties); + info.updateColumn(update, i, status, properties); } } } diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/VMDelegatingPropertiesUpdate.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/VMDelegatingPropertiesUpdate.java new file mode 100644 index 00000000000..80d6ef8ec42 --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/VMDelegatingPropertiesUpdate.java @@ -0,0 +1,42 @@ +package org.eclipse.cdt.dsf.ui.viewmodel.properties; + +import java.util.Map; +import java.util.Set; + +import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.ui.viewmodel.VMViewerUpdate; + +/** + * Properties update used as to collect property data from the provider. + * + * @since 2.0 + */ +public class VMDelegatingPropertiesUpdate extends VMViewerUpdate implements IPropertiesUpdate { + + /** + * Update to write the properties to. + */ + private final IPropertiesUpdate fParentUpdate; + + public VMDelegatingPropertiesUpdate(IPropertiesUpdate parentUpdate, RequestMonitor rm) { + super(parentUpdate, rm); + fParentUpdate = parentUpdate; + } + + public Set getProperties() { + return fParentUpdate.getProperties(); + } + + public void setProperty(String property, Object value) { + fParentUpdate.setProperty(property, value); + } + + public void setAllProperties(Map properties) { + fParentUpdate.setAllProperties(properties); + } + + @Override + public String toString() { + return "VMDelegatingPropertiesUpdate -> " + fParentUpdate; //$NON-NLS-1$ + } +} \ No newline at end of file diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/VMPropertiesUpdate.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/VMPropertiesUpdate.java new file mode 100644 index 00000000000..aa2f89d242b --- /dev/null +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/properties/VMPropertiesUpdate.java @@ -0,0 +1,89 @@ +package org.eclipse.cdt.dsf.ui.viewmodel.properties; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.ui.viewmodel.VMViewerUpdate; +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; + +/** + * Properties update used as to collect property data from the provider. + * + * @since 2.0 + */ +public class VMPropertiesUpdate extends VMViewerUpdate implements IPropertiesUpdate { + + /** + * Properties that the client has requested to retrieve. + */ + private final Set fProperties; + + /** + * Flag indicating that the update has created a new map, as opposed to + * using directly a map that was created using setAllProperties() call. + */ + private boolean fCreatedOwnMap = false; + + /** + * Map of property values, created on demand. + */ + private Map fValues = Collections.emptyMap(); + + public VMPropertiesUpdate(Set properties, IViewerUpdate parentUpdate, DataRequestMonitor> rm) { + super(parentUpdate, rm); + fProperties = properties; + } + + public VMPropertiesUpdate(Set properties, TreePath elementPath, Object viewerInput, IPresentationContext presentationContext, DataRequestMonitor> rm) { + super(elementPath, viewerInput, presentationContext, rm); + fProperties = properties; + } + + + public Set getProperties() { + return fProperties; + } + + public synchronized void setProperty(String property, Object value) { + if (!fCreatedOwnMap) { + fCreatedOwnMap = true; + Map curValues = fValues; + fValues = new HashMap(fProperties.size() * 4 / 3, 0.75f); + if (curValues != null) { + fValues.putAll(curValues); + } + } + fValues.put(property, value); + } + + public synchronized void setAllProperties(Map properties) { + if (fCreatedOwnMap) { + fValues.putAll(properties); + } + else { + fValues = properties; + } + } + + /** + * Overrides the standard done in order to store the retrieved values + * in the client's request monitor. + */ + @Override + public void done() { + @SuppressWarnings("unchecked") + DataRequestMonitor> rm = (DataRequestMonitor>)getRequestMonitor(); + rm.setData(fValues); + super.done(); + } + + @Override + public String toString() { + return "VMPropertiesUpdate:" + getElement() + " " + fProperties; //$NON-NLS-1$ //$NON-NLS-2$/ + } +} \ No newline at end of file diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/update/AbstractCachingVMProvider.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/update/AbstractCachingVMProvider.java index 8bc2957780a..1eb368be825 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/update/AbstractCachingVMProvider.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/update/AbstractCachingVMProvider.java @@ -17,37 +17,31 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.concurrent.Executor; -import java.util.concurrent.RejectedExecutionException; import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; -import org.eclipse.cdt.dsf.concurrent.DsfExecutor; -import org.eclipse.cdt.dsf.concurrent.DsfRunnable; import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; -import org.eclipse.cdt.dsf.datamodel.IDMContext; -import org.eclipse.cdt.dsf.datamodel.IDMData; -import org.eclipse.cdt.dsf.datamodel.IDMService; import org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.update.provisional.AllUpdateScope; import org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.update.provisional.ICachingVMProviderExtension; import org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.update.provisional.IVMUpdateScope; import org.eclipse.cdt.dsf.debug.internal.ui.viewmodel.update.provisional.VisibleUpdateScope; import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin; -import org.eclipse.cdt.dsf.ui.concurrent.SimpleDisplayExecutor; import org.eclipse.cdt.dsf.ui.concurrent.ViewerCountingRequestMonitor; import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor; import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMAdapter; import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMProvider; +import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext; import org.eclipse.cdt.dsf.ui.viewmodel.IVMModelProxy; import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode; import org.eclipse.cdt.dsf.ui.viewmodel.VMChildrenCountUpdate; import org.eclipse.cdt.dsf.ui.viewmodel.VMChildrenUpdate; import org.eclipse.cdt.dsf.ui.viewmodel.VMHasChildrenUpdate; import org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.VMPropertiesUpdate; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.Status; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate; @@ -58,16 +52,27 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta; import org.eclipse.jface.viewers.TreePath; import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeItem; /** - * Base implementation of a caching view model provider. + * Base implementation of a caching view model provider. + * + * @since 1.0 */ -@SuppressWarnings("restriction") -public class AbstractCachingVMProvider extends AbstractVMProvider implements ICachingVMProvider, ICachingVMProviderExtension { - +public class AbstractCachingVMProvider extends AbstractVMProvider + implements ICachingVMProvider, IElementPropertiesProvider, ICachingVMProviderExtension +{ + /** + * @since 2.0 + */ + private final static String PROP_UPDATE_STATUS = "org.eclipse.cdt.dsf.ui.viewmodel.update.update_status"; //$NON-NLS-1$ + + /** + * @since 2.0 + */ + private final static int LENGTH_PROP_IS_CHANGED_PREFIX = PROP_IS_CHANGED_PREFIX.length(); + private boolean fDelayEventHandleForViewUpdate = false; // debug flag @@ -169,7 +174,7 @@ public class AbstractCachingVMProvider extends AbstractVMProvider implements ICa /** * Entry with cached element data. */ - static class ElementDataEntry extends Entry { + private static class ElementDataEntry extends Entry { ElementDataEntry(ElementDataKey key) { super(key); } @@ -210,15 +215,19 @@ public class AbstractCachingVMProvider extends AbstractVMProvider implements ICa Map fChildren = null; /** - * Map of IDMData objects, keyed by the DM context. + * Map containing element properties. + * + * @since 2.0 */ - Map fDataOrStatus = new HashMap(1); - + Map fProperties = null; + /** - * Previous known value of the DM data objects. + * Previous known element properties. + * + * @since 2.0 */ - Map fArchiveData = new HashMap(1);; - + Map fArchiveProperties = null; + void ensureChildrenMap() { if (fChildren == null) { Integer childrenCount = fChildrenCount; @@ -234,8 +243,8 @@ public class AbstractCachingVMProvider extends AbstractVMProvider implements ICa "[hasChildren=" + fHasChildren + ", " +//$NON-NLS-1$ //$NON-NLS-2$ "childrenCount=" + fChildrenCount + //$NON-NLS-1$ ", children=" + fChildren + //$NON-NLS-1$ - ", data/status=" + fDataOrStatus + //$NON-NLS-1$ - ", oldData=" + fArchiveData + "]"; //$NON-NLS-1$ //$NON-NLS-2$ + ", properties=" + fProperties + //$NON-NLS-1$ + ", oldProperties=" + fArchiveProperties + "]"; //$NON-NLS-1$ //$NON-NLS-2$ } } @@ -694,24 +703,22 @@ public class AbstractCachingVMProvider extends AbstractVMProvider implements ICa // We are saving current data for change history, check if the data is valid. // If it valid, save it for archive, if it's not valid old archive data will be used // if there is any. And if there is no old archive data, just remove the cache entry. - for (Iterator> itr = elementDataEntry.fDataOrStatus.entrySet().iterator(); - itr.hasNext();) - { - Map.Entry dataOrStatusEntry = itr.next(); - if (dataOrStatusEntry.getValue() instanceof IDMData) { - elementDataEntry.fArchiveData.put(dataOrStatusEntry.getKey(), (IDMData)dataOrStatusEntry.getValue()); - } + if (elementDataEntry.fProperties != null) { + elementDataEntry.fArchiveProperties = elementDataEntry.fProperties; } - elementDataEntry.fDataOrStatus.clear(); - if (elementDataEntry.fArchiveData.isEmpty()) { + elementDataEntry.fProperties = null; + + // There is no archived data, which means that this entry is empty, so remove it from cache + // completely. + if (elementDataEntry.fArchiveProperties == null) { fCacheData.remove(entry.fKey); entry.remove(); - } + } } else { // We are not changing the archived data. If archive data exists in the entry, leave it. // Otherwise remove the whole entry. - if (!elementDataEntry.fArchiveData.isEmpty()) { - elementDataEntry.fDataOrStatus.clear(); + if (elementDataEntry.fArchiveProperties != null) { + elementDataEntry.fProperties.clear(); } else { fCacheData.remove(entry.fKey); entry.remove(); @@ -943,110 +950,163 @@ public class AbstractCachingVMProvider extends AbstractVMProvider implements ICa } /** - * Retrieves the deprecated IDMData object for the given IDMContext. This - * method should be removed once the use of IDMData is replaced with - * {@link IElementPropertiesProvider}. + * @since 2.0 */ - @Deprecated - public void getModelData(final IVMNode node, final IViewerUpdate update, final IDMService service, final IDMContext dmc, - final DataRequestMonitor rm, final Executor executor) - { - // Determine if this request is being issues on the a VM executor thread. If so - // then we do not need to create a new one to insure data integrity. - Executor vmExecutor = getExecutor(); - if ( vmExecutor instanceof SimpleDisplayExecutor && - Display.getDefault().getThread() == Thread.currentThread() ) - { - getCacheModelData(node, update, service, dmc, rm, executor ); - } else { - vmExecutor.execute(new DsfRunnable() { - public void run() { - getCacheModelData(node, update, service, dmc, rm, executor ); - } - }); - } - } - - private void getCacheModelData(final IVMNode node, final IViewerUpdate update, final IDMService service, final IDMContext dmc, - final DataRequestMonitor rm, final Executor executor) - { - ElementDataKey key = makeEntryKey(node, update); - final ElementDataEntry entry = getElementDataEntry(key); - /*if (entry.fDirty) { - rm.setStatus(Status.CANCEL_STATUS); - rm.done(); - } else */{ - Object dataOrStatus = entry.fDataOrStatus.get(dmc); - if(dataOrStatus != null) { - if (dataOrStatus instanceof IDMData) { - rm.setData( dataOrStatus ); - } else { - rm.setStatus((IStatus)dataOrStatus ); - } - rm.done(); - } else { - // Determine if we are already running on a DSF executor thread. if so then - // we do not need to create a new one to issue the request to the service. - DsfExecutor dsfExecutor = service.getExecutor(); - if ( dsfExecutor.isInExecutorThread() ) { - getModelDataFromService(node, update, service, dmc, rm, executor, entry ); - } - else { - try { - dsfExecutor.execute(new DsfRunnable() { - public void run() { - getModelDataFromService(node, update, service, dmc, rm, executor, entry ); - } - }); - } catch (RejectedExecutionException e) { - rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Service session's executor shut down.", null)); //$NON-NLS-1$ - rm.done(); - } - } - } + public void update(IPropertiesUpdate[] updates) { + if (updates.length == 0) + return; + + // Optimization: if all the updates belong to the same node, avoid + // creating any new lists/arrays. + boolean allNodesTheSame = true; + IVMNode firstNode = getNodeForElement(updates[0].getElement()); + for (int i = 1; i < updates.length; i++) { + if (firstNode != getNodeForElement(updates[i].getElement())) { + allNodesTheSame = false; + break; + } + } + + if (allNodesTheSame) { + if ( !(firstNode instanceof IElementPropertiesProvider) ) { + for (IPropertiesUpdate update : updates) { + update.setStatus(DsfUIPlugin.newErrorStatus(IDsfStatusConstants.INVALID_HANDLE, "Element is not a VM Context or its node is not a properties provider.", null)); //$NON-NLS-1$ + update.done(); + } + } else { + updateNode(firstNode, updates); + } + } else { + // Sort the updates by the node. + Map> nodeUpdatesMap = new HashMap>(); + for (IPropertiesUpdate update : updates) { + // Get the VM Context for last element in path. + IVMNode node = getNodeForElement(update.getElement()); + if ( node == null || !(node instanceof IElementPropertiesProvider) ) { + // Misdirected update. + update.setStatus(DsfUIPlugin.newErrorStatus(IDsfStatusConstants.INVALID_HANDLE, "Element is not a VM Context or its node is not a properties provider.", null)); //$NON-NLS-1$ + update.done(); + continue; + } + if (!nodeUpdatesMap.containsKey(node)) { + nodeUpdatesMap.put(node, new ArrayList()); + } + nodeUpdatesMap.get(node).add(update); + } + + // Iterate through the nodes in the sorted map. + for (IVMNode node : nodeUpdatesMap.keySet()) { + updateNode(node, nodeUpdatesMap.get(node).toArray( + new IPropertiesUpdate[nodeUpdatesMap.get(node).size()])); + } } } - private void getModelDataFromService(final IVMNode node, final IViewerUpdate update, final IDMService service, final IDMContext dmc, - final DataRequestMonitor rm, final Executor executor, final ElementDataEntry entry) - { - service.getModelData( - dmc, - new ViewerDataRequestMonitor(executor, update) { - @Override - protected void handleCompleted() { - if (isSuccess()) { - entry.fDataOrStatus.put(dmc, getData()); - rm.setData(getData()); - } else { - if (!isCanceled()) { - entry.fDataOrStatus.put(dmc, getStatus()); - } - rm.setStatus(getStatus()); - } - rm.done(); - } - }); - } - /** - * Retrieves the deprecated IDMData object for the given IDMContext. This - * method should be removed once the use of IDMData is replaced with - * {@link IElementPropertiesProvider}. + * Convenience method that finds the VM node corresponding to given element. + * It returns null if the element is not a VM context. + * + * @param element Element to find the VM Node for. + * @return View Model Node that this element was created by, or null. + * + * @since 2.0 */ - @Deprecated - public IDMData getArchivedModelData(IVMNode node, IViewerUpdate update, IDMContext dmc) { - ElementDataKey key = makeEntryKey(node, update); - final Entry entry = fCacheData.get(key); - if ( entry instanceof ElementDataEntry) { - Map archiveData = ((ElementDataEntry)entry).fArchiveData; - if (archiveData != null) { - return archiveData.get(dmc); - } + private IVMNode getNodeForElement(Object element) { + if (element instanceof IVMContext) { + return ((IVMContext) element).getVMNode(); } return null; } + + protected void updateNode(final IVMNode node, IPropertiesUpdate[] updates) { + LinkedList missUpdates = new LinkedList(); + for(final IPropertiesUpdate update : updates) { + // Find or create the cache entry for the element of this update. + ElementDataKey key = makeEntryKey(node, update); + final ElementDataEntry entry = getElementDataEntry(key); + + // The request can be retrieved from cache if all the properties that were requested in the update are + // found in the map. + if (entry.fProperties != null && entry.fProperties.keySet().containsAll(update.getProperties())) { + // Cache Hit! Just return the value. + if (DEBUG_CACHE && (DEBUG_PRESENTATION_ID == null || getPresentationContext().getId().equals(DEBUG_PRESENTATION_ID))) { + DsfUIPlugin.debug("cacheHitHasChildren(node = " + node + ", update = " + update + ", " + entry.fHasChildren + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + } + update.setAllProperties(entry.fProperties); + update.setStatus((IStatus)entry.fProperties.get(PROP_UPDATE_STATUS)); + update.done(); + } else { + // Cache miss! Save the flush counter of the entry and create a proxy update. + final int flushCounter = entry.fFlushCounter; + missUpdates.add(new VMPropertiesUpdate( + update.getProperties(), + update, + new ViewerDataRequestMonitor>(getExecutor(), update) { + @Override + protected void handleCompleted() { + Map properties; + if (!isCanceled() && flushCounter == entry.fFlushCounter) { + // We are caching the result of this update. Copy the properties from the update + // to the cached properties map. + if (entry.fProperties == null) { + entry.fProperties = new HashMap(getData().size() + 1 * 4/3); + entry.fProperties.put(PROP_CACHE_ENTRY_DIRTY, entry.fDirty); + } + properties = entry.fProperties; + properties.putAll(getData()); + + // Make sure that all the properties that were requested by the user are in the + // properties map. Otherwise, we'll never get a cache hit because the cache + // test makes sure that all keys that are requested are in the properties map. + for (String updateProperty : update.getProperties()) { + if (!properties.containsKey(updateProperty)) { + properties.put(updateProperty, null); + } + } + } else { + // We are not caching the result of this update, but we should still + // return valid data to the client. + properties = new HashMap(getData().size() + 1 * 4/3); + properties.put(PROP_CACHE_ENTRY_DIRTY, Boolean.TRUE); + properties.putAll(getData()); + } + + properties.put(PROP_UPDATE_STATUS, getStatus()); + + // If there is archive data available, calculate the requested changed value properties. + // Do not calculate the changed flags if the entry has been flushed. + if (entry.fArchiveProperties != null && flushCounter == entry.fFlushCounter) { + for (String updateProperty : update.getProperties()) { + if (updateProperty.startsWith(PROP_IS_CHANGED_PREFIX)) { + String changedPropertyName = updateProperty.substring(LENGTH_PROP_IS_CHANGED_PREFIX); + Object newValue = properties.get(changedPropertyName); + Object oldValue = entry.fArchiveProperties.get(changedPropertyName); + if (oldValue != null) { + properties.put(updateProperty, !oldValue.equals(newValue)); + } + } + } + } + + if (DEBUG_CACHE && (DEBUG_PRESENTATION_ID == null || getPresentationContext().getId().equals(DEBUG_PRESENTATION_ID))) { + DsfUIPlugin.debug("cacheSavedProperties(node = " + node + ", update = " + update + ", " + getData() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ + } + + update.setAllProperties(properties); + update.setStatus(getStatus()); + update.done(); + } + })); + } + } + + // Issue all the update proxies with one call. + if (!missUpdates.isEmpty()) { + ((IElementPropertiesProvider)node).update(missUpdates.toArray(new IPropertiesUpdate[missUpdates.size()])); + } + } + /** * @noreference This method is an implementation of a provisional interface and * not intended to be referenced by clients. diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/update/ICachingVMProvider.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/update/ICachingVMProvider.java index 7872488693e..4e31076f1df 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/update/ICachingVMProvider.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/update/ICachingVMProvider.java @@ -11,6 +11,7 @@ package org.eclipse.cdt.dsf.ui.viewmodel.update; import org.eclipse.cdt.dsf.ui.viewmodel.IVMProvider; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider; /** * A view model provider which supports caching of data returned by view model @@ -19,8 +20,18 @@ import org.eclipse.cdt.dsf.ui.viewmodel.IVMProvider; * * @since 1.0 */ -public interface ICachingVMProvider extends IVMProvider { +public interface ICachingVMProvider extends IVMProvider, IElementPropertiesProvider { + + /** + * @since 2.0 + */ + public static final String PROP_IS_CHANGED_PREFIX = "is_changed."; //$NON-NLS-1$ + /** + * @since 2.0 + */ + public static final String PROP_CACHE_ENTRY_DIRTY = "cache_entry_dirty"; //$NON-NLS-1$ + /** * Returns the update policies that the given provider supports. */ diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/update/MultiLevelUpdateHandler.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/update/MultiLevelUpdateHandler.java index 88bfa7bca60..dd4fe25728a 100644 --- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/update/MultiLevelUpdateHandler.java +++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/ui/viewmodel/update/MultiLevelUpdateHandler.java @@ -39,7 +39,7 @@ import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.RGB; /** - * @since 1.0 + * @since 1.1 */ @SuppressWarnings("restriction") class MultiLevelUpdateHandler extends DataRequestMonitor> { diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/concurrent/CountingRequestMonitor.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/concurrent/CountingRequestMonitor.java index 99731fc1712..371bf91acdd 100644 --- a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/concurrent/CountingRequestMonitor.java +++ b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/concurrent/CountingRequestMonitor.java @@ -38,6 +38,7 @@ import org.eclipse.core.runtime.MultiStatus; * @since 1.0 */ public class CountingRequestMonitor extends RequestMonitor { + /** * Counter tracking the remaining number of times that the done() method * needs to be called before this request monitor is actually done. @@ -51,7 +52,20 @@ public class CountingRequestMonitor extends RequestMonitor { public CountingRequestMonitor(Executor executor, RequestMonitor parentRequestMonitor) { super(executor, parentRequestMonitor); - super.setStatus(new MultiStatus(DsfPlugin.PLUGIN_ID, 0, "Collective status for set of sub-operations.", null)); //$NON-NLS-1$ + super.setStatus(new MultiStatus(DsfPlugin.PLUGIN_ID, 0, "", null) { //$NON-NLS-1$ + @Override + public String getMessage() { + StringBuffer message = new StringBuffer(); + IStatus[] children = getChildren(); + for (int i = 0; i < children.length; i++) { + message.append(children[i].getMessage()); + if (i + 1 < children.length) { + message.append(" ,"); //$NON-NLS-1$ + } + } + return message.toString(); + } + }); } /** diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/concurrent/RequestMonitor.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/concurrent/RequestMonitor.java index 8abe4abd846..38e1beb70d7 100644 --- a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/concurrent/RequestMonitor.java +++ b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/concurrent/RequestMonitor.java @@ -73,7 +73,7 @@ import org.eclipse.core.runtime.Status; * @since 1.0 */ @ThreadSafe -public class RequestMonitor { +public class RequestMonitor extends DsfExecutable { /** * Interface used by RequestMonitor to notify when a given request monitor @@ -227,6 +227,8 @@ public class RequestMonitor { *

*/ public synchronized void done() { + setSubmitted(); + if (fDone) { throw new IllegalStateException("RequestMonitor: " + this + ", done() method called more than once"); //$NON-NLS-1$//$NON-NLS-2$ } diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/datamodel/IDMService.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/datamodel/IDMService.java deleted file mode 100644 index e6cf2697608..00000000000 --- a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/datamodel/IDMService.java +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2006, 2008 Wind River Systems and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Wind River Systems - initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.dsf.datamodel; - -import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; -import org.eclipse.cdt.dsf.service.IDsfService; - -/** - * Interface for DSF services that provide model data to clients. - *

- * For completeness this service interface derives from IDMData - * and has a method which allows clients to retrieve the DM Context that - * represents the service data. - * - * @deprecated Without getModelData method this service has no function. - * There's also no need for it as a marker interface so we may as well - * get rid of it. - * - * @since 1.0 - */ -public interface IDMService extends IDsfService { - /** - * Retrieves model data object for given context. This method makes it - * un-necessary for every model service to declare a separate method - * for retrieving model data of specific type. - * - * @param The Data Model Data type that is to be retrieved. - * @param dmc Data Model Context for the data model data object to be retrieved. - * @param rm Request completion monitor to be filled in with the Data Model Data. - * - * @deprecated This method is now deprecated as there is no compile-time linking - * between IDMContext and IDMData objects (see bug 205132) - */ - @Deprecated - void getModelData(IDMContext dmc, DataRequestMonitor rm); -} diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IDsfBreakpointExtension.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IDsfBreakpointExtension.java index fadd7b33796..9a7ee5314fc 100644 --- a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IDsfBreakpointExtension.java +++ b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IDsfBreakpointExtension.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.cdt.dsf.debug.service; +import org.eclipse.cdt.debug.core.model.ICBreakpoint; import org.eclipse.cdt.debug.core.model.ICBreakpointExtension; import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext; diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IFormattedValues.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IFormattedValues.java index 31dc1493c02..768fd0ed05c 100644 --- a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IFormattedValues.java +++ b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IFormattedValues.java @@ -15,7 +15,7 @@ import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.datamodel.AbstractDMContext; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.datamodel.IDMData; -import org.eclipse.cdt.dsf.datamodel.IDMService; +import org.eclipse.cdt.dsf.service.IDsfService; /** * Formatted values interface describes the kinds of formatted information @@ -24,7 +24,7 @@ import org.eclipse.cdt.dsf.datamodel.IDMService; * * @since 1.0 */ -public interface IFormattedValues extends IDMService { +public interface IFormattedValues extends IDsfService { /** Marker interface for a DMC that has a formatted value. */ public interface IFormattedDataDMContext extends IDMContext {} @@ -78,7 +78,7 @@ public interface IFormattedValues extends IDMService { { private final String fFormatID; - public FormattedValueDMContext(IDMService service, IDMContext parent, String formatId) { + public FormattedValueDMContext(IDsfService service, IDMContext parent, String formatId) { super(service, new IDMContext[] { parent }); fFormatID = formatId; } diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IProcesses.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IProcesses.java index 14a798380ee..680f0f83082 100644 --- a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IProcesses.java +++ b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IProcesses.java @@ -18,7 +18,7 @@ import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.datamodel.IDMData; import org.eclipse.cdt.dsf.datamodel.IDMEvent; -import org.eclipse.cdt.dsf.datamodel.IDMService; +import org.eclipse.cdt.dsf.service.IDsfService; /** * This interface provides access to the OS's process @@ -29,7 +29,7 @@ import org.eclipse.cdt.dsf.datamodel.IDMService; * * @since 1.1 */ -public interface IProcesses extends IDMService { +public interface IProcesses extends IDsfService { /** * A thread as known by the OS. diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IRunControl.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IRunControl.java index 6a09d97fc82..15fc8a2355e 100644 --- a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IRunControl.java +++ b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IRunControl.java @@ -16,7 +16,7 @@ import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.datamodel.IDMData; import org.eclipse.cdt.dsf.datamodel.IDMEvent; -import org.eclipse.cdt.dsf.datamodel.IDMService; +import org.eclipse.cdt.dsf.service.IDsfService; /** * This interface provides access to controlling and monitoring the execution @@ -28,7 +28,7 @@ import org.eclipse.cdt.dsf.datamodel.IDMService; * * @since 1.0 */ -public interface IRunControl extends IDMService +public interface IRunControl extends IDsfService { /** * Execution context is the object on which run control operations can be diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IStack.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IStack.java index 0dc480e7397..d549d2a9a60 100644 --- a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IStack.java +++ b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IStack.java @@ -14,7 +14,7 @@ import org.eclipse.cdt.core.IAddress; import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.datamodel.IDMData; -import org.eclipse.cdt.dsf.datamodel.IDMService; +import org.eclipse.cdt.dsf.service.IDsfService; /** * Stack service provides access to stack information for a @@ -22,7 +22,7 @@ import org.eclipse.cdt.dsf.datamodel.IDMService; * * @since 1.0 */ -public interface IStack extends IDMService { +public interface IStack extends IDsfService { /** * Context for a specific stack frame. Besides allowing access to stack diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/ISymbols.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/ISymbols.java index f66b63a52fb..f2bea733ccd 100644 --- a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/ISymbols.java +++ b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/ISymbols.java @@ -14,7 +14,7 @@ import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.datamodel.IDMData; import org.eclipse.cdt.dsf.datamodel.IDMEvent; -import org.eclipse.cdt.dsf.datamodel.IDMService; +import org.eclipse.cdt.dsf.service.IDsfService; /** * Service for accessing debugger symbols. This service builds on the Modules @@ -24,7 +24,7 @@ import org.eclipse.cdt.dsf.datamodel.IDMService; * @see IModules * @since 1.0 */ -public interface ISymbols extends IDMService { +public interface ISymbols extends IDsfService { public interface ISymbolObjectDMContext extends IDMContext {} /** diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/service/AbstractDsfService.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/service/AbstractDsfService.java index 572a2f012f0..630955b936c 100644 --- a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/service/AbstractDsfService.java +++ b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/service/AbstractDsfService.java @@ -82,6 +82,10 @@ abstract public class AbstractDsfService fTracker = null; rm.done(); } + + public boolean isActive() { + return getServiceRegistration() != null; + } /** Returns the session object for this service */ public DsfSession getSession() { return fSession; } diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/service/IDsfService.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/service/IDsfService.java index 5147fdbb84e..13982031b64 100644 --- a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/service/IDsfService.java +++ b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/service/IDsfService.java @@ -44,24 +44,24 @@ public interface IDsfService { * Property name for the session-id of this service. This property should be set by * all DSF services when they are registered with OSGI service framework. */ - final static String PROP_SESSION_ID = "org.eclipse.cdt.dsf.service.IService.session_id"; //$NON-NLS-1$ + public final static String PROP_SESSION_ID = "org.eclipse.cdt.dsf.service.IService.session_id"; //$NON-NLS-1$ /** * Returns the DSF Session that this service belongs to. */ - DsfSession getSession(); + public DsfSession getSession(); /** * Returns the executor that should be used to call methods of this service. * This method is equivalent to calling getSession().getExecutor() */ - DsfExecutor getExecutor(); + public DsfExecutor getExecutor(); /** * Returns the map of properties that this service was registered with. */ @SuppressWarnings("unchecked") - Dictionary getProperties(); + public Dictionary getProperties(); /** * Returns a filter string that can be used to uniquely identify this @@ -69,7 +69,7 @@ public interface IDsfService { * name, which were used to register this service. * @see org.osgi.framework.BundleContext#getServiceReferences */ - String getServiceFilter(); + public String getServiceFilter(); /** * Performs initialization and registration of the given service. Implementation @@ -81,13 +81,23 @@ public interface IDsfService { * initializaiton should fail. * @param requestMonitor callback to be submitted when the initialization is complete */ - void initialize(RequestMonitor requestMonitor); + public void initialize(RequestMonitor requestMonitor); /** * Performs shutdown and de-registration of the given service. * @param requestMonitor callback to be submitted when shutdown is complete */ - void shutdown(RequestMonitor requestMonitor); + public void shutdown(RequestMonitor requestMonitor); + + /** + * Returns whether the service is currently active. A service should be + * active after it is initialized and before it has been shut down. + * + * @return true if active + * + * @since 2.0 + */ + public boolean isActive(); /** * Returns the startup order number of this service among services in the same session. @@ -97,5 +107,5 @@ public interface IDsfService { * @return startup order number of this service * @see org.eclipse.cdt.dsf.service.DsfSession#getAndIncrementServiceStartupCounter() */ - int getStartupNumber(); + public int getStartupNumber(); } diff --git a/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/launch/PDAThreadsVMNode.java b/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/launch/PDAThreadsVMNode.java index 043f4bc9f08..7b4ba3c7a1a 100644 --- a/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/launch/PDAThreadsVMNode.java +++ b/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/launch/PDAThreadsVMNode.java @@ -11,24 +11,22 @@ *******************************************************************************/ package org.eclipse.cdt.examples.dsf.pda.ui.viewmodel.launch; +import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; import org.eclipse.cdt.dsf.datamodel.IDMContext; -import org.eclipse.cdt.dsf.debug.service.IRunControl; -import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMData; -import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason; import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.AbstractThreadVMNode; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.ILaunchVMConstants; import org.eclipse.cdt.dsf.service.DsfSession; -import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; -import org.eclipse.cdt.examples.dsf.pda.service.PDARunControl; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate; import org.eclipse.cdt.examples.dsf.pda.service.PDAThreadDMContext; +import org.eclipse.cdt.examples.dsf.pda.ui.PDAUIPlugin; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest; -import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; -import org.eclipse.debug.ui.DebugUITools; -import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.ui.IMemento; @@ -50,68 +48,16 @@ public class PDAThreadsVMNode extends AbstractThreadVMNode } @Override - protected void updateLabelInSessionThread(ILabelUpdate[] updates) { - for (final ILabelUpdate update : updates) { - final PDARunControl runControl = getServicesTracker().getService(PDARunControl.class); - if ( runControl == null ) { - handleFailedUpdate(update); - continue; - } - - final PDAThreadDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), PDAThreadDMContext.class); - - String imageKey = null; - if (getServicesTracker().getService(IRunControl.class).isSuspended(dmc)) { - imageKey = IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED; + protected void updatePropertiesInSessionThread(IPropertiesUpdate[] updates) { + for (int i = 0; i < updates.length; i++) { + final PDAThreadDMContext dmc = findDmcInPath(updates[i].getViewerInput(), updates[i].getElementPath(), PDAThreadDMContext.class); + if (dmc != null) { + updates[i].setProperty(ILaunchVMConstants.PROP_ID, Integer.toString(dmc.getID())); } else { - imageKey = IDebugUIConstants.IMG_OBJS_THREAD_RUNNING; + updates[i].setStatus(new Status(IStatus.ERROR, PDAUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$ } - update.setImageDescriptor(DebugUITools.getImageDescriptor(imageKey), 0); - - // Find the Reason for the State - getDMVMProvider().getModelData( - this, update, runControl, dmc, - new ViewerDataRequestMonitor(getSession().getExecutor(), update) { - @Override - public void handleCompleted(){ - if (!isSuccess()) { - update.setLabel("", 0); - update.done(); - return; - } - - // We're in a new dispatch cycle, and we have to check whether the - // service reference is still valid. - final PDARunControl runControl = getServicesTracker().getService(PDARunControl.class); - if ( runControl == null ) { - handleFailedUpdate(update); - return; - } - - final StateChangeReason reason = getData().getStateChangeReason(); - - // Create Labels of type Thread[GDBthreadId]RealThreadID/Name (State: Reason) - // Thread[1] 3457 (Suspended:BREAKPOINT) - final StringBuilder builder = new StringBuilder(); - builder.append("Thread "); - builder.append(dmc.getID()); - if(getServicesTracker().getService(IRunControl.class).isSuspended(dmc)) - builder.append(" (Suspended"); - else - builder.append(" (Running"); - // Reason will be null before ContainerSuspendEvent is fired - if(reason != null) { - builder.append(" : "); - builder.append(reason); - } - builder.append(")"); - update.setLabel(builder.toString(), 0); - update.done(); - } - }, - getExecutor()); - } + super.updatePropertiesInSessionThread(updates); } private String produceThreadElementName(String viewName, PDAThreadDMContext execCtx) { diff --git a/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/launch/PDAVirtualMachineVMNode.java b/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/launch/PDAVirtualMachineVMNode.java index 62b57922fa3..415215349e8 100644 --- a/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/launch/PDAVirtualMachineVMNode.java +++ b/dsf/org.eclipse.cdt.examples.dsf.pda.ui/src/org/eclipse/cdt/examples/dsf/pda/ui/viewmodel/launch/PDAVirtualMachineVMNode.java @@ -13,17 +13,24 @@ package org.eclipse.cdt.examples.dsf.pda.ui.viewmodel.launch; +import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; import org.eclipse.cdt.dsf.datamodel.IDMContext; import org.eclipse.cdt.dsf.debug.service.IRunControl; import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMData; import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.AbstractContainerVMNode; +import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.ILaunchVMConstants; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider; import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +import org.eclipse.cdt.dsf.ui.viewmodel.properties.IPropertiesUpdate; import org.eclipse.cdt.examples.dsf.pda.service.PDACommandControl; +import org.eclipse.cdt.examples.dsf.pda.service.PDAThreadDMContext; import org.eclipse.cdt.examples.dsf.pda.service.PDAVirtualMachineDMContext; +import org.eclipse.cdt.examples.dsf.pda.ui.PDAUIPlugin; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider; @@ -70,70 +77,22 @@ public class PDAVirtualMachineVMNode extends AbstractContainerVMNode update.done(); } - @Override - protected void updateLabelInSessionThread(final ILabelUpdate update) { - // Get a reference to the run control service. - final IRunControl runControl = getServicesTracker().getService(IRunControl.class); - if (runControl == null) { - handleFailedUpdate(update); - return; + protected void updatePropertiesInSessionThread(IPropertiesUpdate[] updates) { + for (int i = 0; i < updates.length; i++) { + // Find the PDA program context. + final PDAVirtualMachineDMContext dmc = + findDmcInPath(updates[i].getViewerInput(), updates[i].getElementPath(), PDAVirtualMachineDMContext.class); + if (dmc != null) { + updates[i].setProperty(PROP_NAME, "PDA"); + updates[i].setProperty(ILaunchVMConstants.PROP_ID, dmc.getProgram()); + } else { + updates[i].setStatus(new Status(IStatus.ERROR, PDAUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$ + } } - - // Find the PDA program context. - final PDAVirtualMachineDMContext programCtx = - findDmcInPath(update.getViewerInput(), update.getElementPath(), PDAVirtualMachineDMContext.class); - - // Call service to get current program state - final boolean isSuspended = runControl.isSuspended(programCtx); - - // Set the program icon based on the running state of the program. - String imageKey = null; - if (isSuspended) { - imageKey = IDebugUIConstants.IMG_OBJS_THREAD_SUSPENDED; - } else { - imageKey = IDebugUIConstants.IMG_OBJS_THREAD_RUNNING; - } - update.setImageDescriptor(DebugUITools.getImageDescriptor(imageKey), 0); - - // Retrieve the last state change reason - getDMVMProvider().getModelData( - this, update, runControl, programCtx, - new ViewerDataRequestMonitor(ImmediateExecutor.getInstance(), update) - { - @Override - public void handleCompleted(){ - // If the request failed, fail the udpate. - if (!isSuccess()) { - handleFailedUpdate(update); - return; - } - - // Compose the thread name string. - final StringBuilder builder = new StringBuilder(); - - builder.append("PDA ["); - builder.append(programCtx.getProgram()); - builder.append("]"); - - if(isSuspended) { - builder.append(" (Suspended"); - } else { - builder.append(" (Running"); - } - // Reason will be null before ContainerSuspendEvent is fired - if(getData().getStateChangeReason() != null) { - builder.append(" : "); - builder.append(getData().getStateChangeReason()); - } - builder.append(")"); - update.setLabel(builder.toString(), 0); - update.done(); - } - }, - getExecutor()); + super.updatePropertiesInSessionThread(updates); } - + private String produceProgramElementName( String viewName , PDAVirtualMachineDMContext execCtx ) { return "PDA." + execCtx.getProgram(); //$NON-NLS-1$ }