Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPawel Piech2009-01-08 21:08:05 +0000
committerPawel Piech2009-01-08 21:08:05 +0000
commit5b471873662a87a77cfd854c98fca9c9948aa878 (patch)
tree3da8dcf3820bf3c2d4ebd17e4e8f3043e9773676 /dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui
parent47093064424981f85335cfdaf25368c54cd840f8 (diff)
parentc1e6da229b8ffcea160498f034bfa6bc8ff6f230 (diff)
downloadorg.eclipse.cdt-5b471873662a87a77cfd854c98fca9c9948aa878.tar.gz
org.eclipse.cdt-5b471873662a87a77cfd854c98fca9c9948aa878.tar.xz
org.eclipse.cdt-5b471873662a87a77cfd854c98fca9c9948aa878.zip
Migrated DSF and DSF-GDB to the CDT project.
Diffstat (limited to 'dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui')
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/DsfDebugUITools.java27
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/IDsfDebugUIConstants.java113
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/PreferenceInitializer.java65
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfCommandRunnable.java113
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfResumeCommand.java76
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfStepIntoCommand.java88
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfStepOverCommand.java88
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfStepReturnCommand.java75
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfSteppingModeTarget.java80
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfSuspendCommand.java75
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/contexts/DsfSuspendTrigger.java121
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/memory/RefreshAction.java77
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/memory/SelectUpdatePolicyAction.java153
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/sourcelookup/DsfSourceDisplayAdapter.java855
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/sourcelookup/InstructionPointerImageProvider.java45
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/sourcelookup/InstructionPointerManager.java264
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/sourcelookup/SourceLookupResult.java129
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/AbstractDebugVMAdapter.java76
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/IDebugVMConstants.java31
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/SteppingController.java572
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/actions/AbstractVMProviderActionDelegate.java107
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/actions/DefaultRefreshAllTarget.java51
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/actions/IRefreshAllTarget.java31
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/actions/VMHandlerUtils.java137
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/AbstractExpressionVMNode.java178
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionColumnPresentation.java74
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionManagerVMNode.java307
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProvider.java379
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProviderContentStragegy.java87
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProviderModelProxyStrategy.java179
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionsBreakpointHitUpdatePolicy.java29
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionsChangedEvent.java38
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionsChangedUpdateTester.java68
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionsManualUpdatePolicy.java29
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/IExpressionUpdate.java34
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/IExpressionVMNode.java63
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/InvalidExpressionVMContext.java88
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/MessagesForExpressionVM.java37
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/VMExpressionUpdate.java79
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/WatchExpressionCellModifier.java80
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/WatchExpressionDelegate.java33
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/messages.properties21
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/AbstractContainerVMNode.java191
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/AbstractLaunchVMProvider.java294
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/AbstractThreadVMNode.java328
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/DefaultDsfModelSelectionPolicyFactory.java44
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/DefaultDsfSelectionPolicy.java154
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/DelayedStackRefreshUpdatePolicy.java175
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/ExpandStackEvent.java27
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/FullStackRefreshEvent.java28
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/LaunchRootVMNode.java130
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/LaunchVMUpdateMessages.java29
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/StackFramesVMNode.java724
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/StandardProcessVMNode.java223
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/actions/ExpandStackAction.java87
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/ModulesVMNode.java180
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/ModulesVMProvider.java75
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/detail/ModuleDetailPane.java525
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/detail/ModuleDetailPaneFactory.java50
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/detail/ModulesAbstractDetailPane.java172
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/detail/ModulesMessages.java37
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/detail/ModulesMessages.properties25
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/FormattedValuePreferenceStore.java41
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/IFormattedValuePreferenceStore.java28
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/IFormattedValueVMContext.java20
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/MessagesForNumberFormat.java35
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/NumberFormatsContribution.java126
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/NumberFormatsPropertyTester.java88
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/messages.properties19
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/MessagesForRegisterVM.java32
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterBitFieldCellModifier.java199
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterBitFieldVMNode.java901
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterCellModifier.java158
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterColumnPresentation.java73
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterGroupVMNode.java586
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterRootDMVMNode.java51
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMNode.java960
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMProvider.java271
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/SyncRegisterDataAccess.java813
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/messages.properties15
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/BreakpointHitUpdatePolicy.java45
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/MessagesForVMUpdate.java27
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/messages.properties12
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/MessagesForVariablesVM.java34
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/SyncVariableDataAccess.java543
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableCellModifier.java138
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableColumnPresentation.java71
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMNode.java995
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java140
-rw-r--r--dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/messages.properties16
90 files changed, 15187 insertions, 0 deletions
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/DsfDebugUITools.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/DsfDebugUITools.java
new file mode 100644
index 00000000000..8ff52b7741d
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/DsfDebugUITools.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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;
+
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.jface.preference.IPreferenceStore;
+
+/**
+ * @since 1.1
+ */
+public class DsfDebugUITools {
+
+ public static IPreferenceStore getPreferenceStore()
+ {
+ return DsfUIPlugin.getDefault().getPreferenceStore();
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/IDsfDebugUIConstants.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/IDsfDebugUIConstants.java
new file mode 100644
index 00000000000..5e51d671a21
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/IDsfDebugUIConstants.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * 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, Inc. - initial implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.ui;
+
+import org.eclipse.debug.ui.IDebugUIConstants;
+
+/**
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IDsfDebugUIConstants {
+
+ /**
+ * Debug UI plug-in identifier (value <code>"org.eclipse.cdt.dsf.debug.ui"</code>).
+ */
+ public static final String PLUGIN_ID = "org.eclipse.cdt.dsf.debug.ui"; //$NON-NLS-1$;
+
+ /** Loaded shared library symbols image identifier. */
+ public static final String IMG_OBJS_SHARED_LIBRARY_SYMBOLS_LOADED = "icons/library_syms_obj.gif"; //$NON-NLS-1$
+
+ /** Unloaded Shared library symbols image identifier. */
+ public static final String IMG_OBJS_SHARED_LIBRARY_SYMBOLS_UNLOADED = "icons/library_obj.gif"; //$NON-NLS-1$
+
+ /*
+ * The orientation of the detail view in the VariablesView
+ * Note: these constants should be removed from API. See bug 246005.
+ */
+ public static final String VARIABLES_DETAIL_PANE_ORIENTATION = "Variables.detail.orientation"; //$NON-NLS-1$
+ public static final String EXPRESSIONS_DETAIL_PANE_ORIENTATION = "Expressions.detail.orientation"; //$NON-NLS-1$
+ public static final String REGISTERS_DETAIL_PANE_ORIENTATION = "Registers.detail.orientation"; //$NON-NLS-1$
+ public static final String MODULES_DETAIL_PANE_ORIENTATION = "Modules.detail.orientation"; //$NON-NLS-1$
+ public static final String VARIABLES_DETAIL_PANE_RIGHT = "Variables.detail.orientation.right"; //$NON-NLS-1$
+ public static final String VARIABLES_DETAIL_PANE_UNDERNEATH = "Variables.detail.orientation.underneath"; //$NON-NLS-1$
+ public static final String VARIABLES_DETAIL_PANE_HIDDEN = "Variables.detail.orientation.hidden"; //$NON-NLS-1$
+
+ /**
+ * Boolean preference controlling whether the text in the detail panes is
+ * wrapped. When <code>true</code> the text in the detail panes will be
+ * wrapped in new variable view.
+ */
+ public static final String PREF_DETAIL_PANE_WORD_WRAP = PLUGIN_ID + ".detail_pane_word_wrap"; //$NON-NLS-1$
+
+ /**
+ * Maximum number of characters to display in the details area of the variables
+ * view, or 0 if unlimited.
+ */
+ public static final String PREF_MAX_DETAIL_LENGTH = PLUGIN_ID + ".max_detail_length"; //$NON-NLS-1$
+
+ /**
+ * The name of the font to use for detail panes. This font is managed via
+ * the workbench font preference page.
+ */
+ public static final String DETAIL_PANE_FONT= PLUGIN_ID + "DetailPaneFont"; //$NON-NLS-1$
+
+ /**
+ * Integer preference to control the maximum amount of stack frames to
+ * retrieve from the backend. Default value is <code>10</code>.
+ * @see {@link #PREF_STACK_FRAME_LIMIT_ENABLE}
+ *
+ * @since 1.1
+ */
+ public static final String PREF_STACK_FRAME_LIMIT = "stackFrameLimit"; //$NON-NLS-1$
+
+ /**
+ * Boolean preference whether to apply the stack frame limit preference. Default is <code>true</code>.
+ * @see {@link #PREF_STACK_FRAME_LIMIT}
+ *
+ * @since 1.1
+ */
+ public static final String PREF_STACK_FRAME_LIMIT_ENABLE = "stackFrameLimitEnable"; //$NON-NLS-1$
+
+ /**
+ * Boolean preference whether to keep stepping speed in sync with UI updates. Default is <code>false</code>.
+ *
+ * @since 1.1
+ */
+ public static final String PREF_WAIT_FOR_VIEW_UPDATE_AFTER_STEP_ENABLE = "delaySteppingForViewUpdatesEnable"; //$NON-NLS-1$
+
+ /**
+ * Integer preference to enforce a minimum time interval between steps. Default is <code>100</code>.
+ *
+ * @since 1.1
+ */
+ public static final String PREF_MIN_STEP_INTERVAL= "minStepInterval"; //$NON-NLS-1$
+
+ /**
+ * Help prefixes.
+ */
+ public static final String PREFIX = IDebugUIConstants.PLUGIN_ID + "."; //$NON-NLS-1$
+
+ public static final String DETAIL_PANE = PREFIX + "detail_pane_context"; //$NON-NLS-1$
+ public static final String DETAIL_PANE_ASSIGN_VALUE_ACTION = PREFIX + "detail_pane_assign_value_action_context"; //$NON-NLS-1$
+ public static final String DETAIL_PANE_CONTENT_ASSIST_ACTION = PREFIX + "detail_pane_content_assist_action_context"; //$NON-NLS-1$
+ public static final String DETAIL_PANE_CUT_ACTION = PREFIX + "detail_pane_cut_action_context"; //$NON-NLS-1$
+ public static final String DETAIL_PANE_COPY_ACTION = PREFIX + "detail_pane_copy_action_context"; //$NON-NLS-1$
+ public static final String DETAIL_PANE_PASTE_ACTION = PREFIX + "detail_pane_paste_action_context"; //$NON-NLS-1$
+ public static final String DETAIL_PANE_SELECT_ALL_ACTION = PREFIX + "detail_pane_select_all_action_context"; //$NON-NLS-1$
+ public static final String DETAIL_PANE_FIND_REPLACE_ACTION = PREFIX + "detail_pane_find_replace_action_context"; //$NON-NLS-1$
+ public static final String DETAIL_PANE_WORD_WRAP_ACTION = PREFIX + "detail_pane_word_wrap_action_context"; //$NON-NLS-1$
+ public static final String DETAIL_PANE_MAX_LENGTH_ACTION = PREFIX + "detail_pane_max_length_action_context"; //$NON-NLS-1$
+
+ /**
+ * @since 1.1
+ */
+ public static final String PREFERENCE_PAGE= PREFIX + "preference_page_context"; //$NON-NLS-1$
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/PreferenceInitializer.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/PreferenceInitializer.java
new file mode 100644
index 00000000000..6c111eee564
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/PreferenceInitializer.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.ui;
+
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceConverter;
+import org.eclipse.swt.graphics.RGB;
+
+// Note: this class should be removed from public API. See bug 246004
+public class PreferenceInitializer extends AbstractPreferenceInitializer {
+
+ public PreferenceInitializer() {
+ super();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer#initializeDefaultPreferences()
+ */
+ @Override
+ public void initializeDefaultPreferences() {
+
+ IPreferenceStore prefs = DsfUIPlugin.getDefault().getPreferenceStore();
+
+ /*
+ * Common to all views.
+ */
+ PreferenceConverter.setDefault(prefs, IDebugUIConstants.PREF_CHANGED_DEBUG_ELEMENT_COLOR, new RGB(255, 0, 0));
+ prefs.setDefault(IDsfDebugUIConstants.PREF_DETAIL_PANE_WORD_WRAP, false);
+ prefs.setDefault(IDsfDebugUIConstants.PREF_MAX_DETAIL_LENGTH, 10000);
+
+ /*
+ * Variables view
+ */
+ prefs.setDefault(IDsfDebugUIConstants.VARIABLES_DETAIL_PANE_ORIENTATION, IDsfDebugUIConstants.VARIABLES_DETAIL_PANE_UNDERNEATH);
+
+ /*
+ * Registers View
+ */
+ prefs.setDefault(IDsfDebugUIConstants.REGISTERS_DETAIL_PANE_ORIENTATION, IDsfDebugUIConstants.VARIABLES_DETAIL_PANE_UNDERNEATH);
+
+ /*
+ * Expressions View
+ */
+ prefs.setDefault(IDsfDebugUIConstants.EXPRESSIONS_DETAIL_PANE_ORIENTATION, IDsfDebugUIConstants.VARIABLES_DETAIL_PANE_UNDERNEATH);
+
+ /*
+ * Debug View
+ */
+ prefs.setDefault(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT, 10);
+ prefs.setDefault(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT_ENABLE, true);
+ prefs.setDefault(IDsfDebugUIConstants.PREF_WAIT_FOR_VIEW_UPDATE_AFTER_STEP_ENABLE, false);
+ prefs.setDefault(IDsfDebugUIConstants.PREF_MIN_STEP_INTERVAL, 100);
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfCommandRunnable.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfCommandRunnable.java
new file mode 100644
index 00000000000..f4bc09280fa
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfCommandRunnable.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * 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.actions;
+
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.concurrent.Immutable;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.debug.service.IProcesses;
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+import org.eclipse.cdt.dsf.debug.service.IStepQueueManager;
+import org.eclipse.cdt.dsf.debug.service.StepQueueManager;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.SteppingController;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.commands.IDebugCommandRequest;
+
+@Immutable
+public abstract class DsfCommandRunnable extends DsfRunnable {
+ private final IExecutionDMContext fContext;
+ private final DsfServicesTracker fTracker;
+ private final IDebugCommandRequest fRequest;
+
+ public IExecutionDMContext getContext() { return fContext; }
+ public IRunControl getRunControl() {
+ return fTracker.getService(IRunControl.class);
+ }
+ /**
+ * @deprecated Use {@link #getStepQueueManager()} instead.
+ */
+ @Deprecated
+ public StepQueueManager getStepQueueMgr() {
+ return fTracker.getService(StepQueueManager.class);
+ }
+
+ /**
+ * @since 1.1
+ */
+ public IStepQueueManager getStepQueueManager() {
+ // for backwards compatibility
+ IStepQueueManager mgr= getStepQueueMgr();
+ if (mgr != null) {
+ return mgr;
+ }
+ return getSteppingController();
+ }
+
+ /**
+ * @since 1.1
+ */
+ public SteppingController getSteppingController() {
+ if (fContext != null) {
+ return (SteppingController) fContext.getAdapter(SteppingController.class);
+ }
+ return null;
+ }
+
+ /**
+ * @since 1.1
+ */
+ public IProcesses getProcessService() {
+ return fTracker.getService(IProcesses.class);
+ }
+
+ public DsfCommandRunnable(DsfServicesTracker servicesTracker, Object element, IDebugCommandRequest request) {
+ fTracker = servicesTracker;
+ if (element instanceof IDMVMContext) {
+ IDMVMContext vmc = (IDMVMContext)element;
+ fContext = DMContexts.getAncestorOfType(vmc.getDMContext(), IExecutionDMContext.class);
+ } else {
+ fContext = null;
+ }
+
+ fRequest = request;
+ }
+
+ public final void run() {
+ if (fRequest.isCanceled()) {
+ fRequest.done();
+ return;
+ }
+ if (getContext() == null) {
+ fRequest.setStatus(makeError("Selected object does not support run control.", null)); //$NON-NLS-1$
+ } else if (getRunControl() == null || getStepQueueManager() == null) {
+ fRequest.setStatus(makeError("Run Control not available", null)); //$NON-NLS-1$
+ } else {
+ doExecute();
+ }
+ fRequest.done();
+ }
+
+ /**
+ * Method to perform the actual work. It should not call monitor.done(), because
+ * it will be called in the super-class.
+ */
+ protected abstract void doExecute();
+
+ protected IStatus makeError(String message, Throwable e) {
+ return new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, -1, message, e);
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfResumeCommand.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfResumeCommand.java
new file mode 100644
index 00000000000..d2d7cb77d1c
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfResumeCommand.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * 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.actions;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
+import org.eclipse.cdt.dsf.concurrent.Immutable;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.debug.core.commands.IDebugCommandRequest;
+import org.eclipse.debug.core.commands.IEnabledStateRequest;
+import org.eclipse.debug.core.commands.IResumeHandler;
+
+@Immutable
+public class DsfResumeCommand implements IResumeHandler {
+
+ private final DsfExecutor fExecutor;
+ private final DsfServicesTracker fTracker;
+
+ public DsfResumeCommand(DsfSession session) {
+ fExecutor = session.getExecutor();
+ fTracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), session.getId());
+ }
+
+ public void dispose() {
+ fTracker.dispose();
+ }
+
+ public void canExecute(final IEnabledStateRequest request) {
+ if (request.getElements().length != 1) {
+ request.setEnabled(false);
+ request.done();
+ return;
+ }
+
+ fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
+ @Override public void doExecute() {
+ getRunControl().canResume(
+ getContext(),
+ new DataRequestMonitor<Boolean>(ImmediateExecutor.getInstance(), null) {
+ @Override
+ protected void handleCompleted() {
+ request.setEnabled(isSuccess() && getData());
+ request.done();
+ }
+ });
+ }
+ });
+ }
+
+ public boolean execute(final IDebugCommandRequest request) {
+ if (request.getElements().length != 1) {
+ request.done();
+ return false;
+ }
+
+ fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
+ @Override public void doExecute() {
+ getRunControl().resume(getContext(), new RequestMonitor(fExecutor, null));
+ }
+ });
+ return false;
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfStepIntoCommand.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfStepIntoCommand.java
new file mode 100644
index 00000000000..94375732dc8
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfStepIntoCommand.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * 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.actions;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
+import org.eclipse.cdt.dsf.concurrent.Immutable;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.StepType;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.debug.core.commands.IDebugCommandRequest;
+import org.eclipse.debug.core.commands.IEnabledStateRequest;
+import org.eclipse.debug.core.commands.IStepIntoHandler;
+
+@Immutable
+public class DsfStepIntoCommand implements IStepIntoHandler {
+
+ private final DsfExecutor fExecutor;
+ private final DsfServicesTracker fTracker;
+ private final DsfSteppingModeTarget fSteppingMode;
+
+ public DsfStepIntoCommand(DsfSession session, DsfSteppingModeTarget steppingMode) {
+ fExecutor = session.getExecutor();
+ fTracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), session.getId());
+ fSteppingMode = steppingMode;
+ }
+
+ public void dispose() {
+ fTracker.dispose();
+ }
+
+ public void canExecute(final IEnabledStateRequest request) {
+ if (request.getElements().length != 1) {
+ request.setEnabled(false);
+ request.done();
+ return;
+ }
+
+ final StepType stepType= getStepType();
+ fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
+ @Override public void doExecute() {
+ getStepQueueManager().canEnqueueStep(
+ getContext(), stepType,
+ new DataRequestMonitor<Boolean>(ImmediateExecutor.getInstance(), null) {
+ @Override
+ protected void handleCompleted() {
+ request.setEnabled(isSuccess() && getData());
+ request.done();
+ }
+ });
+ }
+ });
+ }
+
+ public boolean execute(final IDebugCommandRequest request) {
+ if (request.getElements().length != 1) {
+ request.done();
+ return false;
+ }
+
+ final StepType stepType= getStepType();
+ fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
+ @Override public void doExecute() {
+ getStepQueueManager().enqueueStep(getContext(), stepType);
+ }
+ });
+ return true;
+ }
+
+
+ /**
+ * @return the currently active step type
+ */
+ protected final StepType getStepType() {
+ boolean instructionSteppingEnabled= fSteppingMode != null && fSteppingMode.isInstructionSteppingEnabled();
+ return instructionSteppingEnabled ? StepType.INSTRUCTION_STEP_INTO : StepType.STEP_INTO;
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfStepOverCommand.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfStepOverCommand.java
new file mode 100644
index 00000000000..00d8c35e7c0
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfStepOverCommand.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * 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.actions;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
+import org.eclipse.cdt.dsf.concurrent.Immutable;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.StepType;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.debug.core.commands.IDebugCommandRequest;
+import org.eclipse.debug.core.commands.IEnabledStateRequest;
+import org.eclipse.debug.core.commands.IStepOverHandler;
+
+@Immutable
+public class DsfStepOverCommand implements IStepOverHandler {
+
+ private final DsfExecutor fExecutor;
+ private final DsfServicesTracker fTracker;
+ private final DsfSteppingModeTarget fSteppingMode;
+
+ public DsfStepOverCommand(DsfSession session, DsfSteppingModeTarget steppingMode) {
+ fExecutor = session.getExecutor();
+ fTracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), session.getId());
+ fSteppingMode = steppingMode;
+ }
+
+ public void dispose() {
+ fTracker.dispose();
+ }
+
+ public void canExecute(final IEnabledStateRequest request) {
+ if (request.getElements().length != 1) {
+ request.setEnabled(false);
+ request.done();
+ return;
+ }
+
+ fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
+ final StepType stepType= getStepType();
+ @Override public void doExecute() {
+ getStepQueueManager().canEnqueueStep(
+ getContext(), stepType,
+ new DataRequestMonitor<Boolean>(ImmediateExecutor.getInstance(), null) {
+ @Override
+ protected void handleCompleted() {
+ request.setEnabled(isSuccess() && getData());
+ request.done();
+ }
+ });
+ }
+ });
+ }
+
+ public boolean execute(final IDebugCommandRequest request) {
+ if (request.getElements().length != 1) {
+ request.done();
+ return false;
+ }
+
+ final StepType stepType= getStepType();
+ fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
+ @Override public void doExecute() {
+ getStepQueueManager().enqueueStep(getContext(), stepType);
+ }
+ });
+ return true;
+ }
+
+ /**
+ * @return the currently active step type
+ */
+ protected final StepType getStepType() {
+ boolean instructionSteppingEnabled= fSteppingMode != null && fSteppingMode.isInstructionSteppingEnabled();
+ return instructionSteppingEnabled ? StepType.INSTRUCTION_STEP_OVER : StepType.STEP_OVER;
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfStepReturnCommand.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfStepReturnCommand.java
new file mode 100644
index 00000000000..7127fe2f0cb
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfStepReturnCommand.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * 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.actions;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
+import org.eclipse.cdt.dsf.concurrent.Immutable;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.StepType;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.debug.core.commands.IDebugCommandRequest;
+import org.eclipse.debug.core.commands.IEnabledStateRequest;
+import org.eclipse.debug.core.commands.IStepReturnHandler;
+
+@Immutable
+public class DsfStepReturnCommand implements IStepReturnHandler {
+
+ private final DsfExecutor fExecutor;
+ private final DsfServicesTracker fTracker;
+
+ public DsfStepReturnCommand(DsfSession session) {
+ fExecutor = session.getExecutor();
+ fTracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), session.getId());
+ }
+
+ public void dispose() {
+ fTracker.dispose();
+ }
+
+ public void canExecute(final IEnabledStateRequest request) {
+ if (request.getElements().length != 1) {
+ request.setEnabled(false);
+ request.done();
+ return;
+ }
+
+ fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
+ @Override public void doExecute() {
+ getStepQueueManager().canEnqueueStep(
+ getContext(), StepType.STEP_RETURN,
+ new DataRequestMonitor<Boolean>(ImmediateExecutor.getInstance(), null) {
+ @Override
+ protected void handleCompleted() {
+ request.setEnabled(isSuccess() && getData());
+ request.done();
+ }
+ });
+ }
+ });
+ }
+
+ public boolean execute(final IDebugCommandRequest request) {
+ if (request.getElements().length != 1) {
+ request.done();
+ return false;
+ }
+
+ fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
+ @Override public void doExecute() {
+ getStepQueueManager().enqueueStep(getContext(), StepType.STEP_RETURN);
+ }
+ });
+ return true;
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfSteppingModeTarget.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfSteppingModeTarget.java
new file mode 100644
index 00000000000..aeb4cf64a62
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfSteppingModeTarget.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Wind River Systems, Inc. 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.actions;
+
+import org.eclipse.cdt.debug.core.model.ISteppingModeTarget;
+import org.eclipse.cdt.debug.core.model.ITargetProperties;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.core.runtime.Preferences;
+import org.eclipse.core.runtime.Preferences.IPropertyChangeListener;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ */
+public class DsfSteppingModeTarget implements ISteppingModeTarget, ITargetProperties {
+
+ private static final String ID_DISASSEMBLY_VIEW= "org.eclipse.cdt.dsf.debug.ui.disassembly.view"; //$NON-NLS-1$
+
+ private final Preferences fPreferences;
+
+ public DsfSteppingModeTarget() {
+ fPreferences= new Preferences();
+ fPreferences.setDefault(PREF_INSTRUCTION_STEPPING_MODE, false);
+ }
+
+ /*
+ * @see org.eclipse.cdt.debug.core.model.ISteppingModeTarget#enableInstructionStepping(boolean)
+ */
+ public void enableInstructionStepping(boolean enabled) {
+ fPreferences.setValue(PREF_INSTRUCTION_STEPPING_MODE, enabled);
+ if (enabled) {
+ try {
+ final IWorkbenchWindow activeWorkbenchWindow= PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (activeWorkbenchWindow != null && activeWorkbenchWindow.getActivePage() != null) {
+ activeWorkbenchWindow.getActivePage().showView(ID_DISASSEMBLY_VIEW);
+ }
+ } catch (PartInitException exc) {
+ DsfUIPlugin.log(exc);
+ }
+ }
+ }
+
+ /*
+ * @see org.eclipse.cdt.debug.core.model.ISteppingModeTarget#isInstructionSteppingEnabled()
+ */
+ public boolean isInstructionSteppingEnabled() {
+ return fPreferences.getBoolean(PREF_INSTRUCTION_STEPPING_MODE);
+ }
+
+ /*
+ * @see org.eclipse.cdt.debug.core.model.ISteppingModeTarget#supportsInstructionStepping()
+ */
+ public boolean supportsInstructionStepping() {
+ return true;
+ }
+
+ /*
+ * @see org.eclipse.cdt.debug.core.model.ITargetProperties#addPropertyChangeListener(org.eclipse.core.runtime.Preferences.IPropertyChangeListener)
+ */
+ public void addPropertyChangeListener(IPropertyChangeListener listener) {
+ fPreferences.addPropertyChangeListener(listener);
+ }
+
+ /*
+ * @see org.eclipse.cdt.debug.core.model.ITargetProperties#removePropertyChangeListener(org.eclipse.core.runtime.Preferences.IPropertyChangeListener)
+ */
+ public void removePropertyChangeListener(IPropertyChangeListener listener) {
+ fPreferences.removePropertyChangeListener(listener);
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfSuspendCommand.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfSuspendCommand.java
new file mode 100644
index 00000000000..cee40fccf08
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/actions/DsfSuspendCommand.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * 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.actions;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
+import org.eclipse.cdt.dsf.concurrent.Immutable;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.debug.core.commands.IDebugCommandRequest;
+import org.eclipse.debug.core.commands.IEnabledStateRequest;
+import org.eclipse.debug.core.commands.ISuspendHandler;
+
+@Immutable
+public class DsfSuspendCommand implements ISuspendHandler {
+ private final DsfExecutor fExecutor;
+ private final DsfServicesTracker fTracker;
+
+ public DsfSuspendCommand(DsfSession session) {
+ fExecutor = session.getExecutor();
+ fTracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), session.getId());
+ }
+
+ public void dispose() {
+ fTracker.dispose();
+ }
+
+ public void canExecute(final IEnabledStateRequest request) {
+ if (request.getElements().length != 1) {
+ request.setEnabled(false);
+ request.done();
+ return;
+ }
+
+ fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
+ @Override public void doExecute() {
+ getRunControl().canSuspend(
+ getContext(),
+ new DataRequestMonitor<Boolean>(ImmediateExecutor.getInstance(), null) {
+ @Override
+ protected void handleCompleted() {
+ request.setEnabled(isSuccess() && getData());
+ request.done();
+ }
+ });
+ }
+ });
+ }
+
+ public boolean execute(final IDebugCommandRequest request) {
+ if (request.getElements().length != 1) {
+ request.done();
+ return false;
+ }
+
+ fExecutor.submit(new DsfCommandRunnable(fTracker, request.getElements()[0], request) {
+ @Override public void doExecute() {
+ getRunControl().suspend(getContext(), new RequestMonitor(fExecutor, null));
+ }
+ });
+ return false;
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/contexts/DsfSuspendTrigger.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/contexts/DsfSuspendTrigger.java
new file mode 100644
index 00000000000..c8ed34a9fa1
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/contexts/DsfSuspendTrigger.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * 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.contexts;
+
+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.ThreadSafe;
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.ListenerList;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.SafeRunner;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.ui.contexts.ISuspendTrigger;
+import org.eclipse.debug.ui.contexts.ISuspendTriggerListener;
+
+/**
+ * DSF implementation of the ISuspendTrigger interface. The suspend trigger
+ * is used by the IDE to trigger activation of the debug perspective when
+ * the debugger suspends.
+ *
+ * @see ISuspendTrigger
+ */
+@ConfinedToDsfExecutor("fSession.getExecutor()")
+public class DsfSuspendTrigger implements ISuspendTrigger {
+
+ private final DsfSession fSession;
+ private final ILaunch fLaunch;
+ private boolean fDisposed = false;
+ private boolean fEventListenerRegisterd = false;
+
+ @ThreadSafe
+ private final ListenerList fListeners = new ListenerList();
+
+ @ThreadSafe
+ public DsfSuspendTrigger(DsfSession session, ILaunch launch) {
+ fSession = session;
+ fLaunch = launch;
+ try {
+ fSession.getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ if (!fDisposed) {
+ fSession.addServiceEventListener(DsfSuspendTrigger.this, null);
+ fEventListenerRegisterd = true;
+ }
+ }
+ });
+ } catch(RejectedExecutionException e) {}
+ }
+
+ @ThreadSafe
+ public void addSuspendTriggerListener(ISuspendTriggerListener listener) {
+ if (fListeners != null) {
+ fListeners.add(listener);
+ }
+ }
+
+ @ThreadSafe
+ public void removeSuspendTriggerListener(ISuspendTriggerListener listener) {
+ if (fListeners != null) {
+ fListeners.remove(listener);
+ }
+ }
+
+ public void dispose() {
+ if (fEventListenerRegisterd) {
+ fSession.removeServiceEventListener(this);
+ }
+ fDisposed = true;
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(IRunControl.ISuspendedDMEvent e) {
+ final Object[] listeners = fListeners.getListeners();
+ if (listeners.length != 0) {
+ new Job("DSF Suspend Trigger Notify") { //$NON-NLS-1$
+ {
+ setSystem(true);
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ final MultiStatus status = new MultiStatus(DsfUIPlugin.PLUGIN_ID, 0, "DSF Suspend Trigger Notify Job Status", null); //$NON-NLS-1$
+ for (int i = 0; i < listeners.length; i++) {
+ final ISuspendTriggerListener listener = (ISuspendTriggerListener) listeners[i];
+ SafeRunner.run(new ISafeRunnable() {
+ public void run() throws Exception {
+ listener.suspended(fLaunch, null);
+ }
+
+ public void handleException(Throwable exception) {
+ status.add(new Status(
+ IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, "Exception while calling suspend trigger listeners", exception)); //$NON-NLS-1$
+ }
+
+ });
+ }
+ return status;
+ }
+ }.schedule();
+ }
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/memory/RefreshAction.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/memory/RefreshAction.java
new file mode 100644
index 00000000000..bb86ca6d561
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/memory/RefreshAction.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 - Ted Williams - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.dsf.debug.ui.memory;
+
+import org.eclipse.cdt.dsf.debug.internal.provisional.model.IMemoryBlockUpdatePolicyProvider;
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.IDebugEventSetListener;
+import org.eclipse.debug.core.model.IMemoryBlock;
+import org.eclipse.debug.internal.ui.views.memory.MemoryView;
+import org.eclipse.debug.ui.memory.IMemoryRendering;
+import org.eclipse.debug.ui.memory.IMemoryRenderingContainer;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IViewActionDelegate;
+import org.eclipse.ui.IViewPart;
+
+@SuppressWarnings("restriction")
+public class RefreshAction implements IViewActionDelegate {
+
+ private IMemoryBlock fMemoryBlock = null;
+
+ private MemoryView fView;
+
+ public void init(IViewPart view) {
+ fView = (MemoryView) view;
+ }
+
+ public void run(IAction action) {
+
+ if(fMemoryBlock instanceof IMemoryBlockUpdatePolicyProvider)
+ {
+ ((IMemoryBlockUpdatePolicyProvider) fMemoryBlock).clearCache();
+ IMemoryRenderingContainer containers[] = fView.getMemoryRenderingContainers();
+ for(int i = 0; i < containers.length; i++)
+ {
+ IMemoryRendering renderings[] = containers[i].getRenderings();
+ for(int j = 0; j < renderings.length; j++)
+ {
+ if (renderings[j].getControl() instanceof IDebugEventSetListener)
+ {
+ ((IDebugEventSetListener) renderings[j].getControl()).handleDebugEvents(
+ new DebugEvent[] { new DebugEvent(fMemoryBlock, DebugEvent.CHANGE) } );
+ }
+ }
+ }
+ }
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ fMemoryBlock = null;
+ action.setEnabled(false);
+ if(selection instanceof IStructuredSelection)
+ {
+ if(((IStructuredSelection) selection).getFirstElement() instanceof IMemoryBlock)
+ {
+ fMemoryBlock = (IMemoryBlock) ((IStructuredSelection) selection).getFirstElement();
+ action.setEnabled(true);
+ }
+ else if(((IStructuredSelection) selection).getFirstElement() instanceof IMemoryRendering)
+ {
+ fMemoryBlock = ((IMemoryRendering) ((IStructuredSelection) selection).getFirstElement()).getMemoryBlock();
+ action.setEnabled(true);
+ }
+ }
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/memory/SelectUpdatePolicyAction.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/memory/SelectUpdatePolicyAction.java
new file mode 100644
index 00000000000..026146eb7ba
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/memory/SelectUpdatePolicyAction.java
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * 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 - Ted Williams - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.dsf.debug.ui.memory;
+
+import org.eclipse.cdt.dsf.debug.internal.provisional.model.IMemoryBlockUpdatePolicyProvider;
+import org.eclipse.debug.core.model.IMemoryBlock;
+import org.eclipse.debug.ui.contexts.DebugContextEvent;
+import org.eclipse.debug.ui.contexts.IDebugContextListener;
+import org.eclipse.debug.ui.memory.IMemoryRendering;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ActionContributionItem;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuCreator;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.events.MenuAdapter;
+import org.eclipse.swt.events.MenuEvent;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.ui.IActionDelegate2;
+import org.eclipse.ui.IViewActionDelegate;
+import org.eclipse.ui.IViewPart;
+
+/**
+ *
+ */
+public class SelectUpdatePolicyAction implements IMenuCreator, IViewActionDelegate, IDebugContextListener, IActionDelegate2 {
+
+ private IAction fAction = null;
+ private IMemoryBlock fMemoryBlock = null;
+
+ public void dispose() {
+ // do nothing
+
+ }
+
+ public void runWithEvent(IAction action, Event event) {
+ // do nothing
+ }
+
+ class SelectPolicy extends Action {
+
+ String fID;
+ String fDescription;
+
+ public SelectPolicy(String id, String description) {
+ fID = id;
+ fDescription = description;
+ }
+
+ @Override
+ public String getText() {
+ return fDescription;
+ }
+
+ @Override
+ public void run() {
+ ((IMemoryBlockUpdatePolicyProvider) fMemoryBlock).setUpdatePolicy(fID);
+ }
+
+ }
+
+
+ public Menu getMenu(Control parent) {
+ // Never called
+ return null;
+ }
+
+ protected IAction getAction() { return fAction; }
+
+ public void init(IViewPart view) {
+ }
+
+ public void init(IAction action) {
+ fAction = action;
+ action.setMenuCreator(this);
+ }
+
+ public void run(IAction action) {
+ // Do nothing, this is a pull-down menu
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ fMemoryBlock = null;
+ action.setEnabled(false);
+ if(selection instanceof IStructuredSelection)
+ {
+ if(((IStructuredSelection) selection).getFirstElement() instanceof IMemoryBlock)
+ {
+ fMemoryBlock = (IMemoryBlock) ((IStructuredSelection) selection).getFirstElement();
+ action.setMenuCreator(this);
+ action.setEnabled(true);
+ }
+ else if(((IStructuredSelection) selection).getFirstElement() instanceof IMemoryRendering)
+ {
+ fMemoryBlock = ((IMemoryRendering) ((IStructuredSelection) selection).getFirstElement()).getMemoryBlock();
+ action.setMenuCreator(this);
+ action.setEnabled(true);
+ }
+ }
+ }
+
+ public void debugContextChanged(DebugContextEvent event) {
+ }
+
+ public Menu getMenu(Menu parent) {
+ Menu menu = new Menu(parent);
+ menu.addMenuListener(new MenuAdapter() {
+ @Override
+ public void menuShown(MenuEvent e) {
+ Menu m = (Menu)e.widget;
+ MenuItem[] items = m.getItems();
+ for (int i=0; i < items.length; i++) {
+ items[i].dispose();
+ }
+ fillMenu(m);
+ }
+ });
+ return menu;
+ }
+
+ private void fillMenu(Menu menu) {
+ if(fMemoryBlock instanceof IMemoryBlockUpdatePolicyProvider)
+ {
+ IMemoryBlockUpdatePolicyProvider blockPolicy = (IMemoryBlockUpdatePolicyProvider) fMemoryBlock;
+
+ String currentPolicy = blockPolicy.getUpdatePolicy();
+
+ String policies[] = blockPolicy.getUpdatePolicies();
+ for(int i = 0; i < policies.length; i++)
+ {
+ SelectPolicy action = new SelectPolicy(policies[i], blockPolicy.getUpdatePolicyDescription(policies[i]));
+ ActionContributionItem item = new ActionContributionItem(action);
+ action.setChecked(policies[i].equals(currentPolicy));
+
+ item.fill(menu, -1);
+ }
+ }
+ }
+
+}
+
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/sourcelookup/DsfSourceDisplayAdapter.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/sourcelookup/DsfSourceDisplayAdapter.java
new file mode 100644
index 00000000000..c9140fc99c9
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/sourcelookup/DsfSourceDisplayAdapter.java
@@ -0,0 +1,855 @@
+/*******************************************************************************
+ * 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:
+ * IBM Corporation - initial API and implementation
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.ui.sourcelookup;
+
+import java.io.File;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.eclipse.cdt.core.model.ITranslationUnit;
+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.Query;
+import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+import org.eclipse.cdt.dsf.debug.service.IStack;
+import org.eclipse.cdt.dsf.debug.service.StepQueueManager;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason;
+import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
+import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMData;
+import org.eclipse.cdt.dsf.debug.sourcelookup.DsfSourceLookupParticipant;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.SteppingController;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.SteppingController.ISteppingControlParticipant;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.SteppingController.SteppingTimedOutEvent;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
+import org.eclipse.core.filesystem.EFS;
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.CoreException;
+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.sourcelookup.ISourceLookupDirector;
+import org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant;
+import org.eclipse.debug.core.sourcelookup.containers.LocalFileStorage;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.debug.ui.sourcelookup.CommonSourceNotFoundEditorInput;
+import org.eclipse.debug.ui.sourcelookup.ISourceDisplay;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextOperationTarget;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.ITextViewerExtension5;
+import org.eclipse.jface.text.Position;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IEditorDescriptor;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.editors.text.EditorsUI;
+import org.eclipse.ui.ide.FileStoreEditorInput;
+import org.eclipse.ui.ide.IDE;
+import org.eclipse.ui.part.FileEditorInput;
+import org.eclipse.ui.progress.UIJob;
+import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * Source display adapter that performs the source lookup, opens the editor,
+ * and paints the IP for the given object.
+ * <p>
+ * The implementation relies on three types of jobs to perform the operations.<br>
+ * - The first kind, "lookup job" performs the source lookup operation. <br>
+ * - The second "display job" positions and annotates the editor. <br>
+ * - The third clears the old IP annotations when a thread or process has resumed
+ * or exited.
+ * <p>
+ * The the lookup jobs can run in parallel with the display or the clearing job,
+ * but the clearing job and the display job must not run at the same time.
+ * Hence there is some involved logic which ensures that the jobs are run in
+ * proper order. To avoid race conditions, this logic uses the session's
+ * dispatch thread to synchronize access to the state data of the running jobs.
+ */
+@ThreadSafe
+public class DsfSourceDisplayAdapter implements ISourceDisplay, ISteppingControlParticipant
+{
+ private static final class FrameData {
+ IFrameDMContext fDmc;
+ int fLine;
+ int fLevel;
+ String fFile;
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ FrameData other = (FrameData) obj;
+ if (!fDmc.equals(other.fDmc))
+ return false;
+ if (fFile == null) {
+ if (other.fFile != null)
+ return false;
+ } else if (!fFile.equals(other.fFile))
+ return false;
+ return true;
+ }
+
+ /**
+ * Test whether the given frame data instance refers to the very same location.
+ *
+ * @param frameData
+ * @return <code>true</code> if the frame data refers to the same location
+ */
+ public boolean isIdentical(FrameData frameData) {
+ return equals(frameData) && fLine == frameData.fLine;
+ }
+ }
+
+ /**
+ * A job to perform source lookup on the given DMC.
+ */
+ class LookupJob extends Job {
+
+ private final IWorkbenchPage fPage;
+ private final FrameData fFrameData;
+ private final boolean fEventTriggered;
+
+ /**
+ * Constructs a new source lookup job.
+ */
+ public LookupJob(FrameData frameData, IWorkbenchPage page, boolean eventTriggered) {
+ super("DSF Source Lookup"); //$NON-NLS-1$
+ setPriority(Job.INTERACTIVE);
+ setSystem(true);
+ fFrameData = frameData;
+ fPage = page;
+ fEventTriggered = eventTriggered;
+ }
+
+ IDMContext getDmc() { return fFrameData.fDmc; }
+
+ @Override
+ protected IStatus run(final IProgressMonitor monitor) {
+ if (monitor.isCanceled()) {
+ return Status.CANCEL_STATUS;
+ }
+
+ final SourceLookupResult result = performLookup();
+ executeFromJob(new DsfRunnable() { public void run() {
+ if (!monitor.isCanceled()) {
+ fPrevResult = result;
+ fPrevFrameData = fFrameData;
+ fRunningLookupJob = null;
+ startDisplayJob(fPrevResult, fFrameData, fPage, fEventTriggered);
+ }
+ }});
+ return Status.OK_STATUS;
+ }
+
+ private SourceLookupResult performLookup() {
+ IDMContext dmc = fFrameData.fDmc;
+ SourceLookupResult result = new SourceLookupResult(dmc , null, null, null);
+ String editorId = null;
+ IEditorInput editorInput = null;
+ Object sourceElement = fSourceLookup.getSourceElement(dmc);
+
+ if (sourceElement == null) {
+ editorInput = new CommonSourceNotFoundEditorInput(dmc);
+ editorId = IDebugUIConstants.ID_COMMON_SOURCE_NOT_FOUND_EDITOR;
+ } else if (sourceElement instanceof IFile) {
+ editorId = getEditorIdForFilename(((IFile)sourceElement).getName());
+ editorInput = new FileEditorInput((IFile)sourceElement);
+ } else if (sourceElement instanceof ITranslationUnit) {
+ try {
+ URI uriLocation = ((ITranslationUnit)sourceElement).getLocationURI();
+ IFileStore fileStore = EFS.getStore(uriLocation);
+ editorInput = new FileStoreEditorInput(fileStore);
+ editorId = getEditorIdForFilename(fileStore.getName());
+ } catch (CoreException e) {
+ editorInput = new CommonSourceNotFoundEditorInput(dmc);
+ editorId = IDebugUIConstants.ID_COMMON_SOURCE_NOT_FOUND_EDITOR;
+ }
+ } else if (sourceElement instanceof LocalFileStorage) {
+ File file = ((LocalFileStorage)sourceElement).getFile();
+ IFileStore fileStore = EFS.getLocalFileSystem().fromLocalFile(file);
+ editorInput = new FileStoreEditorInput(fileStore);
+ editorId = getEditorIdForFilename(file.getName());
+ }
+ result.setEditorInput(editorInput);
+ result.setEditorId(editorId);
+ result.setSourceElement(sourceElement);
+
+ return result;
+ }
+
+ private String getEditorIdForFilename(String filename) {
+ try {
+ IEditorDescriptor descriptor= IDE.getEditorDescriptor(filename);
+ return descriptor.getId();
+ } catch (PartInitException exc) {
+ DsfUIPlugin.log(exc);
+ }
+ return "org.eclipse.ui.DefaultTextEditor"; //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Job that positions the editor and paints the IP Annotation for given DMC.
+ */
+ class DisplayJob extends UIJob {
+ private final SourceLookupResult fResult;
+ private final IWorkbenchPage fPage;
+ private final FrameData fFrameData;
+
+ private final DsfRunnable fDisplayJobFinishedRunnable = new DsfRunnable() {
+ public void run() {
+ // If the current display job does not match up with "this", it means that this job got canceled
+ // after it already completed and after this runnable was queued into the dispatch thread.
+ if (fRunningDisplayJob == DisplayJob.this) {
+ fRunningDisplayJob = null;
+ if (fEventTriggered && !fDoneStepping.getAndSet(true)) {
+ doneStepping(fResult.getDmc());
+ }
+ serviceDisplayAndClearingJobs();
+ }
+ }
+ };
+
+ private final AtomicBoolean fDoneStepping = new AtomicBoolean(false);
+ private IRegion fRegion;
+ private ITextViewer fTextViewer;
+ private final boolean fEventTriggered;
+
+ IDMContext getDmc() { return fResult.getDmc(); }
+
+ /**
+ * Constructs a new source display job
+ */
+ public DisplayJob(SourceLookupResult result, FrameData frameData, IWorkbenchPage page, boolean eventTriggered) {
+ super("Debug Source Display"); //$NON-NLS-1$
+ setSystem(true);
+ setPriority(Job.INTERACTIVE);
+ fResult = result;
+ fFrameData = frameData;
+ fPage = page;
+ fEventTriggered = eventTriggered;
+ }
+
+ @Override
+ public IStatus runInUIThread(final IProgressMonitor monitor) {
+
+ if (monitor.isCanceled()) {
+ executeFromJob(fDisplayJobFinishedRunnable);
+ return Status.CANCEL_STATUS;
+ }
+
+ if (fRegion != null && fTextViewer != null) {
+ if (fRunningDisplayJob == this) {
+ if (!shouldCancelSelectionChange()) {
+ enableLineBackgroundPainter();
+ fTextViewer.setSelectedRange(fRegion.getOffset(), 0);
+ }
+ executeFromJob(fDisplayJobFinishedRunnable);
+ }
+ } else {
+ IEditorPart editor = openEditor(fResult, fPage);
+ if (editor == null) {
+ executeFromJob(fDisplayJobFinishedRunnable);
+ return Status.OK_STATUS;
+ }
+
+ ITextEditor textEditor = null;
+ if (editor instanceof ITextEditor) {
+ textEditor = (ITextEditor)editor;
+ } else {
+ textEditor = (ITextEditor) editor.getAdapter(ITextEditor.class);
+ }
+ if (textEditor != null) {
+ if (positionEditor(textEditor, fFrameData)) {
+ return Status.OK_STATUS;
+ }
+ }
+ executeFromJob(fDisplayJobFinishedRunnable);
+ }
+ return Status.OK_STATUS;
+ }
+
+ private boolean shouldCancelSelectionChange() {
+ Query<Boolean> delaySelectionChangeQuery = new Query<Boolean>() {
+ @Override
+ protected void execute(DataRequestMonitor<Boolean> rm) {
+ IExecutionDMContext execCtx = DMContexts.getAncestorOfType(fFrameData.fDmc,
+ IExecutionDMContext.class);
+
+ IRunControl runControl = fServicesTracker.getService(IRunControl.class);
+ rm.setData(runControl != null && execCtx != null &&
+ (fController.getPendingStepCount(execCtx) != 0 || runControl.isStepping(execCtx)));
+ rm.done();
+ }
+ };
+
+ try {
+ fController.getExecutor().execute(delaySelectionChangeQuery);
+ } catch (RejectedExecutionException e) {
+ return false;
+ }
+
+ try {
+ return delaySelectionChangeQuery.get();
+ } catch (InterruptedException e) {
+ return false;
+ } catch (ExecutionException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Opens the editor used to display the source for an element selected in
+ * this view and returns the editor that was opened or <code>null</code> if
+ * no editor could be opened.
+ */
+ private IEditorPart openEditor(SourceLookupResult result, IWorkbenchPage page) {
+ IEditorInput input= result.getEditorInput();
+ String id= result.getEditorId();
+ if (input == null || id == null) {
+ return null;
+ }
+
+ return openEditor(page, input, id);
+ }
+
+ /**
+ * Opens an editor in the workbench and returns the editor that was opened
+ * or <code>null</code> if an error occurred while attempting to open the
+ * editor.
+ */
+ private IEditorPart openEditor(final IWorkbenchPage page, final IEditorInput input, final String id) {
+ final IEditorPart[] editor = new IEditorPart[] {null};
+ Runnable r = new Runnable() {
+ public void run() {
+ if (!page.getWorkbenchWindow().getWorkbench().isClosing()) {
+ try {
+ editor[0] = page.openEditor(input, id, false);
+ } catch (PartInitException e) {}
+ }
+ }
+ };
+ BusyIndicator.showWhile(Display.getDefault(), r);
+ return editor[0];
+ }
+
+ /**
+ * Positions the text editor for the given stack frame
+ */
+ private boolean positionEditor(ITextEditor editor, final FrameData frameData) {
+ // Position and annotate the editor.
+ fRegion= getLineInformation(editor, frameData.fLine);
+ if (fRegion != null) {
+ // add annotation
+ fIPManager.addAnnotation(
+ editor, frameData.fDmc, new Position(fRegion.getOffset(), fRegion.getLength()),
+ frameData.fLevel == 0);
+
+ // this is a dirty trick to get access to the ITextViewer of the editor
+ Object tot = editor.getAdapter(ITextOperationTarget.class);
+ if (tot instanceof ITextViewer) {
+ fTextViewer = (ITextViewer)tot;
+ int widgetLine = frameData.fLine;
+ if (tot instanceof ITextViewerExtension5) {
+ ITextViewerExtension5 ext5 = (ITextViewerExtension5) tot;
+ // expand region if collapsed
+ ext5.exposeModelRange(fRegion);
+ widgetLine = ext5.modelLine2WidgetLine(widgetLine);
+ }
+ revealLine(fTextViewer, widgetLine);
+
+ if (fStepCount > 0 && fSelectionChangeDelay > 0) {
+ disableLineBackgroundPainter();
+ // reschedule for selection change
+ schedule(fSelectionChangeDelay);
+ if (!fDoneStepping.getAndSet(true)) {
+ doneStepping(getDmc());
+ }
+ return true;
+ } else {
+ enableLineBackgroundPainter();
+ fTextViewer.setSelectedRange(fRegion.getOffset(), 0);
+ }
+ } else {
+ editor.selectAndReveal(fRegion.getOffset(), 0);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Scroll the given line into the visible area if it is not yet visible.
+ * @param focusLine
+ * @see org.eclipse.jface.text.TextViewer#revealRange(int, int)
+ */
+ private void revealLine(ITextViewer viewer, int focusLine) {
+ StyledText textWidget = viewer.getTextWidget();
+ int top = textWidget.getTopIndex();
+ if (top > -1) {
+
+ // scroll vertically
+ int lines = getEstimatedVisibleLinesInViewport(textWidget);
+ int bottom = top + lines;
+
+ int bottomBuffer = Math.max(1, lines / 3);
+
+ if (focusLine >= top && focusLine <= bottom - bottomBuffer) {
+ // do not scroll at all as it is already visible
+ } else {
+ if (focusLine > bottom - bottomBuffer && focusLine <= bottom) {
+ // focusLine is already in bottom bufferZone
+ // scroll to top of bottom bufferzone - for smooth down-scrolling
+ int scrollDelta = focusLine - (bottom - bottomBuffer);
+ textWidget.setTopIndex(top + scrollDelta);
+ } else {
+ // scroll to top of visible area minus buffer zone
+ int topBuffer = lines / 3;
+ textWidget.setTopIndex(Math.max(0, focusLine - topBuffer));
+ }
+ }
+ }
+ }
+
+ /**
+ * @return the number of visible lines in the view port assuming a constant
+ * line height.
+ */
+ private int getEstimatedVisibleLinesInViewport(StyledText textWidget) {
+ if (textWidget != null) {
+ Rectangle clArea= textWidget.getClientArea();
+ if (!clArea.isEmpty())
+ return clArea.height / textWidget.getLineHeight();
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the line information for the given line in the given editor
+ */
+ private IRegion getLineInformation(ITextEditor editor, int lineNumber) {
+ IDocumentProvider provider= editor.getDocumentProvider();
+ IEditorInput input= editor.getEditorInput();
+ try {
+ provider.connect(input);
+ } catch (CoreException e) {
+ return null;
+ }
+ try {
+ IDocument document= provider.getDocument(input);
+ if (document != null)
+ return document.getLineInformation(lineNumber);
+ } catch (BadLocationException e) {
+ } finally {
+ provider.disconnect(input);
+ }
+ return null;
+ }
+
+ }
+
+ /**
+ * Job that removes the old IP Annotations associated with given execution
+ * context.
+ */
+ class ClearingJob extends UIJob {
+ Set<IRunControl.IExecutionDMContext> fDmcsToClear;
+
+ public ClearingJob(Set<IRunControl.IExecutionDMContext> dmcs) {
+ super("Debug Source Display"); //$NON-NLS-1$
+ setSystem(true);
+ setPriority(Job.INTERACTIVE);
+ fDmcsToClear = dmcs;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.progress.UIJob#runInUIThread(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ DsfRunnable clearingJobFinishedRunnable = new DsfRunnable() { public void run() {
+ assert fRunningClearingJob == ClearingJob.this;
+ fRunningClearingJob = null;
+ serviceDisplayAndClearingJobs();
+ }};
+
+ enableLineBackgroundPainter();
+
+ if (monitor.isCanceled()) {
+ executeFromJob(clearingJobFinishedRunnable);
+ return Status.CANCEL_STATUS;
+ }
+
+ for (IRunControl.IExecutionDMContext dmc : fDmcsToClear) {
+ fIPManager.removeAnnotations(dmc);
+ }
+
+ executeFromJob(clearingJobFinishedRunnable);
+ return Status.OK_STATUS;
+ }
+ }
+
+ private static final boolean DEBUG = false;
+
+ private DsfSession fSession;
+ private DsfExecutor fExecutor;
+ private DsfServicesTracker fServicesTracker;
+ private FrameData fPrevFrameData;
+ private SourceLookupResult fPrevResult;
+ private ISourceLookupDirector fSourceLookup;
+ private DsfSourceLookupParticipant fSourceLookupParticipant;
+ private InstructionPointerManager fIPManager;
+
+ private LookupJob fRunningLookupJob;
+ private DisplayJob fRunningDisplayJob;
+ private DisplayJob fPendingDisplayJob;
+ private ClearingJob fRunningClearingJob;
+ private Set<IRunControl.IExecutionDMContext> fPendingExecDmcsToClear = new HashSet<IRunControl.IExecutionDMContext>();
+ private SteppingController fController;
+
+ /** Delay (in milliseconds) before the selection is changed to the IP location */
+ private int fSelectionChangeDelay = 150;
+
+ private long fStepStartTime = 0;
+ private long fLastStepTime = 0;
+ private long fStepCount;
+
+ private boolean fEnableLineBackgroundPainter;
+
+ public DsfSourceDisplayAdapter(DsfSession session, ISourceLookupDirector sourceLocator) {
+ this(session, sourceLocator, null);
+ }
+
+ /**
+ * @since 1.1
+ */
+ public DsfSourceDisplayAdapter(DsfSession session, ISourceLookupDirector sourceLocator, SteppingController controller) {
+ fSession = session;
+ fExecutor = session.getExecutor();
+ fServicesTracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), session.getId());
+ fSourceLookup = sourceLocator;
+ fSourceLookupParticipant = new DsfSourceLookupParticipant(session);
+ fSourceLookup.addParticipants(new ISourceLookupParticipant[] {fSourceLookupParticipant} );
+
+ fIPManager = new InstructionPointerManager();
+
+ fSession.addServiceEventListener(this, null);
+
+ fController = controller;
+ if (fController != null) {
+ fController.addSteppingControlParticipant(this);
+ }
+ }
+
+ /**
+ * Configure the delay (in milliseconds) before the selection in the editor
+ * is changed to the IP location.
+ *
+ * @param delay the delay in milliseconds, a non-negative integer
+ *
+ * @since 1.1
+ */
+ public void setSelectionChangeDelay(int delay) {
+ fSelectionChangeDelay = delay;
+ }
+
+ public void dispose() {
+ if (fController != null) {
+ fController.removeSteppingControlParticipant(this);
+ fController = null;
+ }
+ fSession.removeServiceEventListener(this);
+ fServicesTracker.dispose();
+ fSourceLookup.removeParticipants(new ISourceLookupParticipant[] {fSourceLookupParticipant});
+
+ // fSourceLookupParticipant is disposed by the source lookup director
+
+ // Need to remove annotations in UI thread.
+ Display display = Display.getDefault();
+ if (!display.isDisposed()) {
+ display.asyncExec(new Runnable() {
+ public void run() {
+ enableLineBackgroundPainter();
+ fIPManager.removeAllAnnotations();
+ }});
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.contexts.ISourceDisplayAdapter#displaySource(java.lang.Object, org.eclipse.ui.IWorkbenchPage, boolean)
+ */
+ public void displaySource(Object context, final IWorkbenchPage page, final boolean force) {
+ fStepCount = 0;
+
+ if (!(context instanceof IDMVMContext)) return;
+ final IDMContext dmc = ((IDMVMContext)context).getDMContext();
+
+ // Quick test. DMC is checked again in source lookup participant, but
+ // it's much quicker to test here.
+ if (!(dmc instanceof IFrameDMContext)) return;
+ doDisplaySource((IFrameDMContext) dmc, page, force, false);
+ }
+
+ private void doDisplaySource(final IFrameDMContext context, final IWorkbenchPage page, final boolean force, final boolean eventTriggered) {
+ if (context.getLevel() < 0) {
+ return;
+ }
+ // Re-dispatch to executor thread before accessing job lists.
+ fExecutor.execute(new DsfRunnable() { public void run() {
+ // We need to retrieve the frame level and line number from the service.
+ IStack stackService = fServicesTracker.getService(IStack.class);
+ if (stackService == null) {
+ return;
+ }
+ stackService.getFrameData(
+ context,
+ new DataRequestMonitor<IFrameDMData>(fExecutor, null) {
+ @Override
+ public void handleSuccess() {
+ FrameData frameData = new FrameData();
+ frameData.fDmc = context;
+ frameData.fLevel = context.getLevel();
+ // Document line numbers are 0-based. While debugger line numbers are 1-based.
+ IFrameDMData data = getData();
+ frameData.fLine = data.getLine() - 1;
+ frameData.fFile = data.getFile();
+ if (!force && frameData.equals(fPrevFrameData)) {
+ fPrevResult.updateArtifact(context);
+ startDisplayJob(fPrevResult, frameData, page, eventTriggered);
+ } else {
+ startLookupJob(frameData, page, eventTriggered);
+ }
+ }
+ });
+ }});
+ }
+
+ private void executeFromJob(Runnable runnable) {
+ try {
+ fExecutor.execute(runnable);
+ } catch (RejectedExecutionException e) {
+ // Session disposed, ignore
+ }
+ }
+
+ private void startLookupJob(final FrameData frameData, final IWorkbenchPage page, boolean eventTriggered) {
+ // If there is a previous lookup job running, cancel it.
+ if (fRunningLookupJob != null) {
+ fRunningLookupJob.cancel();
+ }
+
+ fRunningLookupJob = new LookupJob(frameData, page, eventTriggered);
+ fRunningLookupJob.schedule();
+ }
+
+ // To be called only on dispatch thread.
+ private void startDisplayJob(SourceLookupResult lookupResult, FrameData frameData, IWorkbenchPage page, boolean eventTriggered) {
+ DisplayJob nextDisplayJob = new DisplayJob(lookupResult, frameData, page, eventTriggered);
+ if (fRunningDisplayJob != null) {
+ fPendingDisplayJob = null;
+ IExecutionDMContext[] execCtxs = DMContexts.getAllAncestorsOfType(frameData.fDmc, IExecutionDMContext.class);
+ fPendingExecDmcsToClear.removeAll(Arrays.asList(execCtxs));
+
+ if (!eventTriggered && frameData.isIdentical(fRunningDisplayJob.fFrameData)) {
+ // identical location - we are done
+ return;
+ }
+ // cancel running display job
+ fRunningDisplayJob.cancel();
+ }
+ if (fRunningClearingJob != null) {
+ // Wait for the clearing job to finish, instead, set the
+ // display job as pending.
+ fPendingDisplayJob = nextDisplayJob;
+ } else {
+ fRunningDisplayJob = nextDisplayJob;
+ fRunningDisplayJob.schedule();
+ }
+ }
+
+ private void doneStepping(IDMContext context) {
+ if (fController != null) {
+ // indicate completion of step
+ final IExecutionDMContext dmc = DMContexts.getAncestorOfType(context, IExecutionDMContext.class);
+ if (dmc != null) {
+ fController.getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ fController.doneStepping(dmc, DsfSourceDisplayAdapter.this);
+ };
+ });
+ }
+ }
+ }
+
+ private void serviceDisplayAndClearingJobs() {
+ if (!fPendingExecDmcsToClear.isEmpty()) {
+ // There are annotations to be cleared, run the job first
+ fRunningClearingJob = new ClearingJob(fPendingExecDmcsToClear);
+ fRunningClearingJob.schedule();
+ fPendingExecDmcsToClear = new HashSet<IRunControl.IExecutionDMContext>();
+ } else if (fPendingDisplayJob != null) {
+ fRunningDisplayJob = fPendingDisplayJob;
+ fRunningDisplayJob.schedule();
+ fPendingDisplayJob = null;
+ }
+ }
+
+ private void startAnnotationClearingJob(IRunControl.IExecutionDMContext execDmc) {
+ // Make sure to add the context to the list.
+ fPendingExecDmcsToClear.add(execDmc);
+
+ // If lookup job is running, check it against the execution context,
+ // and cancel it if matches.
+ if (fRunningLookupJob != null) {
+ if (DMContexts.isAncestorOf(fRunningLookupJob.getDmc(), execDmc)) {
+ fRunningLookupJob.cancel();
+ fRunningLookupJob = null;
+ }
+ }
+ // If there is a pending display job, make sure it doesn't get
+ // preempted by this event. If so, just cancel the pending
+ // display job.
+ if (fPendingDisplayJob != null) {
+ if (DMContexts.isAncestorOf(fPendingDisplayJob.getDmc(), execDmc)) {
+ fPendingDisplayJob = null;
+ }
+ }
+
+ // If no display or clearing jobs are running, schedule the clearing job.
+ if (fRunningClearingJob == null && fRunningDisplayJob == null) {
+ fRunningClearingJob = new ClearingJob(fPendingExecDmcsToClear);
+ fRunningClearingJob.schedule();
+ fPendingExecDmcsToClear = new HashSet<IRunControl.IExecutionDMContext>();
+ }
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(IRunControl.IResumedDMEvent e) {
+ if (e.getReason() != StateChangeReason.STEP) {
+ startAnnotationClearingJob(e.getDMContext());
+ }
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(IRunControl.IExitedDMEvent e) {
+ startAnnotationClearingJob(e.getDMContext());
+ }
+
+ /**
+ * @since 1.1
+ */
+ @DsfServiceEventHandler
+ public void eventDispatched(SteppingTimedOutEvent e) {
+ startAnnotationClearingJob(e.getDMContext());
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(StepQueueManager.ISteppingTimedOutEvent e) {
+ startAnnotationClearingJob(e.getDMContext());
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(final IRunControl.ISuspendedDMEvent e) {
+ updateStepTiming();
+ if (e.getReason() == StateChangeReason.STEP || e.getReason() == StateChangeReason.BREAKPOINT) {
+ // trigger source display immediately (should be optional?)
+ Display.getDefault().asyncExec(new Runnable() {
+ public void run() {
+ Object context = DebugUITools.getDebugContext();
+ if (context instanceof IDMVMContext) {
+ final IDMContext dmc = ((IDMVMContext)context).getDMContext();
+ if (dmc instanceof IFrameDMContext && DMContexts.isAncestorOf(dmc, e.getDMContext())) {
+ IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ doDisplaySource((IFrameDMContext) dmc, page, false, true);
+ }
+ }
+ }});
+ } else {
+ doneStepping(e.getDMContext());
+ }
+ }
+
+ private void updateStepTiming() {
+ long now = System.currentTimeMillis();
+ if (now - fLastStepTime > Math.max(fSelectionChangeDelay, 200)) {
+ fStepCount = 0;
+ fStepStartTime = fLastStepTime = now;
+ return;
+ }
+ fLastStepTime = now;
+ ++fStepCount;
+ if (DEBUG) {
+ long delta = now - fStepStartTime;
+ float meanTime = delta/(float)fStepCount/1000;
+ System.out.println("[DsfSourceDisplayAdapter] step speed = " + 1/meanTime); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Disable editor line background painter if it is enabled.
+ * <p>
+ * <strong>Must be called on display thread.</strong>
+ * </p>
+ */
+ private void disableLineBackgroundPainter() {
+ if (!fEnableLineBackgroundPainter) {
+ fEnableLineBackgroundPainter = EditorsUI.getPreferenceStore().getBoolean(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE);
+ if (fEnableLineBackgroundPainter) {
+ EditorsUI.getPreferenceStore().setValue(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE, false);
+ }
+ }
+ }
+
+ /**
+ * Enable the editor line background painter if it was enabled before.
+ * <p>
+ * <strong>Must be called on display thread.</strong>
+ * </p>
+ */
+ private void enableLineBackgroundPainter() {
+ if (fEnableLineBackgroundPainter) {
+ fEnableLineBackgroundPainter = false;
+ EditorsUI.getPreferenceStore().setValue(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE, true);
+ }
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/sourcelookup/InstructionPointerImageProvider.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/sourcelookup/InstructionPointerImageProvider.java
new file mode 100644
index 00000000000..7a0d2d2196e
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/sourcelookup/InstructionPointerImageProvider.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.dsf.debug.ui.sourcelookup;
+
+import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
+import org.eclipse.cdt.dsf.debug.ui.sourcelookup.InstructionPointerManager.IPAnnotation;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.texteditor.IAnnotationImageProvider;
+
+@ThreadSafe
+public class InstructionPointerImageProvider implements IAnnotationImageProvider {
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.texteditor.IAnnotationImageProvider#getManagedImage(org.eclipse.jface.text.source.Annotation)
+ */
+ public Image getManagedImage(Annotation annotation) {
+ return ((IPAnnotation)annotation).getImage();
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.texteditor.IAnnotationImageProvider#getImageDescriptorId(org.eclipse.jface.text.source.Annotation)
+ */
+ public String getImageDescriptorId(Annotation annotation) {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.texteditor.IAnnotationImageProvider#getImageDescriptor(java.lang.String)
+ */
+ public ImageDescriptor getImageDescriptor(String imageDescritporId) {
+ return null;
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/sourcelookup/InstructionPointerManager.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/sourcelookup/InstructionPointerManager.java
new file mode 100644
index 00000000000..825ec43daf3
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/sourcelookup/InstructionPointerManager.java
@@ -0,0 +1,264 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 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:
+ * IBM Corporation - initial API and implementation
+ * Wind River Systems - Adapter to use with DSF
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.ui.sourcelookup;
+
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+import org.eclipse.cdt.dsf.debug.service.IStack;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.texteditor.IDocumentProvider;
+import org.eclipse.ui.texteditor.ITextEditor;
+
+/**
+ * This class tracks instruction pointer contexts for a single DSF session.
+ */
+@ThreadSafe
+class InstructionPointerManager {
+
+ /**
+ * Current instruction pointer annotation type.
+ */
+ private static final String ID_CURRENT_IP= "org.eclipse.cdt.dsf.debug.currentIP"; //$NON-NLS-1$
+
+ /**
+ * Secondary instruction pointer annotation type.
+ */
+ private static final String ID_SECONDARY_IP= "org.eclipse.cdt.dsf.debug.secondaryIP"; //$NON-NLS-1$
+
+ /**
+ * Editor annotation object for instruction pointers.
+ */
+ static class IPAnnotation extends Annotation {
+
+ /** The image for this annotation. */
+ private Image fImage;
+
+ /** Frame DMC that this IP is for **/
+ private IStack.IFrameDMContext fFrame;
+
+ /**
+ * Constructs an instruction pointer image.
+ *
+ * @param frame stack frame the instruction pointer is associated with
+ * @param annotationType the type of annotation to display (annotation identifier)
+ * @param text the message to display with the annotation as hover help
+ * @param image the image used to display the annotation
+ */
+ IPAnnotation(IStack.IFrameDMContext frame, String annotationType, String text, Image image) {
+ super(annotationType, false, text);
+ fFrame = frame;
+ fImage = image;
+ }
+
+ /**
+ * Returns this annotation's image.
+ *
+ * @return image
+ */
+ protected Image getImage() {
+ return fImage;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof IPAnnotation) {
+ return fFrame.equals(((IPAnnotation)other).fFrame);
+ }
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return fFrame.hashCode();
+ }
+
+ }
+
+ /**
+ * Represents the context for a single instruction pointer. This is a convenience class
+ * used to store the three objects that comprise an instruction pointer 'context' so it
+ * can be stored in collections.
+ */
+ static class AnnotationWrapper {
+
+ /** The text editor for this context. */
+ private ITextEditor fTextEditor;
+
+ /** Stack frame that this annotation is for */
+ private IStack.IFrameDMContext fFrameDmc;
+
+ /** The vertical ruler annotation for this context. */
+ private Annotation fAnnotation;
+
+ AnnotationWrapper(ITextEditor textEditor, Annotation annotation, IStack.IFrameDMContext frameDmc) {
+ fTextEditor = textEditor;
+ fAnnotation = annotation;
+ fFrameDmc = frameDmc;
+ }
+
+ /**
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof AnnotationWrapper) {
+ AnnotationWrapper otherContext = (AnnotationWrapper) other;
+ return getAnnotation().equals(otherContext.getAnnotation());
+ }
+ return false;
+ }
+
+ /**
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return getAnnotation().hashCode();
+ }
+
+ ITextEditor getTextEditor() { return fTextEditor; }
+ Annotation getAnnotation() { return fAnnotation; }
+ IStack.IFrameDMContext getFrameDMC() { return fFrameDmc; }
+ }
+
+ /**
+ * Mapping of IDebugTarget objects to (mappings of IThread objects to lists of instruction
+ * pointer contexts).
+ */
+ private List<AnnotationWrapper> fAnnotationWrappers;
+
+ /**
+ * Clients must not instantiate this class.
+ */
+ public InstructionPointerManager() {
+ fAnnotationWrappers = Collections.synchronizedList(new LinkedList<AnnotationWrapper>());
+ }
+
+ /**
+ * Add an instruction pointer annotation in the specified editor for the
+ * specified stack frame.
+ */
+ public void addAnnotation(ITextEditor textEditor, IStack.IFrameDMContext frame, Position position, boolean isTopFrame) {
+
+ IDocumentProvider docProvider = textEditor.getDocumentProvider();
+ IEditorInput editorInput = textEditor.getEditorInput();
+ // If there is no annotation model, there's nothing more to do
+ IAnnotationModel annModel = docProvider.getAnnotationModel(editorInput);
+ if (annModel == null) {
+ return;
+ }
+
+ String id;
+ String text;
+ Image image;
+ if (isTopFrame) {
+ id = ID_CURRENT_IP;
+ text = "Debug Current Instruction Pointer"; //$NON-NLS-1$
+ image = DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_INSTRUCTION_POINTER_TOP);
+ } else {
+ id = ID_SECONDARY_IP;
+ text = "Debug Call Stack"; //$NON-NLS-1$
+ image = DebugUITools.getImage(IDebugUIConstants.IMG_OBJS_INSTRUCTION_POINTER);
+ }
+
+ if (isTopFrame) {
+ // remove other top-frame IP annotation(s) for this execution-context
+ removeAnnotations(DMContexts.getAncestorOfType(frame.getParents()[0], IExecutionDMContext.class));
+ }
+ Annotation annotation = new IPAnnotation(frame, id, text, image);
+
+ // Add the annotation at the position to the editor's annotation model.
+ annModel.removeAnnotation(annotation);
+ annModel.addAnnotation(annotation, position);
+
+ // Add to list of existing wrappers
+ fAnnotationWrappers.add(new AnnotationWrapper(textEditor, annotation, frame));
+ }
+
+ /**
+ * Remove all annotations associated with the specified debug target that this class
+ * is tracking.
+ */
+ public void removeAnnotations(IRunControl.IExecutionDMContext execDmc) {
+ // Retrieve the mapping of threads to context lists
+ synchronized(fAnnotationWrappers) {
+ for (Iterator<AnnotationWrapper> wrapperItr = fAnnotationWrappers.iterator(); wrapperItr.hasNext();) {
+ AnnotationWrapper wrapper = wrapperItr.next();
+ if (DMContexts.isAncestorOf(wrapper.getFrameDMC(), execDmc)) {
+ removeAnnotation(wrapper.getTextEditor(), wrapper.getAnnotation());
+ wrapperItr.remove();
+ }
+ }
+ }
+ }
+
+ /**
+ * Remove all top-frame annotations associated with the specified debug target that this class
+ * is tracking.
+ */
+ public void removeTopFrameAnnotations(IRunControl.IExecutionDMContext execDmc) {
+ // Retrieve the mapping of threads to context lists
+ synchronized(fAnnotationWrappers) {
+ for (Iterator<AnnotationWrapper> wrapperItr = fAnnotationWrappers.iterator(); wrapperItr.hasNext();) {
+ AnnotationWrapper wrapper = wrapperItr.next();
+ if (DMContexts.isAncestorOf(wrapper.getFrameDMC(), execDmc)
+ && ID_CURRENT_IP.equals(wrapper.getAnnotation().getType())) {
+ removeAnnotation(wrapper.getTextEditor(), wrapper.getAnnotation());
+ wrapperItr.remove();
+ }
+ }
+ }
+ }
+
+ /** Removes all annotations tracked by this manager */
+ public void removeAllAnnotations() {
+ synchronized(fAnnotationWrappers) {
+ for (AnnotationWrapper wrapper : fAnnotationWrappers) {
+ removeAnnotation(wrapper.getTextEditor(), wrapper.getAnnotation());
+ }
+ fAnnotationWrappers.clear();
+ }
+ }
+
+ /**
+ * Remove the specified annotation from the specified text editor.
+ */
+ private void removeAnnotation(ITextEditor textEditor, Annotation annotation) {
+ IDocumentProvider docProvider = textEditor.getDocumentProvider();
+ if (docProvider != null) {
+ IAnnotationModel annotationModel = docProvider.getAnnotationModel(textEditor.getEditorInput());
+ if (annotationModel != null) {
+ annotationModel.removeAnnotation(annotation);
+ }
+ }
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/sourcelookup/SourceLookupResult.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/sourcelookup/SourceLookupResult.java
new file mode 100644
index 00000000000..707d3c4eb3e
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/sourcelookup/SourceLookupResult.java
@@ -0,0 +1,129 @@
+/*******************************************************************************
+ * 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.sourcelookup;
+
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.ui.IEditorInput;
+
+/**
+ * The result of a source lookup contains the source element, editor id, and
+ * editor input resolved for a debug artifact.
+ *
+ * @since 3.1
+ */
+class SourceLookupResult {
+
+ /**
+ * Element that source was resolved for.
+ */
+ private IDMContext fDmc;
+ /**
+ * Corresponding source element, or <code>null</code>
+ * if unknown.
+ */
+ private Object fSourceElement;
+ /**
+ * Associated editor id, used to display the source element,
+ * or <code>null</code> if unknown.
+ */
+ private String fEditorId;
+ /**
+ * Associatd editor input, used to display the source element,
+ * or <code>null</code> if unknown.
+ */
+ private IEditorInput fEditorInput;
+
+ /**
+ * Creates a source lookup result on the given artifact, source element,
+ * editor id, and editor input.
+ */
+ public SourceLookupResult(IDMContext dmc, Object sourceElement, String editorId, IEditorInput editorInput) {
+ fDmc = dmc;
+ setSourceElement(sourceElement);
+ setEditorId(editorId);
+ setEditorInput(editorInput);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.sourcelookup.ISourceLookupResult#getArtifact()
+ */
+ public IDMContext getDmc() {
+ return fDmc;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.sourcelookup.ISourceLookupResult#getSourceElement()
+ */
+ public Object getSourceElement() {
+ return fSourceElement;
+ }
+
+ /**
+ * Sets the source element resolved for the artifact that source
+ * lookup was performed for, or <code>null</code> if a source element
+ * was not resolved.
+ *
+ * @param element resolved source element or <code>null</code> if unknown
+ */
+ protected void setSourceElement(Object element) {
+ fSourceElement = element;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.sourcelookup.ISourceLookupResult#getEditorId()
+ */
+ public String getEditorId() {
+ return fEditorId;
+ }
+
+ /**
+ * Sets the identifier of the editor used to display this source
+ * lookup result's source element, or <code>null</code> if unknown.
+ *
+ * @param id the identifier of the editor used to display this source
+ * lookup result's source element, or <code>null</code> if unknown
+ */
+ protected void setEditorId(String id) {
+ fEditorId = id;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.sourcelookup.ISourceLookupResult#getEditorInput()
+ */
+ public IEditorInput getEditorInput() {
+ return fEditorInput;
+ }
+
+ /**
+ * Sets the editor input used to display this source lookup
+ * result's source element, or <code>null</code> if unknown.
+ *
+ * @param input the editor input used to display this source lookup
+ * result's source element, or <code>null</code> if unknown
+ */
+ protected void setEditorInput(IEditorInput input) {
+ fEditorInput = input;
+ }
+
+ /**
+ * Updates the artifact to refer to the given artifact
+ * if equal. For example, when a source lookup result is resued
+ * for the same stack frame, we still need to update in case
+ * the stack frame is not identical.
+ *
+ * @param artifact new artifact state
+ */
+ public void updateArtifact(IDMContext dmc) {
+ if (fDmc.equals(dmc)) {
+ fDmc = dmc;
+ }
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/AbstractDebugVMAdapter.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/AbstractDebugVMAdapter.java
new file mode 100644
index 00000000000..6a6c8e7fc46
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/AbstractDebugVMAdapter.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * 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.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.SteppingController.ISteppingControlParticipant;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMProvider;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMAdapter;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+
+/**
+ * Base class for VM adapters used for implementing a debugger integration.
+ *
+ * @since 1.1
+ */
+@SuppressWarnings("restriction")
+public class AbstractDebugVMAdapter extends AbstractDMVMAdapter
+ implements ISteppingControlParticipant
+{
+
+ public AbstractDebugVMAdapter(DsfSession session, final SteppingController controller) {
+ super(session);
+ fController = controller;
+ try {
+ fController.getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ fController.addSteppingControlParticipant(AbstractDebugVMAdapter.this);
+ }
+ });
+ } catch (RejectedExecutionException e) {} // Do nothing if session is shut down.
+ }
+
+ private final SteppingController fController;
+
+ @Override
+ protected IVMProvider createViewModelProvider(IPresentationContext context) {
+ return null;
+ }
+
+ @Override
+ public void doneHandleEvent(Object event) {
+ if (event instanceof IRunControl.ISuspendedDMEvent) {
+ final ISuspendedDMEvent suspendedEvent= (IRunControl.ISuspendedDMEvent) event;
+ fController.getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ fController.doneStepping(suspendedEvent.getDMContext(), AbstractDebugVMAdapter.this);
+ };
+ });
+ }
+ }
+
+ @Override
+ public void dispose() {
+ try {
+ fController.getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ fController.removeSteppingControlParticipant(AbstractDebugVMAdapter.this);
+ }
+ });
+ } catch (RejectedExecutionException e) {} // Do nothing if session is shut down.
+ super.dispose();
+ }
+}
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
new file mode 100644
index 00000000000..29647fc5f86
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/IDebugVMConstants.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 - Ted Williams - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.ui.viewmodel;
+
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+
+public interface IDebugVMConstants {
+ /**
+ * Standard across the board column IDs.
+ */
+ public static final String ID = DsfUIPlugin.PLUGIN_ID + ".VARIABLES_COLUMN_PRESENTATION_ID"; //$NON-NLS-1$
+ public static final String COLUMN_ID__NAME = DsfUIPlugin.PLUGIN_ID + ".COLUMN_ID__NAME"; //$NON-NLS-1$
+ public static final String COLUMN_ID__TYPE = DsfUIPlugin.PLUGIN_ID + ".COLUMN_ID__TYPE"; //$NON-NLS-1$
+ public static final String COLUMN_ID__VALUE = DsfUIPlugin.PLUGIN_ID + ".COLUMN_ID__VALUE"; //$NON-NLS-1$
+ public static final String COLUMN_ID__ADDRESS = DsfUIPlugin.PLUGIN_ID + ".COLUMN_ID__ADDRESS"; //$NON-NLS-1$
+ public static final String COLUMN_ID__DESCRIPTION = DsfUIPlugin.PLUGIN_ID + ".COLUMN_ID__DESCRIPTION"; //$NON-NLS-1$
+ public static final String COLUMN_ID__EXPRESSION = DsfUIPlugin.PLUGIN_ID + ".COLUMN_ID__EXPRESSION"; //$NON-NLS-1$
+
+ /**
+ * Location of the current format in the IPresentationContext data store.
+ */
+ public final static String CURRENT_FORMAT_STORAGE = "CurrentNumericStyle" ; //$NON-NLS-1$
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/SteppingController.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/SteppingController.java
new file mode 100644
index 00000000000..1f7a2890fe8
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/SteppingController.java
@@ -0,0 +1,572 @@
+/*******************************************************************************
+ * 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;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+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.AbstractDMEvent;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+import org.eclipse.cdt.dsf.debug.service.IStepQueueManager;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
+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.service.IRunControl.StepType;
+import org.eclipse.cdt.dsf.debug.ui.IDsfDebugUIConstants;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+
+/**
+ * This class builds on top of standard run control service to provide
+ * functionality for step queuing and delaying. Step queuing essentially allows
+ * user to press and hold the step key and achieve maximum stepping speed. If
+ * this class is used, other service implementations, such as stack and
+ * expressions, can use it to avoid requesting data from debugger back end if
+ * another step is about to be executed.
+ *
+ * @since 1.1
+ */
+public final class SteppingController implements IStepQueueManager
+{
+ /**
+ * Amount of time in milliseconds, that it takes the SteppingTimedOutEvent
+ * event to be issued after a step is started.
+ * @see SteppingTimedOutEvent
+ */
+ public final static int STEPPING_TIMEOUT = 500;
+
+ /**
+ * The depth of the step queue. In other words, the maximum number of steps
+ * that are queued before the step queue manager is throwing them away.
+ */
+ public final static int STEP_QUEUE_DEPTH = 2;
+
+ /**
+ * The maximum delay (in milliseconds) between steps when synchronized
+ * stepping is enabled. This also serves as a safeguard in the case stepping
+ * control participants fail to indicate completion of event processing.
+ */
+ public final static int MAX_STEP_DELAY= 5000;
+
+ private final static boolean DEBUG = "true".equals(Platform.getDebugOption("org.eclipse.cdt.dsf.ui/debug/stepping")); //$NON-NLS-1$ //$NON-NLS-2$
+
+ /**
+ * Indicates that the given context has been stepping for some time,
+ * and the UI (views and actions) may need to be updated accordingly.
+ */
+ public static final class SteppingTimedOutEvent extends AbstractDMEvent<IExecutionDMContext> {
+ private SteppingTimedOutEvent(IExecutionDMContext execCtx) {
+ super(execCtx);
+ }
+ }
+
+ /**
+ * Interface for clients interested in stepping control. When a stepping
+ * control participant is registered with the stepping controller, it is
+ * expected to call
+ * {@link SteppingController#doneStepping(IExecutionDMContext, ISteppingControlParticipant)
+ * doneStepping} as soon as a "step", i.e. a suspended event has been
+ * processed. If synchronized stepping is enabled, further stepping is
+ * blocked until all stepping control participants have indicated completion
+ * of event processing or the maximum timeout
+ * {@link SteppingController#MAX_STEP_DELAY} has been reached.
+ *
+ * @see SteppingController#addSteppingControlParticipant(ISteppingControlParticipant)
+ * @see SteppingController#removeSteppingControlParticipant(ISteppingControlParticipant)
+ */
+ public interface ISteppingControlParticipant {
+ }
+
+ private static class StepRequest {
+ IExecutionDMContext fContext;
+ StepType fStepType;
+ boolean inProgress = false;
+ StepRequest(IExecutionDMContext execCtx, StepType type) {
+ fContext = execCtx;
+ fStepType = type;
+ }
+ }
+
+ private final DsfSession fSession;
+ private final DsfServicesTracker fServicesTracker;
+
+ private IRunControl fRunControl;
+ private int fQueueDepth = STEP_QUEUE_DEPTH;
+
+ private final Map<IExecutionDMContext,List<StepRequest>> fStepQueues = new HashMap<IExecutionDMContext,List<StepRequest>>();
+ private final Map<IExecutionDMContext,Boolean> fTimedOutFlags = new HashMap<IExecutionDMContext,Boolean>();
+ private final Map<IExecutionDMContext,ScheduledFuture<?>> fTimedOutFutures = new HashMap<IExecutionDMContext,ScheduledFuture<?>>();
+
+ /**
+ * Records the time of the last step for an execution context.
+ */
+ private final Map<IExecutionDMContext, Long> fLastStepTimes= new HashMap<IExecutionDMContext, Long>();
+
+ /**
+ * Minimum step interval in milliseconds.
+ */
+ private int fMinStepInterval= 0;
+
+ /**
+ * Map of execution contexts for which a step is in progress.
+ */
+ private final Map<IExecutionDMContext, List<ISteppingControlParticipant>> fStepInProgress = new HashMap<IExecutionDMContext, List<ISteppingControlParticipant>>();
+
+ /**
+ * List of registered stepping control participants.
+ */
+ private final List<ISteppingControlParticipant> fParticipants = Collections.synchronizedList(new ArrayList<ISteppingControlParticipant>());
+
+ /**
+ * Property change listener. It updates the stepping control settings.
+ */
+ private IPropertyChangeListener fPreferencesListener;
+
+ public SteppingController(DsfSession session) {
+ fSession = session;
+ fServicesTracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), session.getId());
+
+ final IPreferenceStore store= DsfUIPlugin.getDefault().getPreferenceStore();
+
+ fPreferencesListener = new IPropertyChangeListener() {
+ public void propertyChange(final PropertyChangeEvent event) {
+ handlePropertyChanged(store, event);
+ }};
+ store.addPropertyChangeListener(fPreferencesListener);
+
+ setMinimumStepInterval(store.getInt(IDsfDebugUIConstants.PREF_MIN_STEP_INTERVAL));
+ }
+
+ public void dispose() {
+ if (fRunControl != null) {
+ getSession().removeServiceEventListener(this);
+ }
+
+ IPreferenceStore store= DsfUIPlugin.getDefault().getPreferenceStore();
+ store.removePropertyChangeListener(fPreferencesListener);
+
+ fServicesTracker.dispose();
+ }
+
+ /**
+ * Configure the minimum time (in milliseconds) to wait between steps.
+ *
+ * @param interval
+ */
+ public void setMinimumStepInterval(int interval) {
+ fMinStepInterval = interval;
+ }
+
+ /**
+ * Register given stepping control participant.
+ * <p>
+ * Participants are obliged to call
+ * {@link #doneStepping(IExecutionDMContext, ISteppingControlParticipant)}
+ * when they have received and completed processing an
+ * {@link ISuspendedDMEvent}. If synchronized stepping is enabled, further
+ * stepping is disabled until all participants have indicated completion of
+ * processing the event.
+ * </p>
+ *
+ * @param participant
+ */
+ public void addSteppingControlParticipant(ISteppingControlParticipant participant) {
+ fParticipants.add(participant);
+ }
+
+ /**
+ * Unregister given stepping control participant.
+ *
+ * @param participant
+ */
+ public void removeSteppingControlParticipant(final ISteppingControlParticipant participant) {
+ fParticipants.remove(participant);
+ }
+
+ /**
+ * Indicate that participant has completed processing of the last step.
+ *
+ * @param execCtx
+ */
+ public void doneStepping(final IExecutionDMContext execCtx, final ISteppingControlParticipant participant) {
+ if (DEBUG) System.out.println("[SteppingController] doneStepping participant=" + participant.getClass().getSimpleName()); //$NON-NLS-1$
+ List<ISteppingControlParticipant> participants = fStepInProgress.get(execCtx);
+ if (participants != null) {
+ participants.remove(participant);
+ if (participants.isEmpty()) {
+ doneStepping(execCtx);
+ }
+ } else {
+ for (IExecutionDMContext disabledCtx : fStepInProgress.keySet()) {
+ if (DMContexts.isAncestorOf(disabledCtx, execCtx)) {
+ participants = fStepInProgress.get(disabledCtx);
+ if (participants != null) {
+ participants.remove(participant);
+ if (participants.isEmpty()) {
+ doneStepping(disabledCtx);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public DsfSession getSession() {
+ return fSession;
+ }
+
+ /**
+ * All access to this class should happen through this executor.
+ * @return the executor this class is confined to
+ */
+ public DsfExecutor getExecutor() {
+ return getSession().getExecutor();
+ }
+
+ private DsfServicesTracker getServicesTracker() {
+ return fServicesTracker;
+ }
+
+ private IRunControl getRunControl() {
+ if (fRunControl == null) {
+ fRunControl = getServicesTracker().getService(IRunControl.class);
+ getSession().addServiceEventListener(this, null);
+ }
+ return fRunControl;
+ }
+
+ /**
+ * Checks whether a step command can be queued up for given context.
+ */
+ public void canEnqueueStep(IExecutionDMContext execCtx, StepType stepType, DataRequestMonitor<Boolean> rm) {
+ if (doCanEnqueueStep(execCtx, stepType)) {
+ rm.setData(true);
+ rm.done();
+ } else {
+ getRunControl().canStep(execCtx, stepType, rm);
+ }
+ }
+
+ private boolean doCanEnqueueStep(IExecutionDMContext execCtx, StepType stepType) {
+ return getRunControl().isStepping(execCtx) && !isSteppingTimedOut(execCtx);
+ }
+
+ /**
+ * Check whether the next step on the given execution context should be delayed
+ * based on the configured step delay.
+ *
+ * @param execCtx
+ * @return <code>true</code> if the step should be delayed
+ */
+ private boolean shouldDelayStep(IExecutionDMContext execCtx) {
+ final int stepDelay= getStepDelay(execCtx);
+ if (DEBUG) System.out.println("[SteppingController] shouldDelayStep delay=" + stepDelay); //$NON-NLS-1$
+ return stepDelay > 0;
+ }
+
+ /**
+ * Compute the delay in milliseconds before the next step for the given context may be executed.
+ *
+ * @param execCtx
+ * @return the number of milliseconds before the next possible step
+ */
+ private int getStepDelay(IExecutionDMContext execCtx) {
+ if (fMinStepInterval > 0) {
+ for (IExecutionDMContext lastStepCtx : fLastStepTimes.keySet()) {
+ if (execCtx.equals(lastStepCtx) || DMContexts.isAncestorOf(execCtx, lastStepCtx)) {
+ long now = System.currentTimeMillis();
+ int delay= (int) (fLastStepTimes.get(lastStepCtx) + fMinStepInterval - now);
+ return Math.max(delay, 0);
+ }
+ }
+ }
+ return 0;
+ }
+
+ private void updateLastStepTime(IExecutionDMContext execCtx) {
+ long now = System.currentTimeMillis();
+ fLastStepTimes.put(execCtx, now);
+ for (IExecutionDMContext lastStepCtx : fLastStepTimes.keySet()) {
+ if (!execCtx.equals(lastStepCtx) && DMContexts.isAncestorOf(execCtx, lastStepCtx)) {
+ fLastStepTimes.put(lastStepCtx, now);
+ }
+ }
+ }
+
+ private long getLastStepTime(IExecutionDMContext execCtx) {
+ if (fLastStepTimes.containsKey(execCtx)) {
+ return fLastStepTimes.get(execCtx);
+ }
+ for (IExecutionDMContext lastStepCtx : fLastStepTimes.keySet()) {
+ if (DMContexts.isAncestorOf(execCtx, lastStepCtx)) {
+ return fLastStepTimes.get(lastStepCtx);
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Returns the number of step commands that are queued for given execution
+ * context.
+ */
+ public int getPendingStepCount(IExecutionDMContext execCtx) {
+ List<StepRequest> stepQueue = getStepQueue(execCtx);
+ if (stepQueue == null) return 0;
+ return stepQueue.size();
+ }
+
+ /**
+ * Adds a step command to the execution queue for given context.
+ * @param execCtx Execution context that should perform the step.
+ * @param stepType Type of step to execute.
+ */
+ public void enqueueStep(final IExecutionDMContext execCtx, final StepType stepType) {
+ if (DEBUG) System.out.println("[SteppingController] enqueueStep ctx=" + execCtx); //$NON-NLS-1$
+ if (!shouldDelayStep(execCtx) || doCanEnqueueStep(execCtx, stepType)) {
+ doEnqueueStep(execCtx, stepType);
+ processStepQueue(execCtx);
+ }
+ }
+
+ private void doStep(final IExecutionDMContext execCtx, final StepType stepType) {
+ if (DEBUG) System.out.println("[SteppingController] doStep ctx="+execCtx); //$NON-NLS-1$
+ disableStepping(execCtx);
+ updateLastStepTime(execCtx);
+
+ getRunControl().step(execCtx, stepType, new RequestMonitor(getExecutor(), null) {
+ @Override
+ protected void handleFailure() {
+ if (getStatus().getCode() == IDsfStatusConstants.INVALID_STATE) {
+ // Ignore errors. During fast stepping there can be expected race
+ // conditions leading to stepping errors.
+ return;
+ }
+ super.handleFailure();
+ }
+ });
+ }
+
+ /**
+ * Enqueue the given step for later execution.
+ *
+ * @param execCtx
+ * @param stepType
+ */
+ private void doEnqueueStep(final IExecutionDMContext execCtx, final StepType stepType) {
+ List<StepRequest> stepQueue = fStepQueues.get(execCtx);
+ if (stepQueue == null) {
+ stepQueue = new LinkedList<StepRequest>();
+ fStepQueues.put(execCtx, stepQueue);
+ }
+ if (stepQueue.size() < fQueueDepth) {
+ stepQueue.add(new StepRequest(execCtx, stepType));
+ }
+ }
+
+ /**
+ * Returns whether the step instruction for the given context has timed out.
+ */
+ public boolean isSteppingTimedOut(IExecutionDMContext execCtx) {
+ for (IExecutionDMContext timedOutCtx : fTimedOutFlags.keySet()) {
+ if (execCtx.equals(timedOutCtx) || DMContexts.isAncestorOf(execCtx, timedOutCtx)) {
+ return fTimedOutFlags.get(timedOutCtx);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Process next step on queue if any.
+ * @param execCtx
+ */
+ private void processStepQueue(final IExecutionDMContext execCtx) {
+ final List<StepRequest> queue = getStepQueue(execCtx);
+ if (queue != null) {
+ final int stepDelay = getStepDelay(execCtx);
+ if (stepDelay > 0) {
+ getExecutor().schedule(new DsfRunnable() {
+ public void run() {
+ processStepQueue(execCtx);
+ }
+ }, stepDelay, TimeUnit.MILLISECONDS);
+ return;
+ }
+ final StepRequest request = queue.get(0);
+ if (DEBUG) System.out.println("[SteppingController] processStepQueue request-in-progress="+request.inProgress); //$NON-NLS-1$
+ if (!request.inProgress) {
+ if (isSteppingDisabled(request.fContext)) {
+ return;
+ }
+ request.inProgress = true;
+ getRunControl().canStep(
+ request.fContext, request.fStepType,
+ new DataRequestMonitor<Boolean>(getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (isSuccess() && getData()) {
+ queue.remove(0);
+ if (queue.isEmpty()) fStepQueues.remove(request.fContext);
+ doStep(request.fContext, request.fStepType);
+ } else {
+ // For whatever reason we can't step anymore, so clear out
+ // the step queue.
+ fStepQueues.remove(request.fContext);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ private List<StepRequest> getStepQueue(IExecutionDMContext execCtx) {
+ List<StepRequest> queue = fStepQueues.get(execCtx);
+ if (queue == null) {
+ for (IExecutionDMContext stepCtx : fStepQueues.keySet()) {
+ if (DMContexts.isAncestorOf(stepCtx, execCtx)) {
+ queue = fStepQueues.get(stepCtx);
+ break;
+ }
+ }
+ }
+ return queue;
+ }
+
+ /**
+ * Disable stepping for the given execution context.
+ *
+ * @param execCtx
+ */
+ private void disableStepping(IExecutionDMContext execCtx) {
+ fStepInProgress.put(execCtx, new ArrayList<ISteppingControlParticipant>(fParticipants));
+ }
+
+ /**
+ * Indicate that processing of the last step has completed and
+ * the next step can be issued.
+ *
+ * @param execCtx
+ */
+ private void doneStepping(final IExecutionDMContext execCtx) {
+ if (DEBUG) System.out.println("[SteppingController] doneStepping ctx=" + execCtx); //$NON-NLS-1$
+ enableStepping(execCtx);
+ processStepQueue(execCtx);
+ }
+
+ /**
+ * Enable stepping for the given execution context.
+ *
+ * @param execCtx
+ */
+ private void enableStepping(final IExecutionDMContext execCtx) {
+ fStepInProgress.remove(execCtx);
+ for (IExecutionDMContext disabledCtx : fStepInProgress.keySet()) {
+ if (DMContexts.isAncestorOf(disabledCtx, execCtx)) {
+ fStepInProgress.remove(disabledCtx);
+ }
+ }
+ }
+
+ private boolean isSteppingDisabled(IExecutionDMContext execCtx) {
+ boolean disabled= fStepInProgress.containsKey(execCtx);
+ if (!disabled) {
+ for (IExecutionDMContext disabledCtx : fStepInProgress.keySet()) {
+ if (DMContexts.isAncestorOf(execCtx, disabledCtx)) {
+ disabled = true;
+ break;
+ }
+ }
+ }
+ if (disabled) {
+ long now = System.currentTimeMillis();
+ long lastStepTime = getLastStepTime(execCtx);
+ if (now - lastStepTime > MAX_STEP_DELAY) {
+ if (DEBUG) System.out.println("[SteppingController] stepping control participant(s) timed out"); //$NON-NLS-1$
+ enableStepping(execCtx);
+ disabled = false;
+ }
+ }
+ return disabled;
+ }
+
+ protected void handlePropertyChanged(final IPreferenceStore store, final PropertyChangeEvent event) {
+ String property = event.getProperty();
+ if (IDsfDebugUIConstants.PREF_MIN_STEP_INTERVAL.equals(property)) {
+ setMinimumStepInterval(store.getInt(property));
+ }
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////
+
+ @DsfServiceEventHandler
+ public void eventDispatched(final ISuspendedDMEvent e) {
+ // Take care of the stepping time out
+ fTimedOutFlags.remove(e.getDMContext());
+ ScheduledFuture<?> future = fTimedOutFutures.remove(e.getDMContext());
+ if (future != null) future.cancel(false);
+
+ // Check if there's a step pending, if so execute it
+ processStepQueue(e.getDMContext());
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(final IResumedDMEvent e) {
+ if (e.getReason().equals(StateChangeReason.STEP)) {
+ fTimedOutFlags.put(e.getDMContext(), Boolean.FALSE);
+ // We shouldn't have a stepping timeout running unless we get two
+ // stepping events in a row without a suspended, which would be a
+ // protocol error.
+ assert !fTimedOutFutures.containsKey(e.getDMContext());
+ fTimedOutFutures.put(
+ e.getDMContext(),
+ getExecutor().schedule(
+ new DsfRunnable() { public void run() {
+ fTimedOutFutures.remove(e.getDMContext());
+
+ if (getSession().isActive()) {
+ // Issue the stepping time-out event.
+ getSession().dispatchEvent(
+ new SteppingTimedOutEvent(e.getDMContext()),
+ null);
+ }
+ }},
+ STEPPING_TIMEOUT, TimeUnit.MILLISECONDS)
+ );
+
+ }
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(SteppingTimedOutEvent e) {
+ fTimedOutFlags.put(e.getDMContext(), Boolean.TRUE);
+ enableStepping(e.getDMContext());
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/actions/AbstractVMProviderActionDelegate.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/actions/AbstractVMProviderActionDelegate.java
new file mode 100644
index 00000000000..8bbd0226f4d
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/actions/AbstractVMProviderActionDelegate.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * 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:
+ * Ted R Williams (Wind River Systems, Inc.) - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.dsf.debug.ui.viewmodel.actions;
+
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMAdapter;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMProvider;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer;
+import org.eclipse.debug.ui.AbstractDebugView;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.contexts.DebugContextEvent;
+import org.eclipse.debug.ui.contexts.IDebugContextListener;
+import org.eclipse.debug.ui.contexts.IDebugContextService;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.ui.IActionDelegate2;
+import org.eclipse.ui.IViewActionDelegate;
+import org.eclipse.ui.IViewPart;
+
+/**
+ * @since 1.1
+ */
+@SuppressWarnings("restriction")
+abstract public class AbstractVMProviderActionDelegate implements IViewActionDelegate, IDebugContextListener, IActionDelegate2 {
+
+ private IViewPart fView = null;
+ private IAction fAction = null;
+ private ISelection fDebugContext;
+
+ public void init(IViewPart view) {
+ fView = view;
+
+ // Get the current selection from the DebugView so we can determine if we want this menu action to be live or not.
+ IDebugContextService debugContextService = DebugUITools.getDebugContextManager().getContextService(view.getSite().getWorkbenchWindow());
+ debugContextService.addPostDebugContextListener(this);
+ fDebugContext = debugContextService.getActiveContext();
+ }
+
+ public void selectionChanged(IAction action, ISelection selection) {
+ if (fAction != action) {
+ fAction = action;
+ }
+ }
+
+ public void runWithEvent(IAction action, Event event) {
+ run(action);
+ }
+
+ public void init(IAction action) {
+ fAction = action;
+ }
+
+ public void dispose() {
+ DebugUITools.getDebugContextManager().getContextService(getView().getSite().getWorkbenchWindow()).removePostDebugContextListener(this);
+ }
+
+ public void debugContextChanged(DebugContextEvent event) {
+ fDebugContext = event.getContext();
+ }
+
+ protected IViewPart getView() { return fView; }
+
+ protected IAction getAction() { return fAction; }
+
+ protected Object getViewerInput() {
+ if (fDebugContext instanceof IStructuredSelection) {
+ return ((IStructuredSelection)fDebugContext).getFirstElement();
+ }
+ return null;
+ }
+
+ protected IVMProvider getVMProvider() {
+ Object viewerInput = getViewerInput();
+ IPresentationContext presentationContext = getPresentationContext();
+
+ if (viewerInput instanceof IAdaptable && presentationContext != null) {
+ IVMAdapter adapter = (IVMAdapter) ((IAdaptable)viewerInput).getAdapter(IVMAdapter.class);
+
+ if ( adapter != null ) {
+ return adapter.getVMProvider(presentationContext);
+ }
+ }
+
+ return null;
+ }
+
+ protected IPresentationContext getPresentationContext() {
+ if (fView instanceof AbstractDebugView &&
+ ((AbstractDebugView) fView).getViewer() instanceof TreeModelViewer)
+ {
+ return ((TreeModelViewer) ((AbstractDebugView) fView).getViewer()).getPresentationContext();
+ }
+ return null;
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/actions/DefaultRefreshAllTarget.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/actions/DefaultRefreshAllTarget.java
new file mode 100644
index 00000000000..95bae0930de
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/actions/DefaultRefreshAllTarget.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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.actions;
+
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMAdapterExtension;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMProvider;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.ICachingVMProvider;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+
+/**
+ * The default implementation of the refresh all debug target which
+ * calls the active VM providers, to ask them to refresh.
+ *
+ * @since 1.1
+ */
+public class DefaultRefreshAllTarget implements IRefreshAllTarget {
+
+ public void refresh(ISelection debugContext) throws CoreException {
+ IVMAdapterExtension adapter = getActiveVMAdapter( debugContext );
+
+ if (adapter != null) {
+ for (IVMProvider provider : adapter.getActiveProviders()) {
+ if (provider instanceof ICachingVMProvider) {
+ ((ICachingVMProvider)provider).refresh();
+ }
+ }
+ }
+ }
+
+ protected IVMAdapterExtension getActiveVMAdapter(ISelection debugContext) {
+
+ if (debugContext instanceof IStructuredSelection) {
+ Object activeElement = ((IStructuredSelection)debugContext).getFirstElement();
+ if (activeElement instanceof IAdaptable) {
+ return (IVMAdapterExtension)((IAdaptable)activeElement).getAdapter(IVMAdapterExtension.class);
+ }
+ }
+ return null;
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/actions/IRefreshAllTarget.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/actions/IRefreshAllTarget.java
new file mode 100644
index 00000000000..cf1f50ec876
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/actions/IRefreshAllTarget.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.actions;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.ISelection;
+
+/**
+ * A retargetable action target which allows a debugger to refresh all of its
+ * active views with fresh data from the debug target.
+ *
+ * @since 1.1
+ */
+public interface IRefreshAllTarget {
+
+ /**
+ * Refreshes the debugger data of the given debug context.
+ * @param debugContext The active window debug context.
+ *
+ * @throws CoreException
+ */
+ public void refresh(ISelection debugContext) throws CoreException;
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/actions/VMHandlerUtils.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/actions/VMHandlerUtils.java
new file mode 100644
index 00000000000..594c89290ce
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/actions/VMHandlerUtils.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * 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.actions;
+
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMAdapter;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMProvider;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.IDebugView;
+import org.eclipse.debug.ui.contexts.IDebugContextService;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.ui.IPartService;
+import org.eclipse.ui.ISelectionService;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IViewSite;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.handlers.HandlerUtil;
+import org.eclipse.ui.services.IServiceLocator;
+
+/**
+ * Static utility methods for use with View Model related
+ * commands and handlers.
+ *
+ * @since 1.1
+ */
+@SuppressWarnings("restriction")
+public class VMHandlerUtils {
+
+ /**
+ * Retrieves the active VM provider based on the currently active
+ * selection and part.
+ * @param serviceLocator Service locator for access to active selection
+ * and part.
+ *
+ * @return The active VM provder.
+ */
+ static public IVMProvider getActiveVMProvider(IServiceLocator serviceLocator) {
+ ISelection selection = null;
+
+ ISelectionService selectionService =
+ (ISelectionService)serviceLocator.getService(ISelectionService.class);
+ if (selectionService != null) {
+ selection = selectionService.getSelection();
+ }
+
+ if (selection != null && !selection.isEmpty()) {
+ return getVMProviderForSelection(selection);
+ }
+ else {
+ IWorkbenchPart part = null;
+ IPartService partService = (IPartService)serviceLocator.getService(IPartService.class);
+ if (partService != null) {
+ part = partService.getActivePart();
+ }
+ return getVMProviderForPart(part);
+ }
+ }
+
+ /**
+ * Retrieves the active VM provider based on the given execution event.
+ * @param event The execution event which is usually given as an argument
+ * to the command handler execution call.
+ *
+ * @return The active VM provder.
+ */
+ static public IVMProvider getActiveVMProvider(ExecutionEvent event) {
+ ISelection selection = HandlerUtil.getCurrentSelection(event);
+ if (selection != null && !selection.isEmpty()) {
+ return getVMProviderForSelection(selection);
+ }
+ else {
+ IWorkbenchPart part = HandlerUtil.getActivePart(event);
+ return getVMProviderForPart(part);
+ }
+ }
+
+ public static IVMProvider getVMProviderForPart(IWorkbenchPart part) {
+ IDebugContextService contextService =
+ DebugUITools.getDebugContextManager().getContextService(part.getSite().getWorkbenchWindow());
+
+ ISelection debugContext = contextService.getActiveContext(getPartId(part));
+ if (debugContext == null) {
+ debugContext = contextService.getActiveContext();
+ }
+
+ Object input = null;
+ if (debugContext instanceof IStructuredSelection) {
+ input = ((IStructuredSelection)debugContext).getFirstElement();
+ }
+
+ if (part instanceof IDebugView) {
+ Viewer viewer = ((IDebugView)part).getViewer();
+ if (input instanceof IAdaptable && viewer instanceof TreeModelViewer) {
+ IPresentationContext presContext = ((TreeModelViewer)viewer).getPresentationContext();
+ IVMAdapter vmAdapter = (IVMAdapter)((IAdaptable)input).getAdapter(IVMAdapter.class);
+ if (vmAdapter != null) {
+ return vmAdapter.getVMProvider(presContext);
+ }
+ }
+ }
+ return null;
+ }
+
+ private static String getPartId(IWorkbenchPart part) {
+ if (part instanceof IViewPart) {
+ IViewSite site = (IViewSite)part.getSite();
+ return site.getId() + (site.getSecondaryId() != null ? (":" + site.getSecondaryId()) : ""); //$NON-NLS-1$ //$NON-NLS-2$
+ } else {
+ return part.getSite().getId();
+ }
+ }
+
+ public static IVMProvider getVMProviderForSelection(ISelection selection) {
+ if (selection instanceof IStructuredSelection) {
+ Object element = ((IStructuredSelection)selection).getFirstElement();
+ if (element instanceof IVMContext) {
+ return ((IVMContext)element).getVMNode().getVMProvider();
+ }
+ }
+ return null;
+ }
+
+}
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
new file mode 100644
index 00000000000..6e2a34f3e4c
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/AbstractExpressionVMNode.java
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2007 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.ui.viewmodel.expression;
+
+import java.util.List;
+
+import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
+import org.eclipse.cdt.dsf.concurrent.MultiRequestMonitor;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+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.VMChildrenUpdate;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.model.IExpression;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
+
+/**
+ * Base class for VM Nodes which can be used in the expressions view.
+ * <p>
+ * This base class uses the methods {@link #canParseExpression(IExpression)} and
+ * {@link #update(IChildrenUpdate[])} to implement the
+ * {@link IExpressionVMNode#update(IExpressionUpdate)}
+ * method. Two additional abstract protected methods need to be implemented
+ * by the sub-class as well.
+ * </p>
+ */
+@SuppressWarnings("restriction")
+public abstract class AbstractExpressionVMNode extends AbstractDMVMNode
+ implements IExpressionVMNode
+{
+ public AbstractExpressionVMNode(AbstractDMVMProvider provider, DsfSession session, Class<? extends IDMContext> dmcClassType) {
+ super(provider, session, dmcClassType);
+ }
+
+ public void update(final IExpressionUpdate update) {
+ if (!canParseExpression(update.getExpression())) {
+ // This method should not be called if canParseExpression() returns false.
+ // Return an internal error status.
+ update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Cannot parse expression", null)); //$NON-NLS-1$
+ update.done();
+ return;
+ }
+
+ // Retrieve the list of all elements from the sub-class. Then compare
+ // each returned element to the expression in the update, using
+ // testElementForExpression(). The element that matches the expression
+ // is returned to the client.
+ // If no matching element is found, the createInvalidExpressionVMContext()
+ // method is called to a special context.
+ update(new IChildrenUpdate[] { new VMChildrenUpdate(
+ update, -1, -1,
+ new ViewerDataRequestMonitor<List<Object>>(getExecutor(), update) {
+ @Override
+ protected void handleSuccess() {
+ if (getData().size() == 0) {
+ update.setExpressionElement(createInvalidExpressionVMContext(update.getExpression()));
+ update.done();
+ } else {
+ final List<Object> elements = getData();
+
+ final MultiRequestMonitor<DataRequestMonitor<Boolean>> multiRm = new MultiRequestMonitor<DataRequestMonitor<Boolean>>(getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if (isSuccess()) {
+ boolean foundMatchingContext = false;
+ for (int i = 0; i < getRequestMonitors().size(); i++) {
+ if (getRequestMonitors().get(i).getData()) {
+ Object element = elements.get(i);
+ associateExpression(element, update.getExpression());
+ update.setExpressionElement(element);
+ foundMatchingContext = true;
+ break;
+ }
+ }
+ if (!foundMatchingContext) {
+ update.setExpressionElement(createInvalidExpressionVMContext(update.getExpression()));
+ }
+ } else {
+ update.setStatus(getStatus());
+ }
+ update.done();
+ }
+ };
+
+ for (Object element : elements) {
+ testElementForExpression(
+ element, update.getExpression(),
+ multiRm.add(
+ new DataRequestMonitor<Boolean>(getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ multiRm.requestMonitorDone(this);
+ }
+ }));
+ }
+ }
+ }
+
+ @Override
+ protected void handleFailure() {
+ update.setStatus(getStatus());
+ update.done();
+ }
+ })}
+ );
+
+ }
+
+
+ /**
+ * Tests whether the given element matches the given expression.
+ *
+ * @param element Element to test against the given expression.
+ * @param expression Expression to use to check if the element is matching.
+ * @param rm The request monitor for the result.
+ */
+ @ConfinedToDsfExecutor("#getSession#getExecutor")
+ protected void testElementForExpression(Object element, IExpression expression, final DataRequestMonitor<Boolean> rm) {
+ rm.setData(false);
+ rm.done();
+ }
+
+ /**
+ * Sets the given expression as the expression belonging to the given
+ * element.
+ * <p>
+ * This base class creates VM context elements using the extending class's
+ * {@link #update(IChildrenUpdate[])} method. The element matching the
+ * expression is found using {@link #testElementForExpression(Object, IExpression, DataRequestMonitor)}.
+ * Once the matching element is found it needs to be linked to the expression
+ * so that it can be distinguished from other contexts created for identical
+ * but distinct expressions. This method accomplishes this task. Elements
+ * which are associated with expressions should use the expression object
+ * for implementation of {@link #equals(Object)} and {@link #hashCode()}
+ * methods.
+ * </p>
+ *
+ * @param element
+ * @param expression
+ */
+ protected void associateExpression(Object element, IExpression expression) {
+ }
+
+ /**
+ * Create a place holder for an invalid expression. If for a given expression,
+ * this VM node returns true from {@link #canParseExpression(IExpression)}, which
+ * indicates that the expression matches the node's expected format, but the node
+ * then is not able to find the element represented by the expression, then an
+ * "invalid" expression context needs to be created.
+ * <p>
+ * This method can be overriden to provide a node-specific invalid expression
+ * context.
+ * </p>
+ *
+ * @param expression Expression to create the context for.
+ * @return Returns a VM context object representing an invalid expression with
+ *
+ * @since 1.1
+ */
+ protected IVMContext createInvalidExpressionVMContext(IExpression expression) {
+ return new InvalidExpressionVMContext(this, expression);
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionColumnPresentation.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionColumnPresentation.java
new file mode 100644
index 00000000000..8c5b437d712
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionColumnPresentation.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * 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.expression;
+
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.jface.resource.ImageDescriptor;
+
+/**
+ *
+ */
+@SuppressWarnings("restriction")
+public class ExpressionColumnPresentation implements IColumnPresentation {
+
+ public static final String ID = DsfUIPlugin.PLUGIN_ID + ".EXPRESSION_COLUMN_PRESENTATION_ID"; //$NON-NLS-1$
+
+ public void init(IPresentationContext context) {
+ }
+
+ public void dispose() {
+ }
+
+ // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getAvailableColumns()
+ public String[] getAvailableColumns() {
+ return new String[] { IDebugVMConstants.COLUMN_ID__EXPRESSION, IDebugVMConstants.COLUMN_ID__NAME, IDebugVMConstants.COLUMN_ID__TYPE, IDebugVMConstants.COLUMN_ID__VALUE, IDebugVMConstants.COLUMN_ID__DESCRIPTION, IDebugVMConstants.COLUMN_ID__ADDRESS };
+ }
+
+ // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getHeader(java.lang.String)
+ public String getHeader(String id) {
+ if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(id)) {
+ return MessagesForExpressionVM.ExpressionColumnPresentation_expression;
+ } else if (IDebugVMConstants.COLUMN_ID__NAME.equals(id)) {
+ return MessagesForExpressionVM.ExpressionColumnPresentation_name;
+ } else if (IDebugVMConstants.COLUMN_ID__TYPE.equals(id)) {
+ return MessagesForExpressionVM.ExpressionColumnPresentation_type;
+ } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(id)) {
+ return MessagesForExpressionVM.ExpressionColumnPresentation_value;
+ } else if (IDebugVMConstants.COLUMN_ID__DESCRIPTION.equals(id)) {
+ return MessagesForExpressionVM.ExpressionColumnPresentation_description;
+ } else if (IDebugVMConstants.COLUMN_ID__ADDRESS.equals(id)) {
+ return MessagesForExpressionVM.ExpressionColumnPresentation_address;
+ }
+ return null;
+ }
+
+ // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getId()
+ public String getId() {
+ return ID;
+ }
+
+ public ImageDescriptor getImageDescriptor(String id) {
+ return null;
+ }
+
+ // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getInitialColumns()
+ public String[] getInitialColumns() {
+ return new String[] { IDebugVMConstants.COLUMN_ID__EXPRESSION, IDebugVMConstants.COLUMN_ID__TYPE, IDebugVMConstants.COLUMN_ID__VALUE };
+ }
+
+ // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#isOptional()
+ public boolean isOptional() {
+ return true;
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionManagerVMNode.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionManagerVMNode.java
new file mode 100644
index 00000000000..ae679c01bbb
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionManagerVMNode.java
@@ -0,0 +1,307 @@
+/*******************************************************************************
+ * 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.expression;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants;
+import org.eclipse.cdt.dsf.ui.concurrent.ViewerCountingRequestMonitor;
+import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMContext;
+import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IExpressionManager;
+import org.eclipse.debug.core.model.IExpression;
+import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementEditor;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ICellModifier;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.jface.viewers.TreePath;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * This is the top-level view model node in the expressions view. Its job is to:
+ * <li>
+ * <ol> retrieve the {@link IExpression} objects from the global {@link IExpressionManager},</ol>
+ * <ol> retrieve the expression string from the <code>IExpression</code> object,</ol>
+ * <ol> then to call the configured expression nodes to parse the expression string.</ol>
+ * </li>
+ * <p>
+ * This node is not intended to have any standard child nodes, therefore
+ * the implementation of {@link #setChildNodes(IVMNode[])} throws an exception.
+ * Instead users should call {@link #setExpressionNodes(IExpressionVMNode[])}
+ * to configure the nodes that this node will delegate to when processing expressions.
+ * </p>
+ */
+@SuppressWarnings("restriction")
+public class ExpressionManagerVMNode extends AbstractVMNode
+ implements IElementLabelProvider, IElementEditor
+{
+ /**
+ * VMC for a new expression object to be added. When user clicks on this node to
+ * edit it, he will create a new expression.
+ */
+ class NewExpressionVMC extends AbstractVMContext {
+ public NewExpressionVMC() {
+ super(ExpressionManagerVMNode.this);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Class adapter) {
+ return super.getAdapter(adapter);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof NewExpressionVMC;
+ }
+
+ @Override
+ public int hashCode() {
+ return getClass().hashCode();
+ }
+ }
+
+ /** Local reference to the global expression manager */
+ private IExpressionManager fManager = DebugPlugin.getDefault().getExpressionManager();
+
+ /** Cached reference to a cell modifier for editing expression strings of invalid expressions */
+ private WatchExpressionCellModifier fWatchExpressionCellModifier = new WatchExpressionCellModifier();
+
+ public ExpressionManagerVMNode(ExpressionVMProvider provider) {
+ super(provider);
+ }
+
+ @Override
+ public String toString() {
+ return "ExpressionManagerVMNode"; //$NON-NLS-1$
+ }
+
+ private ExpressionVMProvider getExpressionVMProvider() {
+ return (ExpressionVMProvider)getVMProvider();
+ }
+
+ public void update(IHasChildrenUpdate[] updates) {
+ // Test availability of children based on whether there are any expressions
+ // in the manager. We assume that the getExpressions() will just read
+ // local state data, so we don't bother using a job to perform this
+ // operation.
+ for (int i = 0; i < updates.length; i++) {
+ updates[i].setHasChilren(fManager.getExpressions().length != 0);
+ updates[i].done();
+ }
+ }
+
+ public void update(IChildrenCountUpdate[] updates) {
+ for (IChildrenCountUpdate update : updates) {
+ if (!checkUpdate(update)) continue;
+
+ // We assume that the getExpressions() will just read local state data,
+ // so we don't bother using a job to perform this operation.
+ update.setChildCount(fManager.getExpressions().length + 1);
+ update.done();
+ }
+ }
+
+ public void update(final IChildrenUpdate[] updates) {
+ for (IChildrenUpdate update : updates) {
+ doUpdateChildren(update);
+ }
+ }
+
+ public void doUpdateChildren(final IChildrenUpdate update) {
+ final IExpression[] expressions = fManager.getExpressions();
+
+ // For each (expression) element in update, find the layout node that can
+ // parse it. And for each expression that has a corresponding layout node,
+ // call IExpressionLayoutNode#getElementForExpression to generate a VMC.
+ // Since the last is an async call, we need to create a multi-RM to wait
+ // for all the calls to complete.
+ final CountingRequestMonitor multiRm = new ViewerCountingRequestMonitor(getVMProvider().getExecutor(), update);
+ int multiRmCount = 0;
+
+ int lowOffset= update.getOffset();
+ if (lowOffset < 0) {
+ lowOffset = 0;
+ }
+ int length= update.getLength();
+ if (length <= 0) {
+ length = expressions.length;
+ }
+ final int highOffset= lowOffset + length;
+ for (int i = lowOffset; i < highOffset && i < expressions.length + 1; i++) {
+ if (i < expressions.length) {
+ multiRmCount++;
+ final int childIndex = i;
+ final IExpression expression = expressions[i];
+ // getElementForExpression() accepts a IElementsUpdate as an argument.
+ // Construct an instance of VMElementsUpdate which will call a
+ // the request monitor when it is finished. The request monitor
+ // will in turn set the element in the update argument in this method.
+ ((ExpressionVMProvider)getVMProvider()).update(
+ new VMExpressionUpdate(
+ update, expression,
+ new DataRequestMonitor<Object>(getVMProvider().getExecutor(), multiRm) {
+ @Override
+ protected void handleSuccess() {
+ update.setChild(getData(), childIndex);
+ multiRm.done();
+ }
+
+ @Override
+ protected void handleError() {
+ update.setChild(new InvalidExpressionVMContext(ExpressionManagerVMNode.this, expression), childIndex);
+ multiRm.done();
+ }
+ })
+ );
+ } else {
+ // Last element in the list of expressions is the "add new expression"
+ // dummy entry.
+ update.setChild(new NewExpressionVMC(), i);
+ }
+ }
+
+ // If no expressions were parsed, we're finished.
+ // Set the count to the counting RM.
+ multiRm.setDoneCount(multiRmCount);
+ }
+
+ public void update(ILabelUpdate[] updates) {
+ // The label update handler only handles labels for the invalid expression VMCs.
+ // The expression layout nodes are responsible for supplying label providers
+ // for their VMCs.
+ for (ILabelUpdate update : updates) {
+ if (update.getElement() instanceof NewExpressionVMC) {
+ updateNewExpressionVMCLabel(update, (NewExpressionVMC) update.getElement());
+ } else {
+ update.done();
+ }
+ }
+ }
+
+ /**
+ * Updates the label for the NewExpressionVMC.
+ */
+ private void updateNewExpressionVMCLabel(ILabelUpdate update, NewExpressionVMC vmc) {
+ String[] columnIds = update.getColumnIds() != null ?
+ update.getColumnIds() : new String[] { IDebugVMConstants.COLUMN_ID__NAME };
+
+ for (int i = 0; i < columnIds.length; i++) {
+ if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(columnIds[i])) {
+ update.setLabel(MessagesForExpressionVM.ExpressionManagerLayoutNode__newExpression_label, i);
+ update.setFontData(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0], i);
+ } else {
+ update.setLabel("", i); //$NON-NLS-1$
+ }
+ }
+
+
+ update.done();
+ }
+
+ public int getDeltaFlags(Object event) {
+ int retVal = 0;
+
+ // Add a flag if the list of expressions in the global expression manager has changed.
+ if (event instanceof ExpressionsChangedEvent) {
+ retVal |= IModelDelta.ADDED | IModelDelta.REMOVED | IModelDelta.INSERTED | IModelDelta.CONTENT ;
+ }
+
+ for (IExpression expression : fManager.getExpressions()) {
+ retVal |= getExpressionVMProvider().getDeltaFlagsForExpression(expression, event);
+ }
+
+ return retVal;
+ }
+
+ public void buildDelta(final Object event, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor requestMonitor) {
+ if (event instanceof ExpressionsChangedEvent) {
+ buildDeltaForExpressionsChangedEvent((ExpressionsChangedEvent)event, parentDelta, nodeOffset, requestMonitor);
+ } else {
+
+ // For each expression, find its corresponding node and ask that
+ // layout node for its delta flags for given event. If there are delta flags to be
+ // generated, call the asynchronous method to do so.
+ CountingRequestMonitor multiRm = new CountingRequestMonitor(getExecutor(), requestMonitor);
+
+ int buildDeltaForExpressionCallCount = 0;
+
+ IExpression[] expressions = fManager.getExpressions();
+ for (int i = 0; i < expressions.length; i++ ) {
+ int flags = getExpressionVMProvider().getDeltaFlagsForExpression(expressions[i], event);
+ // If the given expression has no delta flags, skip it.
+ if (flags == IModelDelta.NO_CHANGE) continue;
+
+ int elementOffset = nodeOffset >= 0 ? nodeOffset + i : -1;
+ getExpressionVMProvider().buildDeltaForExpression(
+ expressions[i], elementOffset, event, parentDelta, getTreePathFromDelta(parentDelta),
+ new RequestMonitor(getExecutor(), multiRm));
+ buildDeltaForExpressionCallCount++;
+ }
+
+ multiRm.setDoneCount(buildDeltaForExpressionCallCount);
+ }
+ }
+
+ private void buildDeltaForExpressionsChangedEvent(ExpressionsChangedEvent event, VMDelta parentDelta,
+ int nodeOffset, RequestMonitor requestMonitor)
+ {
+ CountingRequestMonitor multiRm = new CountingRequestMonitor(getExecutor(), requestMonitor);
+ for (int i = 0; i < event.getExpressions().length; i++) {
+ int expIndex = event.getIndex() != -1
+ ? nodeOffset + event.getIndex() + i
+ : -1;
+ getExpressionVMProvider().buildDeltaForExpression(
+ event.getExpressions()[i], expIndex, event, parentDelta, getTreePathFromDelta(parentDelta),
+ new RequestMonitor(getExecutor(), multiRm));
+ }
+ multiRm.setDoneCount(event.getExpressions().length);
+ }
+
+ private TreePath getTreePathFromDelta(IModelDelta delta) {
+ List<Object> elementList = new LinkedList<Object>();
+ IModelDelta listDelta = delta;
+ elementList.add(0, listDelta.getElement());
+ while (listDelta.getParentDelta() != null) {
+ elementList.add(0, listDelta.getElement());
+ listDelta = listDelta.getParentDelta();
+ }
+ return new TreePath(elementList.toArray());
+ }
+
+
+ public CellEditor getCellEditor(IPresentationContext context, String columnId, Object element, Composite parent) {
+ if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(columnId)) {
+ return new TextCellEditor(parent);
+ }
+ return null;
+ }
+
+ public ICellModifier getCellModifier(IPresentationContext context, Object element) {
+ return fWatchExpressionCellModifier;
+ }
+}
diff --git a/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
new file mode 100644
index 00000000000..3f608a9dc0a
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProvider.java
@@ -0,0 +1,379 @@
+/*******************************************************************************
+ * 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.expression;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.debug.service.ICachingService;
+import org.eclipse.cdt.dsf.debug.service.IExpressions;
+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;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.register.SyncRegisterDataAccess;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.variable.SyncVariableDataAccess;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.variable.VariableVMNode;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMAdapter;
+import org.eclipse.cdt.dsf.ui.viewmodel.DefaultVMContentProviderStrategy;
+import org.eclipse.cdt.dsf.ui.viewmodel.IRootVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMModelProxy;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
+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.RootDMVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.AutomaticUpdatePolicy;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.IVMUpdatePolicy;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.model.IExpression;
+import org.eclipse.debug.internal.core.IExpressionsListener2;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.TreePath;
+
+/**
+ * The expression provider is used to populate the contents of the expressions
+ * view. The node hierarchy in this view is a little different than in a typical
+ * provider: the expression manager node should be registered as the single child
+ * of the root node and no nodes should be registered as children of expression node.
+ * Instead the top level expression nodes should be registered with a call to
+ * {@link #setExpressionNodes(IExpressionVMNode[])}. And each expression node can
+ * have its own sub-hierarchy of elements as needed. However all nodes configured
+ * with this provider (with the exception of the root and the expression manager)
+ * should implement {@link IExpressionVMNode}.
+ */
+@SuppressWarnings("restriction")
+public class ExpressionVMProvider extends AbstractDMVMProvider
+ implements IExpressionsListener2
+{
+ private IExpressionVMNode[] fExpressionNodes;
+
+ private IPropertyChangeListener fPreferencesListener = new IPropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ String property = event.getProperty();
+ if (property.equals(IDsfDebugUIConstants.PREF_WAIT_FOR_VIEW_UPDATE_AFTER_STEP_ENABLE)) {
+ IPreferenceStore store = DsfDebugUITools.getPreferenceStore();
+ setDelayEventHandleForViewUpdate(store.getBoolean(property));
+ }
+ }
+ };
+
+ private IPropertyChangeListener fPresentationContextListener = new IPropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ handleEvent(event);
+ }
+ };
+
+ public ExpressionVMProvider(AbstractVMAdapter adapter, IPresentationContext context, DsfSession session) {
+ super(adapter, context, session);
+
+ context.addPropertyChangeListener(fPresentationContextListener);
+
+ IPreferenceStore store = DsfDebugUITools.getPreferenceStore();
+ store.addPropertyChangeListener(fPreferencesListener);
+ setDelayEventHandleForViewUpdate(store.getBoolean(IDsfDebugUIConstants.PREF_WAIT_FOR_VIEW_UPDATE_AFTER_STEP_ENABLE));
+
+ // The VM provider has to handle all events that result in model deltas.
+ // Add the provider as listener to expression changes events.
+ DebugPlugin.getDefault().getExpressionManager().addExpressionListener(this);
+
+ configureLayout();
+ }
+
+ @Override
+ protected DefaultVMContentProviderStrategy createContentStrategy() {
+ return new ExpressionVMProviderContentStragegy(this);
+ }
+
+ @Override
+ protected IVMModelProxy createModelProxyStrategy(Object rootElement) {
+ return new ExpressionVMProviderModelProxyStrategy(this, rootElement);
+ }
+
+ /**
+ * Updates the given expression element. This method is used by the
+ * expression manager node to obtain a view model element based on the
+ * {@link IExpression} retrieved from the expression manager. The
+ * implementation of this method (which is in the content strategy),
+ * checks the configured expression nodes to see which one can
+ * process the given expression, when it finds it it delegates
+ * to that expression node's {@link IExpressionVMNode#update(IExpressionUpdate)}
+ * method.
+ * @param update Expression update to process.
+ */
+ public void update(IExpressionUpdate update) {
+ ((ExpressionVMProviderContentStragegy)getContentStrategy()).update(update);
+ }
+
+ /**
+ * Retrieves the delta flags that can be generated for the given expression
+ * and the given event. This method is used by the
+ * expression manager node to obtain the delta flags based on the
+ * {@link IExpression} retrieved from the expression manager. The
+ * implementation of this method (which is in the model proxy strategy),
+ * checks the configured expression nodes to see which one can
+ * process the given expression, when it finds it it delegates
+ * to that expression node's {@link IExpressionVMNode#getDeltaFlagsForExpression(IExpression, Object)}
+ * method.
+ */
+ public int getDeltaFlagsForExpression(IExpression expression, Object event) {
+ // Workaround: find the first active proxy and use it.
+ if (!getActiveModelProxies().isEmpty()) {
+ return ((ExpressionVMProviderModelProxyStrategy)getActiveModelProxies().get(0)).getDeltaFlagsForExpression(expression, event);
+ }
+ return 0;
+ }
+
+ /**
+ * Builds the model delta based on the given expression
+ * and the given event. This method is used by the
+ * expression manager to build the delta based on the
+ * {@link IExpression} retrieved from the expression manager. The
+ * implementation of this method (which is in the model proxy strategy),
+ * checks the configured expression nodes to see which one can
+ * process the given expression, when it finds it it delegates
+ * to that expression node's {@link IExpressionVMNode#buildDeltaForExpression(IExpression, int, Object, ModelDelta, TreePath, RequestMonitor)}
+ * and {@link IExpressionVMNode#buildDeltaForExpressionElement(Object, int, Object, ModelDelta, RequestMonitor)
+ * methods.
+ */
+ public void buildDeltaForExpression(final IExpression expression, final int expressionElementIdx, final Object event,
+ final VMDelta parentDelta, final TreePath path, final RequestMonitor rm)
+ {
+ // Workaround: find the first active proxy and use it.
+ if (!getActiveModelProxies().isEmpty()) {
+ ((ExpressionVMProviderModelProxyStrategy)getActiveModelProxies().get(0)).buildDeltaForExpression(
+ expression, expressionElementIdx, event, parentDelta, path, rm);
+ } else {
+ rm.done();
+ }
+ }
+
+ /**
+ * Configures the given nodes as the top-level expression nodes.
+ */
+ protected void setExpressionNodes(IExpressionVMNode[] nodes) {
+ fExpressionNodes = nodes;
+
+ // Call the base class to make sure that the nodes are also
+ // returned by the getAllNodes method.
+ for (IExpressionVMNode node : nodes) {
+ addNode(node);
+ }
+ }
+
+ /**
+ * Returns the list of configured top-level expression nodes.
+ * @return
+ */
+ public IExpressionVMNode[] getExpressionNodes() {
+ return fExpressionNodes;
+ }
+
+ /**
+ * Configures the nodes of this provider. This method may be over-ridden by
+ * sub classes to create an alternate configuration in this provider.
+ */
+ protected void configureLayout() {
+
+ IFormattedValuePreferenceStore prefStore = FormattedValuePreferenceStore.getDefault();
+
+ /*
+ * Allocate the synchronous data providers.
+ */
+ SyncRegisterDataAccess syncRegDataAccess = new SyncRegisterDataAccess(getSession());
+ SyncVariableDataAccess syncvarDataAccess = new SyncVariableDataAccess(getSession()) ;
+
+ /*
+ * Create the top level node which provides the anchor starting point.
+ */
+ IRootVMNode rootNode = new RootDMVMNode(this);
+
+ /*
+ * Now the Over-arching management node.
+ */
+ ExpressionManagerVMNode expressionManagerNode = new ExpressionManagerVMNode(this);
+ addChildNodes(rootNode, new IVMNode[] {expressionManagerNode});
+
+ /*
+ * The expression view wants to support fully all of the components of the register view.
+ */
+ IExpressionVMNode registerGroupNode = new RegisterGroupVMNode(this, getSession(), syncRegDataAccess);
+
+ IExpressionVMNode registerNode = new RegisterVMNode(prefStore, 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);
+ addChildNodes(registerNode, new IVMNode[] { bitFieldNode });
+
+ /*
+ * Create the support for the SubExpressions. Anything which is brought into the expressions
+ * 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);
+ addChildNodes(variableNode, new IExpressionVMNode[] {variableNode});
+
+ /*
+ * Tell the expression node which sub-nodes it will directly support. It is very important
+ * that the variables node be the last in this chain. The model assumes that there is some
+ * form of metalanguage expression syntax which each of the nodes evaluates and decides if
+ * they are dealing with it or not. The variables node assumes that the expression is fully
+ * qualified and there is no analysis or subdivision of the expression it will parse. So it
+ * it currently the case that the location of the nodes within the array being passed in is
+ * the order of search/evaluation. Thus variables wants to be last. Otherwise it would just
+ * assume what it was passed was for it and the real node which wants to handle it would be
+ * left out in the cold.
+ */
+ setExpressionNodes(new IExpressionVMNode[] {registerGroupNode, variableNode});
+
+ /*
+ * Let the work know which is the top level node.
+ */
+ setRootNode(rootNode);
+ }
+
+ /**
+ * Finds the expression node which can parse the given expression. This
+ * method is used by the expression content and model proxy strategies.
+ *
+ * @param parentNode The parent of the nodes to search. If <code>null</code>,
+ * then the top level expressions will be searched.
+ * @param expression The expression object.
+ * @return The matching expression node.
+ */
+ public IExpressionVMNode findNodeToParseExpression(IExpressionVMNode parentNode, IExpression expression) {
+ IVMNode[] childNOdes;
+ if (parentNode == null) {
+ childNOdes = getExpressionNodes();
+ } else {
+ childNOdes = getChildVMNodes(parentNode);
+ }
+ for (IVMNode childNode : childNOdes) {
+ if (childNode instanceof IExpressionVMNode) {
+ IExpressionVMNode childExpressionNode = (IExpressionVMNode)childNode;
+ if (childExpressionNode.canParseExpression(expression)) {
+ return childExpressionNode;
+ } else if (!childExpressionNode.equals(parentNode)) {
+ // The above check is to make sure that child isn't the same as
+ // parent to avoid recursive loops.
+ IExpressionVMNode matchingNode =
+ findNodeToParseExpression(childExpressionNode, expression);
+ if (matchingNode != null) {
+ return matchingNode;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+
+ @Override
+ public void dispose() {
+ DebugPlugin.getDefault().getExpressionManager().removeExpressionListener(this);
+ DsfDebugUITools.getPreferenceStore().removePropertyChangeListener(fPreferencesListener);
+ getPresentationContext().removePropertyChangeListener(fPresentationContextListener);
+ super.dispose();
+ }
+
+ @Override
+ public IColumnPresentation createColumnPresentation(IPresentationContext context, Object element) {
+ return new ExpressionColumnPresentation();
+ }
+
+ @Override
+ public String getColumnPresentationId(IPresentationContext context, Object element) {
+ return ExpressionColumnPresentation.ID;
+ }
+
+ @Override
+ protected IVMUpdatePolicy[] createUpdateModes() {
+ return new IVMUpdatePolicy[] { new AutomaticUpdatePolicy(), new ExpressionsManualUpdatePolicy(),
+ new ExpressionsBreakpointHitUpdatePolicy() };
+ }
+
+ public void expressionsAdded(IExpression[] expressions) {
+ expressionsListChanged(ExpressionsChangedEvent.Type.ADDED, expressions, -1);
+ }
+
+ public void expressionsRemoved(IExpression[] expressions) {
+ expressionsListChanged(ExpressionsChangedEvent.Type.REMOVED, expressions, -1);
+ }
+
+ public void expressionsInserted(IExpression[] expressions, int index) {
+ expressionsListChanged(ExpressionsChangedEvent.Type.INSERTED, expressions, index);
+ }
+
+ public void expressionsMoved(IExpression[] expressions, int index) {
+ expressionsListChanged(ExpressionsChangedEvent.Type.MOVED, expressions, index);
+ }
+
+ public void expressionsChanged(IExpression[] expressions) {
+ expressionsListChanged(ExpressionsChangedEvent.Type.CHANGED, expressions, -1);
+ }
+
+ private void expressionsListChanged(ExpressionsChangedEvent.Type type, IExpression[] expressions, int index) {
+ Set<Object> rootElements = new HashSet<Object>();
+ for (IVMModelProxy proxy : getActiveModelProxies()) {
+ rootElements.add(proxy.getRootElement());
+ }
+ handleEvent(new ExpressionsChangedEvent(type, rootElements, expressions, index));
+ }
+
+ @Override
+ protected boolean canSkipHandlingEvent(Object newEvent, Object eventToSkip) {
+ // To optimize the performance of the view when stepping rapidly, skip all
+ // other events when a suspended event is received, including older suspended
+ // events.
+ return newEvent instanceof ISuspendedDMEvent;
+ }
+
+ @Override
+ public void refresh() {
+ super.refresh();
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ DsfServicesTracker tracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), getSession().getId());
+ IExpressions expressionsService = tracker.getService(IExpressions.class);
+ if (expressionsService instanceof ICachingService) {
+ ((ICachingService)expressionsService).flushCache(null);
+ }
+ IRegisters registerService = tracker.getService(IRegisters.class);
+ if (registerService instanceof ICachingService) {
+ ((ICachingService)registerService).flushCache(null);
+ }
+ tracker.dispose();
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ // Session disposed, ignore.
+ }
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProviderContentStragegy.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProviderContentStragegy.java
new file mode 100644
index 00000000000..55535acc67c
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProviderContentStragegy.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * 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.debug.ui.viewmodel.expression;
+
+import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor;
+import org.eclipse.cdt.dsf.ui.viewmodel.DefaultVMContentProviderStrategy;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+/**
+ * The IElementContentProvider implementation to be used with an expression
+ * view model provider.
+ *
+ * @see ExpressionVMProvider
+ */
+@SuppressWarnings("restriction")
+public class ExpressionVMProviderContentStragegy extends DefaultVMContentProviderStrategy {
+ public ExpressionVMProviderContentStragegy(ExpressionVMProvider provider) {
+ super(provider);
+ }
+
+ private ExpressionVMProvider getExpressionVMProvider() {
+ return (ExpressionVMProvider)getVMProvider();
+ }
+
+ public void update(final IExpressionUpdate update) {
+ final IExpressionVMNode matchingNode =
+ getExpressionVMProvider().findNodeToParseExpression(null, update.getExpression());
+
+ if (matchingNode != null) {
+ updateExpressionWithNode(matchingNode, update);
+ } else {
+ update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Cannot parse expression", null)); //$NON-NLS-1$
+ update.done();
+ }
+ }
+
+ private void updateExpressionWithNode(final IExpressionVMNode node, final IExpressionUpdate update) {
+ // Call the expression node to parse the expression and fill in the value.
+ node.update(
+ new VMExpressionUpdate(
+ update, update.getExpression(),
+ new ViewerDataRequestMonitor<Object>(getVMProvider().getExecutor(), update) {
+ @Override
+ protected void handleSuccess() {
+ // Check if the evaluated node has child expression nodes.
+ // If it does, check if any of those nodes can evaluate the given
+ // expression further. If they can, call the child node to further
+ // process the expression. Otherwise we found our element and
+ // we're done.
+ final IExpressionVMNode matchingNode = getExpressionVMProvider().
+ findNodeToParseExpression(node, update.getExpression());
+
+ if (matchingNode != null && !matchingNode.equals(node)) {
+ updateExpressionWithNode(
+ matchingNode,
+ new VMExpressionUpdate(
+ update.getElementPath().createChildPath(getData()), update.getViewerInput(),
+ update.getPresentationContext(), update.getExpression(),
+ new ViewerDataRequestMonitor<Object>(getVMProvider().getExecutor(), update) {
+
+ @Override
+ protected void handleSuccess() {
+ update.setExpressionElement(getData());
+ update.done();
+ }
+ })
+ );
+ } else {
+ update.setExpressionElement(getData());
+ update.done();
+ }
+ }
+ })
+ );
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProviderModelProxyStrategy.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProviderModelProxyStrategy.java
new file mode 100644
index 00000000000..fb59a74e02e
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProviderModelProxyStrategy.java
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * 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.debug.ui.viewmodel.expression;
+
+import java.util.Map;
+
+import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.ui.viewmodel.DefaultVMModelProxyStrategy;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta;
+import org.eclipse.debug.core.model.IExpression;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+import org.eclipse.jface.viewers.TreePath;
+
+/**
+ * The IModelProxy implementation to be used with an expression
+ * view model provider.
+ *
+ * @see ExpressionVMProvider
+ */
+@SuppressWarnings("restriction")
+public class ExpressionVMProviderModelProxyStrategy extends DefaultVMModelProxyStrategy {
+
+ public ExpressionVMProviderModelProxyStrategy(ExpressionVMProvider provider, Object rootElement) {
+ super(provider, rootElement);
+ }
+
+ private ExpressionVMProvider getExpressionVMProvider() {
+ return (ExpressionVMProvider)getVMProvider();
+ }
+
+ public int getDeltaFlagsForExpression(IExpression expression, Object event) {
+ final IExpressionVMNode matchingNode = getExpressionVMProvider().findNodeToParseExpression(null, expression);
+
+ if (matchingNode != null) {
+ return getNodeDeltaFlagsForExpression(matchingNode, expression, event);
+ }
+ return IModelDelta.NO_CHANGE;
+ }
+
+ private int getNodeDeltaFlagsForExpression(IExpressionVMNode node, IExpression expression, Object event) {
+ int flags = node.getDeltaFlagsForExpression(expression, event);
+
+ IExpressionVMNode matchingNode = getExpressionVMProvider().findNodeToParseExpression(node, expression);
+ if (matchingNode != null && !matchingNode.equals(node)) {
+ flags = flags | getNodeDeltaFlagsForExpression(matchingNode, expression, event);
+ } else {
+ // Check the child nodes of this expression node for additional
+ // delta flags.
+ for (IVMNode childNode : getVMProvider().getChildVMNodes(node)) {
+ if (!childNode.equals(node)) {
+ int childNodeDeltaFlags = getDeltaFlags(childNode, null, event);
+ if ((childNodeDeltaFlags & IModelDelta.CONTENT) != 0) {
+ childNodeDeltaFlags &= ~IModelDelta.CONTENT;
+ childNodeDeltaFlags |= IModelDelta.STATE;
+ }
+ flags |= childNodeDeltaFlags;
+ }
+ }
+ }
+ return flags;
+ }
+
+ public void buildDeltaForExpression(IExpression expression, int expressionElementIdx, Object event,
+ VMDelta parentDelta, TreePath path, RequestMonitor rm)
+ {
+ final IExpressionVMNode matchingNode = getExpressionVMProvider().findNodeToParseExpression(null, expression);
+
+ if (matchingNode != null) {
+ buildNodeDeltaForExpression(matchingNode, expression, expressionElementIdx, event,
+ parentDelta, path, rm);
+ } else {
+ rm.done();
+ }
+ }
+
+ private void buildNodeDeltaForExpression(final IExpressionVMNode node, final IExpression expression,
+ final int expressionElementIdx, final Object event, final VMDelta parentDelta, final TreePath path,
+ final RequestMonitor rm)
+ {
+ node.buildDeltaForExpression(
+ expression, expressionElementIdx, event, parentDelta, path,
+ new RequestMonitor(getVMProvider().getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ final IExpressionVMNode matchingNode =
+ getExpressionVMProvider().findNodeToParseExpression(node, expression);
+ if (matchingNode != null && !matchingNode.equals(node)) {
+ buildNodeDeltaForExpression(
+ matchingNode, expression, expressionElementIdx, event, parentDelta, path, rm);
+ } else {
+ getExpressionVMProvider().update(new VMExpressionUpdate(
+ parentDelta, getVMProvider().getPresentationContext(), expression,
+ new DataRequestMonitor<Object>(getVMProvider().getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ buildDeltaForExpressionElement(
+ node, expression, getData(), expressionElementIdx, event, parentDelta, path, rm);
+ }
+
+ @Override
+ protected void handleErrorOrWarning() {
+ // Avoid propagating the error to avoid processing the delta by
+ // all nodes.
+ rm.done();
+ }
+ }));
+ }
+ }
+ });
+ }
+
+
+ private void buildDeltaForExpressionElement(IExpressionVMNode node, IExpression expression, Object expressionElement,
+ int expressionElementIdx, Object event, VMDelta parentDelta, TreePath path, RequestMonitor rm)
+ {
+ CountingRequestMonitor multiRm = new CountingRequestMonitor(getVMProvider().getExecutor(), rm);
+ int multiRmCount = 0;
+
+ node.buildDeltaForExpressionElement(expressionElement, expressionElementIdx, event, parentDelta, multiRm);
+ multiRmCount++;
+
+ // Find the child nodes that have deltas for the given event.
+ Map<IVMNode,Integer> childNodesWithDeltaFlags = getChildNodesWithDeltaFlags(node, parentDelta, event);
+
+ // If no child layout nodes have deltas we can stop here.
+ if (childNodesWithDeltaFlags.size() != 0) {
+ callChildNodesToBuildDelta(
+ node, childNodesWithDeltaFlags,
+ parentDelta.addNode(expressionElement, expressionElementIdx, IModelDelta.NO_CHANGE),
+ event, multiRm);
+ multiRmCount++;
+ }
+
+ if (event instanceof ExpressionsChangedEvent) {
+ buildDeltaForExpressionsChangedEvent(expressionElement, expressionElementIdx,
+ (ExpressionsChangedEvent)event, parentDelta, multiRm);
+ multiRmCount++;
+ }
+
+ multiRm.setDoneCount(multiRmCount);
+ }
+
+ private void buildDeltaForExpressionsChangedEvent(Object element, int elementIdx, ExpressionsChangedEvent event,
+ VMDelta parentDelta, final RequestMonitor rm)
+ {
+ switch (event.getType()) {
+ case ADDED:
+ parentDelta.addNode(element, -1, IModelDelta.ADDED);
+ break;
+ case CHANGED:
+ parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
+ break;
+ case MOVED:
+ parentDelta.addNode(element, -1, IModelDelta.REMOVED);
+ parentDelta.addNode(element, elementIdx, IModelDelta.INSERTED);
+ break;
+ case REMOVED:
+ parentDelta.addNode(element, -1, IModelDelta.REMOVED);
+ break;
+ case INSERTED:
+ parentDelta.addNode(element, elementIdx, IModelDelta.INSERTED);
+ break;
+ default:
+ break;
+ }
+ rm.done();
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionsBreakpointHitUpdatePolicy.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionsBreakpointHitUpdatePolicy.java
new file mode 100644
index 00000000000..63bdc7f58bc
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionsBreakpointHitUpdatePolicy.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * 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.expression;
+
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.update.BreakpointHitUpdatePolicy;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.IElementUpdateTester;
+
+/**
+ * Manual update policy which selectively clears the cache when the expressions
+ * in the expression manager are modified.
+ */
+public class ExpressionsBreakpointHitUpdatePolicy extends BreakpointHitUpdatePolicy {
+
+ @Override
+ public IElementUpdateTester getElementUpdateTester(Object event) {
+ if (event instanceof ExpressionsChangedEvent) {
+ return new ExpressionsChangedUpdateTester((ExpressionsChangedEvent)event);
+ }
+ return super.getElementUpdateTester(event);
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionsChangedEvent.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionsChangedEvent.java
new file mode 100644
index 00000000000..058a6f39e2a
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionsChangedEvent.java
@@ -0,0 +1,38 @@
+package org.eclipse.cdt.dsf.debug.ui.viewmodel.expression;
+
+import java.util.Arrays;
+import java.util.Set;
+
+import org.eclipse.debug.core.model.IExpression;
+
+/**
+ * Object representing a change in configured expressions. This event is
+ * object is used when generating a model delta.
+ */
+public class ExpressionsChangedEvent {
+ enum Type {ADDED, CHANGED, REMOVED, MOVED, INSERTED}
+
+ private final Set<Object> fExpressionManagerElements;
+ private final ExpressionsChangedEvent.Type fType;
+ private final IExpression[] fExpressions;
+ private final int fIndex;
+
+ public ExpressionsChangedEvent(ExpressionsChangedEvent.Type type, Set<Object> expressionManagerElements,
+ IExpression[] expressions, int index)
+ {
+ fExpressionManagerElements = expressionManagerElements;
+ fType = type;
+ fExpressions = expressions;
+ fIndex = index;
+ }
+
+ public Set<Object> getExpressionManagerElements() { return fExpressionManagerElements; }
+ public ExpressionsChangedEvent.Type getType() { return fType; }
+ public IExpression[] getExpressions() { return fExpressions; }
+ public int getIndex() { return fIndex; }
+
+ @Override
+ public String toString() {
+ return Arrays.asList(fExpressions).toString() + " " + fType + "@" + fIndex; //$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/debug/ui/viewmodel/expression/ExpressionsChangedUpdateTester.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionsChangedUpdateTester.java
new file mode 100644
index 00000000000..9f29b3c466a
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionsChangedUpdateTester.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * 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.expression;
+
+import org.eclipse.cdt.dsf.ui.viewmodel.update.IElementUpdateTester;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.debug.core.model.IExpression;
+import org.eclipse.jface.viewers.TreePath;
+
+class ExpressionsChangedUpdateTester implements IElementUpdateTester {
+
+ private final ExpressionsChangedEvent fEvent;
+
+ public ExpressionsChangedUpdateTester(ExpressionsChangedEvent event) {
+ fEvent = event;
+ }
+
+ public int getUpdateFlags(Object viewerInput, TreePath path) {
+ // Check whether the element in the cache matches the expression manager element.
+ Object element = path.getSegmentCount() == 0 ? viewerInput : path.getLastSegment();
+ if (fEvent.getExpressionManagerElements().contains(element)) {
+ return ExpressionsManualUpdatePolicy.FLUSH;
+ }
+
+ // If the expressions were modified, flush the entries which are under the
+ // given expression. To do that, check whether the element path contains one
+ // of the changed expressions.
+ if (fEvent.getType().equals(ExpressionsChangedEvent.Type.CHANGED)) {
+ for (int i = 0; i < path.getSegmentCount(); i++) {
+ if (eventContainsElement(path.getSegment(i))) {
+ return ExpressionsManualUpdatePolicy.FLUSH;
+ }
+ }
+ }
+ return 0;
+ }
+
+ private boolean eventContainsElement(Object element) {
+ if (element instanceof IAdaptable) {
+ IExpression expression = (IExpression)((IAdaptable)element).getAdapter(IExpression.class);
+ if (expression != null) {
+ for (int i = 0; i < fEvent.getExpressions().length; i++) {
+ if (expression.equals(fEvent.getExpressions()[i])) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ public boolean includes(IElementUpdateTester tester) {
+ return tester instanceof ExpressionsChangedUpdateTester;
+ }
+
+ @Override
+ public String toString() {
+ return "(" + fEvent + ") update tester"; //$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/debug/ui/viewmodel/expression/ExpressionsManualUpdatePolicy.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionsManualUpdatePolicy.java
new file mode 100644
index 00000000000..8ca367468a6
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionsManualUpdatePolicy.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * 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.expression;
+
+import org.eclipse.cdt.dsf.ui.viewmodel.update.IElementUpdateTester;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.ManualUpdatePolicy;
+
+/**
+ * Manual update policy which selectively clears the cache when the expressions
+ * in the expression manager are modified.
+ */
+public class ExpressionsManualUpdatePolicy extends ManualUpdatePolicy {
+
+ @Override
+ public IElementUpdateTester getElementUpdateTester(Object event) {
+ if (event instanceof ExpressionsChangedEvent) {
+ return new ExpressionsChangedUpdateTester((ExpressionsChangedEvent)event);
+ }
+ return super.getElementUpdateTester(event);
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/IExpressionUpdate.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/IExpressionUpdate.java
new file mode 100644
index 00000000000..e3fd41fc4a7
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/IExpressionUpdate.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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.debug.ui.viewmodel.expression;
+
+import org.eclipse.debug.core.model.IExpression;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
+
+/**
+ * An update for an element based on the given expression. The provider processing
+ * this update needs to create an expression element based on the tree path and the
+ * expression object in this update.
+ */
+@SuppressWarnings("restriction")
+public interface IExpressionUpdate extends IViewerUpdate {
+
+ /**
+ * Returns the expression object for this update.
+ */
+ public IExpression getExpression();
+
+ /**
+ * Sets the element to the update. The element is to be calculated by the provider
+ * handling the update.
+ */
+ public void setExpressionElement(Object element);
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/IExpressionVMNode.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/IExpressionVMNode.java
new file mode 100644
index 00000000000..1403d73d25e
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/IExpressionVMNode.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * 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.debug.ui.viewmodel.expression;
+
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta;
+import org.eclipse.debug.core.model.IExpression;
+import org.eclipse.jface.viewers.TreePath;
+
+/**
+ * Interface for view model nodes that can be used within the expression view.
+ * The methods of this interface allow the {@link ExpressionManagerVMNode}
+ * to use this node to delegate expression parsing to this node, and to
+ * generate deltas for expressions that are owned by this node.
+ */
+public interface IExpressionVMNode extends IVMNode {
+
+ /**
+ * Returns whether the given expression node recognizes and can parse the given
+ * expression.
+ * @param expression Expression that needs to be parsed.
+ * @return true if expression can be parsed
+ */
+ public boolean canParseExpression(IExpression expression);
+
+ /**
+ * Asynchronously fills in the given expression update.
+ * @param update Update to complete.
+ */
+ public void update(IExpressionUpdate update);
+
+ /**
+ * Returns the flags that this node can generate for the given expression and
+ * event.
+ */
+ public int getDeltaFlagsForExpression(IExpression expression, Object event);
+
+ /**
+ * Adds delta flags to the given parent delta based on the expression
+ * object given. The nodes add flags to the expression view's root
+ * delta using this method, regardless of whether the node is directly
+ * below the expression manager or not.
+ *
+ */
+ public void buildDeltaForExpression(IExpression expression, int elementIdx, Object event, VMDelta parentDelta,
+ TreePath path, RequestMonitor rm);
+
+ /**
+ * Adds delta to the given parent delta based on the given element that
+ * was created base on an expression parsed by this node. The VM nodes can
+ * add a new delta node to the parentDela by implementing this method.
+ */
+ public void buildDeltaForExpressionElement(Object element, int elementIdx, Object event, VMDelta parentDelta, final RequestMonitor rm);
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/InvalidExpressionVMContext.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/InvalidExpressionVMContext.java
new file mode 100644
index 00000000000..9731351bb98
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/InvalidExpressionVMContext.java
@@ -0,0 +1,88 @@
+package org.eclipse.cdt.dsf.debug.ui.viewmodel.expression;
+
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants;
+import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMContext;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
+import org.eclipse.debug.core.model.IExpression;
+import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
+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.jface.resource.JFaceResources;
+
+/**
+ * VMC of an expression object that failed to get parsed by any of the
+ * configured expression layout nodes. It is only used to display an
+ * error message in the view, and to allow the user to edit the
+ * expression.
+ * <p>
+ * Note: VM Nodes using this invalid expression VM context should
+ * provide a cell modifier to edit the expressions. The cell modifier
+ * should subclass {@link WatchExpressionCellModifier}.
+ * </p>
+ *
+ * @since 1.1
+ */
+@SuppressWarnings("restriction")
+public class InvalidExpressionVMContext extends AbstractVMContext implements IElementLabelProvider {
+
+ final private IExpression fExpression;
+
+ public InvalidExpressionVMContext(IVMNode node, IExpression expression) {
+ super(node);
+ fExpression = expression;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Class adapter) {
+ if (adapter.isAssignableFrom(fExpression.getClass())) {
+ return fExpression;
+ } else {
+ return super.getAdapter(adapter);
+ }
+ }
+
+ public IExpression getExpression() {
+ return fExpression;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof InvalidExpressionVMContext && ((InvalidExpressionVMContext)obj).fExpression.equals(fExpression);
+ }
+
+ @Override
+ public int hashCode() {
+ return fExpression.hashCode();
+ }
+
+ /**
+ * Updates the label for the InvalidExpressionVMC.
+ */
+ public void update(ILabelUpdate[] updates) {
+ for (ILabelUpdate update : updates) {
+ String[] columnIds = update.getColumnIds() != null ?
+ update.getColumnIds() : new String[] { IDebugVMConstants.COLUMN_ID__NAME };
+
+ for (int i = 0; i < columnIds.length; i++) {
+ if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(columnIds[i])) {
+ update.setLabel(getExpression().getExpressionText(), i);
+ update.setImageDescriptor(DebugUITools.getImageDescriptor( IDebugUIConstants.IMG_OBJS_EXPRESSION ), i);
+ } else if (IDebugVMConstants.COLUMN_ID__NAME.equals(columnIds[i])) {
+ update.setLabel(getExpression().getExpressionText(), i);
+ update.setImageDescriptor(DebugUITools.getImageDescriptor( IDebugUIConstants.IMG_OBJS_EXPRESSION ), i);
+ } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(columnIds[i])) {
+ update.setLabel(MessagesForExpressionVM.ExpressionManagerLayoutNode__invalidExpression_valueColumn_label, i);
+ } else {
+ update.setLabel("", i); //$NON-NLS-1$
+ }
+ update.setFontData(JFaceResources.getFontDescriptor(IInternalDebugUIConstants.VARIABLE_TEXT_FONT).getFontData()[0], i);
+ }
+
+ update.done();
+ }
+ }
+
+} \ No newline at end of file
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/MessagesForExpressionVM.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/MessagesForExpressionVM.java
new file mode 100644
index 00000000000..02014605b57
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/MessagesForExpressionVM.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * 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.expression;
+
+import org.eclipse.osgi.util.NLS;
+
+public class MessagesForExpressionVM extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.messages"; //$NON-NLS-1$
+
+ public static String ExpressionColumnPresentation_expression;
+ public static String ExpressionColumnPresentation_name;
+ public static String ExpressionColumnPresentation_type;
+ public static String ExpressionColumnPresentation_value;
+ public static String ExpressionColumnPresentation_address;
+ public static String ExpressionColumnPresentation_description;
+
+ public static String ExpressionManagerLayoutNode__invalidExpression_nameColumn_label;
+ public static String ExpressionManagerLayoutNode__invalidExpression_valueColumn_label;
+
+ public static String ExpressionManagerLayoutNode__newExpression_label;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, MessagesForExpressionVM.class);
+ }
+
+ private MessagesForExpressionVM() {
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/VMExpressionUpdate.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/VMExpressionUpdate.java
new file mode 100644
index 00000000000..8f64c623b28
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/VMExpressionUpdate.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * 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.debug.ui.viewmodel.expression;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.cdt.dsf.ui.viewmodel.VMViewerUpdate;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.model.IExpression;
+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.jface.viewers.TreePath;
+
+/**
+ *
+ */
+@SuppressWarnings("restriction")
+class VMExpressionUpdate extends VMViewerUpdate implements IExpressionUpdate {
+
+ private final IExpression fExpression;
+ private Object fExpressionElement;
+
+ public VMExpressionUpdate(IViewerUpdate clientUpdate, IExpression expression, DataRequestMonitor<Object> rm)
+ {
+ super(clientUpdate, rm);
+ fExpression = expression;
+ }
+
+ public VMExpressionUpdate(IModelDelta delta, IPresentationContext presentationContext, IExpression expression, DataRequestMonitor<Object> rm)
+ {
+ super(delta, presentationContext, rm);
+ fExpression = expression;
+ }
+
+ public VMExpressionUpdate(TreePath elementPath, Object viewerInput, IPresentationContext presentationContext, IExpression expression, DataRequestMonitor<Object> rm)
+ {
+ super(elementPath, viewerInput, presentationContext, rm);
+ fExpression = expression;
+ }
+
+
+ public IExpression getExpression() {
+ return fExpression;
+ }
+
+
+ public void setExpressionElement(Object element) {
+ fExpressionElement = element;
+ }
+
+ @Override
+ public String toString() {
+ return "VMExpressionUpdate for elements under parent = " + getElement() + ", in for expression " + getExpression().getExpressionText(); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ @Override
+ public void done() {
+ @SuppressWarnings("unchecked")
+
+ DataRequestMonitor<Object> rm = (DataRequestMonitor<Object>)getRequestMonitor();
+ if (fExpressionElement != null) {
+ rm.setData(fExpressionElement);
+ } else if (rm.isSuccess()) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "Incomplete elements of updates", null)); //$NON-NLS-1$
+ }
+ super.done();
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/WatchExpressionCellModifier.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/WatchExpressionCellModifier.java
new file mode 100644
index 00000000000..8f4413bab8a
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/WatchExpressionCellModifier.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * 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.expression;
+
+import org.eclipse.cdt.dsf.concurrent.ThreadSafeAndProhibitedFromDsfExecutor;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.ExpressionManagerVMNode.NewExpressionVMC;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IExpressionManager;
+import org.eclipse.debug.core.model.IWatchExpression;
+import org.eclipse.jface.viewers.ICellModifier;
+
+/**
+ *
+ */
+@ThreadSafeAndProhibitedFromDsfExecutor("")
+public class WatchExpressionCellModifier implements ICellModifier {
+
+ /**
+ * Constructor for the modifier requires a valid DSF session in order to
+ * initialize the service tracker.
+ * @param session DSF session this modifier will use.
+ */
+ public WatchExpressionCellModifier() {
+ }
+
+ public boolean canModify(Object element, String property) {
+ return IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(property) &&
+ (getWatchExpression(element) != null || element instanceof NewExpressionVMC);
+ }
+
+ public Object getValue(Object element, String property) {
+ if (!IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(property)) return ""; //$NON-NLS-1$
+
+ IWatchExpression expression = getWatchExpression(element);
+
+ if (expression != null) {
+ return expression.getExpressionText();
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ public void modify(Object element, String property, Object value) {
+ if (!IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(property)) return;
+ if (!(value instanceof String)) return;
+
+ String origStrValue = (String) value;
+ String strValue = origStrValue.trim();
+ IWatchExpression expression = getWatchExpression(element);
+ IExpressionManager expressionManager = DebugPlugin.getDefault().getExpressionManager();
+ if (expression != null) {
+ if (strValue.length() != 0) {
+ expression.setExpressionText(origStrValue);
+ } else {
+ // (bug 233111) If user entered a blank string, remove the expression.
+ expressionManager.removeExpression(expression);
+ }
+ } else if (element instanceof NewExpressionVMC && strValue.length() != 0) {
+ IWatchExpression watchExpression = expressionManager.newWatchExpression(origStrValue);
+ expressionManager.addExpression(watchExpression);
+ }
+ }
+
+ private IWatchExpression getWatchExpression(Object element) {
+ if (element instanceof IAdaptable) {
+ return (IWatchExpression)((IAdaptable)element).getAdapter(IWatchExpression.class);
+ }
+ return null;
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/WatchExpressionDelegate.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/WatchExpressionDelegate.java
new file mode 100644
index 00000000000..91fa6f1492c
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/WatchExpressionDelegate.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * 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.debug.ui.viewmodel.expression;
+
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.model.IDebugElement;
+import org.eclipse.debug.core.model.IValue;
+import org.eclipse.debug.core.model.IWatchExpressionDelegate;
+import org.eclipse.debug.core.model.IWatchExpressionListener;
+import org.eclipse.debug.core.model.IWatchExpressionResult;
+
+/**
+ *
+ */
+public class WatchExpressionDelegate implements IWatchExpressionDelegate {
+ public void evaluateExpression(final String expression, IDebugElement context, IWatchExpressionListener listener) {
+ listener.watchEvaluationFinished(new IWatchExpressionResult() {
+ public String[] getErrorMessages() { return new String[0]; }
+ public DebugException getException() { return null; }
+ public String getExpressionText() { return expression; }
+ public IValue getValue() { return null; }
+ public boolean hasErrors() { return false; }
+ });
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/messages.properties b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/messages.properties
new file mode 100644
index 00000000000..9102d757a58
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/messages.properties
@@ -0,0 +1,21 @@
+###############################################################################
+# 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
+# Wind River Systems - added Address
+###############################################################################
+
+ExpressionColumnPresentation_expression=Expression
+ExpressionColumnPresentation_name=Name
+ExpressionColumnPresentation_type=Type
+ExpressionColumnPresentation_value=Value
+ExpressionColumnPresentation_address=Address
+ExpressionColumnPresentation_description=Description
+ExpressionManagerLayoutNode__invalidExpression_nameColumn_label=Invalid expression
+ExpressionManagerLayoutNode__invalidExpression_valueColumn_label=Invalid expression
+ExpressionManagerLayoutNode__newExpression_label=Add new expression
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
new file mode 100644
index 00000000000..26cfc2d5468
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/AbstractContainerVMNode.java
@@ -0,0 +1,191 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Wind River Systems, Inc. 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:
+ * Anton Leherbauer (Wind River Systems) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.ui.viewmodel.launch;
+
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+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.datamodel.IDMEvent;
+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.IExitedDMEvent;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IStartedDMEvent;
+import org.eclipse.cdt.dsf.debug.service.StepQueueManager.ISteppingTimedOutEvent;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.SteppingController.SteppingTimedOutEvent;
+import org.eclipse.cdt.dsf.service.DsfSession;
+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.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;
+
+/**
+ * Abstract implementation of a container view model node.
+ * Clients need to implement {@link #updateLabelInSessionThread(ILabelUpdate[])}.
+ *
+ * @since 1.1
+ */
+@SuppressWarnings("restriction")
+public abstract class AbstractContainerVMNode extends AbstractDMVMNode implements IElementLabelProvider {
+
+ 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);
+ }
+ }
+ }
+
+ /**
+ * 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 update);
+
+ @Override
+ public void getContextsForEvent(VMDelta parentDelta, Object e, final DataRequestMonitor<IVMContext[]> rm) {
+ super.getContextsForEvent(parentDelta, e, rm);
+ }
+
+ public int getDeltaFlags(Object e) {
+ IDMContext dmc = e instanceof IDMEvent<?> ? ((IDMEvent<?>)e).getDMContext() : null;
+
+ if (e instanceof IContainerResumedDMEvent) {
+ if (((IContainerResumedDMEvent)e).getReason() != IRunControl.StateChangeReason.STEP)
+ {
+ return IModelDelta.CONTENT;
+ }
+ } else if (e instanceof IContainerSuspendedDMEvent) {
+ return IModelDelta.NO_CHANGE;
+ } else if (e instanceof FullStackRefreshEvent) {
+ if (dmc instanceof IContainerDMContext) {
+ return IModelDelta.CONTENT;
+ }
+ } else if (e instanceof SteppingTimedOutEvent) {
+ if (dmc instanceof IContainerDMContext)
+ {
+ return IModelDelta.CONTENT;
+ }
+ } else if (e instanceof ISteppingTimedOutEvent) {
+ if (dmc instanceof IContainerDMContext)
+ {
+ return IModelDelta.CONTENT;
+ }
+ } else if (e instanceof IExitedDMEvent) {
+ return IModelDelta.CONTENT;
+ } else if (e instanceof IStartedDMEvent) {
+ if (dmc instanceof IContainerDMContext) {
+ return IModelDelta.EXPAND | IModelDelta.SELECT;
+ } else {
+ return IModelDelta.CONTENT;
+ }
+ }
+ return IModelDelta.NO_CHANGE;
+ }
+
+ public void buildDelta(Object e, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor requestMonitor) {
+ IDMContext dmc = e instanceof IDMEvent<?> ? ((IDMEvent<?>)e).getDMContext() : null;
+
+ if(e instanceof IContainerResumedDMEvent) {
+ // Container resumed:
+ // - If not stepping, update the container and the execution
+ // contexts under it.
+ // - If stepping, do nothing to avoid too many updates. If a
+ // time-out is reached before the step completes, the
+ // ISteppingTimedOutEvent will trigger a full refresh.
+ if (((IContainerResumedDMEvent)e).getReason() != IRunControl.StateChangeReason.STEP)
+ {
+ parentDelta.addNode(createVMContext(((IDMEvent<?>)e).getDMContext()), IModelDelta.CONTENT);
+ }
+ } else if (e instanceof IContainerSuspendedDMEvent) {
+ // Container suspended. Do nothing here to give the stack the
+ // priority in updating. The container and threads will update as
+ // a result of FullStackRefreshEvent.
+ } else if (e instanceof FullStackRefreshEvent) {
+ // Full-stack refresh event is generated following a suspended event
+ // and a fixed delay. If the suspended event was generated for the
+ // container refresh the whole container.
+ if (dmc instanceof IContainerDMContext) {
+ parentDelta.addNode(createVMContext(dmc), IModelDelta.CONTENT);
+ }
+ } else if (e instanceof SteppingTimedOutEvent) {
+ // Stepping time-out indicates that a step operation is taking
+ // a long time, and the view needs to be refreshed to show
+ // the user that the program is running.
+ // If the step was issued for the whole container refresh
+ // the whole container.
+ if (dmc instanceof IContainerDMContext) {
+ parentDelta.addNode(createVMContext(dmc), IModelDelta.CONTENT);
+ }
+ } else if (e instanceof ISteppingTimedOutEvent) {
+ // Stepping time-out indicates that a step operation is taking
+ // a long time, and the view needs to be refreshed to show
+ // the user that the program is running.
+ // If the step was issued for the whole container refresh
+ // the whole container.
+ if (dmc instanceof IContainerDMContext) {
+ parentDelta.addNode(createVMContext(dmc), IModelDelta.CONTENT);
+ }
+ } else if (e instanceof IExitedDMEvent) {
+ // An exited event could either be for a thread within a container
+ // or for the container itself.
+ // If a container exited, refresh the parent element so that the
+ // container may be removed.
+ // If a thread exited within a container, refresh that container.
+ if (dmc instanceof IContainerDMContext) {
+ parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
+ } else {
+ IContainerDMContext containerCtx = DMContexts.getAncestorOfType(dmc, IContainerDMContext.class);
+ if (containerCtx != null) {
+ parentDelta.addNode(createVMContext(containerCtx), IModelDelta.CONTENT);
+ }
+ }
+ } else if (e instanceof IStartedDMEvent) {
+ // A started event could either be for a thread within a container
+ // or for the container itself.
+ // If a container started, issue an expand and select event to
+ // show the threads in the new container.
+ // Note: the EXPAND flag implies refreshing the parent element.
+ if (dmc instanceof IContainerDMContext) {
+ parentDelta.addNode(createVMContext(dmc), IModelDelta.EXPAND | IModelDelta.SELECT);
+ } else {
+ IContainerDMContext containerCtx = DMContexts.getAncestorOfType(dmc, IContainerDMContext.class);
+ if (containerCtx != null) {
+ parentDelta.addNode(createVMContext(containerCtx), IModelDelta.CONTENT);
+ }
+ }
+ }
+
+ requestMonitor.done();
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/AbstractLaunchVMProvider.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/AbstractLaunchVMProvider.java
new file mode 100644
index 00000000000..28de36ba1d8
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/AbstractLaunchVMProvider.java
@@ -0,0 +1,294 @@
+/*******************************************************************************
+ * 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
+ * Ericsson - Modified for new functionality
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.ui.viewmodel.launch;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.datamodel.IDMEvent;
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IExitedDMEvent;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IStartedDMEvent;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
+import org.eclipse.cdt.dsf.debug.ui.IDsfDebugUIConstants;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.LaunchRootVMNode.LaunchesEvent;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.StackFramesVMNode.IncompleteStackVMContext;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMAdapter;
+import org.eclipse.cdt.dsf.ui.viewmodel.IRootVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMModelProxy;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.AutomaticUpdatePolicy;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.IVMUpdatePolicy;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.ManualUpdatePolicy;
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IDebugEventSetListener;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchesListener2;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+
+
+/**
+ * @since 1.1
+ */
+@SuppressWarnings("restriction")
+public class AbstractLaunchVMProvider extends AbstractDMVMProvider
+ implements IDebugEventSetListener, ILaunchesListener2
+{
+ /**
+ * Delay (in milliseconds) before a full stack trace will be requested.
+ */
+ private static final int FRAME_UPDATE_DELAY= 200;
+
+ private final Map<IExecutionDMContext,ScheduledFuture<?>> fRefreshStackFramesFutures = new HashMap<IExecutionDMContext,ScheduledFuture<?>>();
+
+ private IPropertyChangeListener fPreferencesListener;
+
+ @ThreadSafe
+ public AbstractLaunchVMProvider(AbstractVMAdapter adapter, IPresentationContext presentationContext, DsfSession session)
+ {
+ super(adapter, presentationContext, session);
+
+ final IPreferenceStore store= DsfUIPlugin.getDefault().getPreferenceStore();
+ if (store.getBoolean(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT_ENABLE)) {
+ getPresentationContext().setProperty(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT, store.getInt(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT));
+ }
+
+ fPreferencesListener = new IPropertyChangeListener() {
+ public void propertyChange(final PropertyChangeEvent event) {
+ handlePropertyChanged(store, event);
+ }};
+ store.addPropertyChangeListener(fPreferencesListener);
+ }
+
+ @Override
+ protected IVMUpdatePolicy[] createUpdateModes() {
+ return new IVMUpdatePolicy[] {
+ new DelayedStackRefreshUpdatePolicy(new AutomaticUpdatePolicy()),
+ new DelayedStackRefreshUpdatePolicy(new ManualUpdatePolicy())
+ };
+ }
+
+ public void handleDebugEvents(final DebugEvent[] events) {
+ if (isDisposed()) return;
+
+ // We're in session's executor thread. Re-dispach to VM Adapter
+ // executor thread and then call root layout node.
+ try {
+ getExecutor().execute(new Runnable() {
+ public void run() {
+ if (isDisposed()) return;
+
+ for (final DebugEvent event : events) {
+ handleEvent(event);
+ }
+ }});
+ } catch (RejectedExecutionException e) {
+ // Ignore. This exception could be thrown if the provider is being
+ // shut down.
+ }
+ }
+
+ @Override
+ public void handleEvent(Object event, final RequestMonitor rm) {
+ if (event instanceof DoubleClickEvent && !isDisposed()) {
+ final ISelection selection= ((DoubleClickEvent) event).getSelection();
+ if (selection instanceof IStructuredSelection) {
+ Object element= ((IStructuredSelection) selection).getFirstElement();
+ if (element instanceof IncompleteStackVMContext) {
+ IncompleteStackVMContext incStackVmc = ((IncompleteStackVMContext) element);
+ IVMNode node = incStackVmc.getVMNode();
+ if (node instanceof StackFramesVMNode && node.getVMProvider() == this) {
+ IExecutionDMContext exeCtx= incStackVmc.getExecutionDMContext();
+ ((StackFramesVMNode) node).incrementStackFrameLimit(exeCtx);
+ // replace double click event with expand stack event
+ final ExpandStackEvent expandStackEvent = new ExpandStackEvent(exeCtx);
+ getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ handleEvent(expandStackEvent, null);
+ }
+ });
+ }
+ }
+ }
+ if (rm != null) {
+ rm.done();
+ }
+ return;
+ }
+ super.handleEvent(event, rm);
+ }
+
+ @Override
+ protected void handleEvent(IVMModelProxy proxyStrategy, final Object event, RequestMonitor rm) {
+ super.handleEvent(proxyStrategy, event, rm);
+
+ if (event instanceof IRunControl.ISuspendedDMEvent) {
+ final IExecutionDMContext exeContext= ((IRunControl.ISuspendedDMEvent) event).getDMContext();
+ ScheduledFuture<?> refreshStackFramesFuture = getRefreshFuture(exeContext);
+ // trigger delayed full stack frame update
+ if (refreshStackFramesFuture != null) {
+ // cancel previously scheduled frame update
+ refreshStackFramesFuture.cancel(false);
+ }
+
+ refreshStackFramesFuture = getSession().getExecutor().schedule(
+ new DsfRunnable() {
+ public void run() {
+ if (getSession().isActive()) {
+ getExecutor().execute(new Runnable() {
+ public void run() {
+ // trigger full stack frame update
+ ScheduledFuture<?> future= fRefreshStackFramesFutures.get(exeContext);
+ if (future != null && !isDisposed()) {
+ fRefreshStackFramesFutures.remove(exeContext);
+ handleEvent(new FullStackRefreshEvent(exeContext), null);
+ }
+ }});
+ }
+ }
+ },
+ FRAME_UPDATE_DELAY, TimeUnit.MILLISECONDS);
+ fRefreshStackFramesFutures.put(exeContext, refreshStackFramesFuture);
+ } else if (event instanceof IRunControl.IResumedDMEvent) {
+ IExecutionDMContext exeContext= ((IRunControl.IResumedDMEvent) event).getDMContext();
+ ScheduledFuture<?> refreshStackFramesFuture= fRefreshStackFramesFutures.get(exeContext);
+ if (refreshStackFramesFuture != null) {
+ // cancel previously scheduled frame update
+ refreshStackFramesFuture.cancel(false);
+ fRefreshStackFramesFutures.remove(exeContext);
+ }
+ }
+
+ }
+
+ /**
+ * Returns the future for the given execution context or for any child of the
+ * given execution context.
+ */
+ private ScheduledFuture<?> getRefreshFuture(IExecutionDMContext execCtx) {
+ for (IExecutionDMContext refreshCtx : fRefreshStackFramesFutures.keySet()) {
+ if (refreshCtx.equals(execCtx) || DMContexts.isAncestorOf(refreshCtx, execCtx)) {
+ return fRefreshStackFramesFutures.remove(refreshCtx);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void dispose() {
+ DebugPlugin.getDefault().removeDebugEventListener(this);
+ DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(this);
+
+ final IPreferenceStore store= DsfUIPlugin.getDefault().getPreferenceStore();
+ store.removePropertyChangeListener(fPreferencesListener);
+
+ super.dispose();
+ }
+
+ public void launchesAdded(ILaunch[] launches) {
+ handleLaunchesEvent(new LaunchesEvent(launches, LaunchesEvent.Type.ADDED));
+ }
+
+ public void launchesRemoved(ILaunch[] launches) {
+ handleLaunchesEvent(new LaunchesEvent(launches, LaunchesEvent.Type.REMOVED));
+ }
+
+ public void launchesChanged(ILaunch[] launches) {
+ handleLaunchesEvent(new LaunchesEvent(launches, LaunchesEvent.Type.CHANGED));
+ }
+
+ public void launchesTerminated(ILaunch[] launches) {
+ handleLaunchesEvent(new LaunchesEvent(launches, LaunchesEvent.Type.TERMINATED));
+ }
+
+ private void handleLaunchesEvent(final LaunchesEvent event) {
+ if (isDisposed()) return;
+
+ // We're in session's executor thread. Re-dispach to VM Adapter
+ // executor thread and then call root layout node.
+ try {
+ getExecutor().execute(new Runnable() {
+ public void run() {
+ if (isDisposed()) return;
+
+ IRootVMNode rootLayoutNode = getRootVMNode();
+ if (rootLayoutNode != null && rootLayoutNode.getDeltaFlags(event) != 0) {
+ handleEvent(event);
+ }
+ }});
+ } catch (RejectedExecutionException e) {
+ // Ignore. This exception could be thrown if the provider is being
+ // shut down.
+ }
+ }
+
+ @Override
+ protected boolean canSkipHandlingEvent(Object newEvent, Object eventToSkip) {
+ // To optimize view performance when stepping rapidly, skip events that came
+ // before the last suspended events. However, the debug view can get suspended
+ // events for different threads, so make sure to skip only the events if they
+ // were in the same hierarchy as the last suspended event.
+ // Note: Avoid skipping thread started/exited events which require a larger
+ // scope refresh than some suspended events.
+ if (newEvent instanceof IStartedDMEvent || newEvent instanceof IExitedDMEvent) {
+ return false;
+ }
+
+ if (newEvent instanceof ISuspendedDMEvent && eventToSkip instanceof IDMEvent<?>) {
+ IDMContext newEventDmc = ((IDMEvent<?>)newEvent).getDMContext();
+ IDMContext eventToSkipDmc = ((IDMEvent<?>)eventToSkip).getDMContext();
+
+ if (newEventDmc.equals(eventToSkipDmc) || DMContexts.isAncestorOf(eventToSkipDmc, newEventDmc)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ protected void handlePropertyChanged(final IPreferenceStore store, final PropertyChangeEvent event) {
+ String property = event.getProperty();
+ if (IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT_ENABLE.equals(property)
+ || IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT.equals(property)) {
+ if (store.getBoolean(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT_ENABLE)) {
+ getPresentationContext().setProperty(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT, store.getInt(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT));
+ } else {
+ getPresentationContext().setProperty(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT, null);
+ }
+ getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ handleEvent(event);
+ }
+ });
+ }
+ }
+
+}
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
new file mode 100644
index 00000000000..51f28dc57f9
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/AbstractThreadVMNode.java
@@ -0,0 +1,328 @@
+/*******************************************************************************
+ * 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
+ * Ericsson - Modified for multi threaded functionality
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.ui.viewmodel.launch;
+
+import java.util.List;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+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.DMContexts;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.datamodel.IDMEvent;
+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.IResumedDMEvent;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
+import org.eclipse.cdt.dsf.debug.service.StepQueueManager.ISteppingTimedOutEvent;
+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.IVMContext;
+import org.eclipse.cdt.dsf.ui.viewmodel.ModelProxyInstalledEvent;
+import org.eclipse.cdt.dsf.ui.viewmodel.VMChildrenUpdate;
+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.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;
+
+
+/**
+ * Abstract implementation of a thread view model node.
+ * Clients need to implement {@link #updateLabelInSessionThread(ILabelUpdate[])}.
+ *
+ * @since 1.1
+ */
+@SuppressWarnings("restriction")
+public abstract class AbstractThreadVMNode extends AbstractDMVMNode
+ implements IElementLabelProvider
+{
+ public AbstractThreadVMNode(AbstractDMVMProvider provider, DsfSession session) {
+ super(provider, session, IExecutionDMContext.class);
+ }
+
+ @Override
+ protected void updateElementsInSessionThread(final IChildrenUpdate update) {
+ IRunControl runControl = getServicesTracker().getService(IRunControl.class);
+ final IContainerDMContext contDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IContainerDMContext.class);
+ if (runControl == null || contDmc == null) {
+ handleFailedUpdate(update);
+ return;
+ }
+
+ runControl.getExecutionContexts(contDmc,
+ new ViewerDataRequestMonitor<IExecutionDMContext[]>(getSession().getExecutor(), update){
+ @Override
+ public void handleCompleted() {
+ if (!isSuccess()) {
+ handleFailedUpdate(update);
+ return;
+ }
+ fillUpdateWithVMCs(update, getData());
+ update.done();
+ }
+ });
+ }
+
+
+ public void update(final ILabelUpdate[] updates) {
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ updateLabelInSessionThread(updates);
+ }});
+ } catch (RejectedExecutionException e) {
+ for (ILabelUpdate update : updates) {
+ handleFailedUpdate(update);
+ }
+ }
+ }
+
+ @Override
+ public void getContextsForEvent(VMDelta parentDelta, Object e, final DataRequestMonitor<IVMContext[]> rm) {
+ if(e instanceof IContainerResumedDMEvent) {
+ IExecutionDMContext[] triggerContexts = ((IContainerResumedDMEvent)e).getTriggeringContexts();
+ if (triggerContexts.length != 0) {
+ rm.setData(new IVMContext[] { createVMContext(triggerContexts[0]) });
+ rm.done();
+ return;
+ }
+ } else if(e instanceof IContainerSuspendedDMEvent) {
+ IExecutionDMContext[] triggerContexts = ((IContainerSuspendedDMEvent)e).getTriggeringContexts();
+ if (triggerContexts.length != 0) {
+ rm.setData(new IVMContext[] { createVMContext(triggerContexts[0]) });
+ rm.done();
+ return;
+ }
+ } else if (e instanceof SteppingTimedOutEvent &&
+ ((SteppingTimedOutEvent)e).getDMContext() instanceof IContainerDMContext)
+ {
+ // The timed out event occured on a container and not on a thread. Do not
+ // return a context for this event, which will force the view model to generate
+ // a delta for all the threads.
+ rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ } else if (e instanceof ISteppingTimedOutEvent &&
+ ((ISteppingTimedOutEvent)e).getDMContext() instanceof IContainerDMContext)
+ {
+ // The timed out event occured on a container and not on a thread. Do not
+ // return a context for this event, which will force the view model to generate
+ // a delta for all the threads.
+ rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ } else if (e instanceof FullStackRefreshEvent &&
+ ((FullStackRefreshEvent)e).getDMContext() instanceof IContainerDMContext)
+ {
+ // The step sequence end event occured on a container and not on a thread. Do not
+ // return a context for this event, which will force the view model to generate
+ // a delta for all the threads.
+ rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ } else if (e instanceof ModelProxyInstalledEvent) {
+ getThreadVMCForModelProxyInstallEvent(
+ parentDelta,
+ new DataRequestMonitor<VMContextInfo>(getExecutor(), rm) {
+ @Override
+ protected void handleCompleted() {
+ if (isSuccess()) {
+ rm.setData(new IVMContext[] { getData().fVMContext });
+ } else {
+ rm.setData(new IVMContext[0]);
+ }
+ rm.done();
+ }
+ });
+ return;
+ }
+ super.getContextsForEvent(parentDelta, e, rm);
+ }
+
+ private static class VMContextInfo {
+ final IVMContext fVMContext;
+ final int fIndex;
+ final boolean fIsSuspended;
+ VMContextInfo(IVMContext vmContext, int index, boolean isSuspended) {
+ fVMContext = vmContext;
+ fIndex = index;
+ fIsSuspended = isSuspended;
+ }
+ }
+
+ private void getThreadVMCForModelProxyInstallEvent(VMDelta parentDelta, final DataRequestMonitor<VMContextInfo> rm) {
+ getVMProvider().updateNode(this, new VMChildrenUpdate(
+ parentDelta, getVMProvider().getPresentationContext(), -1, -1,
+ new DataRequestMonitor<List<Object>>(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ final IRunControl runControl = getServicesTracker().getService(IRunControl.class);
+ if (runControl != null) {
+ int vmcIdx = -1;
+ int suspendedVmcIdx = -1;
+
+ for (int i = 0; i < getData().size(); i++) {
+ if (getData().get(i) instanceof IDMVMContext) {
+ IDMVMContext vmc = (IDMVMContext)getData().get(i);
+ IExecutionDMContext execDmc = DMContexts.getAncestorOfType(
+ vmc.getDMContext(), IExecutionDMContext.class);
+ if (execDmc != null) {
+ vmcIdx = vmcIdx < 0 ? i : vmcIdx;
+ if (runControl.isSuspended(execDmc)) {
+ suspendedVmcIdx = suspendedVmcIdx < 0 ? i : suspendedVmcIdx;
+ }
+ }
+ }
+ }
+ if (suspendedVmcIdx >= 0) {
+ rm.setData(new VMContextInfo(
+ (IVMContext)getData().get(suspendedVmcIdx), suspendedVmcIdx, true));
+ } else if (vmcIdx >= 0) {
+ rm.setData(new VMContextInfo((IVMContext)getData().get(vmcIdx), vmcIdx, false));
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "No threads available", null)); //$NON-NLS-1$
+ }
+ rm.done();
+ } else {
+ rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED, "No threads available", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+ }));
+ }
+
+ /**
+ * 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;
+
+ if (dmc instanceof IContainerDMContext) {
+ return IModelDelta.NO_CHANGE;
+ } else if (e instanceof IResumedDMEvent &&
+ ((IResumedDMEvent)e).getReason() != IRunControl.StateChangeReason.STEP)
+ {
+ return IModelDelta.CONTENT;
+ } else if (e instanceof ISuspendedDMEvent) {
+ return IModelDelta.NO_CHANGE;
+ } else if (e instanceof FullStackRefreshEvent) {
+ return IModelDelta.CONTENT;
+ } else if (e instanceof SteppingTimedOutEvent) {
+ return IModelDelta.CONTENT;
+ } else if (e instanceof ISteppingTimedOutEvent) {
+ return IModelDelta.CONTENT;
+ } else if (e instanceof ModelProxyInstalledEvent) {
+ return IModelDelta.SELECT | IModelDelta.EXPAND;
+ }
+ return IModelDelta.NO_CHANGE;
+ }
+
+ public void buildDelta(Object e, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) {
+ IDMContext dmc = e instanceof IDMEvent<?> ? ((IDMEvent<?>)e).getDMContext() : null;
+
+ if(dmc instanceof IContainerDMContext) {
+ // The IContainerDMContext sub-classes IExecutionDMContext.
+ // Also IContainerResumedDMEvent sub-classes IResumedDMEvent and
+ // IContainerSuspendedDMEvnet sub-classes ISuspendedEvent.
+ // Because of this relationship, the thread VM node can be called
+ // with data-model evnets for the containers. This statement
+ // filters out those event.
+ rm.done();
+ } else if(e instanceof IResumedDMEvent) {
+ // Resumed:
+ // - If not stepping, update the thread and its content (its stack).
+ // - If stepping, do nothing to avoid too many updates. If a
+ // time-out is reached before the step completes, the
+ // ISteppingTimedOutEvent will trigger a refresh.
+ if (((IResumedDMEvent)e).getReason() != IRunControl.StateChangeReason.STEP) {
+ parentDelta.addNode(createVMContext(dmc), IModelDelta.CONTENT);
+ }
+ rm.done();
+ } else if (e instanceof ISuspendedDMEvent) {
+ // Container suspended. Do nothing here to give the stack the
+ // priority in updating. The thread will update as a result of
+ // FullStackRefreshEvent.
+ rm.done();
+ } else if (e instanceof FullStackRefreshEvent) {
+ // Full-stack refresh event is generated following a suspended event
+ // and a fixed delay. Refresh the whole thread upon this event.
+ parentDelta.addNode(createVMContext(dmc), IModelDelta.CONTENT);
+ rm.done();
+ } else if (e instanceof SteppingTimedOutEvent) {
+ // Stepping time-out indicates that a step operation is taking
+ // a long time, and the view needs to be refreshed to show
+ // the user that the program is running.
+ parentDelta.addNode(createVMContext(dmc), IModelDelta.CONTENT);
+ rm.done();
+ } else if (e instanceof ISteppingTimedOutEvent) {
+ // Stepping time-out indicates that a step operation is taking
+ // a long time, and the view needs to be refreshed to show
+ // the user that the program is running.
+ parentDelta.addNode(createVMContext(dmc), IModelDelta.CONTENT);
+ rm.done();
+ } else if (e instanceof ModelProxyInstalledEvent) {
+ // Model Proxy install event is generated when the model is first
+ // populated into the view. This happens when a new debug session
+ // is started or when the view is first opened.
+ // In both cases, if there are already threads in the debug model,
+ // the desired user behavior is to show the threads and to select
+ // the first thread.
+ // If the thread is suspended, do not select the thread, instead,
+ // its top stack frame will be selected.
+ getThreadVMCForModelProxyInstallEvent(
+ parentDelta,
+ new DataRequestMonitor<VMContextInfo>(getExecutor(), rm) {
+ @Override
+ protected void handleCompleted() {
+ if (isSuccess()) {
+ parentDelta.addNode(
+ getData().fVMContext, nodeOffset + getData().fIndex,
+ IModelDelta.EXPAND | (getData().fIsSuspended ? 0 : IModelDelta.SELECT));
+ }
+ rm.done();
+ }
+ });
+ } else {
+
+ rm.done();
+ }
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/DefaultDsfModelSelectionPolicyFactory.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/DefaultDsfModelSelectionPolicyFactory.java
new file mode 100644
index 00000000000..7a05904d4a4
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/DefaultDsfModelSelectionPolicyFactory.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Wind River Systems, Inc. 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:
+ * Anton Leherbauer (Wind River Systems) - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.dsf.debug.ui.viewmodel.launch;
+
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelSelectionPolicy;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelSelectionPolicyFactory;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.ui.IDebugUIConstants;
+
+/**
+ * Default model selection policy factory for DSF.
+ * @since 1.1
+ */
+@SuppressWarnings("restriction")
+public class DefaultDsfModelSelectionPolicyFactory implements IModelSelectionPolicyFactory {
+
+ /*
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IModelSelectionPolicyFactory#createModelSelectionPolicyAdapter(java.lang.Object, org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext)
+ */
+ public IModelSelectionPolicy createModelSelectionPolicyAdapter(Object element, IPresentationContext context) {
+ if (IDebugUIConstants.ID_DEBUG_VIEW.equals(context.getId())) {
+ if (element instanceof IDMVMContext) {
+ IDMVMContext dmvmContext= (IDMVMContext) element;
+ IDMContext dmContext= dmvmContext.getDMContext();
+ if (dmContext != null) {
+ return new DefaultDsfSelectionPolicy(dmContext);
+ }
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/DefaultDsfSelectionPolicy.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/DefaultDsfSelectionPolicy.java
new file mode 100644
index 00000000000..cb1e8faffbc
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/DefaultDsfSelectionPolicy.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Wind River Systems, Inc. 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:
+ * Anton Leherbauer (Wind River Systems) - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.ui.viewmodel.launch;
+
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
+import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelSelectionPolicy;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeSelection;
+import org.eclipse.jface.viewers.TreePath;
+import org.eclipse.jface.viewers.TreeSelection;
+
+/**
+ * Default DSF selection policy implementation modelled after platform version
+ * (<code>DefaultSelectionPolicy</code>).
+ * @since 1.1
+ */
+@SuppressWarnings("restriction")
+public class DefaultDsfSelectionPolicy implements IModelSelectionPolicy {
+
+ private IDMContext fDMContext;
+
+ /**
+ * Create selection policy instance for the given data model context.
+ *
+ * @param dmContext
+ */
+ public DefaultDsfSelectionPolicy(IDMContext dmContext) {
+ fDMContext= dmContext;
+ }
+
+ /*
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IModelSelectionPolicy#contains(org.eclipse.jface.viewers.ISelection, org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext)
+ */
+ public boolean contains(ISelection selection, IPresentationContext context) {
+ if (IDebugUIConstants.ID_DEBUG_VIEW.equals(context.getId())) {
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection ss= (IStructuredSelection) selection;
+ Object element= ss.getFirstElement();
+ if (element instanceof IDMVMContext) {
+ IDMVMContext dmvmContext= (IDMVMContext) element;
+ IDMContext dmContext= dmvmContext.getDMContext();
+ if (dmContext != null) {
+ return fDMContext.getSessionId().equals(dmContext.getSessionId());
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /*
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IModelSelectionPolicy#isSticky(org.eclipse.jface.viewers.ISelection, org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext)
+ */
+ public boolean isSticky(ISelection selection, IPresentationContext context) {
+ if (IDebugUIConstants.ID_DEBUG_VIEW.equals(context.getId())) {
+ if (selection instanceof IStructuredSelection) {
+ IStructuredSelection ss= (IStructuredSelection) selection;
+ Object element= ss.getFirstElement();
+ return isSticky(element);
+ }
+ }
+ return false;
+ }
+
+ protected boolean isSticky(Object element) {
+ if (element instanceof IDMVMContext) {
+ IDMVMContext dmvmContext= (IDMVMContext) element;
+ IDMContext dmContext= dmvmContext.getDMContext();
+ if (dmContext instanceof IFrameDMContext) {
+ IExecutionDMContext execContext= DMContexts.getAncestorOfType(dmContext, IExecutionDMContext.class);
+ if (execContext != null) {
+ DsfServicesTracker servicesTracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), dmContext.getSessionId());
+ try {
+ IRunControl runControl= servicesTracker.getService(IRunControl.class);
+ if (runControl != null) {
+ if (runControl.isSuspended(execContext)) {
+ return true;
+ }
+ }
+ } finally {
+ servicesTracker.dispose();
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ /*
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IModelSelectionPolicy#overrides(org.eclipse.jface.viewers.ISelection, org.eclipse.jface.viewers.ISelection, org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext)
+ */
+ public boolean overrides(ISelection existing, ISelection candidate, IPresentationContext context) {
+ if (IDebugUIConstants.ID_DEBUG_VIEW.equals(context.getId())) {
+ if (existing instanceof IStructuredSelection && candidate instanceof IStructuredSelection) {
+ IStructuredSelection ssExisting = (IStructuredSelection) existing;
+ IStructuredSelection ssCandidate = (IStructuredSelection) candidate;
+ return overrides(ssExisting.getFirstElement(), ssCandidate.getFirstElement());
+ }
+ }
+ return true;
+ }
+
+
+ protected boolean overrides(Object existing, Object candidate) {
+ if (existing == null || existing.equals(candidate)) {
+ return true;
+ }
+ if (existing instanceof IDMVMContext && candidate instanceof IDMVMContext) {
+ IDMContext curr = ((IDMVMContext) existing).getDMContext();
+ IDMContext cand = ((IDMVMContext) candidate).getDMContext();
+ if (curr instanceof IFrameDMContext && cand instanceof IFrameDMContext) {
+ IExecutionDMContext currExecContext= DMContexts.getAncestorOfType(curr, IExecutionDMContext.class);
+ if (currExecContext != null) {
+ IExecutionDMContext candExecContext= DMContexts.getAncestorOfType(cand, IExecutionDMContext.class);
+ return currExecContext.equals(candExecContext) || !isSticky(existing);
+ }
+ }
+ }
+ return !isSticky(existing);
+ }
+
+ /*
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IModelSelectionPolicy#replaceInvalidSelection(org.eclipse.jface.viewers.ISelection, org.eclipse.jface.viewers.ISelection)
+ */
+ public ISelection replaceInvalidSelection(ISelection invalidSelection, ISelection newSelection) {
+ if (invalidSelection instanceof ITreeSelection) {
+ ITreeSelection treeSelection = (ITreeSelection)invalidSelection;
+ if (treeSelection.getPaths().length == 1) {
+ TreePath path = treeSelection.getPaths()[0];
+ return new TreeSelection(path.getParentPath());
+ }
+ }
+ return newSelection;
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/DelayedStackRefreshUpdatePolicy.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/DelayedStackRefreshUpdatePolicy.java
new file mode 100644
index 00000000000..8cdfc04d8d7
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/DelayedStackRefreshUpdatePolicy.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Wind River Systems, Inc. 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.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IExitedDMEvent;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
+import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.IElementUpdateTester;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.IVMUpdatePolicy;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.UpdatePolicyDecorator;
+import org.eclipse.jface.viewers.TreePath;
+
+/**
+ * An update strategy decorator specialized for delayed stack frame refresh. The
+ * strategy flushes only the cached top stack frame in case of an normal {@link ISuspendedDMEvent},
+ * while in in case of a special {@link FullStackRefreshEvent} everything is invalidated.
+ *
+ * <p>
+ * The underlying base update policy is considered for container contexts only.
+ * In other cases the cache data is always flushed.
+ * </p>
+ *
+ * @since 1.1
+ */
+public class DelayedStackRefreshUpdatePolicy extends UpdatePolicyDecorator {
+
+ private static final class DelayedStackRefreshUpdateTester implements IElementUpdateTester {
+
+ private final IElementUpdateTester fBaseTester;
+
+ /** Indicates whether only the top stack frame should be updated */
+ private final boolean fLazyStackFrameMode;
+
+ DelayedStackRefreshUpdateTester(IElementUpdateTester baseTester, boolean lazyStackFrameMode) {
+ fBaseTester = baseTester;
+ fLazyStackFrameMode = lazyStackFrameMode;
+ }
+ public int getUpdateFlags(Object viewerInput, TreePath path) {
+ Object element = path.getSegmentCount() != 0 ? path.getLastSegment() : viewerInput;
+ if (element instanceof IDMVMContext) {
+ IDMContext dmc = ((IDMVMContext) element).getDMContext();
+ if (fLazyStackFrameMode) {
+ if (dmc instanceof IFrameDMContext) {
+ if (((IFrameDMContext) dmc).getLevel() == 0) {
+ return FLUSH;
+ }
+ } else if (dmc instanceof IExecutionDMContext) {
+ return fBaseTester.getUpdateFlags(viewerInput, path);
+ }
+ return DIRTY;
+ } else if (dmc instanceof IContainerDMContext) {
+ return fBaseTester.getUpdateFlags(viewerInput, path);
+ }
+ }
+ return FLUSH;
+ }
+
+ public boolean includes(IElementUpdateTester tester) {
+ // A non-lazy tester includes a lazy tester, but not vice versa.
+ // This allows entries that were marked as dirty by a flush with
+ // the lazy mode to be superseded by a non-lazy update which
+ // actually clears the entries that were marked as dirty.
+ if (tester instanceof DelayedStackRefreshUpdateTester) {
+ DelayedStackRefreshUpdateTester sfTester = (DelayedStackRefreshUpdateTester)tester;
+ if (fLazyStackFrameMode) {
+ if (sfTester.fLazyStackFrameMode) {
+ return fBaseTester.includes(sfTester.fBaseTester);
+ }
+ } else {
+ if (!sfTester.fLazyStackFrameMode) {
+ return fBaseTester.includes(sfTester.fBaseTester);
+ }
+ // non-lazy includes lazy
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "Delayed stack refresh (lazy = " + fLazyStackFrameMode + ", base = " + fBaseTester + ") update tester"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ }
+
+ private static final class ThreadsUpdateTester implements IElementUpdateTester {
+
+ private final IElementUpdateTester fBaseTester;
+
+ private final boolean fRefreshAll;
+
+ ThreadsUpdateTester(IElementUpdateTester baseTester, boolean refreshAll) {
+ fBaseTester = baseTester;
+ fRefreshAll = refreshAll;
+ }
+
+ public int getUpdateFlags(Object viewerInput, TreePath path) {
+ Object element = path.getSegmentCount() != 0 ? path.getLastSegment() : viewerInput;
+
+ if (!fRefreshAll && element instanceof IDMVMContext) {
+ IDMContext dmc = ((IDMVMContext) element).getDMContext();
+ if (dmc instanceof IContainerDMContext) {
+ return fBaseTester.getUpdateFlags(viewerInput, path);
+ }
+ }
+
+ // If the element is not a container or if the flush all flag is set,
+ // always flush it.
+ return FLUSH;
+ }
+
+ public boolean includes(IElementUpdateTester tester) {
+ // A refresh-all tester includes a non-refresh-all tester, but not
+ // vice versa. This allows entries that were marked as dirty by
+ // a flush with
+ // the non-refresh-all to be superseded by a refresh-all update which
+ // actually clears the entries that were marked as dirty.
+ if (tester instanceof ThreadsUpdateTester) {
+ ThreadsUpdateTester threadsTester = (ThreadsUpdateTester)tester;
+ if (fRefreshAll) {
+ if (threadsTester.fRefreshAll) {
+ return fBaseTester.includes(threadsTester.fBaseTester);
+ }
+ // refresh-all includes the non-refresh-all
+ return true;
+ } else {
+ if (!threadsTester.fRefreshAll) {
+ return fBaseTester.includes(threadsTester.fBaseTester);
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "Threads update tester (base = " + fBaseTester + ") update tester"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+
+
+ public DelayedStackRefreshUpdatePolicy(IVMUpdatePolicy base) {
+ super(base);
+ }
+
+ @Override
+ public IElementUpdateTester getElementUpdateTester(Object event) {
+ if (event instanceof ISuspendedDMEvent) {
+ return new DelayedStackRefreshUpdateTester(getBaseUpdatePolicy().getElementUpdateTester(event), true);
+ } else if (event instanceof FullStackRefreshEvent) {
+ return new DelayedStackRefreshUpdateTester(getBaseUpdatePolicy().getElementUpdateTester(event), false);
+ } else if (event instanceof IExitedDMEvent &&
+ ((IExitedDMEvent)event).getDMContext() instanceof IContainerDMContext)
+ {
+ // container exit should always trigger a refresh
+ return new ThreadsUpdateTester(super.getElementUpdateTester(event), true);
+ } else {
+ return new ThreadsUpdateTester(super.getElementUpdateTester(event), false);
+ }
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/ExpandStackEvent.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/ExpandStackEvent.java
new file mode 100644
index 00000000000..bed23000bb8
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/ExpandStackEvent.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Wind River Systems, Inc. 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.cdt.dsf.datamodel.AbstractDMEvent;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
+
+/**
+ * Event to increase the stack frame limit for an execution context.
+ *
+ * @since 1.1
+ */
+public class ExpandStackEvent extends AbstractDMEvent<IExecutionDMContext> {
+
+ public ExpandStackEvent(IExecutionDMContext execCtx) {
+ super(execCtx);
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/FullStackRefreshEvent.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/FullStackRefreshEvent.java
new file mode 100644
index 00000000000..ecca6de8eb6
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/FullStackRefreshEvent.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Wind River Systems, Inc. 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.cdt.dsf.datamodel.AbstractDMEvent;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
+
+/**
+ * Indicates the end of a sequence of steps. Should be handled like a suspended
+ * event to trigger a full refresh of stack frames.
+ *
+ * @since 1.1
+ */
+public class FullStackRefreshEvent extends AbstractDMEvent<IExecutionDMContext> {
+
+ public FullStackRefreshEvent(IExecutionDMContext execCtx) {
+ super(execCtx);
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/LaunchRootVMNode.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/LaunchRootVMNode.java
new file mode 100644
index 00000000000..faed099a305
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/LaunchRootVMNode.java
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * 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.launch;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMProvider;
+import org.eclipse.cdt.dsf.ui.viewmodel.IRootVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.RootVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.core.model.IDebugElement;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+
+/**
+ * Layout node for the standard ILaunch object. This node can only be used at
+ * the root of a hierarchy. It does not implement the label provider
+ * functionality, so the default adapters should be used to retrieve the label.
+ */
+@SuppressWarnings("restriction")
+public class LaunchRootVMNode extends RootVMNode
+ implements IRootVMNode
+{
+ public static class LaunchesEvent {
+ public enum Type { ADDED, REMOVED, CHANGED, TERMINATED }
+ public final ILaunch[] fLaunches;
+ public final Type fType;
+
+ public LaunchesEvent(ILaunch[] launches, Type type) {
+ fLaunches = launches;
+ fType = type;
+ }
+ }
+
+
+ public LaunchRootVMNode(AbstractVMProvider provider) {
+ super(provider);
+ }
+
+ @Override
+ public String toString() {
+ return "LaunchRootVMNode"; //$NON-NLS-1$
+ }
+
+ @Override
+ public boolean isDeltaEvent(Object rootObject, Object e) {
+ if (e instanceof DebugEvent) {
+ DebugEvent de = (DebugEvent)e;
+ if (de.getSource() instanceof IProcess &&
+ !((IProcess)de.getSource()).getLaunch().equals(rootObject) )
+ {
+ return false;
+ }
+ else if (de.getSource() instanceof IDebugElement &&
+ !rootObject.equals(((IDebugElement)de.getSource()).getLaunch()))
+ {
+ return false;
+ }
+ }
+ return super.isDeltaEvent(rootObject, e);
+ }
+
+ @Override
+ public int getDeltaFlags(Object e) {
+ int flags = 0;
+ if (e instanceof LaunchesEvent) {
+ LaunchesEvent le = (LaunchesEvent)e;
+ if (le.fType == LaunchesEvent.Type.CHANGED || le.fType == LaunchesEvent.Type.TERMINATED) {
+ flags = IModelDelta.STATE | IModelDelta.CONTENT;
+ }
+ }
+
+ return flags;
+ }
+
+ @Override
+ public void createRootDelta(Object rootObject, Object event, final DataRequestMonitor<VMDelta> rm) {
+ if (!(rootObject instanceof ILaunch)) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Invalid root element configured with launch root node.", null)); //$NON-NLS-1$
+ return;
+ }
+
+ ILaunch rootLaunch = (ILaunch)rootObject;
+
+ /*
+ * Create the root of the delta. Since the launch object is not at the
+ * root of the view, create the delta with the path to the launch.
+ */
+ ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager();
+ List<ILaunch> launchList = Arrays.asList(manager.getLaunches());
+ final VMDelta viewRootDelta = new VMDelta(manager, 0, IModelDelta.NO_CHANGE, launchList.size());
+ final VMDelta rootDelta = viewRootDelta.addNode(rootLaunch, launchList.indexOf(rootLaunch), IModelDelta.NO_CHANGE);
+
+ // Generate delta for launch node.
+ if (event instanceof LaunchesEvent) {
+ LaunchesEvent le = (LaunchesEvent)event;
+ for (ILaunch launch : le.fLaunches) {
+ if (rootLaunch == launch) {
+ if (le.fType == LaunchesEvent.Type.CHANGED) {
+ rootDelta.setFlags(rootDelta.getFlags() | IModelDelta.STATE | IModelDelta.CONTENT);
+ } else if (le.fType == LaunchesEvent.Type.TERMINATED) {
+ rootDelta.setFlags(rootDelta.getFlags() | IModelDelta.STATE | IModelDelta.CONTENT);
+ }
+ }
+ }
+ }
+
+ rm.setData(rootDelta);
+ rm.done();
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/LaunchVMUpdateMessages.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/LaunchVMUpdateMessages.java
new file mode 100644
index 00000000000..0a5db99385e
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/LaunchVMUpdateMessages.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * @since 1.1
+ */
+public class LaunchVMUpdateMessages extends NLS {
+
+ private static final String BUNDLE_NAME = "org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.LaunchVMUpdateMessages";//$NON-NLS-1$
+
+ public static String ThreadsAutomaticUpdatePolicy_name;
+ public static String ThreadsManualUpdatePolicy_name;
+
+ static {
+ // load message values from bundle file
+ NLS.initializeMessages(BUNDLE_NAME, LaunchVMUpdateMessages.class);
+ }
+}
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
new file mode 100644
index 00000000000..957f25598f1
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/StackFramesVMNode.java
@@ -0,0 +1,724 @@
+/*******************************************************************************
+ * 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.launch;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+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.DMContexts;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+import org.eclipse.cdt.dsf.debug.service.IStack;
+import org.eclipse.cdt.dsf.debug.service.IStack2;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
+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.IExitedDMEvent;
+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.IFrameDMData;
+import org.eclipse.cdt.dsf.debug.service.StepQueueManager.ISteppingTimedOutEvent;
+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.service.DsfSession;
+import org.eclipse.cdt.dsf.ui.concurrent.ViewerDataRequestMonitor;
+import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMContext;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext;
+import org.eclipse.cdt.dsf.ui.viewmodel.ModelProxyInstalledEvent;
+import org.eclipse.cdt.dsf.ui.viewmodel.VMChildrenUpdate;
+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.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;
+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.IHasChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+import org.eclipse.debug.ui.DebugUITools;
+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
+{
+
+ /**
+ * View model context representing the end of an incomplete stack.
+ *
+ * @since 1.1
+ */
+ public class IncompleteStackVMContext extends AbstractVMContext {
+ private final int fLevel;
+ private final IExecutionDMContext fDmc;
+
+ public IncompleteStackVMContext(IExecutionDMContext dmc, int level) {
+ super(StackFramesVMNode.this);
+ fDmc = dmc;
+ fLevel = level;
+ }
+ public int getLevel() {
+ return fLevel;
+ }
+ public IExecutionDMContext getExecutionDMContext() {
+ return fDmc;
+ }
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof IncompleteStackVMContext &&
+ ((IncompleteStackVMContext)obj).fDmc.equals(fDmc);
+ }
+
+ @Override
+ public int hashCode() {
+ return fDmc.hashCode();
+ }
+ }
+
+ /**
+ * Temporary stack frame limit to allow incremental stack updates.
+ */
+ private Map<IExecutionDMContext, Integer> fTemporaryLimits = new HashMap<IExecutionDMContext, Integer>();
+
+ public StackFramesVMNode(AbstractDMVMProvider provider, DsfSession session) {
+ super(provider, session, IStack.IFrameDMContext.class);
+ }
+
+ @Override
+ public String toString() {
+ return "StackFramesVMNode(" + getSession().getId() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMNode#updateHasElementsInSessionThread(org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate)
+ */
+ @Override
+ protected void updateHasElementsInSessionThread(IHasChildrenUpdate update) {
+ IRunControl runControl = getServicesTracker().getService(IRunControl.class);
+ IExecutionDMContext execCtx = findDmcInPath(update.getViewerInput(), update.getElementPath(), IExecutionDMContext.class);
+ if (runControl == null || execCtx == null) {
+ handleFailedUpdate(update);
+ return;
+ }
+
+ update.setHasChilren(runControl.isSuspended(execCtx) || runControl.isStepping(execCtx));
+ update.done();
+ }
+
+ @Override
+ protected void updateElementCountInSessionThread(final IChildrenCountUpdate update) {
+ IStack stackService = getServicesTracker().getService(IStack.class);
+ final IExecutionDMContext execDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IExecutionDMContext.class);
+ if (stackService == null || execDmc == null) {
+ handleFailedUpdate(update);
+ return;
+ }
+
+ final int stackFrameLimit= getStackFrameLimit(execDmc);
+ stackService.getStackDepth(
+ execDmc, stackFrameLimit == Integer.MAX_VALUE ? 0 : stackFrameLimit + 1,
+ new ViewerDataRequestMonitor<Integer>(getSession().getExecutor(), update) {
+ @Override
+ public void handleCompleted() {
+ if (!isSuccess()) {
+ handleFailedUpdate(update);
+ return;
+ }
+ int stackDepth= getData();
+ if (stackFrameLimit < stackDepth) {
+ stackDepth = stackFrameLimit + 1;
+ }
+ update.setChildCount(stackDepth);
+ update.done();
+ }
+ });
+ }
+
+ /*
+ * (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) {
+ IStack stackService = getServicesTracker().getService(IStack.class);
+ final IExecutionDMContext execDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IExecutionDMContext.class);
+ if (stackService == null || execDmc == null) {
+ handleFailedUpdate(update);
+ return;
+ }
+
+ final int stackFrameLimit= getStackFrameLimit(execDmc);
+ final int startIndex= update.getOffset();
+
+ if (startIndex == 0 && update.getLength() == 1) {
+ // Requesting top stack frame only
+ stackService.getTopFrame(
+ execDmc,
+ new ViewerDataRequestMonitor<IFrameDMContext>(getSession().getExecutor(), update) {
+ @Override
+ public void handleCompleted() {
+ if (!isSuccess()) {
+ handleFailedUpdate(update);
+ return;
+ }
+ update.setChild(createVMContext(getData()), 0);
+ update.done();
+ }
+ });
+
+ } else {
+ if (startIndex >= 0 && update.getLength() > 0 && stackService instanceof IStack2) {
+ // partial stack dump
+ IStack2 stackService2= (IStack2) stackService;
+ int endIndex= startIndex + update.getLength() - 1;
+ if (startIndex < stackFrameLimit && endIndex >= stackFrameLimit) {
+ endIndex = stackFrameLimit - 1;
+ }
+ stackService2.getFrames(
+ execDmc,
+ startIndex,
+ endIndex,
+ new ViewerDataRequestMonitor<IFrameDMContext[]>(getSession().getExecutor(), update) {
+ @Override
+ public void handleCompleted() {
+ if (!isSuccess()) {
+ handleFailedUpdate(update);
+ return;
+ }
+ IFrameDMContext[] frames = getData();
+ fillUpdateWithVMCs(update, frames, startIndex);
+ if (startIndex + update.getLength() > stackFrameLimit) {
+ update.setChild(new IncompleteStackVMContext(execDmc, stackFrameLimit), stackFrameLimit);
+ }
+ update.done();
+ }
+ });
+ } else {
+ // full stack dump
+ stackService.getFrames(
+ execDmc,
+ new ViewerDataRequestMonitor<IFrameDMContext[]>(getSession().getExecutor(), update) {
+ @Override
+ public void handleCompleted() {
+ if (!isSuccess()) {
+ handleFailedUpdate(update);
+ return;
+ }
+ IFrameDMContext[] frames = getData();
+ if (frames.length > stackFrameLimit) {
+ IFrameDMContext[] tmpFrames = new IFrameDMContext[stackFrameLimit];
+ System.arraycopy(frames, 0, tmpFrames, 0, stackFrameLimit);
+ frames = tmpFrames;
+ update.setChild(new IncompleteStackVMContext(execDmc, stackFrameLimit), stackFrameLimit);
+ }
+ fillUpdateWithVMCs(update, frames);
+ update.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) {
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ updateLabelInSessionThread(updates);
+ }});
+ } catch (RejectedExecutionException e) {
+ for (ILabelUpdate update : updates) {
+ handleFailedUpdate(update);
+ }
+ }
+ }
+
+ protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
+ for (final ILabelUpdate update : updates) {
+ IStack stackService = getServicesTracker().getService(IStack.class);
+
+ if (stackService == 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.done();
+ continue;
+ }
+
+ final IFrameDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IFrameDMContext.class);
+ if (dmc == null) {
+ handleFailedUpdate(update);
+ continue;
+ }
+
+ getDMVMProvider().getModelData(
+ this, update,
+ getServicesTracker().getService(IStack.class, null),
+ dmc,
+ new ViewerDataRequestMonitor<IFrameDMData>(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);
+ }
+ update.done();
+ }
+ },
+ getExecutor());
+ }
+ }
+
+ protected void fillColumnLabel(IFrameDMContext dmContext, IFrameDMData dmData, String columnId, int idx, ILabelUpdate update)
+ {
+ if (idx != 0) return;
+
+ final IExecutionDMContext execDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IExecutionDMContext.class);
+ if (execDmc == null) {
+ return;
+ }
+ IRunControl runControlService = getServicesTracker().getService(IRunControl.class);
+ SteppingController stepQueueMgr = (SteppingController) execDmc.getAdapter(SteppingController.class);
+ if (runControlService == null || stepQueueMgr == null) return;
+
+ String imageKey = null;
+ if (runControlService.isSuspended(execDmc) ||
+ (runControlService.isStepping(execDmc) && !stepQueueMgr.isSteppingTimedOut(execDmc)))
+ {
+ imageKey = IDebugUIConstants.IMG_OBJS_STACKFRAME;
+ } else {
+ imageKey = IDebugUIConstants.IMG_OBJS_STACKFRAME_RUNNING;
+ }
+ update.setImageDescriptor(DebugUITools.getImageDescriptor(imageKey), 0);
+
+ //
+ // Finally, if all goes well, set the label.
+ //
+ StringBuilder label = new StringBuilder();
+
+ // Add the function name
+ if (dmData.getFunction() != null && dmData.getFunction().length() != 0) {
+ label.append(" "); //$NON-NLS-1$
+ label.append(dmData.getFunction());
+ label.append("()"); //$NON-NLS-1$
+ }
+
+ // Add full file name
+ if (dmData.getFile() != null && dmData.getFile().length() != 0) {
+ label.append(" at "); //$NON-NLS-1$
+ label.append(dmData.getFile());
+ }
+
+ // Add line number
+ if (dmData.getLine() >= 0) {
+ label.append(":"); //$NON-NLS-1$
+ label.append(dmData.getLine());
+ label.append(" "); //$NON-NLS-1$
+ }
+
+ // Add the address
+ if (dmData.getAddress() != null) {
+ label.append("- 0x" + dmData.getAddress().toString(16)); //$NON-NLS-1$
+ }
+
+ // Set the label to the result listener
+ update.setLabel(label.toString(), 0);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMNode#getContextsForEvent(org.eclipse.cdt.dsf.ui.viewmodel.VMDelta, java.lang.Object, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
+ */
+ @Override
+ public void getContextsForEvent(final VMDelta parentDelta, Object e, final DataRequestMonitor<IVMContext[]> rm) {
+ if (e instanceof ModelProxyInstalledEvent) {
+ // Retrieve the list of stack frames, and mark the top frame to be selected.
+ getVMProvider().updateNode(
+ this,
+ new VMChildrenUpdate(
+ parentDelta, getVMProvider().getPresentationContext(), 0, 1,
+ new DataRequestMonitor<List<Object>>(getExecutor(), rm) {
+ @Override
+ public void handleCompleted() {
+ if (isSuccess() && getData().size() != 0) {
+ rm.setData(new IVMContext[] { (IVMContext)getData().get(0) });
+ } else {
+ // In case of errors, return an empty set of frames.
+ rm.setData(new IVMContext[0]);
+ }
+ rm.done();
+ }
+ })
+ );
+ return;
+ }
+ super.getContextsForEvent(parentDelta, e, rm);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.ui.viewmodel.IVMNode#getDeltaFlags(java.lang.Object)
+ */
+ public int getDeltaFlags(Object e) {
+ // This node generates delta if the timers have changed, or if the
+ // label has changed.
+ if (e instanceof ISuspendedDMEvent) {
+ return IModelDelta.CONTENT | IModelDelta.EXPAND | IModelDelta.SELECT;
+ } else if (e instanceof FullStackRefreshEvent) {
+ return IModelDelta.CONTENT | IModelDelta.EXPAND;
+ } else if (e instanceof SteppingTimedOutEvent) {
+ return IModelDelta.CONTENT;
+ } else if (e instanceof ISteppingTimedOutEvent) {
+ return IModelDelta.CONTENT;
+ } else if (e instanceof ModelProxyInstalledEvent) {
+ return IModelDelta.SELECT | IModelDelta.EXPAND;
+ } else if (e instanceof ExpandStackEvent) {
+ return IModelDelta.CONTENT;
+ } else if (e instanceof IExitedDMEvent) {
+ // Do not generate a delta for this event, but do clear the
+ // internal stack frame limit to avoid a memory leak.
+ clearStackFrameLimit( ((IExitedDMEvent)e).getDMContext() );
+ return IModelDelta.NO_CHANGE;
+ } else if (e instanceof PropertyChangeEvent) {
+ String property = ((PropertyChangeEvent)e).getProperty();
+ if (IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT_ENABLE.equals(property)
+ || IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT.equals(property))
+ {
+ return IModelDelta.CONTENT;
+ }
+ } else {
+ }
+
+ 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(final Object e, final VMDelta parent, final int nodeOffset, final RequestMonitor rm) {
+ if (e instanceof IContainerSuspendedDMEvent) {
+ // Clear the limit on the stack frames for all stack frames under a given container.
+ clearStackFrameLimit( ((IContainerSuspendedDMEvent)e).getDMContext() );
+
+ IContainerSuspendedDMEvent csEvent = (IContainerSuspendedDMEvent)e;
+
+ IExecutionDMContext triggeringCtx = csEvent.getTriggeringContexts().length != 0
+ ? csEvent.getTriggeringContexts()[0] : null;
+
+ if (parent.getElement() instanceof IDMVMContext) {
+ IExecutionDMContext threadDmc = null;
+ threadDmc = DMContexts.getAncestorOfType( ((IDMVMContext)parent.getElement()).getDMContext(), IExecutionDMContext.class);
+ buildDeltaForSuspendedEvent(threadDmc, triggeringCtx, parent, nodeOffset, rm);
+ } else {
+ rm.done();
+ }
+ } else if (e instanceof FullStackRefreshEvent) {
+ IExecutionDMContext execDmc = ((FullStackRefreshEvent)e).getDMContext();
+ buildDeltaForFullStackRefreshEvent(execDmc, execDmc, parent, nodeOffset, rm);
+ } else if (e instanceof ISuspendedDMEvent) {
+ clearStackFrameLimit( ((ISuspendedDMEvent)e).getDMContext() );
+ IExecutionDMContext execDmc = ((ISuspendedDMEvent)e).getDMContext();
+ buildDeltaForSuspendedEvent(execDmc, execDmc, parent, nodeOffset, rm);
+ } else if (e instanceof SteppingTimedOutEvent) {
+ buildDeltaForSteppingTimedOutEvent((SteppingTimedOutEvent)e, parent, nodeOffset, rm);
+ } else if (e instanceof ISteppingTimedOutEvent) {
+ buildDeltaForSteppingTimedOutEvent((ISteppingTimedOutEvent)e, parent, nodeOffset, rm);
+ } else if (e instanceof ModelProxyInstalledEvent) {
+ buildDeltaForModelProxyInstalledEvent(parent, nodeOffset, rm);
+ } else if (e instanceof ExpandStackEvent) {
+ IExecutionDMContext execDmc = ((ExpandStackEvent)e).getDMContext();
+ buildDeltaForExpandStackEvent(execDmc, parent, rm);
+ } else if (e instanceof PropertyChangeEvent) {
+ String property = ((PropertyChangeEvent)e).getProperty();
+ if (IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT_ENABLE.equals(property)
+ || IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT.equals(property))
+ {
+ buildDeltaForStackFrameLimitPreferenceChangedEvent(parent, rm);
+ } else {
+ rm.done();
+ }
+ } else {
+ rm.done();
+ }
+ }
+
+ private void buildDeltaForSuspendedEvent(final IExecutionDMContext executionCtx, final IExecutionDMContext triggeringCtx, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) {
+ IRunControl runControlService = getServicesTracker().getService(IRunControl.class);
+ IStack stackService = getServicesTracker().getService(IStack.class);
+ if (stackService == null || runControlService == null) {
+ // Required services have not initialized yet. Ignore the event.
+ rm.done();
+ return;
+ }
+
+ // Check if we are building a delta for the thread that triggered the event.
+ // Only then expand the stack frames and select the top one.
+ if (executionCtx.equals(triggeringCtx)) {
+ // Always expand the thread node to show the stack frames.
+ parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.EXPAND);
+
+ // Retrieve the list of stack frames, and mark the top frame to be selected.
+ getVMProvider().updateNode(
+ this,
+ new VMChildrenUpdate(
+ parentDelta, getVMProvider().getPresentationContext(), 0, 2,
+ new DataRequestMonitor<List<Object>>(getExecutor(), rm) {
+ @Override
+ public void handleCompleted() {
+ final List<Object> data= getData();
+ if (data != null && data.size() != 0) {
+ parentDelta.addNode(data.get(0), 0, IModelDelta.SELECT | IModelDelta.STATE);
+
+ // Refresh the whole list of stack frames unless the target is already stepping the next command. In
+ // which case, the refresh will occur when the stepping sequence slows down or stops. Trying to
+ // refresh the whole stack trace with every step would slow down stepping too much.
+ IRunControl runControlService = getServicesTracker().getService(IRunControl.class);
+ if (runControlService != null &&
+ triggeringCtx != null && runControlService.isStepping(triggeringCtx) &&
+ data.size() >= 2)
+ {
+ parentDelta.addNode( data.get(1), 1, IModelDelta.STATE);
+ }
+ }
+ // Even in case of errors, complete the request monitor.
+ rm.done();
+ }
+ })
+ );
+ } else {
+ rm.done();
+ }
+ }
+
+ private void buildDeltaForFullStackRefreshEvent(final IExecutionDMContext executionCtx, final IExecutionDMContext triggeringCtx, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) {
+ IRunControl runControlService = getServicesTracker().getService(IRunControl.class);
+ IStack stackService = getServicesTracker().getService(IStack.class);
+ if (stackService == null || runControlService == null) {
+ // Required services have not initialized yet. Ignore the event.
+ rm.done();
+ return;
+ }
+
+ // Refresh the whole list of stack frames unless the target is already stepping the next command. In
+ // which case, the refresh will occur when the stepping sequence slows down or stops. Trying to
+ // refresh the whole stack trace with every step would slow down stepping too much.
+ if (triggeringCtx == null || !runControlService.isStepping(triggeringCtx)) {
+ parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
+ }
+
+ rm.done();
+ }
+
+ private void buildDeltaForSteppingTimedOutEvent(final SteppingTimedOutEvent e, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) {
+ // Repaint the stack frame images to have the running symbol.
+ //parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
+ rm.done();
+ }
+
+ private void buildDeltaForSteppingTimedOutEvent(final ISteppingTimedOutEvent e, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) {
+ // Repaint the stack frame images to have the running symbol.
+ //parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
+ rm.done();
+ }
+
+ private void buildDeltaForModelProxyInstalledEvent(final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) {
+ // Retrieve the list of stack frames, and mark the top frame to be selected.
+ getVMProvider().updateNode(
+ this,
+ new VMChildrenUpdate(
+ parentDelta, getVMProvider().getPresentationContext(), -1, -1,
+ new DataRequestMonitor<List<Object>>(getExecutor(), rm) {
+ @Override
+ public void handleCompleted() {
+ if (isSuccess() && getData().size() != 0) {
+ parentDelta.addNode( getData().get(0), 0, IModelDelta.SELECT | IModelDelta.EXPAND);
+ }
+ rm.done();
+ }
+ })
+ );
+ }
+
+ private void buildDeltaForExpandStackEvent(IExecutionDMContext execDmc, final VMDelta parentDelta, final RequestMonitor rm) {
+ parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
+ rm.done();
+ }
+
+
+ private void buildDeltaForStackFrameLimitPreferenceChangedEvent(final VMDelta parentDelta, final RequestMonitor rm) {
+ parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
+ rm.done();
+ }
+
+ private String produceFrameElementName( String viewName , IFrameDMContext frame ) {
+ /*
+ * We are addressing Bugzilla 211490 which wants the Register View to keep the same expanded
+ * state for registers for stack frames within the same thread. Different threads could have
+ * different register sets ( e.g. one thread may have floating point & another may not ). But
+ * within a thread we are enforcing the assumption that the register sets will be the same.
+ * So we make a more convenient work flow by keeping the same expansion when selecting amount
+ * stack frames within the same thread. We accomplish this by only differentiating by adding
+ * the level for the Expression/Variables view. Otherwise we do not delineate based on which
+ * view and this captures the Register View in its filter.
+ */
+ if ( viewName.startsWith(IDebugUIConstants.ID_VARIABLE_VIEW) ||
+ viewName.startsWith(IDebugUIConstants.ID_EXPRESSION_VIEW) )
+ {
+ return "Frame." + frame.getLevel() + "." + frame.getSessionId(); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ else {
+ return "Frame" + frame.getSessionId(); //$NON-NLS-1$
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider#compareElements(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest[])
+ */
+ public void compareElements(IElementCompareRequest[] requests) {
+
+ for ( IElementCompareRequest request : requests ) {
+
+ Object element = request.getElement();
+ IMemento memento = request.getMemento();
+ String mementoName = memento.getString("STACK_FRAME_MEMENTO_NAME"); //$NON-NLS-1$
+
+ if (mementoName != null) {
+ if (element instanceof IDMVMContext) {
+
+ IDMContext dmc = ((IDMVMContext)element).getDMContext();
+
+ if ( dmc instanceof IFrameDMContext) {
+
+ String elementName = produceFrameElementName( request.getPresentationContext().getId(), (IFrameDMContext) dmc );
+ request.setEqual( elementName.equals( mementoName ) );
+ }
+ }
+ }
+ request.done();
+ }
+ }
+
+ /*
+ * (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 ) {
+
+ Object element = request.getElement();
+ IMemento memento = request.getMemento();
+
+ if (element instanceof IDMVMContext) {
+
+ IDMContext dmc = ((IDMVMContext)element).getDMContext();
+
+ if ( dmc instanceof IFrameDMContext) {
+
+ String elementName = produceFrameElementName( request.getPresentationContext().getId(), (IFrameDMContext) dmc );
+ memento.putString("STACK_FRAME_MEMENTO_NAME", elementName); //$NON-NLS-1$
+ }
+ }
+ request.done();
+ }
+ }
+
+ /**
+ * Get the current active stack frame limit. If no limit is applicable {@link Integer.MAX_VALUE} is returned.
+ *
+ * @return the current stack frame limit
+ *
+ * @since 1.1
+ */
+ public int getStackFrameLimit(IExecutionDMContext execCtx) {
+ if (fTemporaryLimits.containsKey(execCtx)) {
+ return fTemporaryLimits.get(execCtx);
+ }
+ Object stackDepthLimit= getVMProvider().getPresentationContext().getProperty(IDsfDebugUIConstants.PREF_STACK_FRAME_LIMIT);
+ if (stackDepthLimit instanceof Integer) {
+ return (Integer)stackDepthLimit;
+ }
+ return Integer.MAX_VALUE;
+ }
+
+ private void clearStackFrameLimit(IExecutionDMContext execCtx) {
+ if (execCtx instanceof IContainerDMContext) {
+ for (Iterator<IExecutionDMContext> itr = fTemporaryLimits.keySet().iterator(); itr.hasNext();) {
+ IExecutionDMContext limitCtx = itr.next();
+ if (limitCtx.equals(execCtx) || DMContexts.isAncestorOf(limitCtx, execCtx)) {
+ itr.remove();
+ }
+ }
+ } else {
+ fTemporaryLimits.remove(execCtx);
+ }
+ }
+
+
+ /**
+ * Increment the stack frame limit by the default increment.
+ * This implementation doubles the current limit.
+ *
+ * @since 1.1
+ */
+ public void incrementStackFrameLimit(IExecutionDMContext execCtx) {
+ final int stackFrameLimit= getStackFrameLimit(execCtx);
+ if (stackFrameLimit < Integer.MAX_VALUE / 2) {
+ fTemporaryLimits.put(execCtx, stackFrameLimit * 2);
+ } else {
+ fTemporaryLimits.put(execCtx, Integer.MAX_VALUE);
+ }
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/StandardProcessVMNode.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/StandardProcessVMNode.java
new file mode 100644
index 00000000000..5e0e7212e23
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/StandardProcessVMNode.java
@@ -0,0 +1,223 @@
+/*******************************************************************************
+ * 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.launch;
+
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMContext;
+import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMProvider;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta;
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugException;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.debug.core.model.IStreamsProxy;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
+import org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor;
+import org.eclipse.jface.viewers.TreePath;
+
+/**
+ * Layout node for the standard platform debug model IProcess object. This
+ * node requires that an ILaunch object be found as an ancestor of this node.
+ * It does not implement the label provider functionality, so the default
+ * adapters should be used to retrieve the label.
+ */
+@SuppressWarnings("restriction")
+public class StandardProcessVMNode extends AbstractVMNode {
+
+ /**
+ * VMC element implementation, it is a proxy for the IProcess class, to
+ * allow the standard label adapter to be used with this object.
+ */
+ private class VMC extends AbstractVMContext
+ implements IProcess
+ {
+ private final IProcess fProcess;
+
+ VMC(IProcess process) {
+ super(StandardProcessVMNode.this);
+ fProcess = process;
+ }
+
+ @Override
+ public IVMNode getVMNode() { return StandardProcessVMNode.this; }
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Class adapter) {
+ Object vmcAdapter = super.getAdapter(adapter);
+ if (vmcAdapter != null) {
+ return vmcAdapter;
+ }
+ return fProcess.getAdapter(adapter);
+ }
+ @Override
+ public String toString() { return "IProcess " + fProcess.toString(); } //$NON-NLS-1$
+
+ public String getAttribute(String key) { return fProcess.getAttribute(key); }
+ public int getExitValue() throws DebugException { return fProcess.getExitValue(); }
+ public String getLabel() { return fProcess.getLabel(); }
+ public ILaunch getLaunch() { return fProcess.getLaunch(); }
+ public IStreamsProxy getStreamsProxy() { return fProcess.getStreamsProxy(); }
+ public void setAttribute(String key, String value) { fProcess.setAttribute(key, value); }
+ public boolean canTerminate() { return fProcess.canTerminate(); }
+ public boolean isTerminated() { return fProcess.isTerminated(); }
+ public void terminate() throws DebugException { fProcess.terminate(); }
+
+ @Override
+ public boolean equals(Object other) {
+ return other instanceof VMC && fProcess.equals(((VMC)other).fProcess);
+ }
+ @Override
+ public int hashCode() { return fProcess.hashCode(); }
+ }
+
+ public StandardProcessVMNode(AbstractVMProvider provider) {
+ super(provider);
+ }
+
+ @Override
+ public String toString() {
+ return "StandardProcessVMNode"; //$NON-NLS-1$
+ }
+
+ public void update(IChildrenUpdate[] updates) {
+ for (IChildrenUpdate update : updates) {
+ ILaunch launch = findLaunch(update.getElementPath());
+ if (launch == null) {
+ // There is no launch in the parent of this node. This means that the
+ // layout is misconfigured.
+ assert false;
+ update.done();
+ continue;
+ }
+
+ /*
+ * Assume that the process objects are stored within the launch, and
+ * retrieve them on dispatch thread.
+ */
+ IProcess[] processes = launch.getProcesses();
+ for (int i = 0; i < processes.length; i++) {
+ update.setChild(new VMC(processes[i]), i);
+ }
+ update.done();
+ }
+ }
+
+ public void update(final IChildrenCountUpdate[] updates) {
+ for (IChildrenCountUpdate update : updates) {
+ if (!checkUpdate(update)) continue;
+ ILaunch launch = findLaunch(update.getElementPath());
+ if (launch == null) {
+ assert false;
+ update.setChildCount(0);
+ update.done();
+ return;
+ }
+
+ update.setChildCount(launch.getProcesses().length);
+ update.done();
+ }
+ }
+
+ // @see org.eclipse.cdt.dsf.ui.viewmodel.IViewModelLayoutNode#hasElements(org.eclipse.cdt.dsf.ui.viewmodel.IVMContext, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
+ public void update(IHasChildrenUpdate[] updates) {
+ for (IHasChildrenUpdate update : updates) {
+ ILaunch launch = findLaunch(update.getElementPath());
+ if (launch == null) {
+ assert false;
+ update.setHasChilren(false);
+ update.done();
+ return;
+ }
+
+ update.setHasChilren(launch.getProcesses().length != 0);
+ update.done();
+ }
+ }
+
+ // @see org.eclipse.cdt.dsf.ui.viewmodel.IViewModelLayoutNode#retrieveLabel(org.eclipse.cdt.dsf.ui.viewmodel.IVMContext, org.eclipse.debug.internal.ui.viewers.provisional.ILabelRequestMonitor)
+ public void updateLabel(IVMContext vmc, ILabelRequestMonitor result, String[] columns) {
+
+ /*
+ * The implementation of IAdapterFactory that uses this node should not
+ * register a label adapter for IProcess. This will cause the default
+ * label provider to be used instead, and this method should then never
+ * be called.
+ */
+ assert false;
+ result.done();
+ }
+
+ /**
+ * Recursively searches the VMC for Launch VMC, and returns its ILaunch.
+ * Returns null if an ILaunch is not found.
+ */
+ private ILaunch findLaunch(TreePath path) {
+ for (int i = path.getSegmentCount() - 1; i >= 0; i--) {
+ if (path.getSegment(i) instanceof ILaunch) {
+ return (ILaunch)path.getSegment(i);
+ }
+ }
+ return null;
+ }
+
+ public int getDeltaFlags(Object e) {
+ int myFlags = 0;
+ if (e instanceof DebugEvent) {
+ DebugEvent de = (DebugEvent)e;
+ if ( de.getSource() instanceof IProcess &&
+ (de.getKind() == DebugEvent.CHANGE ||
+ de.getKind() == DebugEvent.CREATE ||
+ de.getKind() == DebugEvent.TERMINATE) )
+ {
+ myFlags = IModelDelta.STATE;
+ }
+ }
+ return myFlags;
+ }
+
+ public void buildDelta(Object e, VMDelta parent, int nodeOffset, RequestMonitor requestMonitor) {
+ if (e instanceof DebugEvent && ((DebugEvent)e).getSource() instanceof IProcess) {
+ DebugEvent de = (DebugEvent)e;
+ if (de.getKind() == DebugEvent.CHANGE) {
+ handleChange(de, parent);
+ } else if (de.getKind() == DebugEvent.CREATE) {
+ handleCreate(de, parent);
+ } else if (de.getKind() == DebugEvent.TERMINATE) {
+ handleTerminate(de, parent);
+ }
+ /*
+ * No other node should need to process events related to process.
+ * Therefore, just invoke the request monitor without calling super.buildDelta().
+ */
+ }
+ requestMonitor.done();
+ }
+
+ protected void handleChange(DebugEvent event, ModelDelta parent) {
+ parent.addNode(new VMC((IProcess)event.getSource()), IModelDelta.STATE);
+ }
+
+ protected void handleCreate(DebugEvent event, ModelDelta parent) {
+ parent.setFlags(parent.getFlags() | IModelDelta.CONTENT);
+ }
+
+ protected void handleTerminate(DebugEvent event, ModelDelta parent) {
+ handleChange(event, parent);
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/actions/ExpandStackAction.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/actions/ExpandStackAction.java
new file mode 100644
index 00000000000..665d6e9f109
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/launch/actions/ExpandStackAction.java
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Wind River Systems, Inc. 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.actions;
+
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.actions.AbstractVMProviderActionDelegate;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.AbstractLaunchVMProvider;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.ExpandStackEvent;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.StackFramesVMNode;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.StackFramesVMNode.IncompleteStackVMContext;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
+import org.eclipse.debug.ui.contexts.DebugContextEvent;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IWorkbenchPart;
+
+/**
+ * Increment the (temporary) stack limit for the selected stack.
+ */
+public class ExpandStackAction extends AbstractVMProviderActionDelegate implements IObjectActionDelegate {
+
+ /*
+ * @see org.eclipse.ui.IActionDelegate#run(org.eclipse.jface.action.IAction)
+ */
+ public void run(IAction action) {
+ Object element = getViewerInput();
+ if (element instanceof IncompleteStackVMContext) {
+ IncompleteStackVMContext incStackVmc = ((IncompleteStackVMContext) element);
+ IVMNode node = incStackVmc.getVMNode();
+ if (incStackVmc.getVMNode() instanceof StackFramesVMNode) {
+ final IExecutionDMContext exeCtx= incStackVmc.getExecutionDMContext();
+ ((StackFramesVMNode) node).incrementStackFrameLimit(exeCtx);
+ final ExpandStackEvent event = new ExpandStackEvent(exeCtx);
+ final AbstractLaunchVMProvider vmProvider = (AbstractLaunchVMProvider) getVMProvider();
+ vmProvider.getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ vmProvider.handleEvent(event);
+ }
+ });
+ }
+ }
+ }
+
+ @Override
+ public void init(IViewPart view) {
+ super.init(view);
+ updateEnablement();
+ }
+
+ @Override
+ public void debugContextChanged(DebugContextEvent event) {
+ super.debugContextChanged(event);
+ updateEnablement();
+ }
+
+ @Override
+ public void selectionChanged(IAction action, ISelection selection) {
+ super.selectionChanged(action, selection);
+ updateEnablement();
+ }
+
+ private void updateEnablement() {
+ boolean enabled = false;
+ if (getVMProvider() instanceof AbstractLaunchVMProvider) {
+ Object element = getViewerInput();
+ enabled = element instanceof IncompleteStackVMContext;
+ }
+ getAction().setEnabled(enabled);
+ }
+
+ public void setActivePart(IAction action, IWorkbenchPart targetPart) {
+ if (targetPart instanceof IViewPart) {
+ init((IViewPart) targetPart);
+ }
+ }
+}
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
new file mode 100644
index 00000000000..83c9bbe2e4c
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/ModulesVMNode.java
@@ -0,0 +1,180 @@
+/*******************************************************************************
+ * 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
+ * Ericsson AB - Modules view for DSF implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.ui.viewmodel.modules;
+
+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.RequestMonitor;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.debug.service.IModules;
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+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.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.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;
+
+@SuppressWarnings("restriction")
+public class ModulesVMNode extends AbstractDMVMNode
+ implements IElementLabelProvider
+{
+ /**
+ * Marker type for the modules VM context. It allows action enablement
+ * expressions to check for module context type.
+ */
+ public class ModuleVMContext extends DMVMContext {
+ protected ModuleVMContext(IDMContext dmc) {
+ super(dmc);
+ }
+ }
+
+
+ public ModulesVMNode(AbstractDMVMProvider provider, DsfSession session) {
+ super(provider, session, IModuleDMContext.class);
+ }
+
+ @Override
+ public String toString() {
+ return "ModulesVMNode(" + getSession().getId() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ @Override
+ protected void updateElementsInSessionThread(final IChildrenUpdate update) {
+ IModules modulesService = getServicesTracker().getService(IModules.class);
+ final ISymbolDMContext symDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), ISymbolDMContext.class) ;
+
+ if (modulesService == null || symDmc == null) {
+ handleFailedUpdate(update);
+ return;
+ }
+
+ modulesService.getModules(
+ symDmc,
+ new ViewerDataRequestMonitor<IModuleDMContext[]>(getSession().getExecutor(), update) {
+ @Override
+ public void handleCompleted() {
+ if (!isSuccess()) {
+ update.done();
+ return;
+ }
+ fillUpdateWithVMCs(update, getData());
+ update.done();
+ }});
+ }
+
+ @Override
+ protected IDMVMContext createVMContext(IDMContext dmc) {
+ return new ModuleVMContext(dmc);
+ }
+
+ public void update(final ILabelUpdate[] updates) {
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ updateLabelInSessionThread(updates);
+ }});
+ } catch (RejectedExecutionException e) {
+ for (ILabelUpdate update : updates) {
+ handleFailedUpdate(update);
+ }
+ }
+ }
+
+
+ protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
+ for (final ILabelUpdate update : updates) {
+ IModules modulesService = getServicesTracker().getService(IModules.class);
+ 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;
+ }
+
+ // 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<IModuleDMData>(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);
+ }
+ 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);
+ }
+ }
+
+ public int getDeltaFlags(Object e) {
+ if (e instanceof IRunControl.ISuspendedDMEvent) {
+ return IModelDelta.CONTENT;
+ }
+ return IModelDelta.NO_CHANGE;
+ }
+
+ public void buildDelta(Object e, VMDelta parentDelta, int nodeOffset, RequestMonitor rm) {
+ if (e instanceof IRunControl.ISuspendedDMEvent) {
+ // Create a delta that indicates all groups have changed
+ parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
+ }
+
+ rm.done();
+ }
+}
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
new file mode 100644
index 00000000000..fc713683cdc
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/ModulesVMProvider.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * 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
+ * Ericsson AB - Modules view for DSF implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.ui.viewmodel.modules;
+
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.debug.service.ICachingService;
+import org.eclipse.cdt.dsf.debug.service.IModules;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMAdapter;
+import org.eclipse.cdt.dsf.ui.viewmodel.IRootVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.RootDMVMNode;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+
+/**
+ *
+ */
+@SuppressWarnings("restriction")
+public class ModulesVMProvider extends AbstractDMVMProvider {
+ /*
+ * Current default for register formatting.
+ */
+ public ModulesVMProvider(AbstractVMAdapter adapter, IPresentationContext context, DsfSession session) {
+ super(adapter, context, session);
+
+ /*
+ * Create the top level node to deal with the root selection.
+ */
+ IRootVMNode rootNode = new RootDMVMNode(this);
+
+ /*
+ * Create the Group nodes next. They represent the first level shown in the view.
+ */
+ IVMNode modulesNode = new ModulesVMNode(this, getSession());
+ addChildNodes(rootNode, new IVMNode[] { modulesNode });
+
+ /*
+ * Now set this schema set as the layout set.
+ */
+ setRootNode(rootNode);
+ }
+
+ @Override
+ public void refresh() {
+ super.refresh();
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ DsfServicesTracker tracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), getSession().getId());
+ IModules modulesService = tracker.getService(IModules.class);
+ if (modulesService instanceof ICachingService) {
+ ((ICachingService)modulesService).flushCache(null);
+ }
+ tracker.dispose();
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ // Session disposed, ignore.
+ }
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/detail/ModuleDetailPane.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/detail/ModuleDetailPane.java
new file mode 100644
index 00000000000..f014c8f4c7b
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/detail/ModuleDetailPane.java
@@ -0,0 +1,525 @@
+/*******************************************************************************
+ * 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:
+ * IBM Corporation - initial API and implementation
+ * QNX Software Systems - Mikhail Khodjaiants - Registers View (Bug 53640)
+ * Wind River Systems - adopted to use with Modules view
+ * Ericsson AB - Modules view for DSF implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.ui.viewmodel.modules.detail;
+
+
+import java.util.concurrent.ExecutionException;
+
+import org.eclipse.cdt.debug.ui.ICDebugUIConstants;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
+import org.eclipse.cdt.dsf.concurrent.Query;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+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.IModules;
+import org.eclipse.cdt.dsf.debug.service.IModules.IModuleDMContext;
+import org.eclipse.cdt.dsf.debug.service.IModules.IModuleDMData;
+import org.eclipse.cdt.dsf.debug.ui.IDsfDebugUIConstants;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.cdt.dsf.service.DsfServicesTracker;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
+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.ui.IDebugView;
+import org.eclipse.jface.action.IMenuListener;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.jface.text.ITextOperationTarget;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.FocusAdapter;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.progress.WorkbenchJob;
+import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds;
+
+
+/**
+ *
+ */
+public class ModuleDetailPane extends ModulesAbstractDetailPane implements IAdaptable, IPropertyChangeListener {
+
+ /**
+ * These are the IDs for the actions in the context menu
+ */
+ protected static final String DETAIL_COPY_ACTION = ActionFactory.COPY.getId() + ".SourceDetailPane"; //$NON-NLS-1$
+ protected static final String DETAIL_SELECT_ALL_ACTION = IDebugView.SELECT_ALL_ACTION + ".SourceDetailPane"; //$NON-NLS-1$
+
+ /**
+ * The ID, name and description of this pane are stored in constants so that the class
+ * does not have to be instantiated to access them.
+ */
+ public static final String ID = "ModuleDetailPane"; //$NON-NLS-1$
+ public static final String NAME = "Module Viewer"; //$NON-NLS-1$
+ public static final String DESCRIPTION = "A detail pane that is based on a source viewer. Displays as text and has actions for assigning values, content assist and text modifications."; //$NON-NLS-1$
+
+
+ /**
+ * The source viewer in which the computed string detail
+ * of selected modules will be displayed.
+ */
+ private SourceViewer fSourceViewer;
+ public Control createControl(Composite parent) {
+ createSourceViewer(parent);
+
+ if (isInView()){
+ createViewSpecificComponents();
+ createActions();
+ DsfUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this);
+ JFaceResources.getFontRegistry().addListener(this);
+ }
+ return fSourceViewer.getControl();
+ }
+
+ private DetailJob fDetailJob = null;
+ public void display(IStructuredSelection selection) {
+ if (selection == null){
+ clearSourceViewer();
+ return;
+ }
+
+ if (isInView()){
+ fSourceViewer.setEditable(true);
+ }
+
+ if (selection.isEmpty()){
+ clearSourceViewer();
+ return;
+ }
+
+ synchronized (this) {
+ if (fDetailJob != null) {
+ fDetailJob.cancel();
+ }
+ fDetailJob = new DetailJob(selection.getFirstElement());
+ fDetailJob.schedule();
+ }
+
+ }
+
+ /**
+ * Clears the source viewer, removes all text.
+ */
+ protected void clearSourceViewer(){
+ if (fDetailJob != null) {
+ fDetailJob.cancel();
+ }
+ fDetailDocument.set(""); //$NON-NLS-1$
+ fSourceViewer.setEditable(false);
+ }
+
+ @Override
+ public void dispose() {
+ super.dispose();
+ if (fDetailJob != null) fDetailJob.cancel();
+ if (fSourceViewer != null && fSourceViewer.getControl() != null) fSourceViewer.getControl().dispose();
+
+ if (isInView()){
+ DsfUIPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this);
+ JFaceResources.getFontRegistry().removeListener(this);
+ }
+
+ }
+ public String getDescription() {
+ return DESCRIPTION;
+ }
+ public String getID() {
+ return ID;
+ }
+ public String getName() {
+ return NAME;
+ }
+
+ public boolean setFocus() {
+ if (fSourceViewer != null){
+ fSourceViewer.getTextWidget().setFocus();
+ return true;
+ }
+ return false;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Class adapter) {
+ if (ITextViewer.class.equals(adapter)) {
+ return fSourceViewer;
+ }
+ return null;
+ }
+
+ public void propertyChange(PropertyChangeEvent event) {
+ String propertyName= event.getProperty();
+ if (propertyName.equals(IDsfDebugUIConstants.DETAIL_PANE_FONT)) {
+ fSourceViewer.getTextWidget().setFont(JFaceResources.getFont(IDsfDebugUIConstants.DETAIL_PANE_FONT));
+ }
+ }
+
+
+ /**
+ * Creates the source viewer in the given parent composite
+ *
+ * @param parent Parent composite to create the source viewer in
+ */
+ private void createSourceViewer(Composite parent) {
+
+ // Create & configure a SourceViewer
+ fSourceViewer = new SourceViewer(parent, null, SWT.V_SCROLL | SWT.H_SCROLL);
+ fSourceViewer.setDocument(getDetailDocument());
+ fSourceViewer.getTextWidget().setFont(JFaceResources.getFont(IDsfDebugUIConstants.DETAIL_PANE_FONT));
+ fSourceViewer.getTextWidget().setWordWrap(DsfUIPlugin.getDefault().getPreferenceStore().getBoolean(IDsfDebugUIConstants.PREF_DETAIL_PANE_WORD_WRAP));
+ fSourceViewer.setEditable(false);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(fSourceViewer.getTextWidget(), IDsfDebugUIConstants.DETAIL_PANE);
+ Control control = fSourceViewer.getControl();
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ control.setLayoutData(gd);
+ }
+
+ /**
+ * Variables used to create the detailed information for a selection
+ */
+ private IDocument fDetailDocument;
+
+ /**
+ * Lazily instantiate and return a Document for the detail pane text viewer.
+ */
+ protected IDocument getDetailDocument() {
+ if (fDetailDocument == null) {
+ fDetailDocument = new Document();
+ }
+ return fDetailDocument;
+ }
+
+ /**
+ * Creates listeners and other components that should only be added to the
+ * source viewer when this detail pane is inside a view.
+ */
+ private void createViewSpecificComponents(){
+
+ // Add a document listener so actions get updated when the document changes
+ getDetailDocument().addDocumentListener(new IDocumentListener() {
+ public void documentAboutToBeChanged(DocumentEvent event) {}
+ public void documentChanged(DocumentEvent event) {
+ updateSelectionDependentActions();
+ }
+ });
+
+ // Add the selection listener so selection dependent actions get updated.
+ fSourceViewer.getSelectionProvider().addSelectionChangedListener(new ISelectionChangedListener() {
+ public void selectionChanged(SelectionChangedEvent event) {
+ updateSelectionDependentActions();
+ }
+ });
+
+ // Add a focus listener to update actions when details area gains focus
+ fSourceViewer.getControl().addFocusListener(new FocusAdapter() {
+ @Override
+ public void focusGained(FocusEvent e) {
+
+ getViewSite().setSelectionProvider(fSourceViewer.getSelectionProvider());
+
+ setGlobalAction(IDebugView.SELECT_ALL_ACTION, getAction(DETAIL_SELECT_ALL_ACTION));
+ setGlobalAction(IDebugView.COPY_ACTION, getAction(DETAIL_COPY_ACTION));
+
+ getViewSite().getActionBars().updateActionBars();
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+
+ getViewSite().setSelectionProvider(null);
+
+ setGlobalAction(IDebugView.SELECT_ALL_ACTION, null);
+ setGlobalAction(IDebugView.COPY_ACTION, null);
+ getViewSite().getActionBars().updateActionBars();
+
+ }
+ });
+
+ // Add a context menu to the detail area
+ createDetailContextMenu(fSourceViewer.getTextWidget());
+ }
+
+ /**
+ * Create the context menu particular to the detail pane. Note that anyone
+ * wishing to contribute an action to this menu must use
+ * <code>ICDebugUIConstants.MODULES_VIEW_DETAIL_ID</code> as the
+ * <code>targetID</code> in the extension XML.
+ */
+ protected void createDetailContextMenu(Control menuControl) {
+ MenuManager menuMgr= new MenuManager();
+ menuMgr.setRemoveAllWhenShown(true);
+ menuMgr.addMenuListener(new IMenuListener() {
+ public void menuAboutToShow(IMenuManager mgr) {
+ fillDetailContextMenu(mgr);
+ }
+ });
+ Menu menu= menuMgr.createContextMenu(menuControl);
+ menuControl.setMenu(menu);
+
+ getViewSite().registerContextMenu(ICDebugUIConstants.MODULES_VIEW_DETAIL_ID, menuMgr, fSourceViewer.getSelectionProvider());
+
+ }
+ /**
+ * Adds items to the detail pane's context menu including any extension defined
+ * actions.
+ *
+ * @param menu The menu to add the item to.
+ */
+ protected void fillDetailContextMenu(IMenuManager menu) {
+
+ menu.add(new Separator(ICDebugUIConstants.MODULES_GROUP));
+ menu.add(new Separator());
+ menu.add(getAction(DETAIL_COPY_ACTION));
+ menu.add(getAction(DETAIL_SELECT_ALL_ACTION));
+ menu.add(new Separator());
+ menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
+
+ }
+ /**
+ * Creates the actions to add to the context menu
+ */
+ private void createActions() {
+ TextViewerAction textAction= new TextViewerAction(fSourceViewer, ITextOperationTarget.SELECT_ALL);
+ textAction.configureAction(MessagesForDetailPane.DetailPane_Select_All, "", ""); //$NON-NLS-1$ //$NON-NLS-2$
+ textAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.SELECT_ALL);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(textAction, IDsfDebugUIConstants.DETAIL_PANE_SELECT_ALL_ACTION);
+ setAction(DETAIL_SELECT_ALL_ACTION, textAction);
+
+ textAction= new TextViewerAction(fSourceViewer, ITextOperationTarget.COPY);
+ textAction.configureAction(MessagesForDetailPane.DetailPane_Copy, "", ""); //$NON-NLS-1$ //$NON-NLS-2$
+ textAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.COPY);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(textAction, IDsfDebugUIConstants.DETAIL_PANE_COPY_ACTION);
+ setAction(DETAIL_COPY_ACTION, textAction);
+
+ setSelectionDependantAction(DETAIL_COPY_ACTION);
+
+ updateSelectionDependentActions();
+ }
+
+
+ /**
+ * Job to compute the details for a selection
+ */
+ class DetailJob extends Job {
+
+ private Object fElement;
+ // whether a result was collected
+ private IProgressMonitor fMonitor;
+
+ public DetailJob(Object element) {
+ super("compute module details"); //$NON-NLS-1$
+ setSystem(true);
+ fElement = element;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
+ */
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ fMonitor = monitor;
+ /*
+ * Make sure this is an element we want to deal with.
+ */
+ IModuleDMContext dmc = null;
+ if (fElement instanceof IDMVMContext) {
+ IDMContext vmcdmc = ((IDMVMContext)fElement).getDMContext();
+ dmc = DMContexts.getAncestorOfType(vmcdmc, IModuleDMContext.class);
+ }
+
+ if (dmc == null) return Status.OK_STATUS;
+ DsfSession session = DsfSession.getSession(dmc.getSessionId());
+ if (session == null) return Status.OK_STATUS;
+
+ /*
+ * Create the query to write the value to the service. Note: no need to
+ * guard against RejectedExecutionException, because
+ * DsfSession.getSession() above would only return an active session.
+ */
+ GetModuleDetailsQuery query = new GetModuleDetailsQuery(dmc);
+ session.getExecutor().execute(query);
+
+ /*
+ * Now we have the data, go and get it. Since the call is completed now
+ * the ".get()" will not suspend it will immediately return with the
+ * data.
+ */
+ try {
+ detailComputed(getModuleDetail((IModuleDMData) query.get()));
+ } catch (InterruptedException e) {
+ assert false;
+ return Status.OK_STATUS;
+ } catch (ExecutionException e) {
+ return Status.OK_STATUS;
+ }
+ return Status.OK_STATUS;
+ }
+
+ /**
+ * Set the module details in the detail pane view
+ * @param result
+ */
+ private void detailComputed(final String result) {
+ if (!fMonitor.isCanceled()) {
+ WorkbenchJob setDetail = new WorkbenchJob("set details") { //$NON-NLS-1$
+ @Override
+ public IStatus runInUIThread(IProgressMonitor monitor) {
+ if (!fMonitor.isCanceled()) {
+ getDetailDocument().set(result);
+ }
+ return Status.OK_STATUS;
+ }
+ };
+ setDetail.setSystem(true);
+ setDetail.schedule();
+ }
+ }
+
+ }
+
+ /**
+ * To get the details of the given module selected in Modules View
+ * @param module
+ * @return
+ */
+ private String getModuleDetail( IModuleDMData module ) {
+ StringBuffer sb = new StringBuffer();
+
+ // Type
+ String type = null;
+// switch( module.getType() ) {
+// case ICModule.EXECUTABLE:
+// type = ModulesMessages.getString( "ModulesView.Executable" ); //$NON-NLS-1$
+// break;
+// case ICModule.SHARED_LIBRARY:
+// type = ModulesMessages.getString( "ModulesView.SharedLibrary" ); //$NON-NLS-1$
+// break;
+// }
+ type = ModulesMessages.getString( "ModulesView.SharedLibrary" ); //$NON-NLS-1$
+ if ( type != null ) {
+ sb.append( ModulesMessages.getString( "ModulesView.Type" ) ); //$NON-NLS-1$
+ sb.append( type );
+ sb.append( '\n' );
+ }
+
+ // Symbols flag
+ sb.append( ModulesMessages.getString( "ModulesView.Symbols" ) ); //$NON-NLS-1$
+ sb.append( ( module.isSymbolsLoaded()) ? ModulesMessages.getString( "ModulesView.Loaded" ) : ModulesMessages.getString( "ModulesView.NotLoaded" ) ); //$NON-NLS-1$ //$NON-NLS-2$
+ sb.append( '\n' );
+
+ // Symbols file
+ sb.append( ModulesMessages.getString( "ModulesView.SymbolsFile" ) ); //$NON-NLS-1$
+ sb.append( module.getFile());
+ sb.append( '\n' );
+
+ // Base address
+ String baseAddress = module.getBaseAddress();
+ sb.append( ModulesMessages.getString( "ModulesView.BaseAddress" ) ); //$NON-NLS-1$
+ sb.append( baseAddress );
+ sb.append( '\n' );
+
+ // Size
+ long size = module.getSize();
+ if ( size > 0 ) {
+ sb.append( ModulesMessages.getString( "ModulesView.Size" ) ); //$NON-NLS-1$
+ sb.append( size );
+ sb.append( '\n' );
+ }
+
+ return sb.toString();
+ }
+
+
+ public class GetModuleDetailsQuery extends Query<Object> {
+
+ private IModuleDMContext fDmc;
+
+ public GetModuleDetailsQuery(IModuleDMContext dmc) {
+ super();
+ fDmc = dmc;
+ }
+
+ @Override
+ protected void execute(final DataRequestMonitor<Object> rm) {
+ /*
+ * We're in another dispatch, so we must guard against executor
+ * shutdown again.
+ */
+ final DsfSession session = DsfSession.getSession(fDmc.getSessionId());
+ if (session == null) {
+ cancel(false);
+ return;
+ }
+
+ /*
+ * Guard against a disposed service
+ */
+ DsfServicesTracker tracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), fDmc.getSessionId());
+ IModules service = tracker.getService(IModules.class);
+ tracker.dispose();
+ if (service == null) {
+ rm .setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Service unavailable", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ service.getModuleData(fDmc, new DataRequestMonitor<IModuleDMData>( session.getExecutor(), rm) {
+ @Override
+ protected void handleCompleted() {
+ /*
+ * We're in another dispatch, so we must guard against executor shutdown again.
+ */
+ if (!DsfSession.isSessionActive(session.getId())) {
+ GetModuleDetailsQuery.this.cancel(false);
+ return;
+ }
+ super.handleCompleted();
+ }
+
+ @Override
+ protected void handleSuccess() {
+ /*
+ * All good set return value.
+ */
+ rm.setData(getData());
+ rm.done();
+ }
+ });
+ }
+ }
+}
+
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/detail/ModuleDetailPaneFactory.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/detail/ModuleDetailPaneFactory.java
new file mode 100644
index 00000000000..e3796b39a23
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/detail/ModuleDetailPaneFactory.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * 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:
+ * Ericsson AB - Modules view for DSF implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.ui.viewmodel.modules.detail;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.debug.ui.IDetailPane;
+import org.eclipse.debug.ui.IDetailPaneFactory;
+import org.eclipse.jface.viewers.IStructuredSelection;
+
+public class ModuleDetailPaneFactory implements IDetailPaneFactory {
+ public static final String MODULE_DETAIL_PANE_ID = ModuleDetailPane.ID;
+ public IDetailPane createDetailPane(String paneID) {
+ return new ModuleDetailPane();
+ }
+
+ public String getDefaultDetailPane(IStructuredSelection selection) {
+ return null;
+ }
+
+ public String getDetailPaneDescription(String paneID) {
+ if (paneID.equals(ModuleDetailPane.ID)){
+ return ModuleDetailPane.DESCRIPTION;
+ }
+ return null;
+ }
+
+ public String getDetailPaneName(String paneID) {
+ if (paneID.equals(ModuleDetailPane.ID)){
+ return ModuleDetailPane.NAME;
+ }
+ return null;
+ }
+
+ public Set<?> getDetailPaneTypes(IStructuredSelection selection) {
+ Set<String> possibleIDs = new HashSet<String>(1);
+ possibleIDs.add(ModuleDetailPane.ID);
+ return possibleIDs;
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/detail/ModulesAbstractDetailPane.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/detail/ModulesAbstractDetailPane.java
new file mode 100644
index 00000000000..277cfd054db
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/detail/ModulesAbstractDetailPane.java
@@ -0,0 +1,172 @@
+/*******************************************************************************
+ * 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:
+ * IBM Corporation - initial API and implementation
+ * Wind River Systems - adopted to use with Modules view
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.ui.viewmodel.modules.detail;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.debug.ui.IDetailPane;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.ui.IViewSite;
+import org.eclipse.ui.IWorkbenchPartSite;
+import org.eclipse.ui.texteditor.IUpdate;
+
+/**
+ * Abstract class that holds common methods used by implementors of IDetailPane.
+ */
+public abstract class ModulesAbstractDetailPane implements IDetailPane {
+
+ /**
+ * The <code>IWorkbenchPartSite</code> that the details area (and the
+ * variables view) belongs to.
+ */
+ private IWorkbenchPartSite fWorkbenchPartSite;
+
+ /**
+ * Map of actions. Keys are strings, values
+ * are <code>IAction</code>.
+ */
+ private Map<String,IAction> fActionMap = new HashMap<String,IAction>();
+
+ /**
+ * Collection to track actions that should be updated when selection occurs.
+ */
+ private List<String> fSelectionActions = new ArrayList<String>();
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.IDetailPane#init(org.eclipse.ui.IWorkbenchPartSite)
+ */
+ public void init(IWorkbenchPartSite workbench) {
+ fWorkbenchPartSite = workbench;
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.ui.IDetailPane#dispose()
+ */
+ public void dispose() {
+ fActionMap.clear();
+ fSelectionActions.clear();
+ }
+
+ /**
+ * Adds an action to the Map storing actions. Removes it if action is null.
+ *
+ * @param actionID The ID of the action, used as the key in the Map
+ * @param action The action associated with the ID
+ */
+ protected void setAction(String actionID, IAction action) {
+ if (action == null) {
+ fActionMap.remove(actionID);
+ } else {
+ fActionMap.put(actionID, action);
+ }
+ }
+
+ /**
+ * Adds the given action to the global action handler for the ViewSite.
+ * A call to <code>updateActionBars()</code> must be called after changes
+ * to propagate changes through the workbench.
+ *
+ * @param actionID The ID of the action
+ * @param action The action to be set globally
+ */
+ protected void setGlobalAction(String actionID, IAction action){
+ getViewSite().getActionBars().setGlobalActionHandler(actionID, action);
+ }
+
+ /**
+ * Adds the given action to the list of actions that will be updated when
+ * <code>updateSelectionDependentActions()</code> is called. If the string
+ * is null it will not be added to the list.
+ *
+ * @param actionID The ID of the action which should be updated
+ */
+ protected void setSelectionDependantAction(String actionID){
+ if (actionID != null) fSelectionActions.add(actionID);
+ }
+
+ /**
+ * Gets the action out of the map, casts it to an <code>IAction</code>
+ *
+ * @param actionID The ID of the action to find
+ * @return The action associated with the ID or null if none is found.
+ */
+ protected IAction getAction(String actionID) {
+ return fActionMap.get(actionID);
+ }
+
+ /**
+ * Calls the update method of the action with the given action ID.
+ * The action must exist in the action map and must be an instance of
+ * </code>IUpdate</code>
+ *
+ * @param actionId The ID of the action to update
+ */
+ protected void updateAction(String actionId) {
+ IAction action= getAction(actionId);
+ if (action instanceof IUpdate) {
+ ((IUpdate) action).update();
+ }
+ }
+
+ /**
+ * Iterates through the list of selection dependent actions and
+ * updates them. Use <code>setSelectionDependentAction(String actionID)</code>
+ * to add an action to the list. The action must have been added to the known
+ * actions map by calling <code>setAction(String actionID, IAction action)</code>
+ * before it can be updated by this method.
+ */
+ protected void updateSelectionDependentActions() {
+ Iterator<String> iterator= fSelectionActions.iterator();
+ while (iterator.hasNext()) {
+ updateAction(iterator.next());
+ }
+ }
+
+ /**
+ * Gets the view site for this view. May be null if this detail pane
+ * is not part of a view.
+ *
+ * @return The site for this view or <code>null</code>
+ */
+ protected IViewSite getViewSite(){
+ if (fWorkbenchPartSite == null){
+ return null;
+ } else {
+ return (IViewSite) fWorkbenchPartSite.getPart().getSite();
+ }
+ }
+
+ /**
+ * Gets the workbench part site for this view. May be null if this detail pane
+ * is not part of a view.
+ *
+ * @return The workbench part site or <code>null</code>
+ */
+ protected IWorkbenchPartSite getWorkbenchPartSite() {
+ return fWorkbenchPartSite;
+ }
+
+ /**
+ * Returns whether this detail pane is being displayed in a view with a workbench part site.
+ *
+ * @return whether this detail pane is being displayed in a view with a workbench part site.
+ */
+ protected boolean isInView(){
+ return fWorkbenchPartSite != null;
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/detail/ModulesMessages.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/detail/ModulesMessages.java
new file mode 100644
index 00000000000..a29cb586e50
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/detail/ModulesMessages.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2008 QNX Software 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:
+ * QNX Software Systems - Initial API and implementation
+ * Wind River Systems, Inc. - extended implementation
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.ui.viewmodel.modules.detail;
+
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * Comment for .
+ */
+public class ModulesMessages {
+
+ private static final String BUNDLE_NAME = "org.eclipse.cdt.dsf.debug.ui.viewmodel.modules.detail.ModulesMessages";//$NON-NLS-1$
+
+ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle( BUNDLE_NAME );
+
+ private ModulesMessages() {
+ }
+
+ public static String getString( String key ) {
+ try {
+ return RESOURCE_BUNDLE.getString( key );
+ }
+ catch( MissingResourceException e ) {
+ return '!' + key + '!';
+ }
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/detail/ModulesMessages.properties b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/detail/ModulesMessages.properties
new file mode 100644
index 00000000000..14cb80d4921
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/modules/detail/ModulesMessages.properties
@@ -0,0 +1,25 @@
+###############################################################################
+# Copyright (c) 2005, 2008 QNX Software 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:
+# QNX Software Systems - initial API and implementation
+# Wind River Systems - adapted to work with platform Modules view (bug 210558)
+###############################################################################
+ModulesView.Executable=executable
+ModulesView.SharedLibrary=shared library
+ModulesView.Type=Type:
+ModulesView.Symbols=Symbols:
+ModulesView.Loaded=loaded
+ModulesView.NotLoaded=not loaded
+ModulesView.SymbolsFile=Symbols file:
+ModulesView.CPU=CPU:
+ModulesView.BaseAddress=Base address:
+ModulesView.Size=Size:
+ModulesView.SymbolsLoaded=\ (symbols loaded)
+ModulesView.SymbolsNotLoaded=(symbols not loaded)
+ModulesView.SelectAll=Select &All
+ModulesView.Copy=&Copy
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
new file mode 100644
index 00000000000..b0e78f1adac
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/FormattedValuePreferenceStore.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * 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.
+ */
+@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/IFormattedValuePreferenceStore.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/IFormattedValuePreferenceStore.java
new file mode 100644
index 00000000000..8b6f7d6c41a
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/IFormattedValuePreferenceStore.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ *
+ */
+
+@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
new file mode 100644
index 00000000000..561908d575d
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/IFormattedValueVMContext.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * 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.ui.viewmodel.IVMContext;
+
+/**
+ *
+ */
+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
new file mode 100644
index 00000000000..3db13710902
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/MessagesForNumberFormat.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * 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.numberformat;
+
+import org.eclipse.osgi.util.NLS;
+
+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 NumberFormatContribution_EmptyFormatsList_label;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, MessagesForNumberFormat.class);
+ }
+
+ private MessagesForNumberFormat() {}
+}
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
new file mode 100644
index 00000000000..bda57b093c4
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/NumberFormatsContribution.java
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * 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.util.ArrayList;
+import java.util.LinkedHashMap;
+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;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.actions.VMHandlerUtils;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ActionContributionItem;
+import org.eclipse.jface.action.ContributionItem;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.ui.actions.CompoundContributionItem;
+import org.eclipse.ui.menus.IWorkbenchContribution;
+import org.eclipse.ui.services.IServiceLocator;
+
+/**
+ * Dynamic menu contribution that shows available number formats
+ * in the current view.
+ *
+ * @since 1.1
+ */
+@SuppressWarnings("restriction")
+public class NumberFormatsContribution extends CompoundContributionItem implements IWorkbenchContribution {
+
+ private static final Map<String, String> FORMATS = new LinkedHashMap<String, String>();
+ 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);
+ }
+
+ 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);
+ fContext = context;
+ fFormatId = formatId;
+ }
+
+ @Override
+ public void run() {
+ if (isChecked()) {
+ fContext.setProperty(IDebugVMConstants.CURRENT_FORMAT_STORAGE, fFormatId);
+ }
+ }
+ }
+
+ private IServiceLocator fServiceLocator;
+
+ private static IContributionItem[] NO_BREAKPOINT_TYPES_CONTRIBUTION_ITEMS = new IContributionItem[] {
+ new ContributionItem() {
+ @Override
+ public void fill(Menu menu, int index) {
+ MenuItem item = new MenuItem(menu, SWT.NONE);
+ item.setEnabled(false);
+ item.setText(MessagesForNumberFormat.NumberFormatContribution_EmptyFormatsList_label);
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return false;
+ }
+ }
+ };
+
+ @Override
+ protected IContributionItem[] getContributionItems() {
+ IVMProvider provider = VMHandlerUtils.getActiveVMProvider(fServiceLocator);
+
+ // If no part or selection, disable all.
+ if (provider == null) {
+ return NO_BREAKPOINT_TYPES_CONTRIBUTION_ITEMS;
+ }
+
+ IPresentationContext context = provider.getPresentationContext();
+ Object activeId = context.getProperty(IDebugVMConstants.CURRENT_FORMAT_STORAGE);
+ if (activeId == null) {
+ activeId = IFormattedValues.NATURAL_FORMAT;
+ }
+
+ List<Action> actions = new ArrayList<Action>(FORMATS.size());
+ for (String formatId : FORMATS.keySet()) {
+ Action action = new SelectNumberFormatAction(context, formatId);
+ if (formatId.equals(activeId)) {
+ action.setChecked(true);
+ }
+ actions.add(action);
+ }
+
+ if ( actions.isEmpty() ) {
+ return NO_BREAKPOINT_TYPES_CONTRIBUTION_ITEMS;
+ }
+
+ IContributionItem[] items = new IContributionItem[actions.size()];
+ for (int i = 0; i < actions.size(); i++) {
+ items[i] = new ActionContributionItem(actions.get(i));
+ }
+ return items;
+ }
+
+ public void initialize(IServiceLocator serviceLocator) {
+ fServiceLocator = serviceLocator;
+ }
+}
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
new file mode 100644
index 00000000000..7dc699bf345
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/NumberFormatsPropertyTester.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * 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.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.actions.VMHandlerUtils;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMProvider;
+import org.eclipse.core.expressions.PropertyTester;
+import org.eclipse.debug.ui.IDebugView;
+import org.eclipse.ui.IWorkbenchPart;
+
+/**
+ * Property tester for number format information available through the given
+ * object. The object being tested should be either an {@link IVMContext},
+ * through which an instance of {@link IVMProvider} could be obtained.
+ * Or it could be an {@link IWorkbenchPart}, which is tested to see if it
+ * is a debug view through which a caching VM provider can be obtained.
+ * The view's presentation context is used to test the given property.
+ * <p>
+ * Three properties are supported:
+ * <ul>
+ * <li> "areNumberFormatsSupported" - Checks whether number formats are
+ * available at all given the receiver.</li>
+ * <li> "isNumberFormatAvailable" - Checks whether the number format ID in the
+ * expected value is available for the given receiver.</li>
+ * <li> "isNumberFormatActive" - Checks whether the number format ID in the expected
+ * value is the currently active number format for the given receiver.</li>
+ * </ul>
+ * </p>
+ */
+@SuppressWarnings("restriction")
+public class NumberFormatsPropertyTester extends PropertyTester {
+
+ private static final String SUPPORTED = "areNumberFormatsSupported"; //$NON-NLS-1$
+ private static final String AVAILABLE = "isNumberFormatAvailable"; //$NON-NLS-1$
+ private static final String ACTIVE = "isNumberFormatActive"; //$NON-NLS-1$
+
+ private static final List<String> AVAILABLE_FORMATS = new ArrayList<String>();
+ static {
+ AVAILABLE_FORMATS.add(IFormattedValues.NATURAL_FORMAT);
+ AVAILABLE_FORMATS.add(IFormattedValues.HEX_FORMAT);
+ AVAILABLE_FORMATS.add(IFormattedValues.DECIMAL_FORMAT);
+ AVAILABLE_FORMATS.add(IFormattedValues.OCTAL_FORMAT);
+ AVAILABLE_FORMATS.add(IFormattedValues.BINARY_FORMAT);
+ AVAILABLE_FORMATS.add(IFormattedValues.STRING_FORMAT);
+ };
+
+ public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
+ if (receiver instanceof IVMContext) {
+ IVMProvider provider = ((IVMContext)receiver).getVMNode().getVMProvider();
+ if (provider != null) {
+ return testProvider(provider, property, expectedValue);
+ }
+ } else if (receiver instanceof IDebugView) {
+ IVMProvider provider = VMHandlerUtils.getVMProviderForPart((IDebugView)receiver);
+ if (provider != null) {
+ return testProvider(provider, property, expectedValue);
+ }
+ }
+ return false;
+ }
+
+ private boolean testProvider(IVMProvider provider, String property, Object expectedValue) {
+ if (SUPPORTED.equals(property)) {
+ return true;
+ } else if (AVAILABLE.equals(property)) {
+ return AVAILABLE_FORMATS.contains(expectedValue);
+ } else if (ACTIVE.equals(property)) {
+ Object activeId = provider.getPresentationContext().getProperty(IDebugVMConstants.CURRENT_FORMAT_STORAGE);
+ 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
new file mode 100644
index 00000000000..fbebfa748d8
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/numberformat/messages.properties
@@ -0,0 +1,19 @@
+###############################################################################
+# 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 - copied for non-restricted version for DSDP/DD/DSF
+###############################################################################
+
+NumberFormatContribution_Natural_label=Natural
+NumberFormatContribution_Decimal_label=Decimal
+NumberFormatContribution_Hex_label=Hex
+NumberFormatContribution_Octal_label=Octal
+NumberFormatContribution_Binary_label=Binary
+NumberFormatContribution_String_label=String
+
+NumberFormatContribution_EmptyFormatsList_label=Number formats not available \ No newline at end of file
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
new file mode 100644
index 00000000000..432b0f07d3d
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/MessagesForRegisterVM.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * 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;
+
+import org.eclipse.osgi.util.NLS;
+
+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;
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, MessagesForRegisterVM.class);
+ }
+
+ private MessagesForRegisterVM() {
+ }
+}
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
new file mode 100644
index 00000000000..48c8d7b471c
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterBitFieldCellModifier.java
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * 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;
+
+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.IBitFieldDMContext;
+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.ui.viewmodel.IVMContext;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.AbstractCachingVMProvider;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.UserEditEvent;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+
+@SuppressWarnings("restriction")
+public class RegisterBitFieldCellModifier extends WatchExpressionCellModifier {
+
+ public static enum BitFieldEditorStyle { NOTHING, BITFIELDCOMBO, BITFIELDTEXT }
+
+ private AbstractCachingVMProvider fProvider;
+ private BitFieldEditorStyle fStyle;
+ private IBitFieldDMData fBitFieldData = null;
+ private Object fElement = null;
+ private SyncRegisterDataAccess fDataAccess = null;
+ private IFormattedValuePreferenceStore fFormatPrefStore;
+
+ public RegisterBitFieldCellModifier(AbstractCachingVMProvider provider,
+ IFormattedValuePreferenceStore formatPrefStore, BitFieldEditorStyle style, SyncRegisterDataAccess access )
+ {
+ fProvider = provider;
+ fStyle = style;
+ fDataAccess = access;
+ fFormatPrefStore = formatPrefStore;
+ }
+
+ /*
+ * Used to make sure we are dealing with a valid register.
+ */
+ private IBitFieldDMContext getBitFieldDMC(Object element) {
+ if (element instanceof IDMVMContext) {
+ IDMContext dmc = ((IDMVMContext)element).getDMContext();
+ return DMContexts.getAncestorOfType(dmc, IBitFieldDMContext.class);
+ }
+ return null;
+ }
+
+ @Override
+ public boolean canModify(Object element, String property) {
+
+ /*
+ * If we're in the column value, modify the register data.
+ * Otherwise, call the super-class to edit the watch expression.
+ */
+ if ( IDebugVMConstants.COLUMN_ID__VALUE.equals(property) ) {
+ /*
+ * Make sure we are are dealing with a valid set of information.
+ */
+ if ( getBitFieldDMC(element) == null ) return false;
+
+ fElement = element;
+
+ /*
+ * We need to read the register in order to get the attributes.
+ */
+ fBitFieldData = fDataAccess.readBitField(element);
+
+ if ( ( fBitFieldData != null ) && ( ! fBitFieldData.isWriteable() ) ) return false;
+
+ return true ;
+ } else {
+ return super.canModify(element, property);
+ }
+ }
+
+ @Override
+ public Object getValue(Object element, String property) {
+ /*
+ * If we're in the column value, modify the register data.
+ * Otherwise, call the super-class to edit the watch expression.
+ */
+ if ( IDebugVMConstants.COLUMN_ID__VALUE.equals(property) ) {
+ /*
+ * Make sure we are working on the editable areas.
+ */
+ if ( element != fElement ) return false;
+
+ if ( fStyle == BitFieldEditorStyle.BITFIELDTEXT ) {
+ /*
+ * We let the Model provider supply the current format.
+ */
+ String formatId;
+
+ if ( element instanceof IVMContext) {
+ /*
+ * Find the presentation context and then use it to get the current desired format.
+ */
+ IVMContext ctx = (IVMContext) element;
+ IPresentationContext presCtx = ctx.getVMNode().getVMProvider().getPresentationContext();
+
+ formatId = fFormatPrefStore.getCurrentNumericFormat(presCtx);
+ }
+ else {
+ formatId = IFormattedValues.NATURAL_FORMAT;
+ }
+
+ String value = fDataAccess.getFormattedBitFieldValue(fElement, formatId);
+
+ if ( value == null ) { value = "..."; } //$NON-NLS-1$
+
+ return value;
+ }
+ else {
+ /*
+ * This is a COMBO BOX. So we need to take the value of the bitfield and
+ * compare it to the associated mnemonic values to see which mnemonic is
+ * representing the current value. At this point the Bitfield Model data
+ * has already been established since the "canModify()" method is called
+ * first by the flexible hierarchy proxies.
+ */
+ IMnemonic curMnemonic = fBitFieldData.getCurrentMnemonicValue();
+
+ int index = 0 ;
+ for ( IMnemonic mnemonic : fBitFieldData.getMnemonics() ) {
+ if ( mnemonic.equals( curMnemonic ) ) {
+ return new Integer( index );
+ }
+ index ++;
+ }
+
+ return null;
+ }
+ } else {
+ return super.getValue(element, property);
+ }
+ }
+
+ @Override
+ public void modify(Object element, String property, Object value) {
+ /*
+ * If we're in the column value, modify the register data.
+ * Otherwise, call the super-class to edit the watch expression.
+ */
+ if ( IDebugVMConstants.COLUMN_ID__VALUE.equals(property) ) {
+ if ( fStyle == BitFieldEditorStyle.BITFIELDTEXT ) {
+ if (value instanceof String) {
+ /*
+ * We let the Model provider supply the current format.
+ */
+ String formatId;
+
+ if ( element instanceof IVMContext) {
+ /*
+ * Find the presentation context and then use it to get the current desired format.
+ */
+ IVMContext ctx = (IVMContext) element;
+ IPresentationContext presCtx = ctx.getVMNode().getVMProvider().getPresentationContext();
+
+ formatId = fFormatPrefStore.getCurrentNumericFormat(presCtx);
+ }
+ else {
+ formatId = IFormattedValues.NATURAL_FORMAT;
+ }
+ fDataAccess.writeBitField(element, (String) value, formatId);
+ fProvider.handleEvent(new UserEditEvent(element));
+ }
+ }
+ else {
+ if (value instanceof Integer) {
+ /*
+ * Get the integer value corresponding to the selected entry.
+ */
+ Integer val = (Integer) value;
+
+ /*
+ * Write the bit field using the selected mnemonic.
+ */
+ fDataAccess.writeBitField(element, fBitFieldData.getMnemonics()[val.intValue()]);
+ fProvider.handleEvent(new UserEditEvent(element));
+ }
+ }
+ } else {
+ super.modify(element, property, value);
+ }
+ }
+}
+
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
new file mode 100644
index 00000000000..0e96bf90d8a
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterBitFieldVMNode.java
@@ -0,0 +1,901 @@
+/*******************************************************************************
+ * 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.register;
+
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+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.IBitFieldChangedDMEvent;
+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.IMnemonic;
+import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterChangedDMEvent;
+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.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.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.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+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;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementEditor;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.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.internal.ui.viewers.model.provisional.IPresentationContext;
+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;
+import org.eclipse.jface.viewers.CellEditor;
+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.widgets.Composite;
+
+@SuppressWarnings("restriction")
+public class RegisterBitFieldVMNode extends AbstractExpressionVMNode
+ implements IElementEditor, IElementLabelProvider, IElementMementoProvider
+{
+ protected class BitFieldVMC extends DMVMContext
+ implements IFormattedValueVMContext
+ {
+ private IExpression fExpression;
+ public BitFieldVMC(IDMContext dmc) {
+ super(dmc);
+ }
+
+ public IFormattedValuePreferenceStore getPreferenceStore() {
+ return fFormattedPrefStore;
+ }
+
+ public void setExpression(IExpression expression) {
+ fExpression = expression;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Class adapter) {
+ if (fExpression != null && adapter.isAssignableFrom(fExpression.getClass())) {
+ return fExpression;
+ } else if (adapter.isAssignableFrom(IWatchExpressionFactoryAdapter2.class)) {
+ return getWatchExpressionFactory();
+ } else {
+ return super.getAdapter(adapter);
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof BitFieldVMC && super.equals(other)) {
+ BitFieldVMC otherBitField = (BitFieldVMC)other;
+ return (otherBitField.fExpression == null && fExpression == null) ||
+ (otherBitField.fExpression != null && otherBitField.fExpression.equals(fExpression));
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode() + (fExpression != null ? fExpression.hashCode() : 0);
+ }
+ }
+
+ protected class BitFieldExpressionFactory implements IWatchExpressionFactoryAdapter2 {
+
+ public boolean canCreateWatchExpression(Object element) {
+ return element instanceof BitFieldVMC;
+ }
+
+ /**
+ * Expected format: GRP( GroupName ).REG( RegisterName ).BFLD( BitFieldname )
+ */
+ public String createWatchExpression(Object element) throws CoreException {
+ IRegisterGroupDMData groupData = getSyncRegisterDataAccess().getRegisterGroupDMData(element);
+ IRegisterDMData registerData = getSyncRegisterDataAccess().getRegisterDMData(element);
+ IBitFieldDMData bitFieldData = getSyncRegisterDataAccess().getBitFieldDMData(element);
+
+ if (groupData != null && registerData != null && bitFieldData != null) {
+ StringBuffer exprBuf = new StringBuffer();
+
+ exprBuf.append("GRP( "); exprBuf.append(groupData.getName()); exprBuf.append(" )"); //$NON-NLS-1$ //$NON-NLS-2$
+ exprBuf.append(".REG( "); exprBuf.append(registerData.getName()); exprBuf.append(" )"); //$NON-NLS-1$ //$NON-NLS-2$
+ exprBuf.append(".BFLD( "); exprBuf.append(bitFieldData.getName()); exprBuf.append(" )"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ return exprBuf.toString();
+ }
+
+ return null;
+ }
+ }
+
+ private SyncRegisterDataAccess fSyncRegisterDataAccess = null;
+ protected IWatchExpressionFactoryAdapter2 fBitFieldExpressionFactory = null;
+ private final IFormattedValuePreferenceStore fFormattedPrefStore;
+
+ public RegisterBitFieldVMNode(IFormattedValuePreferenceStore prefStore, AbstractDMVMProvider provider, DsfSession session, SyncRegisterDataAccess access) {
+ super(provider, session, IBitFieldDMContext.class);
+ fSyncRegisterDataAccess = access;
+ fFormattedPrefStore = prefStore;
+ }
+
+
+ @Override
+ public String toString() {
+ return "RegisterBitFieldVMNode(" + getSession().getId() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public IFormattedValuePreferenceStore getPreferenceStore() {
+ return fFormattedPrefStore;
+ }
+
+ /**
+ * @since 1.1
+ */
+ public SyncRegisterDataAccess getSyncRegisterDataAccess() {
+ return fSyncRegisterDataAccess;
+ }
+
+ /**
+ * @since 1.1
+ */
+ public IWatchExpressionFactoryAdapter2 getWatchExpressionFactory() {
+ if ( fBitFieldExpressionFactory == null ) {
+ fBitFieldExpressionFactory = new BitFieldExpressionFactory();
+ }
+ 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<String[]>(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<FormattedValueDMData>(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) {
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ updateLabelInSessionThread(updates);
+ }});
+ } catch (RejectedExecutionException e) {
+ for (ILabelUpdate update : updates) {
+ handleFailedUpdate(update);
+ }
+ }
+ }
+
+ /*
+ * Updates the requested label based on the specified column.
+ */
+ protected void updateLabelInSessionThread(ILabelUpdate[] updates) {
+ for (final ILabelUpdate update : updates) {
+
+ final IRegisters regService = getServicesTracker().getService(IRegisters.class);
+
+ if ( regService == null ) {
+ handleFailedUpdate(update);
+ continue;
+ }
+
+ final IBitFieldDMContext dmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IBitFieldDMContext.class);
+
+ getDMVMProvider().getModelData(
+ this,
+ update,
+ regService,
+ dmc,
+ new ViewerDataRequestMonitor<IBitFieldDMData>(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();
+ } 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);
+ }
+ }
+ }
+ },
+ getExecutor()
+ );
+ }
+ }
+
+ /*
+ * (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);
+
+ if (regDmc == null) {
+ handleFailedUpdate(update);
+ return;
+ }
+
+ IRegisters regService = getServicesTracker().getService(IRegisters.class);
+
+ if ( regService == null ) {
+ handleFailedUpdate(update);
+ return;
+ }
+
+
+ regService.getBitFields(
+ regDmc,
+ new ViewerDataRequestMonitor<IBitFieldDMContext[]>(getSession().getExecutor(), update) {
+ @Override
+ protected void handleFailure() {
+ handleFailedUpdate(update);
+ }
+
+ @Override
+ protected void handleSuccess() {
+ fillUpdateWithVMCs(update, getData());
+ 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 BitFieldVMC(dmc);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.ui.viewmodel.IVMNode#getDeltaFlags(java.lang.Object)
+ */
+ public int getDeltaFlags(Object e) {
+ if ( e instanceof ISuspendedDMEvent ||
+ e instanceof IMemoryChangedEvent ||
+ e instanceof IRegisterChangedDMEvent ||
+ (e instanceof PropertyChangeEvent &&
+ ((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) )
+ {
+ return IModelDelta.CONTENT;
+ }
+
+ if (e instanceof IBitFieldChangedDMEvent) {
+ return IModelDelta.STATE;
+ }
+
+ 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) {
+ // The following events can affect any bit field's values,
+ // refresh the contents of the parent element (i.e. all the registers).
+ if ( e instanceof ISuspendedDMEvent ||
+ e instanceof IMemoryChangedEvent ||
+ e instanceof IRegisterChangedDMEvent ||
+ (e instanceof PropertyChangeEvent &&
+ ((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) )
+ {
+ parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
+ }
+
+ if (e instanceof IBitFieldChangedDMEvent) {
+ // Create a delta indicating that the value of bit field has changed.
+ parentDelta.addNode( createVMContext(((IBitFieldChangedDMEvent)e).getDMContext()), IModelDelta.STATE );
+ }
+
+ rm.done();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementEditor#getCellEditor(org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext, java.lang.String, java.lang.Object, org.eclipse.swt.widgets.Composite)
+ */
+ public CellEditor getCellEditor(IPresentationContext context, String columnId, Object element, Composite parent) {
+
+ if (IDebugVMConstants.COLUMN_ID__VALUE.equals(columnId)) {
+ /*
+ * In order to decide what kind of editor to present we need to know if there are
+ * mnemonics which can be used to represent the values. If there are then we will
+ * create a Combo editor for them. Otherwise we will just make a normal text cell
+ * editor. If there are bit groups then the modifier will check the size of the
+ * value being entered.
+ */
+ IBitFieldDMData bitFieldData = getSyncRegisterDataAccess().readBitField(element);
+
+ if ( bitFieldData != null && bitFieldData.isWriteable() ) {
+
+ IMnemonic[] mnemonics = bitFieldData.getMnemonics();
+
+ if ( mnemonics != null && mnemonics.length != 0 ) {
+
+ /*
+ * Create the list of readable dropdown selections.
+ */
+ String[] StringValues = new String[ mnemonics.length ];
+
+ int idx = 0 ;
+ for ( IMnemonic mnemonic : mnemonics ) {
+ StringValues[ idx ++ ] = mnemonic.getLongName();
+ }
+
+ /*
+ * Not we are complex COMBO and return the right editor.
+ */
+ return new ComboBoxCellEditor(parent, StringValues);
+ }
+ else {
+ /*
+ * Text editor even if we need to clamp the value entered.
+ */
+ return new TextCellEditor(parent);
+ }
+ }
+ } else if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(columnId)) {
+ return new TextCellEditor(parent);
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @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) {
+
+ /*
+ * In order to decide what kind of modifier to present we need to know if there
+ * are mnemonics which can be used to represent the values.
+ */
+ IBitFieldDMData bitFieldData = getSyncRegisterDataAccess().readBitField(element);
+
+ if ( bitFieldData != null && bitFieldData.isWriteable() ) {
+
+ IMnemonic[] mnemonics = bitFieldData.getMnemonics();
+
+ if ( mnemonics != null && mnemonics.length != 0 ) {
+ /*
+ * Note we are complex COMBO and return the right editor.
+ */
+ return new RegisterBitFieldCellModifier(
+ getDMVMProvider(), fFormattedPrefStore, BitFieldEditorStyle.BITFIELDCOMBO, getSyncRegisterDataAccess() );
+ }
+ else {
+ /*
+ * Text editor even if we need to clamp the value entered.
+ */
+ return new RegisterBitFieldCellModifier(
+ getDMVMProvider(), fFormattedPrefStore, BitFieldEditorStyle.BITFIELDTEXT, getSyncRegisterDataAccess() );
+ }
+ }
+ else {
+ return null;
+ }
+ }
+
+ /**
+ * Expected format: GRP( GroupName ).REG( RegisterName ).BFLD( BitFieldname )
+ */
+
+ public boolean canParseExpression(IExpression expression) {
+ return parseExpressionForBitFieldName(expression.getExpressionText()) != null;
+ }
+
+ private String parseExpressionForBitFieldName(String expression) {
+
+ if (expression.startsWith("GRP(")) { //$NON-NLS-1$
+
+ /*
+ * Get the group portion.
+ */
+ int startIdx = "GRP(".length(); //$NON-NLS-1$
+ int endIdx = expression.indexOf(')', startIdx);
+ if ( startIdx == -1 || endIdx == -1 ) {
+ return null;
+ }
+ String remaining = expression.substring(endIdx+1);
+ if ( ! remaining.startsWith(".REG(") ) { //$NON-NLS-1$
+ return null;
+ }
+
+ /*
+ * Get the register portion.
+ */
+ startIdx = ".REG(".length(); //$NON-NLS-1$
+ endIdx = remaining.indexOf(')', startIdx);
+ if ( startIdx == -1 || endIdx == -1 ) {
+ return null;
+ }
+ remaining = remaining.substring(endIdx+1);
+
+ /*
+ * Get the bit-field portion.
+ */
+ if ( ! remaining.startsWith(".BFLD(") ) { //$NON-NLS-1$
+ return null;
+ }
+ startIdx = ".BFLD(".length(); //$NON-NLS-1$
+ endIdx = remaining.indexOf(')', startIdx);
+ if ( startIdx == -1 || endIdx == -1 ) {
+ return null;
+ }
+ String bitFieldName = remaining.substring(startIdx, endIdx);
+
+ /*
+ * Make sure there is nothing following. If there is then this
+ * is not a properly formed expression and we do not claim it.
+ */
+ remaining = remaining.substring( endIdx + 1);
+
+ if ( remaining.length() != 0 ) {
+ return null;
+ }
+
+ return bitFieldName.trim();
+ }
+
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.AbstractExpressionVMNode#testElementForExpression(java.lang.Object, org.eclipse.debug.core.model.IExpression, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
+ */
+ @Override
+ protected void testElementForExpression(Object element, IExpression expression, final DataRequestMonitor<Boolean> rm) {
+ if (!(element instanceof IDMVMContext)) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ final IBitFieldDMContext dmc = DMContexts.getAncestorOfType(((IDMVMContext)element).getDMContext(), IBitFieldDMContext.class);
+ if (dmc == null) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ final String bitFieldName = parseExpressionForBitFieldName(expression.getExpressionText());
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ IRegisters registersService = getServicesTracker().getService(IRegisters.class);
+ if (registersService != null) {
+ registersService.getBitFieldData(
+ dmc,
+ new DataRequestMonitor<IBitFieldDMData>(ImmediateExecutor.getInstance(), rm) {
+ @Override
+ protected void handleSuccess() {
+ rm.setData( getData().getName().equals(bitFieldName) );
+ rm.done();
+ }
+ });
+ } else {
+ rm.setStatus(new Status(IStatus.WARNING, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Register service not available", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ rm.setStatus(new Status(IStatus.WARNING, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "DSF session shut down", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.AbstractExpressionVMNode#associateExpression(java.lang.Object, org.eclipse.debug.core.model.IExpression)
+ */
+ @Override
+ protected void associateExpression(Object element, IExpression expression) {
+ if (element instanceof BitFieldVMC) {
+ ((BitFieldVMC)element).setExpression(expression);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.IExpressionVMNode#getDeltaFlagsForExpression(org.eclipse.debug.core.model.IExpression, java.lang.Object)
+ */
+ public int getDeltaFlagsForExpression(IExpression expression, Object event) {
+ if (event instanceof ISuspendedDMEvent) {
+ return IModelDelta.CONTENT;
+ }
+
+ if (event instanceof PropertyChangeEvent &&
+ ((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) {
+ return IModelDelta.CONTENT;
+ }
+
+ if (event instanceof IMemoryChangedEvent) {
+ return IModelDelta.CONTENT;
+ }
+
+ return IModelDelta.NO_CHANGE;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.IExpressionVMNode#buildDeltaForExpression(org.eclipse.debug.core.model.IExpression, int, java.lang.Object, org.eclipse.cdt.dsf.ui.viewmodel.VMDelta, org.eclipse.jface.viewers.TreePath, org.eclipse.cdt.dsf.concurrent.RequestMonitor)
+ */
+ public void buildDeltaForExpression(final IExpression expression, final int elementIdx, final Object event, final VMDelta parentDelta, final TreePath path, final RequestMonitor rm)
+ {
+ // Always refresh the contents of the view upon suspended event.
+ if (event instanceof ISuspendedDMEvent) {
+ parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
+ }
+
+ rm.done();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.IExpressionVMNode#buildDeltaForExpressionElement(java.lang.Object, int, java.lang.Object, org.eclipse.cdt.dsf.ui.viewmodel.VMDelta, org.eclipse.cdt.dsf.concurrent.RequestMonitor)
+ */
+ public void buildDeltaForExpressionElement(Object element, int elementIdx, Object event, VMDelta parentDelta, final RequestMonitor rm)
+ {
+ // The following events can affect register values, refresh the state
+ // of the expression.
+ if ( event instanceof IRegisterChangedDMEvent ||
+ event instanceof IMemoryChangedEvent ||
+ (event instanceof PropertyChangeEvent &&
+ ((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) )
+ {
+ parentDelta.addNode(element, IModelDelta.STATE);
+ }
+
+ rm.done();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider#compareElements(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest[])
+ */
+ private final String MEMENTO_NAME = "BITFIELD_MEMENTO_NAME"; //$NON-NLS-1$
+
+ public void compareElements(IElementCompareRequest[] requests) {
+ for ( final IElementCompareRequest request : requests ) {
+ final String mementoName = request.getMemento().getString(MEMENTO_NAME);
+
+ final IBitFieldDMContext regDmc = findDmcInPath(request.getViewerInput(), request.getElementPath(), IBitFieldDMContext.class);
+ if (regDmc == null || mementoName == null) {
+ request.done();
+ continue;
+ }
+
+ // Now go get the model data for the single register group found.
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ final IRegisters regService = getServicesTracker().getService(IRegisters.class);
+ if ( regService != null ) {
+ regService.getBitFieldData(
+ regDmc,
+ new DataRequestMonitor<IBitFieldDMData>(regService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if ( getStatus().isOK() ) {
+ // Now make sure the register group is the one we want.
+ request.setEqual( mementoName.equals( "BitField." + getData().getName() ) ); //$NON-NLS-1$
+ }
+ request.done();
+ }
+ });
+ } else {
+ request.done();
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ request.done();
+ }
+ }
+ }
+
+ /*
+ * (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 ( final IElementMementoRequest request : requests ) {
+ final IBitFieldDMContext regDmc = findDmcInPath(request.getViewerInput(), request.getElementPath(), IBitFieldDMContext.class);
+ if (regDmc == null) {
+ request.done();
+ continue;
+ }
+
+ // Now go get the model data for the single register group found.
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ final IRegisters regService = getServicesTracker().getService(IRegisters.class);
+ if ( regService != null ) {
+ regService.getBitFieldData(
+ regDmc,
+ new DataRequestMonitor<IBitFieldDMData>(regService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if ( getStatus().isOK() ) {
+ // Now make sure the register group is the one we want.
+ request.getMemento().putString(MEMENTO_NAME, "BitField." + getData().getName()); //$NON-NLS-1$
+ }
+ request.done();
+ }
+ });
+ } else {
+ request.done();
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ request.done();
+ }
+ }
+ }
+}
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
new file mode 100644
index 00000000000..60b6e8d92f6
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterCellModifier.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * 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.register;
+
+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.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.ui.viewmodel.IVMContext;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.AbstractCachingVMProvider;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.UserEditEvent;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+
+@SuppressWarnings("restriction")
+public class RegisterCellModifier extends WatchExpressionCellModifier {
+
+ private AbstractCachingVMProvider fProvider;
+ private SyncRegisterDataAccess fDataAccess = null;
+ private IFormattedValuePreferenceStore fFormattedValuePreferenceStore;
+
+ public RegisterCellModifier(AbstractCachingVMProvider provider,
+ IFormattedValuePreferenceStore formattedValuePreferenceStore, 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.
+ */
+ protected IRegisterDMContext getRegisterDMC(Object element) {
+ if (element instanceof IDMVMContext) {
+ IDMContext dmc = ((IDMVMContext)element).getDMContext();
+ return DMContexts.getAncestorOfType(dmc, IRegisterDMContext.class);
+ }
+ return null;
+ }
+
+ @Override
+ public boolean canModify(Object element, String property) {
+
+ /*
+ * If we're in the column value, modify the register data.
+ * Otherwise, call the super-class to edit the watch expression.
+ */
+ if (IDebugVMConstants.COLUMN_ID__VALUE.equals(property)) {
+ /*
+ * Make sure we are are dealing with a valid set of information.
+ */
+ if ( getRegisterDMC(element) == null ) return false;
+
+ /*
+ * We need to read the register in order to get the attributes.
+ */
+
+ IRegisterDMData regData = fDataAccess.readRegister(element);
+
+ if ( ( regData != null ) && ( ! regData.isWriteable() ) ) return false;
+
+ return true ;
+ } else {
+ return super.canModify(element, property);
+ }
+ }
+
+ @Override
+ public Object getValue(Object element, String property) {
+ /*
+ * If we're in the column value, modify the register data.
+ * Otherwise, call the super-class to edit the watch expression.
+ */
+ if ( IDebugVMConstants.COLUMN_ID__VALUE.equals(property) ) {
+ /*
+ * We let the Model provider supply the current format.
+ */
+ String formatId;
+
+ if ( element instanceof IVMContext) {
+ /*
+ * Find the presentation context and then use it to get the current desired format.
+ */
+ IVMContext ctx = (IVMContext) element;
+ IPresentationContext presCtx = ctx.getVMNode().getVMProvider().getPresentationContext();
+
+ formatId = fFormattedValuePreferenceStore.getCurrentNumericFormat(presCtx);
+ }
+ else {
+ formatId = IFormattedValues.NATURAL_FORMAT;
+ }
+
+ String value =
+
+ fDataAccess.getFormattedRegisterValue(element, formatId);
+
+ if ( value == null ) { return "..."; } //$NON-NLS-1$
+ else { return value; }
+ } else {
+ return super.getValue(element, property);
+ }
+ }
+
+ @Override
+ public void modify(Object element, String property, Object value) {
+ /*
+ * If we're in the column value, modify the register data.
+ * Otherwise, call the super-class to edit the watch expression.
+ */
+
+ if ( IDebugVMConstants.COLUMN_ID__VALUE.equals(property) ) {
+
+ if (value instanceof String) {
+ /*
+ * We let the Model provider supply the current format.
+ */
+ String formatId;
+
+ if ( element instanceof IVMContext) {
+ /*
+ * Find the presentation context and then use it to get the current desired format.
+ */
+ IVMContext ctx = (IVMContext) element;
+ IPresentationContext presCtx = ctx.getVMNode().getVMProvider().getPresentationContext();
+
+ formatId = fFormattedValuePreferenceStore.getCurrentNumericFormat(presCtx);
+ }
+ else {
+ formatId = IFormattedValues.NATURAL_FORMAT;
+ }
+
+ fDataAccess.writeRegister(element, (String) value, formatId);
+ fProvider.handleEvent(new UserEditEvent(element));
+ }
+ } else {
+ super.modify(element, property, value);
+ }
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterColumnPresentation.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterColumnPresentation.java
new file mode 100644
index 00000000000..03ef9ee3ff5
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterColumnPresentation.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * 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.register;
+
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.jface.resource.ImageDescriptor;
+
+/**
+ *
+ */
+@SuppressWarnings("restriction")
+public class RegisterColumnPresentation implements IColumnPresentation {
+
+ public static final String ID = DsfUIPlugin.PLUGIN_ID + ".REGISTERS_COLUMN_PRESENTATION_ID"; //$NON-NLS-1$
+
+ public void init(IPresentationContext context) {
+ }
+
+ public void dispose() {
+ }
+
+ // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getAvailableColumns()
+ public String[] getAvailableColumns() {
+ return new String[] { IDebugVMConstants.COLUMN_ID__NAME, IDebugVMConstants.COLUMN_ID__TYPE, IDebugVMConstants.COLUMN_ID__VALUE, IDebugVMConstants.COLUMN_ID__DESCRIPTION, };
+ }
+
+ // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getHeader(java.lang.String)
+ public String getHeader(String id) {
+ if (IDebugVMConstants.COLUMN_ID__NAME.equals(id)) {
+ return MessagesForRegisterVM.RegisterColumnPresentation_name;
+ } else if (IDebugVMConstants.COLUMN_ID__TYPE.equals(id)) {
+ return MessagesForRegisterVM.RegisterColumnPresentation_type;
+ } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(id)) {
+ return MessagesForRegisterVM.RegisterColumnPresentation_value;
+ } else if (IDebugVMConstants.COLUMN_ID__DESCRIPTION.equals(id)) {
+ return MessagesForRegisterVM.RegisterColumnPresentation_description;
+ }
+ return null;
+ }
+
+ // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getId()
+ public String getId() {
+ return ID;
+ }
+
+ public ImageDescriptor getImageDescriptor(String id) {
+ return null;
+ }
+
+
+
+ // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getInitialColumns()
+ public String[] getInitialColumns() {
+ return new String[] { IDebugVMConstants.COLUMN_ID__NAME, IDebugVMConstants.COLUMN_ID__VALUE, IDebugVMConstants.COLUMN_ID__DESCRIPTION };
+ }
+
+ // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#isOptional()
+ public boolean isOptional() {
+ return true;
+ }
+
+}
diff --git a/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
new file mode 100644
index 00000000000..0d6fc7b2c9e
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterGroupVMNode.java
@@ -0,0 +1,586 @@
+/*******************************************************************************
+ * 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.register;
+
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+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.IRegisters;
+import org.eclipse.cdt.dsf.debug.service.IRegisters.IGroupChangedDMEvent;
+import org.eclipse.cdt.dsf.debug.service.IRegisters.IGroupsChangedDMEvent;
+import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMContext;
+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.IDebugVMConstants;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.AbstractExpressionVMNode;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.WatchExpressionCellModifier;
+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.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+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;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementEditor;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.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.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.debug.ui.actions.IWatchExpressionFactoryAdapter2;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ICellModifier;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.jface.viewers.TreePath;
+import org.eclipse.swt.widgets.Composite;
+
+@SuppressWarnings("restriction")
+public class RegisterGroupVMNode extends AbstractExpressionVMNode
+ implements IElementEditor, IElementLabelProvider, IElementMementoProvider
+{
+ protected class RegisterGroupVMC extends DMVMContext
+ {
+ private IExpression fExpression;
+ public RegisterGroupVMC(IDMContext dmc) {
+ super(dmc);
+ }
+
+ public void setExpression(IExpression expression) {
+ fExpression = expression;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Class adapter) {
+ if (fExpression != null && adapter.isAssignableFrom(fExpression.getClass())) {
+ return fExpression;
+ } else if (adapter.isAssignableFrom(IWatchExpressionFactoryAdapter2.class)) {
+ return getWatchExpressionFactory();
+ } else {
+ return super.getAdapter(adapter);
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof RegisterGroupVMC && super.equals(other)) {
+ RegisterGroupVMC otherGroup = (RegisterGroupVMC)other;
+ return (otherGroup.fExpression == null && fExpression == null) ||
+ (otherGroup.fExpression != null && otherGroup.fExpression.equals(fExpression));
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode() + (fExpression != null ? fExpression.hashCode() : 0);
+ }
+ }
+
+ protected class RegisterGroupExpressionFactory implements IWatchExpressionFactoryAdapter2 {
+
+ public boolean canCreateWatchExpression(Object element) {
+ return element instanceof RegisterGroupVMC;
+ }
+
+ /**
+ * Expected format: Group(GroupName)
+ */
+ public String createWatchExpression(Object element) throws CoreException {
+ IRegisterGroupDMData groupData = getSyncRegisterDataAccess().getRegisterGroupDMData(element);
+ if (groupData != null) {
+ StringBuffer exprBuf = new StringBuffer();
+ exprBuf.append("GRP( "); //$NON-NLS-1$
+ exprBuf.append(groupData.getName());
+ exprBuf.append(" )"); //$NON-NLS-1$
+ return exprBuf.toString();
+ }
+
+ return null;
+ }
+ }
+
+ final private SyncRegisterDataAccess fSyncRegisterDataAccess;
+ private IWatchExpressionFactoryAdapter2 fRegisterGroupExpressionFactory = null;
+ private WatchExpressionCellModifier fWatchExpressionCellModifier = new WatchExpressionCellModifier();
+
+ public RegisterGroupVMNode(AbstractDMVMProvider provider, DsfSession session, SyncRegisterDataAccess syncDataAccess) {
+ super(provider, session, IRegisterGroupDMContext.class);
+ fSyncRegisterDataAccess = syncDataAccess;
+ }
+
+ @Override
+ public String toString() {
+ return "RegisterGroupVMNode(" + getSession().getId() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public SyncRegisterDataAccess getSyncRegisterDataAccess() {
+ return fSyncRegisterDataAccess;
+ }
+
+ /**
+ * @since 1.1
+ */
+ public IWatchExpressionFactoryAdapter2 getWatchExpressionFactory() {
+ if ( fRegisterGroupExpressionFactory == null ) {
+ fRegisterGroupExpressionFactory = new RegisterGroupExpressionFactory();
+ }
+ 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) {
+
+ IRegisters regService = getServicesTracker().getService(IRegisters.class);
+
+ if ( regService == null ) {
+ handleFailedUpdate(update);
+ return;
+ }
+
+ regService.getRegisterGroups(
+ createCompositeDMVMContext(update),
+ new ViewerDataRequestMonitor<IRegisterGroupDMContext[]>(getSession().getExecutor(), update) {
+ @Override
+ public void handleCompleted() {
+ if (!isSuccess()) {
+ update.done();
+ return;
+ }
+ fillUpdateWithVMCs(update, getData());
+ 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[])
+ */
+ public void update(final ILabelUpdate[] updates) {
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ updateLabelInSessionThread(updates);
+ }});
+ } catch (RejectedExecutionException e) {
+ for (ILabelUpdate update : updates) {
+ handleFailedUpdate(update);
+ }
+ }
+ }
+
+ /*
+ * Updates the labels with the required information for each visible column.
+ */
+ 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;
+ }
+
+ IRegisters regService = getServicesTracker().getService(IRegisters.class);
+ if ( regService == null ) {
+ handleFailedUpdate(update);
+ continue;
+ }
+
+ getDMVMProvider().getModelData(
+ this,
+ update,
+ regService,
+ dmc,
+ new ViewerDataRequestMonitor<IRegisterGroupDMData>(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);
+ }
+ update.done();
+ }
+ },
+ getExecutor());
+ }
+ }
+
+ /*
+ * 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;
+ }
+ else if (e instanceof IGroupsChangedDMEvent) {
+ return IModelDelta.CONTENT;
+ }
+ else if (e instanceof IGroupChangedDMEvent) {
+ return IModelDelta.STATE;
+ }
+ 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
+ // flag to the parent to repaint all the groups and their registers.
+ if (e instanceof ISuspendedDMEvent) {
+ // Create a delta that indicates all groups have changed
+ parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
+ }
+ else if (e instanceof IGroupsChangedDMEvent) {
+ // Create a delta that indicates all groups have changed
+ parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
+ }
+ else if (e instanceof IGroupChangedDMEvent) {
+ // Create a delta that indicates that specific group changed
+ parentDelta.addNode( createVMContext(((IGroupChangedDMEvent)e).getDMContext()), IModelDelta.STATE );
+ }
+ 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;
+ }
+
+ /**
+ * Expected format: Group(GroupName)
+ */
+ private String parseExpressionForGroupName(String expression) {
+ if (expression.startsWith("GRP(")) { //$NON-NLS-1$
+ /*
+ * Extract the group name.
+ */
+ int startIdx = "GRP(".length(); //$NON-NLS-1$
+ int endIdx = expression.indexOf(')', startIdx);
+ if ( startIdx == -1 || endIdx == -1 ) {
+ return null;
+ }
+ String groupName = expression.substring(startIdx, endIdx);
+ return groupName.trim();
+ }
+
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.IExpressionVMNode#getDeltaFlagsForExpression(org.eclipse.debug.core.model.IExpression, java.lang.Object)
+ */
+ public int getDeltaFlagsForExpression(IExpression expression, Object event) {
+
+ if (event instanceof ISuspendedDMEvent ||
+ event instanceof IGroupsChangedDMEvent)
+ {
+ return IModelDelta.CONTENT;
+ }
+
+ if (event instanceof IGroupChangedDMEvent) {
+ return IModelDelta.STATE;
+ }
+
+ return IModelDelta.NO_CHANGE;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.IExpressionVMNode#buildDeltaForExpression(org.eclipse.debug.core.model.IExpression, int, java.lang.Object, org.eclipse.cdt.dsf.ui.viewmodel.VMDelta, org.eclipse.jface.viewers.TreePath, org.eclipse.cdt.dsf.concurrent.RequestMonitor)
+ */
+ public void buildDeltaForExpression(IExpression expression, int elementIdx, Object event, VMDelta parentDelta,
+ TreePath path, RequestMonitor rm)
+ {
+ if (event instanceof ISuspendedDMEvent) {
+ // Mark the parent delta indicating that elements were added and/or removed.
+ parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
+ }
+
+ // If the group definitions have changed, refresh the whole expressions
+ // view contents since previously invalid expressions may now evaluate
+ // to valid groups
+ if (event instanceof IGroupsChangedDMEvent) {
+ parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
+ }
+
+
+ rm.done();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.IExpressionVMNode#buildDeltaForExpressionElement(java.lang.Object, int, java.lang.Object, org.eclipse.cdt.dsf.ui.viewmodel.VMDelta, org.eclipse.cdt.dsf.concurrent.RequestMonitor)
+ */
+ public void buildDeltaForExpressionElement(Object element, int elementIdx, Object event, VMDelta parentDelta, final RequestMonitor rm)
+ {
+ if (event instanceof IGroupChangedDMEvent) {
+ parentDelta.addNode(element, IModelDelta.STATE);
+ }
+ rm.done();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.AbstractExpressionVMNode#testElementForExpression(java.lang.Object, org.eclipse.debug.core.model.IExpression, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
+ */
+ @Override
+ protected void testElementForExpression(Object element, IExpression expression, final DataRequestMonitor<Boolean> rm) {
+ if (!(element instanceof IDMVMContext)) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+ final IRegisterGroupDMContext dmc = DMContexts.getAncestorOfType(((IDMVMContext)element).getDMContext(), IRegisterGroupDMContext.class);
+ if (dmc == null) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ final String groupName = parseExpressionForGroupName(expression.getExpressionText());
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ IRegisters registersService = getServicesTracker().getService(IRegisters.class);
+ if (registersService != null) {
+ registersService.getRegisterGroupData(
+ dmc,
+ new DataRequestMonitor<IRegisterGroupDMData>(ImmediateExecutor.getInstance(), rm) {
+ @Override
+ protected void handleSuccess() {
+ rm.setData( getData().getName().equals(groupName) );
+ rm.done();
+ }
+ });
+ } else {
+ rm.setStatus(new Status(IStatus.WARNING, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Register service not available", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ rm.setStatus(new Status(IStatus.WARNING, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "DSF session shut down", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.AbstractExpressionVMNode#associateExpression(java.lang.Object, org.eclipse.debug.core.model.IExpression)
+ */
+ @Override
+ protected void associateExpression(Object element, IExpression expression) {
+ if (element instanceof RegisterGroupVMC) {
+ ((RegisterGroupVMC)element).setExpression(expression);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementEditor#getCellEditor(org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext, java.lang.String, java.lang.Object, org.eclipse.swt.widgets.Composite)
+ */
+ public CellEditor getCellEditor(IPresentationContext context, String columnId, Object element, Composite parent) {
+ if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(columnId)) {
+ return new TextCellEditor(parent);
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @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 fWatchExpressionCellModifier;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider#compareElements(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest[])
+ */
+ private final String MEMENTO_NAME = "GROUP_MEMENTO_NAME"; //$NON-NLS-1$
+
+ public void compareElements(IElementCompareRequest[] requests) {
+ for (final IElementCompareRequest request : requests ) {
+ final IRegisterGroupDMContext regDmc = findDmcInPath(request.getViewerInput(), request.getElementPath(), IRegisterGroupDMContext.class);
+ final String mementoName = request.getMemento().getString(MEMENTO_NAME);
+
+ if (regDmc == null || mementoName == null) {
+ request.done();
+ continue;
+ }
+
+ // Now go get the model data for the single register group found.
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ final IRegisters regService = getServicesTracker().getService(IRegisters.class);
+ if ( regService != null ) {
+ regService.getRegisterGroupData(
+ regDmc,
+ new DataRequestMonitor<IRegisterGroupDMData>(regService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if ( getStatus().isOK() ) {
+ // Now make sure the register group is the one we want.
+ request.setEqual( mementoName.equals( "Group." + getData().getName()) ); //$NON-NLS-1$
+ }
+ request.done();
+ }
+ });
+ } else {
+ request.done();
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ request.done();
+ }
+ }
+ }
+
+ /*
+ * (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 ( final IElementMementoRequest request : requests ) {
+ final IRegisterGroupDMContext regDmc = findDmcInPath(request.getViewerInput(), request.getElementPath(), IRegisterGroupDMContext.class);
+ if (regDmc == null) {
+ request.done();
+ continue;
+ }
+
+ // Now go get the model data for the single register group found.
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ final IRegisters regService = getServicesTracker().getService(IRegisters.class);
+ if ( regService != null ) {
+ regService.getRegisterGroupData(
+ regDmc,
+ new DataRequestMonitor<IRegisterGroupDMData>(regService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if ( getStatus().isOK() ) {
+ // Now make sure the register group is the one we want.
+ request.getMemento().putString(MEMENTO_NAME, "Group." + getData().getName()); //$NON-NLS-1$
+ }
+ request.done();
+ }
+ });
+ } else {
+ request.done();
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ request.done();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterRootDMVMNode.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterRootDMVMNode.java
new file mode 100644
index 00000000000..316a0477d2f
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterRootDMVMNode.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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;
+
+import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMProvider;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.RootDMVMNode;
+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;
+
+/*
+ * We are extending the ROOT VM node for the register view so we can
+ * provide Memento providers for the root node. In the Register VM
+ * Provider we are returning a pseudo VMContext selection when the
+ * original input is a child of an execution context we return a selection
+ * which represents an Execution Context instead. This ensures that the
+ * Register View does not collapse and redraw when going from frame to frame
+ * when stepping or just when selecting within the view.
+ */
+@SuppressWarnings("restriction")
+public class RegisterRootDMVMNode extends RootDMVMNode implements IElementMementoProvider {
+
+ public RegisterRootDMVMNode(AbstractVMProvider provider) {
+ super(provider);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider#compareElements(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest[])
+ */
+ public void compareElements(IElementCompareRequest[] requests) {
+ for ( IElementMementoRequest request : requests ) { request.done(); }
+ }
+
+ /*
+ * (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 ) { request.done(); }
+ }
+}
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
new file mode 100644
index 00000000000..c48ec9590b9
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMNode.java
@@ -0,0 +1,960 @@
+/*******************************************************************************
+ * 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.register;
+
+import java.util.ArrayList;
+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.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;
+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.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.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.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+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;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementEditor;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoRequest;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.debug.ui.actions.IWatchExpressionFactoryAdapter2;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.CellEditor;
+import org.eclipse.jface.viewers.ICellModifier;
+import org.eclipse.jface.viewers.TextCellEditor;
+import org.eclipse.jface.viewers.TreePath;
+import org.eclipse.swt.widgets.Composite;
+
+@SuppressWarnings("restriction")
+public class RegisterVMNode extends AbstractExpressionVMNode
+ implements IElementEditor, IElementLabelProvider, IElementMementoProvider
+{
+ protected class RegisterVMC extends DMVMContext
+ implements IFormattedValueVMContext
+ {
+ private IExpression fExpression;
+ public RegisterVMC(IDMContext dmc) {
+ super(dmc);
+ }
+
+ public void setExpression(IExpression expression) {
+ fExpression = expression;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Class adapter) {
+ if (fExpression != null && adapter.isAssignableFrom(fExpression.getClass())) {
+ return fExpression;
+ } else if (adapter.isAssignableFrom(IWatchExpressionFactoryAdapter2.class)) {
+ return getWatchExpressionFactory();
+ } else {
+ return super.getAdapter(adapter);
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof RegisterVMC && super.equals(other)) {
+ RegisterVMC otherReg = (RegisterVMC)other;
+ return (otherReg.fExpression == null && fExpression == null) ||
+ (otherReg.fExpression != null && otherReg.fExpression.equals(fExpression));
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode() + (fExpression != null ? fExpression.hashCode() : 0);
+ }
+
+ public IFormattedValuePreferenceStore getPreferenceStore() {
+ return fFormattedPrefStore;
+ }
+ }
+
+ protected class RegisterExpressionFactory implements IWatchExpressionFactoryAdapter2 {
+
+ public boolean canCreateWatchExpression(Object element) {
+ return element instanceof RegisterVMC;
+ }
+
+ /**
+ * Expected format: GRP( GroupName ).REG( RegisterName )
+ */
+ public String createWatchExpression(Object element) throws CoreException {
+ IRegisterGroupDMData groupData = getSyncRegisterDataAccess().getRegisterGroupDMData(element);
+ IRegisterDMData registerData = getSyncRegisterDataAccess().getRegisterDMData(element);
+
+ if (groupData != null && registerData != null) {
+ StringBuffer exprBuf = new StringBuffer();
+
+ exprBuf.append("GRP( "); exprBuf.append(groupData.getName()); exprBuf.append(" )"); //$NON-NLS-1$ //$NON-NLS-2$
+ exprBuf.append(".REG( "); exprBuf.append(registerData.getName()); exprBuf.append(" )"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ return exprBuf.toString();
+ }
+
+ return null;
+ }
+ }
+
+ private IWatchExpressionFactoryAdapter2 fRegisterExpressionFactory = null;
+ final private SyncRegisterDataAccess fSyncRegisterDataAccess;
+ private final IFormattedValuePreferenceStore fFormattedPrefStore;
+
+ public RegisterVMNode(IFormattedValuePreferenceStore prefStore, AbstractDMVMProvider provider, DsfSession session, SyncRegisterDataAccess syncDataAccess) {
+ super(provider, session, IRegisterDMContext.class);
+ fSyncRegisterDataAccess = syncDataAccess;
+ fFormattedPrefStore = prefStore;
+ }
+
+ @Override
+ public String toString() {
+ return "RegisterVMNode(" + getSession().getId() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ protected SyncRegisterDataAccess getSyncRegisterDataAccess() {
+ return fSyncRegisterDataAccess;
+ }
+
+ public IFormattedValuePreferenceStore getPreferenceStore() {
+ return fFormattedPrefStore;
+ }
+
+ /**
+ * @since 1.1
+ */
+ public IWatchExpressionFactoryAdapter2 getWatchExpressionFactory() {
+ if ( fRegisterExpressionFactory == null ) {
+ fRegisterExpressionFactory = new RegisterExpressionFactory();
+ }
+ 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<QueuedValueUpdate> 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<FormattedValueDMData>(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<FormattedValueDMContext> 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<String[]>(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) {
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ updateLabelInSessionThread(updates);
+ }});
+ } catch (RejectedExecutionException e) {
+ for (ILabelUpdate update : updates) {
+ handleFailedUpdate(update);
+ }
+ }
+ }
+
+ /*
+ * Updates the labels which are controlled by the column being requested.
+ */
+ 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<QueuedValueUpdate> valueUpdatesToProcess = new ArrayList<QueuedValueUpdate>();
+
+ 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 );
+ }
+ };
+
+ crm.setDoneCount( calculateTheNumberOfRowsWithValueColumns(updates) );
+
+ /*
+ * 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<IRegisterDMData>(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<FormattedValueDMContext>(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());
+ }
+ }
+
+ 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;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMNode#update(org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate[])
+ */
+ @Override
+ public void update(IHasChildrenUpdate[] updates) {
+ // As an optimization, always indicate that register groups have
+ // children.
+ for (IHasChildrenUpdate update : updates) {
+ update.setHasChilren(true);
+ update.done();
+ }
+ }
+
+ /*
+ * (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) {
+
+ IRegisters regService = getServicesTracker().getService(IRegisters.class);
+
+ if ( regService == null ) {
+ handleFailedUpdate(update);
+ return;
+ }
+
+ regService.getRegisters(
+ createCompositeDMVMContext(update),
+ new ViewerDataRequestMonitor<IRegisterDMContext[]>(getSession().getExecutor(), update) {
+ @Override
+ public void handleCompleted() {
+ if (!isSuccess()) {
+ handleFailedUpdate(update);
+ return;
+ }
+ fillUpdateWithVMCs(update, getData());
+ 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 RegisterVMC(dmc);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.ui.viewmodel.IVMNode#getDeltaFlags(java.lang.Object)
+ */
+ public int getDeltaFlags(Object e) {
+ if ( e instanceof ISuspendedDMEvent ||
+ e instanceof IMemoryChangedEvent ||
+ e instanceof IRegistersChangedDMEvent ||
+ (e instanceof PropertyChangeEvent &&
+ ((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) )
+ {
+ return IModelDelta.CONTENT;
+ }
+
+ if (e instanceof IRegisterChangedDMEvent) {
+ return IModelDelta.STATE;
+ }
+
+ 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) {
+ // The following events can affect any register's values,
+ // refresh the contents of the parent element (i.e. all the registers).
+ if ( e instanceof ISuspendedDMEvent ||
+ e instanceof IMemoryChangedEvent ||
+ e instanceof IRegistersChangedDMEvent ||
+ (e instanceof PropertyChangeEvent &&
+ ((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) )
+ {
+ // Create a delta that the whole register group has changed.
+ parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
+ }
+
+ if (e instanceof IRegisterChangedDMEvent) {
+ parentDelta.addNode( createVMContext(((IRegisterChangedDMEvent)e).getDMContext()), IModelDelta.STATE );
+ }
+
+ rm.done();
+ }
+
+ /**
+ * Expected format: GRP( GroupName ).REG( RegisterName )
+ * or: $RegisterName
+ */
+ public boolean canParseExpression(IExpression expression) {
+ return parseExpressionForRegisterName(expression.getExpressionText()) != null;
+ }
+
+ private String parseExpressionForRegisterName(String expression) {
+ if (expression.startsWith("GRP(")) { //$NON-NLS-1$
+ /*
+ * Get the group portion.
+ */
+ int startIdx = "GRP(".length(); //$NON-NLS-1$
+ int endIdx = expression.indexOf(')', startIdx);
+ if ( startIdx == -1 || endIdx == -1 ) {
+ return null;
+ }
+ String remaining = expression.substring(endIdx+1);
+ if ( ! remaining.startsWith(".REG(") ) { //$NON-NLS-1$
+ return null;
+ }
+
+ /*
+ * Get the register portion.
+ */
+ startIdx = ".REG(".length(); //$NON-NLS-1$
+ endIdx = remaining.indexOf(')', startIdx);
+ if ( startIdx == -1 || endIdx == -1 ) {
+ return null;
+ }
+ String regName = remaining.substring(startIdx,endIdx);
+ return regName.trim();
+ }
+ else if ( expression.startsWith("$") ) { //$NON-NLS-1$
+ /*
+ * At this point I am leaving this code here to represent the register case. To do this
+ * correctly would be to use the findRegister function and upgrade the register service
+ * to deal with registers that do not have a specified group parent context. I do not
+ * have the time for this right now. So by saying we do not handle this the Expression
+ * VM node will take it and pass it to the debug engine as a generic expression. Most
+ * debug engines ( GDB included ) have an inherent knowledge of the core registers as
+ * part of their expression evaluation and will respond with a flat value for the reg.
+ * This is not totally complete in that you should be able to express a register which
+ * has bit fields for example and the bit fields should be expandable in the expression
+ * view. With this method it will just appear to have a single value and no sub-fields.
+ * I will file a defect/enhancement for this to mark it. This comment will act as the
+ * place-holder for the future work.
+ */
+ return null;
+ }
+
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.AbstractExpressionVMNode#testElementForExpression(java.lang.Object, org.eclipse.debug.core.model.IExpression, org.eclipse.cdt.dsf.concurrent.DataRequestMonitor)
+ */
+ @Override
+ protected void testElementForExpression(Object element, IExpression expression, final DataRequestMonitor<Boolean> rm) {
+ if (!(element instanceof IDMVMContext)) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+ final IRegisterDMContext dmc = DMContexts.getAncestorOfType(((IDMVMContext)element).getDMContext(), IRegisterDMContext.class);
+ if (dmc == null) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ final String regName = parseExpressionForRegisterName(expression.getExpressionText());
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ IRegisters registersService = getServicesTracker().getService(IRegisters.class);
+ if (registersService != null) {
+ registersService.getRegisterData(
+ dmc,
+ new DataRequestMonitor<IRegisterDMData>(ImmediateExecutor.getInstance(), rm) {
+ @Override
+ protected void handleSuccess() {
+ rm.setData( getData().getName().equals(regName) );
+ rm.done();
+ }
+ });
+ } else {
+ rm.setStatus(new Status(IStatus.WARNING, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Register service not available", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ rm.setStatus(new Status(IStatus.WARNING, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "DSF session shut down", null)); //$NON-NLS-1$
+ rm.done();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.AbstractExpressionVMNode#associateExpression(java.lang.Object, org.eclipse.debug.core.model.IExpression)
+ */
+ @Override
+ protected void associateExpression(Object element, IExpression expression) {
+ if (element instanceof RegisterVMC) {
+ ((RegisterVMC)element).setExpression(expression);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.IExpressionVMNode#getDeltaFlagsForExpression(org.eclipse.debug.core.model.IExpression, java.lang.Object)
+ */
+ public int getDeltaFlagsForExpression(IExpression expression, Object event) {
+ if ( event instanceof IRegisterChangedDMEvent ||
+ event instanceof IMemoryChangedEvent ||
+ (event instanceof PropertyChangeEvent &&
+ ((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) )
+ {
+ return IModelDelta.STATE;
+ }
+
+ if (event instanceof IRegistersChangedDMEvent ||
+ event instanceof ISuspendedDMEvent)
+ {
+ return IModelDelta.CONTENT;
+ }
+
+ return IModelDelta.NO_CHANGE;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.IExpressionVMNode#buildDeltaForExpression(org.eclipse.debug.core.model.IExpression, int, java.lang.Object, org.eclipse.cdt.dsf.ui.viewmodel.VMDelta, org.eclipse.jface.viewers.TreePath, org.eclipse.cdt.dsf.concurrent.RequestMonitor)
+ */
+ public void buildDeltaForExpression(IExpression expression, int elementIdx, Object event, VMDelta parentDelta,
+ TreePath path, RequestMonitor rm)
+ {
+ // If the register definition has changed, refresh all the
+ // expressions in the expression manager. This is because some
+ // expressions that were previously invalid, may now represent new
+ // registers.
+ if (event instanceof IRegistersChangedDMEvent) {
+ parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
+ }
+
+ // Always refresh the contents of the view upon suspended event.
+ if (event instanceof ISuspendedDMEvent) {
+ parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
+ }
+
+ rm.done();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.IExpressionVMNode#buildDeltaForExpressionElement(java.lang.Object, int, java.lang.Object, org.eclipse.cdt.dsf.ui.viewmodel.VMDelta, org.eclipse.cdt.dsf.concurrent.RequestMonitor)
+ */
+ public void buildDeltaForExpressionElement(Object element, int elementIdx, Object event, VMDelta parentDelta, final RequestMonitor rm)
+ {
+ // The following events can affect register values, refresh the state
+ // of the expression.
+ if ( event instanceof IRegisterChangedDMEvent ||
+ event instanceof IMemoryChangedEvent ||
+ (event instanceof PropertyChangeEvent &&
+ ((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) )
+ {
+ parentDelta.addNode(element, IModelDelta.STATE);
+ }
+
+ rm.done();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementEditor#getCellEditor(org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext, java.lang.String, java.lang.Object, org.eclipse.swt.widgets.Composite)
+ */
+ public CellEditor getCellEditor(IPresentationContext context, String columnId, Object element, Composite parent) {
+ if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(columnId)) {
+ return new TextCellEditor(parent);
+ }
+ else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(columnId)) {
+ /*
+ * See if the register is writable and if so we will created a
+ * cell editor for it.
+ */
+ IRegisterDMData regData = getSyncRegisterDataAccess().readRegister(element);
+
+ if ( regData != null && regData.isWriteable() ) {
+ return new TextCellEditor(parent);
+ }
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @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() );
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider#compareElements(org.eclipse.debug.internal.ui.viewers.model.provisional.IElementCompareRequest[])
+ */
+ private final String MEMENTO_NAME = "REGISTER_MEMENTO_NAME"; //$NON-NLS-1$
+
+ public void compareElements(IElementCompareRequest[] requests) {
+ for ( final IElementCompareRequest request : requests ) {
+ final IRegisterDMContext regDmc = findDmcInPath(request.getViewerInput(), request.getElementPath(), IRegisterDMContext.class);
+ final String mementoName = request.getMemento().getString(MEMENTO_NAME);
+ if (regDmc == null || mementoName == null) {
+ request.done();
+ continue;
+ }
+
+ // Now go get the model data for the single register group found.
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ final IRegisters regService = getServicesTracker().getService(IRegisters.class);
+ if ( regService != null ) {
+ regService.getRegisterData(
+ regDmc,
+ new DataRequestMonitor<IRegisterDMData>(regService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if ( getStatus().isOK() ) {
+ // Now make sure the register group is the one we want.
+ request.setEqual( mementoName.equals( "Register." + getData().getName() ) ); //$NON-NLS-1$
+ }
+ request.done();
+ }
+ });
+ } else {
+ request.done();
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ request.done();
+ }
+ }
+ }
+
+ /*
+ * (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 ( final IElementMementoRequest request : requests ) {
+ final IRegisterDMContext regDmc = findDmcInPath(request.getViewerInput(), request.getElementPath(), IRegisterDMContext.class);
+ if (regDmc == null) {
+ request.done();
+ continue;
+ }
+
+ // Now go get the model data for the single register group found.
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ final IRegisters regService = getServicesTracker().getService(IRegisters.class);
+ if ( regService != null ) {
+ regService.getRegisterData(
+ regDmc,
+ new DataRequestMonitor<IRegisterDMData>(regService.getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ if ( getStatus().isOK() ) {
+ // Now make sure the register group is the one we want.
+ request.getMemento().putString(MEMENTO_NAME, "Register." + getData().getName()); //$NON-NLS-1$
+ }
+ request.done();
+ }
+ });
+ } else {
+ request.done();
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ request.done();
+ }
+ }
+ }
+}
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
new file mode 100644
index 00000000000..01badb93297
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/RegisterVMProvider.java
@@ -0,0 +1,271 @@
+/*******************************************************************************
+ * 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.register;
+
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.debug.service.ICachingService;
+import org.eclipse.cdt.dsf.debug.service.IRegisters;
+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;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMAdapter;
+import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMContext;
+import org.eclipse.cdt.dsf.ui.viewmodel.IRootVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
+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.update.AutomaticUpdatePolicy;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.IVMUpdatePolicy;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.ManualUpdatePolicy;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerInputUpdate;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+
+/**
+ * Provides the VIEW MODEL for the DEBUG MODEL REGISTER view.
+ */
+@SuppressWarnings("restriction")
+public class RegisterVMProvider extends AbstractDMVMProvider
+{
+ private IPropertyChangeListener fPreferencesListener = new IPropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ String property = event.getProperty();
+ if (property.equals(IDsfDebugUIConstants.PREF_WAIT_FOR_VIEW_UPDATE_AFTER_STEP_ENABLE)) {
+ IPreferenceStore store = DsfDebugUITools.getPreferenceStore();
+ setDelayEventHandleForViewUpdate(store.getBoolean(property));
+ }
+ }
+ };
+
+ private IPropertyChangeListener fPresentationContextListener = new IPropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ handleEvent(event);
+ }
+ };
+
+ /*
+ * Current default for register formatting.
+ */
+ public RegisterVMProvider(AbstractVMAdapter adapter, IPresentationContext context, DsfSession session) {
+ super(adapter, context, session);
+
+ context.addPropertyChangeListener(fPresentationContextListener);
+
+ IPreferenceStore store = DsfDebugUITools.getPreferenceStore();
+ store.addPropertyChangeListener(fPreferencesListener);
+ setDelayEventHandleForViewUpdate(store.getBoolean(IDsfDebugUIConstants.PREF_WAIT_FOR_VIEW_UPDATE_AFTER_STEP_ENABLE));
+
+ /*
+ * Create the register data access routines.
+ */
+ SyncRegisterDataAccess regAccess = new SyncRegisterDataAccess(session) ;
+
+ /*
+ * Create the top level node to deal with the root selection.
+ */
+ IRootVMNode rootNode = new RegisterRootDMVMNode(this);
+
+ /*
+ * Create the Group nodes next. They represent the first level shown in the view.
+ */
+ IVMNode registerGroupNode = new RegisterGroupVMNode(this, getSession(), regAccess);
+ addChildNodes(rootNode, new IVMNode[] { registerGroupNode });
+
+ /*
+ * Create the next level which is the registers themselves.
+ */
+ IVMNode registerNode = new RegisterVMNode(FormattedValuePreferenceStore.getDefault(), 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);
+ addChildNodes(registerNode, new IVMNode[] { bitFieldNode });
+
+ /*
+ * Now set this schema set as the layout set.
+ */
+ setRootNode(rootNode);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.ui.viewmodel.update.AbstractCachingVMProvider#createUpdateModes()
+ */
+ @Override
+ protected IVMUpdatePolicy[] createUpdateModes() {
+ return new IVMUpdatePolicy[] { new AutomaticUpdatePolicy(), new ManualUpdatePolicy(), new BreakpointHitUpdatePolicy() };
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider#dispose()
+ */
+ @Override
+ public void dispose() {
+ DsfDebugUITools.getPreferenceStore().removePropertyChangeListener(fPreferencesListener);
+ getPresentationContext().removePropertyChangeListener(fPresentationContextListener);
+ super.dispose();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMProvider#createColumnPresentation(org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext, java.lang.Object)
+ */
+ @Override
+ public IColumnPresentation createColumnPresentation(IPresentationContext context, Object element) {
+ return new RegisterColumnPresentation();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMProvider#getColumnPresentationId(org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext, java.lang.Object)
+ */
+ @Override
+ public String getColumnPresentationId(IPresentationContext context, Object element) {
+ return RegisterColumnPresentation.ID;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMProvider#canSkipHandlingEvent(java.lang.Object, java.lang.Object)
+ */
+ @Override
+ protected boolean canSkipHandlingEvent(Object newEvent, Object eventToSkip) {
+ /*
+ * To optimize the performance of the view when stepping rapidly, skip all
+ * other events when a suspended event is received, including older suspended
+ * events.
+ */
+ return newEvent instanceof ISuspendedDMEvent;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMProvider#update(org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerInputUpdate)
+ */
+ @Override
+ public void update(IViewerInputUpdate update) {
+ /*
+ * Use the execution context in the current selection as the input provider.
+ * This insures that the REGISTER VIEW will not collapse and expand on stepping or on
+ * re-selection in the DEBUG VIEW. Currently the register content is not stack frame
+ * specific. If it were to become so then we would need to modify this policy.
+ */
+ Object element = update.getElement();
+ if (element instanceof IDMVMContext) {
+ IDMContext ctx = ((IDMVMContext) element).getDMContext();
+
+ IExecutionDMContext execDmc = DMContexts.getAncestorOfType(ctx, IExecutionDMContext.class);
+ if ( execDmc != null ) {
+ /*
+ * This tells the Flexible Hierarchy that element driving this view has not changed
+ * and there is no need to redraw the view. Since this is a somewhat fake VMContext
+ * we provide our Root Layout node as the representative VM node.
+ */
+ update.setInputElement(new ViewInputElement(RegisterVMProvider.this.getRootVMNode(), execDmc));
+ update.done();
+ return;
+ }
+ }
+
+ /*
+ * If we reach here, then we did not override the standard behavior. Invoke the
+ * super class and this will provide the default standard behavior.
+ */
+ super.update(update);
+ }
+
+ /*
+ * Provides a local implementation of the IDMVMContext. This allows us to return one
+ * of our own making, representing the DMContext we want to use as selection criteria.
+ */
+ private class ViewInputElement extends AbstractVMContext implements IDMVMContext {
+
+ final private IDMContext fDMContext;
+
+ public ViewInputElement(IVMNode node, IDMContext dmc) {
+ super(node);
+ fDMContext = dmc;
+ }
+
+ public IDMContext getDMContext() {
+ return fDMContext;
+ }
+
+ /**
+ * The IAdaptable implementation. If the adapter is the DM context,
+ * return the context, otherwise delegate to IDMContext.getAdapter().
+ */
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Class adapter) {
+ Object superAdapter = super.getAdapter(adapter);
+ if (superAdapter != null) {
+ return superAdapter;
+ } else {
+ // Delegate to the Data Model to find the context.
+ if (adapter.isInstance(fDMContext)) {
+ return fDMContext;
+ } else {
+ return fDMContext.getAdapter(adapter);
+ }
+ }
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+
+ if ( obj instanceof ViewInputElement && ((ViewInputElement) obj).fDMContext.equals(fDMContext) ) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return fDMContext.hashCode();
+ }
+ }
+
+ @Override
+ public void refresh() {
+ super.refresh();
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ DsfServicesTracker tracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), getSession().getId());
+ IRegisters registerService = tracker.getService(IRegisters.class);
+ if (registerService instanceof ICachingService) {
+ ((ICachingService)registerService).flushCache(null);
+ }
+ tracker.dispose();
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ // Session disposed, ignore.
+ }
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/SyncRegisterDataAccess.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/SyncRegisterDataAccess.java
new file mode 100644
index 00000000000..bca7931582b
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/SyncRegisterDataAccess.java
@@ -0,0 +1,813 @@
+/*******************************************************************************
+ * 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.debug.ui.viewmodel.register;
+
+import java.util.concurrent.ExecutionException;
+
+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.Query;
+import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
+import org.eclipse.cdt.dsf.concurrent.ThreadSafeAndProhibitedFromDsfExecutor;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+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.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.IMnemonic;
+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.IRegisterGroupDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRegisters.IRegisterGroupDMData;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.cdt.dsf.service.DsfServices;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.util.tracker.ServiceTracker;
+
+@ThreadSafeAndProhibitedFromDsfExecutor("fSession#getExecutor")
+public class SyncRegisterDataAccess {
+
+ abstract public class RegistersServiceQuery<V, K extends IDMContext> extends Query<V> {
+
+ final protected K fDmc;
+
+ public RegistersServiceQuery(K dmc) {
+ fDmc = dmc;
+ }
+
+ @Override
+ protected void execute(final DataRequestMonitor<V> rm) {
+ /*
+ * We're in another dispatch, so we must guard against executor
+ * shutdown again.
+ */
+ final DsfSession session = DsfSession.getSession(fDmc.getSessionId());
+ if (session == null) {
+ cancel(false);
+ rm.done();
+ return;
+ }
+
+ /*
+ * Guard against a disposed service
+ */
+ IRegisters service = getService();
+ if (service == null) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE,
+ "Service unavailable", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ doExecute(service, rm);
+ }
+
+ abstract protected void doExecute(IRegisters registersService, DataRequestMonitor<V> rm);
+ }
+
+
+ /**
+ * The session that this data access operates in.
+ */
+ private final DsfSession fSession;
+
+ /**
+ * Need to use the OSGi service tracker here (instead of DsfServiceTracker),
+ * because we're accessing it in non-dispatch thread. DsfServiceTracker is
+ * not thread-safe.
+ */
+ @ThreadSafe
+ private ServiceTracker fServiceTracker;
+
+ public SyncRegisterDataAccess(DsfSession session) {
+ fSession = session;
+ }
+
+ @ThreadSafe
+ private synchronized IRegisters getService() {
+
+ String serviceId = DsfServices.createServiceFilter(IRegisters.class, fSession.getId());
+ if (fServiceTracker == null) {
+ try {
+ fServiceTracker = new ServiceTracker(DsfUIPlugin.getBundleContext(), DsfUIPlugin
+ .getBundleContext().createFilter(serviceId), null);
+ fServiceTracker.open();
+ } catch (InvalidSyntaxException e) {
+ return null;
+ }
+ }
+ return (IRegisters) fServiceTracker.getService();
+ }
+
+ @ThreadSafe
+ public synchronized void dispose() {
+ if (fServiceTracker != null) {
+ fServiceTracker.close();
+ }
+ }
+
+ public class GetBitFieldValueQuery extends RegistersServiceQuery<IBitFieldDMData, IBitFieldDMContext> {
+
+ public GetBitFieldValueQuery(IBitFieldDMContext dmc) {
+ super(dmc);
+ }
+
+ @Override
+ protected void doExecute(IRegisters service, final DataRequestMonitor<IBitFieldDMData> rm) {
+ service.getBitFieldData(
+ fDmc,
+ new DataRequestMonitor<IBitFieldDMData>(ImmediateExecutor.getInstance(), rm) {
+ @Override
+ protected void handleSuccess() {
+ /*
+ * All good set return value.
+ */
+ rm.setData(getData());
+ rm.done();
+ }
+ });
+ }
+ }
+
+ public IBitFieldDMContext getBitFieldDMC(Object element) {
+ if (element instanceof IDMVMContext) {
+ IDMContext dmc = ((IDMVMContext) element).getDMContext();
+ return DMContexts.getAncestorOfType(dmc, IBitFieldDMContext.class);
+ }
+ return null;
+ }
+
+ public IBitFieldDMData readBitField(Object element) {
+ /*
+ * Get the DMC and the session. If element is not an register DMC, or
+ * session is stale, then bail out.
+ */
+ IBitFieldDMContext dmc = getBitFieldDMC(element);
+ if (dmc == null)
+ return null;
+ DsfSession session = DsfSession.getSession(dmc.getSessionId());
+ if (session == null)
+ return null;
+
+ /*
+ * Create the query to request the value from service. Note: no need to
+ * guard agains RejectedExecutionException, because
+ * DsfSession.getSession() above would only return an active session.
+ */
+ GetBitFieldValueQuery query = new GetBitFieldValueQuery(dmc);
+ session.getExecutor().execute(query);
+
+ /*
+ * Now we have the data, go and get it. Since the call is completed now
+ * the ".get()" will not suspend it will immediately return with the
+ * data.
+ */
+ try {
+ return query.get();
+ } catch (InterruptedException e) {
+ assert false;
+ return null;
+ } catch (ExecutionException e) {
+ return null;
+ }
+ }
+
+ public class SetBitFieldValueQuery extends RegistersServiceQuery<Object, IBitFieldDMContext> {
+
+ private String fValue;
+ private String fFormatId;
+
+ public SetBitFieldValueQuery(IBitFieldDMContext dmc, String value, String formatId) {
+ super(dmc);
+ fValue = value;
+ fFormatId = formatId;
+ }
+
+ @Override
+ protected void doExecute(IRegisters service, final DataRequestMonitor<Object> rm) {
+ // Write the bit field using a string/format style.
+ service.writeBitField(
+ fDmc, fValue, fFormatId,
+ new DataRequestMonitor<IBitFieldDMData>(ImmediateExecutor.getInstance(), rm) {
+ @Override
+ protected void handleSuccess() {
+ /*
+ * All good set return value.
+ */
+ rm.setData(new Object());
+ rm.done();
+ }
+ });
+ }
+ }
+
+ public void writeBitField(Object element, String value, String formatId) {
+
+ /*
+ * Get the DMC and the session. If element is not an register DMC, or
+ * session is stale, then bail out.
+ */
+ IBitFieldDMContext dmc = getBitFieldDMC(element);
+ if (dmc == null)
+ return;
+ DsfSession session = DsfSession.getSession(dmc.getSessionId());
+ if (session == null)
+ return;
+
+ /*
+ * Create the query to write the value to the service. Note: no need to
+ * guard agains RejectedExecutionException, because
+ * DsfSession.getSession() above would only return an active session.
+ */
+ SetBitFieldValueQuery query = new SetBitFieldValueQuery(dmc, value, formatId);
+ session.getExecutor().execute(query);
+
+ /*
+ * Now we have the data, go and get it. Since the call is completed now
+ * the ".get()" will not suspend it will immediately return with the
+ * data.
+ */
+ try {
+ /*
+ * Return value is irrelevant, any error would come through with an
+ * exception.
+ */
+ query.get();
+ } catch (InterruptedException e) {
+ assert false;
+ } catch (ExecutionException e) {
+ assert false;
+ /*
+ * View must be shutting down, no need to show erro dialog.
+ */
+ }
+ }
+
+ public class SetBitFieldValueMnemonicQuery extends RegistersServiceQuery<Object, IBitFieldDMContext> {
+ IMnemonic fMnemonic;
+
+ public SetBitFieldValueMnemonicQuery(IBitFieldDMContext dmc, IMnemonic mnemonic) {
+ super(dmc);
+ fMnemonic = mnemonic;
+ }
+
+ @Override
+ protected void doExecute(IRegisters service, final DataRequestMonitor<Object> rm) {
+ // Write the bit field using the mnemonic style.
+ service.writeBitField(
+ fDmc, fMnemonic,
+ new DataRequestMonitor<IBitFieldDMData>(ImmediateExecutor.getInstance(), rm) {
+ @Override
+ protected void handleSuccess() {
+ /*
+ * All good set return value.
+ */
+ rm.setData(new Object());
+ rm.done();
+ }
+ });
+ }
+ }
+
+ public void writeBitField(Object element, IMnemonic mnemonic) {
+
+ /*
+ * Get the DMC and the session. If element is not an register DMC, or
+ * session is stale, then bail out.
+ */
+ IBitFieldDMContext dmc = getBitFieldDMC(element);
+ if (dmc == null)
+ return;
+ DsfSession session = DsfSession.getSession(dmc.getSessionId());
+ if (session == null)
+ return;
+
+ /*
+ * Create the query to write the value to the service. Note: no need to
+ * guard agains RejectedExecutionException, because
+ * DsfSession.getSession() above would only return an active session.
+ */
+ SetBitFieldValueMnemonicQuery query = new SetBitFieldValueMnemonicQuery(dmc, mnemonic);
+ session.getExecutor().execute(query);
+
+ /*
+ * Now we have the data, go and get it. Since the call is completed now
+ * the ".get()" will not suspend it will immediately return with the
+ * data.
+ */
+ try {
+ /*
+ * Return value is irrelevant, any error would come through with an
+ * exception.
+ */
+ query.get();
+ } catch (InterruptedException e) {
+ assert false;
+ } catch (ExecutionException e) {
+ /*
+ * View must be shutting down, no need to show erro dialog.
+ */
+ }
+ }
+
+ public IRegisterGroupDMContext getRegisterGroupDMC(Object element) {
+ if (element instanceof IDMVMContext) {
+ IDMContext dmc = ((IDMVMContext) element).getDMContext();
+ return DMContexts.getAncestorOfType(dmc, IRegisterGroupDMContext.class);
+ }
+ return null;
+ }
+
+ public IRegisterDMContext getRegisterDMC(Object element) {
+ if (element instanceof IDMVMContext) {
+ IDMContext dmc = ((IDMVMContext) element).getDMContext();
+ return DMContexts.getAncestorOfType(dmc, IRegisterDMContext.class);
+ }
+ return null;
+ }
+
+ public IFormattedDataDMContext getFormattedDMC(Object element) {
+ if (element instanceof IDMVMContext) {
+ IDMContext dmc = ((IDMVMContext) element).getDMContext();
+ IRegisterDMContext regdmc = DMContexts.getAncestorOfType(dmc, IRegisterDMContext.class);
+ return DMContexts.getAncestorOfType(regdmc, IFormattedDataDMContext.class);
+ }
+ return null;
+ }
+
+ public class GetRegisterGroupValueQuery extends RegistersServiceQuery<IRegisterGroupDMData, IRegisterGroupDMContext> {
+ public GetRegisterGroupValueQuery(IRegisterGroupDMContext dmc) {
+ super(dmc);
+ }
+
+ @Override
+ protected void doExecute(IRegisters service, final DataRequestMonitor<IRegisterGroupDMData> rm) {
+ service.getRegisterGroupData(
+ fDmc,
+ new DataRequestMonitor<IRegisterGroupDMData>(ImmediateExecutor.getInstance(), rm) {
+ @Override
+ protected void handleSuccess() {
+ /*
+ * All good set return value.
+ */
+ rm.setData(getData());
+ rm.done();
+ }
+ });
+ }
+ }
+
+ public IRegisterGroupDMData readRegisterGroup(Object element) {
+ /*
+ * Get the DMC and the session. If element is not an register DMC, or
+ * session is stale, then bail out.
+ */
+ IRegisterGroupDMContext dmc = getRegisterGroupDMC(element);
+ if (dmc == null)
+ return null;
+ DsfSession session = DsfSession.getSession(dmc.getSessionId());
+ if (session == null)
+ return null;
+
+ /*
+ * Create the query to request the value from service. Note: no need to
+ * guard agains RejectedExecutionException, because
+ * DsfSession.getSession() above would only return an active session.
+ */
+ GetRegisterGroupValueQuery query = new GetRegisterGroupValueQuery(dmc);
+ session.getExecutor().execute(query);
+
+ /*
+ * Now we have the data, go and get it. Since the call is completed now
+ * the ".get()" will not suspend it will immediately return with the
+ * data.
+ */
+ try {
+ return query.get();
+ } catch (InterruptedException e) {
+ assert false;
+ return null;
+ } catch (ExecutionException e) {
+ return null;
+ }
+ }
+
+ public class GetRegisterValueQuery extends RegistersServiceQuery<IRegisterDMData, IRegisterDMContext> {
+ public GetRegisterValueQuery(IRegisterDMContext dmc) {
+ super(dmc);
+ }
+
+ @Override
+ protected void doExecute(IRegisters service, final DataRequestMonitor<IRegisterDMData> rm) {
+ service.getRegisterData(
+ fDmc,
+ new DataRequestMonitor<IRegisterDMData>(ImmediateExecutor.getInstance(), rm) {
+ @Override
+ protected void handleSuccess() {
+ /*
+ * All good set return value.
+ */
+ rm.setData(getData());
+ rm.done();
+ }
+ });
+ }
+ }
+
+ public IRegisterDMData readRegister(Object element) {
+ /*
+ * Get the DMC and the session. If element is not an register DMC, or
+ * session is stale, then bail out.
+ */
+ IRegisterDMContext dmc = getRegisterDMC(element);
+ if (dmc == null)
+ return null;
+ DsfSession session = DsfSession.getSession(dmc.getSessionId());
+ if (session == null)
+ return null;
+
+ /*
+ * Create the query to request the value from service. Note: no need to
+ * guard agains RejectedExecutionException, because
+ * DsfSession.getSession() above would only return an active session.
+ */
+ GetRegisterValueQuery query = new GetRegisterValueQuery(dmc);
+ session.getExecutor().execute(query);
+
+ /*
+ * Now we have the data, go and get it. Since the call is completed now
+ * the ".get()" will not suspend it will immediately return with the
+ * data.
+ */
+ try {
+ return query.get();
+ } catch (InterruptedException e) {
+ assert false;
+ return null;
+ } catch (ExecutionException e) {
+ return null;
+ }
+ }
+
+ public class SetRegisterValueQuery extends RegistersServiceQuery<Object, IRegisterDMContext> {
+ private String fValue;
+
+ private String fFormatId;
+
+ public SetRegisterValueQuery(IRegisterDMContext dmc, String value, String formatId) {
+ super(dmc);
+ fValue = value;
+ fFormatId = formatId;
+ }
+
+ @Override
+ protected void doExecute(IRegisters service, final DataRequestMonitor<Object> rm) {
+ /*
+ * Write the bit field using a string/format style.
+ */
+ service.writeRegister(
+ fDmc, fValue, fFormatId,
+ new DataRequestMonitor<IBitFieldDMData>(ImmediateExecutor.getInstance(), rm) {
+ @Override
+ protected void handleSuccess() {
+ /*
+ * All good set return value.
+ */
+ rm.setData(new Object());
+ rm.done();
+ }
+ });
+ }
+ }
+
+ public void writeRegister(Object element, String value, String formatId) {
+
+ /*
+ * Get the DMC and the session. If element is not an register DMC, or
+ * session is stale, then bail out.
+ */
+ IRegisterDMContext dmc = getRegisterDMC(element);
+ if (dmc == null)
+ return;
+ DsfSession session = DsfSession.getSession(dmc.getSessionId());
+ if (session == null)
+ return;
+
+ /*
+ * Create the query to write the value to the service. Note: no need to
+ * guard agains RejectedExecutionException, because
+ * DsfSession.getSession() above would only return an active session.
+ */
+ SetRegisterValueQuery query = new SetRegisterValueQuery(dmc, value, formatId);
+ session.getExecutor().execute(query);
+
+ /*
+ * Now we have the data, go and get it. Since the call is completed now
+ * the ".get()" will not suspend it will immediately return with the
+ * data.
+ */
+ try {
+ /*
+ * Return value is irrelevant, any error would come through with an
+ * exception.
+ */
+ query.get();
+ } catch (InterruptedException e) {
+ assert false;
+ } catch (ExecutionException e) {
+ /*
+ * View must be shutting down, no need to show erro dialog.
+ */
+ }
+ }
+
+ public class GetSupportFormatsValueQuery extends RegistersServiceQuery<String[], IFormattedDataDMContext> {
+
+ public GetSupportFormatsValueQuery(IFormattedDataDMContext dmc) {
+ super(dmc);
+ }
+
+ @Override
+ protected void doExecute(IRegisters service, final DataRequestMonitor<String[]> rm) {
+ service.getAvailableFormats(fDmc, rm);
+ }
+ }
+
+ public String[] getSupportedFormats(Object element) {
+
+ /*
+ * Get the DMC and the session. If element is not an register DMC, or
+ * session is stale, then bail out.
+ */
+ IFormattedDataDMContext dmc = null;
+ if (element instanceof IDMVMContext) {
+ IDMContext vmcdmc = ((IDMVMContext) element).getDMContext();
+ IRegisterDMContext regdmc = DMContexts.getAncestorOfType(vmcdmc, IRegisterDMContext.class);
+ dmc = DMContexts.getAncestorOfType(regdmc, IFormattedDataDMContext.class);
+ }
+
+ if (dmc == null)
+ return null;
+ DsfSession session = DsfSession.getSession(dmc.getSessionId());
+ if (session == null)
+ return null;
+
+ /*
+ * Create the query to write the value to the service. Note: no need to
+ * guard agains RejectedExecutionException, because
+ * DsfSession.getSession() above would only return an active session.
+ */
+ GetSupportFormatsValueQuery query = new GetSupportFormatsValueQuery(dmc);
+ session.getExecutor().execute(query);
+
+ /*
+ * Now we have the data, go and get it. Since the call is completed now
+ * the ".get()" will not suspend it will immediately return with the
+ * data.
+ */
+ try {
+ return query.get();
+ } catch (InterruptedException e) {
+ assert false;
+ return null;
+ } catch (ExecutionException e) {
+ return null;
+ }
+ }
+
+ public class GetFormattedValueValueQuery extends RegistersServiceQuery<String, IFormattedDataDMContext> {
+
+ private String fFormatId;
+
+ public GetFormattedValueValueQuery(IFormattedDataDMContext dmc, String formatId) {
+ super(dmc);
+ fFormatId = formatId;
+ }
+
+ @Override
+ protected void doExecute(IRegisters service, final DataRequestMonitor<String> rm) {
+ /*
+ * Convert to the proper formatting DMC then go get the formatted
+ * value.
+ */
+
+ FormattedValueDMContext formDmc = service.getFormattedValueContext(fDmc, fFormatId);
+
+ service.getFormattedExpressionValue(
+ formDmc,
+ new DataRequestMonitor<FormattedValueDMData>(ImmediateExecutor.getInstance(), rm) {
+ @Override
+ protected void handleSuccess() {
+ /*
+ * All good set return value.
+ */
+ rm.setData(getData().getFormattedValue());
+ rm.done();
+ }
+ });
+ }
+ }
+
+ public String getFormattedRegisterValue(Object element, String formatId) {
+
+ /*
+ * Get the DMC and the session. If element is not an register DMC, or
+ * session is stale, then bail out.
+ */
+ IFormattedDataDMContext dmc = null;
+ if (element instanceof IDMVMContext) {
+ IDMContext vmcdmc = ((IDMVMContext) element).getDMContext();
+ IRegisterDMContext regdmc = DMContexts.getAncestorOfType(vmcdmc, IRegisterDMContext.class);
+ dmc = DMContexts.getAncestorOfType(regdmc, IFormattedDataDMContext.class);
+ }
+
+ if (dmc == null)
+ return null;
+ DsfSession session = DsfSession.getSession(dmc.getSessionId());
+ if (session == null)
+ return null;
+
+ /*
+ * Create the query to write the value to the service. Note: no need to
+ * guard agains RejectedExecutionException, because
+ * DsfSession.getSession() above would only return an active session.
+ */
+ GetFormattedValueValueQuery query = new GetFormattedValueValueQuery(dmc, formatId);
+ session.getExecutor().execute(query);
+
+ /*
+ * Now we have the data, go and get it. Since the call is completed now
+ * the ".get()" will not suspend it will immediately return with the
+ * data.
+ */
+ try {
+ return query.get();
+ } catch (InterruptedException e) {
+ assert false;
+ return null;
+ } catch (ExecutionException e) {
+ return null;
+ }
+ }
+
+ public String getFormattedBitFieldValue(Object element, String formatId) {
+
+ /*
+ * Get the DMC and the session. If element is not an register DMC, or
+ * session is stale, then bail out.
+ */
+ IFormattedDataDMContext dmc = null;
+ if (element instanceof IDMVMContext) {
+ IDMContext vmcdmc = ((IDMVMContext) element).getDMContext();
+ IBitFieldDMContext bitfielddmc = DMContexts.getAncestorOfType(vmcdmc, IBitFieldDMContext.class);
+ dmc = DMContexts.getAncestorOfType(bitfielddmc, IFormattedDataDMContext.class);
+ }
+
+ if (dmc == null)
+ return null;
+ DsfSession session = DsfSession.getSession(dmc.getSessionId());
+ if (session == null)
+ return null;
+
+ /*
+ * Create the query to write the value to the service. Note: no need to
+ * guard agains RejectedExecutionException, because
+ * DsfSession.getSession() above would only return an active session.
+ */
+ GetFormattedValueValueQuery query = new GetFormattedValueValueQuery(dmc, formatId);
+ session.getExecutor().execute(query);
+
+ /*
+ * Now we have the data, go and get it. Since the call is completed now
+ * the ".get()" will not suspend it will immediately return with the
+ * data.
+ */
+ try {
+ return query.get();
+ } catch (InterruptedException e) {
+ assert false;
+ return null;
+ } catch (ExecutionException e) {
+ return null;
+ }
+ }
+
+ public class GetRegisterGroupDataQuery extends RegistersServiceQuery<IRegisterGroupDMData, IRegisterGroupDMContext> {
+
+ public GetRegisterGroupDataQuery(IRegisterGroupDMContext dmc) {
+ super(dmc);
+ }
+
+ @Override
+ protected void doExecute(IRegisters service, final DataRequestMonitor<IRegisterGroupDMData> rm) {
+ service.getRegisterGroupData(fDmc, rm);
+ }
+ }
+
+ public IRegisterGroupDMData getRegisterGroupDMData(Object element) {
+ IRegisterGroupDMContext dmc = null;
+ if (element instanceof IDMVMContext) {
+ dmc = DMContexts.getAncestorOfType(
+ ((IDMVMContext) element).getDMContext(),
+ IRegisterGroupDMContext.class);
+ }
+
+ DsfSession session = DsfSession.getSession(dmc.getSessionId());
+
+ if (dmc != null && session != null) {
+ GetRegisterGroupDataQuery query = new GetRegisterGroupDataQuery(dmc);
+ session.getExecutor().execute(query);
+
+ try {
+ return query.get();
+ } catch (InterruptedException e) {
+ } catch (ExecutionException e) {
+ }
+ }
+ return null;
+ }
+
+
+ public class GetRegisterDataQuery extends RegistersServiceQuery<IRegisterDMData, IRegisterDMContext> {
+
+ public GetRegisterDataQuery(IRegisterDMContext dmc) {
+ super(dmc);
+ }
+
+ @Override
+ protected void doExecute(IRegisters service, final DataRequestMonitor<IRegisterDMData> rm) {
+ service.getRegisterData(fDmc, rm);
+ }
+ }
+
+ public IRegisterDMData getRegisterDMData(Object element) {
+ IRegisterDMContext dmc = null;
+ if (element instanceof IDMVMContext) {
+ dmc = DMContexts.getAncestorOfType( ((IDMVMContext) element).getDMContext(), IRegisterDMContext.class );
+ }
+ DsfSession session = DsfSession.getSession(dmc.getSessionId());
+
+ if (dmc != null && session != null) {
+ GetRegisterDataQuery query = new GetRegisterDataQuery(dmc);
+ session.getExecutor().execute(query);
+
+ try {
+ return query.get();
+ } catch (InterruptedException e) {
+ } catch (ExecutionException e) {
+ }
+ }
+ return null;
+ }
+
+ public class GetBitFieldQuery extends RegistersServiceQuery<IBitFieldDMData, IBitFieldDMContext> {
+
+ public GetBitFieldQuery(IBitFieldDMContext dmc) {
+ super(dmc);
+ }
+
+ @Override
+ protected void doExecute(IRegisters service, final DataRequestMonitor<IBitFieldDMData> rm) {
+ service.getBitFieldData(fDmc, rm);
+ }
+ }
+
+ public IBitFieldDMData getBitFieldDMData(Object element) {
+ IBitFieldDMContext dmc = null;
+ if (element instanceof IDMVMContext) {
+ dmc = DMContexts.getAncestorOfType( ((IDMVMContext) element).getDMContext(), IBitFieldDMContext.class );
+ }
+ DsfSession session = DsfSession.getSession(dmc.getSessionId());
+
+ if (dmc != null && session != null) {
+ GetBitFieldQuery query = new GetBitFieldQuery(dmc);
+ session.getExecutor().execute(query);
+
+ try {
+ return query.get();
+ } catch (InterruptedException e) {
+ } catch (ExecutionException e) {
+ }
+ }
+ return null;
+ }
+
+
+}
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
new file mode 100644
index 00000000000..a5bb472ba12
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/register/messages.properties
@@ -0,0 +1,15 @@
+###############################################################################
+# 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
+###############################################################################
+
+RegisterColumnPresentation_name=Name
+RegisterColumnPresentation_type=Type
+RegisterColumnPresentation_value=Value
+RegisterColumnPresentation_description=Description
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/BreakpointHitUpdatePolicy.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/BreakpointHitUpdatePolicy.java
new file mode 100644
index 00000000000..49ae09bbfaa
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/BreakpointHitUpdatePolicy.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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.debug.ui.viewmodel.update;
+
+import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.StateChangeReason;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.IElementUpdateTester;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.ManualUpdatePolicy;
+
+/**
+ *
+ */
+public class BreakpointHitUpdatePolicy extends ManualUpdatePolicy {
+
+ public static String BREAKPOINT_HIT_UPDATE_POLICY_ID = "org.eclipse.cdt.dsf.debug.ui.viewmodel.update.breakpointHitUpdatePolicy"; //$NON-NLS-1$
+
+ @Override
+ public String getID() {
+ return BREAKPOINT_HIT_UPDATE_POLICY_ID;
+ }
+
+ @Override
+ public String getName() {
+ return MessagesForVMUpdate.BreakpointHitUpdatePolicy_name;
+ }
+
+ @Override
+ public IElementUpdateTester getElementUpdateTester(Object event) {
+ if(event instanceof ISuspendedDMEvent) {
+ ISuspendedDMEvent suspendedEvent = (ISuspendedDMEvent)event;
+ if(suspendedEvent.getReason().equals(StateChangeReason.BREAKPOINT)) {
+ return super.getElementUpdateTester(REFRESH_EVENT);
+ }
+ }
+ return super.getElementUpdateTester(event);
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/MessagesForVMUpdate.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/MessagesForVMUpdate.java
new file mode 100644
index 00000000000..a734d7d623f
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/MessagesForVMUpdate.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * 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.update;
+
+import org.eclipse.osgi.util.NLS;
+
+public class MessagesForVMUpdate extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.cdt.dsf.debug.ui.viewmodel.update.messages"; //$NON-NLS-1$
+
+ public static String BreakpointHitUpdatePolicy_name;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, MessagesForVMUpdate.class);
+ }
+
+ private MessagesForVMUpdate() {
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/messages.properties b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/messages.properties
new file mode 100644
index 00000000000..98e6fad25fd
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/update/messages.properties
@@ -0,0 +1,12 @@
+###############################################################################
+# 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
+###############################################################################
+
+BreakpointHitUpdatePolicy_name=Breakpoint Hit
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
new file mode 100644
index 00000000000..8ea0064be22
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/MessagesForVariablesVM.java
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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.variable;
+
+import org.eclipse.osgi.util.NLS;
+
+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;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, MessagesForVariablesVM.class);
+ }
+
+ private MessagesForVariablesVM() {
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/SyncVariableDataAccess.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/SyncVariableDataAccess.java
new file mode 100644
index 00000000000..e49197e51df
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/SyncVariableDataAccess.java
@@ -0,0 +1,543 @@
+/*******************************************************************************
+ * 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.debug.ui.viewmodel.variable;
+
+import java.util.concurrent.ExecutionException;
+
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
+import org.eclipse.cdt.dsf.concurrent.Query;
+import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
+import org.eclipse.cdt.dsf.concurrent.ThreadSafeAndProhibitedFromDsfExecutor;
+import org.eclipse.cdt.dsf.debug.service.IExpressions;
+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.IFormattedValues.IFormattedDataDMContext;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.dsf.service.IDsfService;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.util.tracker.ServiceTracker;
+
+@ThreadSafeAndProhibitedFromDsfExecutor("fSession#getExecutor")
+public class SyncVariableDataAccess {
+
+ /**
+ * The session that this data access operates in.
+ */
+ private final DsfSession fSession;
+
+ /**
+ * Need to use the OSGi service tracker here (instead of DsfServiceTracker),
+ * because we're accessing it in non-dispatch thread. DsfServiceTracker is
+ * not thread-safe.
+ */
+ @ThreadSafe
+ private ServiceTracker fServiceTracker;
+
+
+ public SyncVariableDataAccess(DsfSession session) {
+ fSession = session;
+ }
+
+ @ThreadSafe
+ private synchronized IExpressions getService() {
+
+ if (fServiceTracker == null) {
+ try {
+ fServiceTracker = new ServiceTracker(
+ DsfUIPlugin.getBundleContext(),
+ DsfUIPlugin.getBundleContext().createFilter(getServiceFilter()), null);
+ fServiceTracker.open();
+ } catch (InvalidSyntaxException e) {
+ return null;
+ }
+ }
+ return (IExpressions) fServiceTracker.getService();
+ }
+
+ private String getServiceFilter() {
+ StringBuffer filter = new StringBuffer();
+ filter.append("(&"); //$NON-NLS-1$
+ filter.append("(OBJECTCLASS="); //$NON-NLS-1$
+ filter.append(IExpressions.class.getName());
+ filter.append(')');
+ filter.append('(');
+ filter.append(IDsfService.PROP_SESSION_ID);
+ filter.append('=');
+ filter.append(fSession.getId());
+ filter.append(')');
+ filter.append(')');
+ return filter.toString();
+ }
+
+ @ThreadSafe
+ public synchronized void dispose() {
+ if (fServiceTracker != null) {
+ fServiceTracker.close();
+ }
+ }
+
+ public IExpressionDMContext getVariableDMC(Object element) {
+ if (element instanceof IAdaptable) {
+ return (IExpressionDMContext) ((IAdaptable) element).getAdapter(IExpressionDMContext.class);
+ }
+ return null;
+ }
+
+
+ public class GetVariableValueQuery extends Query<IExpressionDMData> {
+
+ private IExpressionDMContext fDmc;
+
+ public GetVariableValueQuery(IExpressionDMContext dmc) {
+ super();
+ fDmc = dmc;
+ }
+
+ @Override
+ protected void execute(final DataRequestMonitor<IExpressionDMData> rm) {
+ /*
+ * Guard against the session being disposed. If session is disposed
+ * it could mean that the executor is shut-down, which in turn could
+ * mean that we can't complete the RequestMonitor argument. in that
+ * case, cancel to notify waiting thread.
+ */
+ final DsfSession session = DsfSession.getSession(fDmc.getSessionId());
+ if (session == null) {
+ cancel(false);
+ rm.done();
+ return;
+ }
+
+ IExpressions service = getService();
+ if (service == null) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Service not available", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ service.getExpressionData(fDmc, new DataRequestMonitor<IExpressionDMData>(session.getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ /*
+ * All good set return value.
+ */
+ rm.setData(getData());
+ rm.done();
+ }
+ });
+ }
+ }
+
+ public IExpressionDMContext getExpressionDMC(Object element) {
+ if (element instanceof IAdaptable) {
+ return (IExpressionDMContext) ((IAdaptable) element).getAdapter(IExpressionDMContext.class);
+ }
+ return null;
+ }
+
+ public IExpressionDMData readVariable(Object element) {
+ /*
+ * Get the DMC and the session. If element is not an expression DMC, or
+ * session is stale, then bail out.
+ */
+ IExpressionDMContext dmc = getExpressionDMC(element);
+ if (dmc == null) return null;
+ DsfSession session = DsfSession.getSession(dmc.getSessionId());
+ if (session == null) return null;
+
+ /*
+ * Create the query to request the value from service. Note: no need to
+ * guard against RejectedExecutionException, because
+ * DsfSession.getSession() above would only return an active session.
+ */
+ GetVariableValueQuery query = new GetVariableValueQuery(dmc);
+ session.getExecutor().execute(query);
+
+ /*
+ * Now we have the data, go and get it. Since the call is completed now
+ * the ".get()" will not suspend it will immediately return with the
+ * data.
+ */
+ try {
+ return query.get();
+ } catch (InterruptedException e) {
+ assert false;
+ return null;
+ } catch (ExecutionException e) {
+ return null;
+ }
+ }
+
+ public class SetVariableValueQuery extends Query<Object> {
+
+ private IExpressionDMContext fDmc;
+ private String fValue;
+ private String fFormatId;
+
+ public SetVariableValueQuery(IExpressionDMContext dmc, String value, String formatId) {
+ super();
+ fDmc = dmc;
+ fValue = value;
+ fFormatId = formatId;
+ }
+
+ @Override
+ protected void execute(final DataRequestMonitor<Object> rm) {
+ /*
+ * We're in another dispatch, so we must guard against executor
+ * shutdown again.
+ */
+ final DsfSession session = DsfSession.getSession(fDmc.getSessionId());
+ if (session == null) {
+ cancel(false);
+ rm.done();
+ return;
+ }
+
+ /*
+ * Guard against a disposed service
+ */
+ IExpressions service = getService();
+ if (service == null) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Service unavailable", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ /*
+ * Write the expression value using a string/format style.
+ */
+ service.writeExpression(
+ fDmc,
+ fValue,
+ fFormatId,
+ new DataRequestMonitor<IExpressionDMData>(session.getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ /*
+ * All good set return value.
+ */
+ rm.setData(new Object());
+ rm.done();
+ }
+ }
+ );
+ }
+ }
+
+ public void writeVariable(Object element, String value, String formatId) {
+
+ /*
+ * Get the DMC and the session. If element is not an register DMC, or
+ * session is stale, then bail out.
+ */
+ IExpressionDMContext dmc = getExpressionDMC(element);
+ if (dmc == null) return;
+ DsfSession session = DsfSession.getSession(dmc.getSessionId());
+ if (session == null) return;
+
+ /*
+ * Create the query to write the value to the service. Note: no need to
+ * guard against RejectedExecutionException, because
+ * DsfSession.getSession() above would only return an active session.
+ */
+ SetVariableValueQuery query = new SetVariableValueQuery(dmc, value, formatId);
+ session.getExecutor().execute(query);
+
+ /*
+ * Now we have the data, go and get it. Since the call is completed now
+ * the ".get()" will not suspend it will immediately return with the
+ * data.
+ */
+ try {
+ /*
+ * Return value is irrelevant, any error would come through with an
+ * exception.
+ */
+ query.get();
+ } catch (InterruptedException e) {
+ assert false;
+ } catch (ExecutionException e) {
+ /*
+ * View must be shutting down, no need to show error dialog.
+ */
+ }
+ }
+
+ public IFormattedDataDMContext getFormattedDMC(Object element) {
+ if (element instanceof IAdaptable) {
+ return (IFormattedDataDMContext) ((IAdaptable) element).getAdapter(IFormattedDataDMContext.class);
+ }
+ return null;
+ }
+
+ public class GetSupportFormatsValueQuery extends Query<Object> {
+
+ IFormattedDataDMContext fDmc;
+
+ public GetSupportFormatsValueQuery(IFormattedDataDMContext dmc) {
+ super();
+ fDmc = dmc;
+ }
+
+ @Override
+ protected void execute(final DataRequestMonitor<Object> rm) {
+ /*
+ * We're in another dispatch, so we must guard against executor
+ * shutdown again.
+ */
+ final DsfSession session = DsfSession.getSession(fDmc.getSessionId());
+ if (session == null) {
+ cancel(false);
+ rm.done();
+ return;
+ }
+
+ /*
+ * Guard against a disposed service
+ */
+ IExpressions service = getService();
+ if (service == null) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Service unavailable", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ /*
+ * Get the available formats from the service.
+ */
+ service.getAvailableFormats(
+ fDmc,
+ new DataRequestMonitor<String[]>(session.getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ /*
+ * All good set return value.
+ */
+ rm.setData(new Object());
+ rm.done();
+ }
+ }
+ );
+ }
+ }
+
+ public String[] getSupportedFormats(Object element) {
+
+ /*
+ * Get the DMC and the session. If element is not an register DMC, or
+ * session is stale, then bail out.
+ */
+ IFormattedDataDMContext dmc = getFormattedDMC(element);
+ if (dmc == null) return null;
+ DsfSession session = DsfSession.getSession(dmc.getSessionId());
+ if (session == null) return null;
+
+ /*
+ * Create the query to write the value to the service. Note: no need to
+ * guard against RejectedExecutionException, because
+ * DsfSession.getSession() above would only return an active session.
+ */
+ GetSupportFormatsValueQuery query = new GetSupportFormatsValueQuery(dmc);
+ session.getExecutor().execute(query);
+
+ /*
+ * Now we have the data, go and get it. Since the call is completed now
+ * the ".get()" will not suspend it will immediately return with the
+ * data.
+ */
+ try {
+ return (String[]) query.get();
+ } catch (InterruptedException e) {
+ assert false;
+ return null;
+ } catch (ExecutionException e) {
+ return null;
+ }
+ }
+
+ public class GetFormattedValueValueQuery extends Query<Object> {
+
+ private IFormattedDataDMContext fDmc;
+ private String fFormatId;
+
+ public GetFormattedValueValueQuery(IFormattedDataDMContext dmc, String formatId) {
+ super();
+ fDmc = dmc;
+ fFormatId = formatId;
+ }
+
+ @Override
+ protected void execute(final DataRequestMonitor<Object> rm) {
+ /*
+ * We're in another dispatch, so we must guard against executor
+ * shutdown again.
+ */
+ final DsfSession session = DsfSession.getSession(fDmc.getSessionId());
+ if (session == null) {
+ cancel(false);
+ rm.done();
+ return;
+ }
+
+ /*
+ * Guard against a disposed service
+ */
+ IExpressions service = getService();
+ if (service == null) {
+ rm .setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Service unavailable", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ /*
+ * Convert to the proper formatting DMC then go get the formatted value.
+ */
+
+ FormattedValueDMContext formDmc = service.getFormattedValueContext(fDmc, fFormatId);
+
+ service.getFormattedExpressionValue(formDmc, new DataRequestMonitor<FormattedValueDMData>(session.getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ /*
+ * All good set return value.
+ */
+ rm.setData(getData().getFormattedValue());
+ rm.done();
+ }
+ });
+ }
+ }
+
+ public String getFormattedValue(Object element, String formatId) {
+
+ /*
+ * Get the DMC and the session. If element is not an register DMC, or
+ * session is stale, then bail out.
+ */
+ IFormattedDataDMContext dmc = getFormattedDMC(element);
+ if (dmc == null) return null;
+ DsfSession session = DsfSession.getSession(dmc.getSessionId());
+ if (session == null) return null;
+
+ /*
+ * Create the query to write the value to the service. Note: no need to
+ * guard against RejectedExecutionException, because
+ * DsfSession.getSession() above would only return an active session.
+ */
+ GetFormattedValueValueQuery query = new GetFormattedValueValueQuery(dmc, formatId);
+ session.getExecutor().execute(query);
+
+ /*
+ * Now we have the data, go and get it. Since the call is completed now
+ * the ".get()" will not suspend it will immediately return with the
+ * data.
+ */
+ try {
+ return (String) query.get();
+ } catch (InterruptedException e) {
+ assert false;
+ return null;
+ } catch (ExecutionException e) {
+ return null;
+ }
+ }
+
+ /**
+ * @since 1.1
+ */
+ public class CanWriteExpressionQuery extends Query<Boolean> {
+
+ private IExpressionDMContext fDmc;
+
+ public CanWriteExpressionQuery(IExpressionDMContext dmc) {
+ super();
+ fDmc = dmc;
+ }
+
+ @Override
+ protected void execute(final DataRequestMonitor<Boolean> rm) {
+ /*
+ * We're in another dispatch, so we must guard against executor
+ * shutdown again.
+ */
+ final DsfSession session = DsfSession.getSession(fDmc.getSessionId());
+ if (session == null) {
+ cancel(false);
+ rm.done();
+ return;
+ }
+
+ /*
+ * Guard against a disposed service
+ */
+ IExpressions service = getService();
+ if (service == null) {
+ rm .setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Service unavailable", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ service.canWriteExpression(fDmc, new DataRequestMonitor<Boolean>(session.getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ /*
+ * All good set return value.
+ */
+ rm.setData(getData());
+ rm.done();
+ }
+ });
+ }
+ }
+
+ public boolean canWriteExpression(Object element) {
+ /*
+ * Get the DMC and the session. If element is not an expression DMC, or
+ * session is stale, then bail out.
+ */
+ IExpressionDMContext dmc = getExpressionDMC(element);
+ if (dmc == null) return false;
+ DsfSession session = DsfSession.getSession(dmc.getSessionId());
+ if (session == null) return false;
+
+ /*
+ * Create the query to make the request to the service. Note: no need to
+ * guard against RejectedExecutionException, because
+ * DsfSession.getSession() above would only return an active session.
+ */
+ CanWriteExpressionQuery query = new CanWriteExpressionQuery(dmc);
+ session.getExecutor().execute(query);
+
+ /*
+ * Now we have the data, go and get it. Since the call is completed now
+ * the ".get()" will not suspend it will immediately return with the
+ * data.
+ */
+ try {
+ return query.get();
+ } catch (InterruptedException e) {
+ assert false;
+ return false;
+ } catch (ExecutionException e) {
+ return false;
+ }
+ }
+
+
+}
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
new file mode 100644
index 00000000000..7d558cbbd5e
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableCellModifier.java
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * 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.debug.ui.viewmodel.variable;
+
+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.ui.viewmodel.IVMContext;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.AbstractCachingVMProvider;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.UserEditEvent;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+
+@SuppressWarnings("restriction")
+public class VariableCellModifier extends WatchExpressionCellModifier {
+
+ private AbstractCachingVMProvider fProvider;
+ private SyncVariableDataAccess fDataAccess = null;
+ private IFormattedValuePreferenceStore fPrefStore;
+
+ public VariableCellModifier(AbstractCachingVMProvider provider,
+ IFormattedValuePreferenceStore formattedValuePreferenceStore, SyncVariableDataAccess access)
+ {
+ fProvider = provider;
+ fDataAccess = access;
+ fPrefStore = formattedValuePreferenceStore;
+ }
+
+ /*
+ * Used to make sure we are dealing with a valid variable.
+ */
+ private IExpressionDMContext getVariableDMC(Object element) {
+ if (element instanceof IAdaptable) {
+ return (IExpressionDMContext)((IAdaptable)element).getAdapter(IExpressionDMContext.class);
+ }
+ return null;
+ }
+
+ @Override
+ public boolean canModify(Object element, String property) {
+ // If we're in the column value, modify the register data. Otherwise, call the super-class to edit
+ // the watch expression.
+
+ if (IDebugVMConstants.COLUMN_ID__VALUE.equals(property)) {
+ // Make sure we are are dealing with a valid set of information.
+
+ if (getVariableDMC(element) == null) {
+ return false;
+ }
+
+ return fDataAccess.canWriteExpression(element);
+ }
+
+ return super.canModify(element, property);
+ }
+
+ @Override
+ public Object getValue(Object element, String property) {
+ // If we're in the column value, modify the variable value. Otherwise, call the super-class to edit
+ // the watch expression.
+
+ if (IDebugVMConstants.COLUMN_ID__VALUE.equals(property)) {
+ /*
+ * We let the Model provider supply the current format.
+ */
+ String formatId;
+
+ if ( element instanceof IVMContext) {
+ /*
+ * Find the presentation context and then use it to get the current desired format.
+ */
+ IVMContext ctx = (IVMContext) element;
+ IPresentationContext presCtx = ctx.getVMNode().getVMProvider().getPresentationContext();
+
+ formatId = fPrefStore.getCurrentNumericFormat(presCtx);
+ }
+ else {
+ formatId = IFormattedValues.NATURAL_FORMAT;
+ }
+
+ String value = fDataAccess.getFormattedValue(element, formatId);
+
+ if (value == null) {
+ return "..."; //$NON-NLS-1$
+ }
+
+ return value;
+ }
+
+ return super.getValue(element, property);
+ }
+
+ @Override
+ public void modify(Object element, String property, Object value) {
+ /*
+ * If we're in the column value, modify the register data. Otherwise, call the super-class to edit
+ * the watch expression.
+ */
+ if (IDebugVMConstants.COLUMN_ID__VALUE.equals(property)) {
+ if (value instanceof String) {
+ /*
+ * We let the Model provider supply the current format.
+ */
+ String formatId;
+
+ if ( element instanceof IVMContext) {
+ /*
+ * Find the presentation context and then use it to get the current desired format.
+ */
+ IVMContext ctx = (IVMContext) element;
+ IPresentationContext presCtx = ctx.getVMNode().getVMProvider().getPresentationContext();
+
+ formatId = fPrefStore.getCurrentNumericFormat(presCtx);
+ }
+ else {
+ formatId = IFormattedValues.NATURAL_FORMAT;
+ }
+
+ fDataAccess.writeVariable(element, (String) value, formatId);
+ fProvider.handleEvent(new UserEditEvent(element));
+ }
+ }
+ else {
+ super.modify(element, property, value);
+ }
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableColumnPresentation.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableColumnPresentation.java
new file mode 100644
index 00000000000..725b02c0c59
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableColumnPresentation.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * 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.variable;
+
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.jface.resource.ImageDescriptor;
+
+/**
+ *
+ */
+@SuppressWarnings("restriction")
+public class VariableColumnPresentation implements IColumnPresentation {
+ public static final String ID = DsfUIPlugin.PLUGIN_ID + ".VARIABLES_COLUMN_PRESENTATION_ID"; //$NON-NLS-1$
+
+ // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#init(org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext)
+ public void init(IPresentationContext context) {}
+
+ // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#dispose()
+ public void dispose() {}
+
+ // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getAvailableColumns()
+ public String[] getAvailableColumns() {
+ return new String[] { IDebugVMConstants.COLUMN_ID__NAME, IDebugVMConstants.COLUMN_ID__TYPE, IDebugVMConstants.COLUMN_ID__VALUE, IDebugVMConstants.COLUMN_ID__ADDRESS };
+ }
+
+ // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getHeader(java.lang.String)
+ public String getHeader(String id) {
+ if (IDebugVMConstants.COLUMN_ID__NAME.equals(id)) {
+ return MessagesForVariablesVM.VariableColumnPresentation_name;
+ } else if (IDebugVMConstants.COLUMN_ID__TYPE.equals(id)) {
+ return MessagesForVariablesVM.VariableColumnPresentation_type;
+ } else if (IDebugVMConstants.COLUMN_ID__VALUE.equals(id)) {
+ return MessagesForVariablesVM.VariableColumnPresentation_value;
+ } else if (IDebugVMConstants.COLUMN_ID__ADDRESS.equals(id)) {
+ return MessagesForVariablesVM.VariableColumnPresentation_address;
+ }
+ return null;
+ }
+
+ // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getId()
+ public String getId() {
+ return ID;
+ }
+
+ // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getImageDescriptor(java.lang.String)
+ public ImageDescriptor getImageDescriptor(String id) {
+ return null;
+ }
+
+ // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#getInitialColumns()
+ public String[] getInitialColumns() {
+ return new String[] { IDebugVMConstants.COLUMN_ID__NAME, IDebugVMConstants.COLUMN_ID__TYPE, IDebugVMConstants.COLUMN_ID__VALUE };
+ }
+
+ // @see org.eclipse.debug.internal.ui.viewers.provisional.IColumnPresentation#isOptional()
+ public boolean isOptional() {
+ return true;
+ }
+
+}
diff --git a/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
new file mode 100644
index 00000000000..bed8ab511e7
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMNode.java
@@ -0,0 +1,995 @@
+/*******************************************************************************
+ * 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.variable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.core.IAddress;
+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.MultiRequestMonitor;
+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.IExpressions;
+import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
+import org.eclipse.cdt.dsf.debug.service.IStack;
+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.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.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.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+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;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementEditor;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.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.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
+import org.eclipse.debug.ui.actions.IWatchExpressionFactoryAdapter2;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.util.PropertyChangeEvent;
+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;
+import org.eclipse.ui.IMemento;
+
+@SuppressWarnings({"restriction", "nls"})
+public class VariableVMNode extends AbstractExpressionVMNode
+ implements IElementEditor, IElementLabelProvider, IElementMementoProvider
+{
+
+ private final IFormattedValuePreferenceStore fFormattedPrefStore;
+
+ private final SyncVariableDataAccess fSyncVariableDataAccess;
+
+ public class VariableExpressionVMC extends DMVMContext implements IFormattedValueVMContext {
+
+ private IExpression fExpression;
+
+ public VariableExpressionVMC(IDMContext dmc) {
+ super(dmc);
+ }
+
+ public IFormattedValuePreferenceStore getPreferenceStore() {
+ return fFormattedPrefStore;
+ }
+
+ public void setExpression(IExpression expression) {
+ fExpression = expression;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Object getAdapter(Class adapter) {
+ if (fExpression != null && adapter.isAssignableFrom(fExpression.getClass())) {
+ return fExpression;
+ } else if (adapter.isAssignableFrom(IWatchExpressionFactoryAdapter2.class)) {
+ return fVariableExpressionFactory;
+ } else {
+ return super.getAdapter(adapter);
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof VariableExpressionVMC && super.equals(other)) {
+ VariableExpressionVMC otherGroup = (VariableExpressionVMC)other;
+ return (otherGroup.fExpression == null && fExpression == null) ||
+ (otherGroup.fExpression != null && otherGroup.fExpression.equals(fExpression));
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode() + (fExpression != null ? fExpression.hashCode() : 0);
+ }
+ }
+
+ protected class VariableExpressionFactory implements IWatchExpressionFactoryAdapter2 {
+
+ public boolean canCreateWatchExpression(Object element) {
+ return element instanceof VariableExpressionVMC;
+ }
+
+ public String createWatchExpression(Object element) throws CoreException {
+
+ VariableExpressionVMC exprVmc = (VariableExpressionVMC) element;
+
+ IExpressionDMContext exprDmc = DMContexts.getAncestorOfType(exprVmc.getDMContext(), IExpressionDMContext.class);
+ if (exprDmc != null) {
+ return exprDmc.getExpression();
+ }
+
+ return null;
+ }
+ }
+
+ final protected VariableExpressionFactory fVariableExpressionFactory = new VariableExpressionFactory();
+
+ public VariableVMNode(IFormattedValuePreferenceStore prefStore, AbstractDMVMProvider provider,
+ DsfSession session, SyncVariableDataAccess syncVariableDataAccess)
+ {
+ super(provider, session, IExpressions.IExpressionDMContext.class);
+ fFormattedPrefStore = prefStore;
+ fSyncVariableDataAccess = syncVariableDataAccess;
+ }
+
+ @Override
+ public String toString() {
+ return "VariableVMNode(" + getSession().getId() + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ @Override
+ protected IDMVMContext createVMContext(IDMContext dmc) {
+ return new VariableExpressionVMC(dmc);
+ }
+
+
+ public void update(final ILabelUpdate[] updates) {
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ updateLabelInSessionThread(updates);
+ }});
+ } catch (RejectedExecutionException e) {
+ for (ILabelUpdate update : updates) {
+ handleFailedUpdate(update);
+ }
+ }
+ }
+
+ 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 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();
+ continue;
+ }
+
+ getDMVMProvider().getModelData(
+ this, update,
+ getServicesTracker().getService(IExpressions.class, null),
+ dmc,
+ new ViewerDataRequestMonitor<IExpressionDMData>(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<RequestMonitor> mrm =
+ new MultiRequestMonitor<RequestMonitor>(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<IExpressionDMAddress>(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<String[]>(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 ( ! 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<FormattedValueDMData>(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<FormattedValueDMData>(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()
+ );
+ }
+ }
+ );
+ }
+
+ private void completeFillinInUpdateWithValue(ILabelUpdate update,
+ int labelIndex,
+ FormattedValueDMContext valueDmc,
+ String value,
+ FormattedValueDMContext stringFormatDmc,
+ String stringFormatValue,
+ RequestMonitor monitor)
+ {
+ /*
+ * 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();
+ }
+
+ public CellEditor getCellEditor(IPresentationContext context, String columnId, Object element, Composite parent) {
+ if (IDebugVMConstants.COLUMN_ID__VALUE.equals(columnId)) {
+ return new TextCellEditor(parent);
+ }
+ else if (IDebugVMConstants.COLUMN_ID__EXPRESSION.equals(columnId)) {
+ return new TextCellEditor(parent);
+ }
+
+ return null;
+ }
+
+ public ICellModifier getCellModifier(IPresentationContext context, Object element) {
+ return new VariableCellModifier(getDMVMProvider(), fFormattedPrefStore, fSyncVariableDataAccess);
+ }
+
+ public boolean canParseExpression(IExpression expression) {
+ // At this point we are going to say we will allow anything as an expression.
+ // Since the evaluation of VM Node implementations searches in the order of
+ // registration and we always make sure we register the VariableVMNode last,
+ // we know that the other possible handlers have passed the expression by. So
+ // we are going to say OK and let the expression evaluation of whatever debug
+ // backend is connected to decide. This does not allow us to put up any good
+ // diagnostic error message ( instead the error will come from the backend ).
+ // But it does allow for the most flexibility
+
+ return true;
+ }
+
+ @Override
+ public void update(final IExpressionUpdate update) {
+ try {
+ getSession().getExecutor().execute(new Runnable() {
+ public void run() {
+ final IExpressions expressionService = getServicesTracker().getService(IExpressions.class);
+ if (expressionService != null) {
+ IExpressionDMContext expressionDMC = expressionService.createExpression(
+ createCompositeDMVMContext(update),
+ update.getExpression().getExpressionText());
+ VariableExpressionVMC variableVmc = new VariableExpressionVMC(expressionDMC);
+ variableVmc.setExpression(update.getExpression());
+
+ update.setExpressionElement(variableVmc);
+ update.done();
+ } else {
+ handleFailedUpdate(update);
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ handleFailedUpdate(update);
+ }
+ }
+
+
+ @Override
+ protected void handleFailedUpdate(IViewerUpdate update) {
+ if (update instanceof IExpressionUpdate) {
+ update.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Update failed", null)); //$NON-NLS-1$
+ update.done();
+ } else {
+ super.handleFailedUpdate(update);
+ }
+ }
+ @Override
+ protected void associateExpression(Object element, IExpression expression) {
+ if (element instanceof VariableExpressionVMC) {
+ ((VariableExpressionVMC)element).setExpression(expression);
+ }
+ }
+
+ @Override
+ protected void updateElementsInSessionThread(final IChildrenUpdate update) {
+ // Get the data model context object for the current node in the hierarchy.
+
+ final IExpressionDMContext expressionDMC = findDmcInPath(update.getViewerInput(), update.getElementPath(), IExpressionDMContext.class);
+
+ if ( expressionDMC != null ) {
+ getSubexpressionsUpdateElementsInSessionThread( update );
+ }
+ else {
+ getLocalsUpdateElementsInSessionThread( update );
+ }
+ }
+
+ private void getSubexpressionsUpdateElementsInSessionThread(final IChildrenUpdate update) {
+
+ final IExpressionDMContext expressionDMC = findDmcInPath(update.getViewerInput(), update.getElementPath(), IExpressionDMContext.class);
+
+ if ( expressionDMC != null ) {
+
+ // Get the services we need to use.
+
+ final IExpressions expressionService = getServicesTracker().getService(IExpressions.class);
+
+ if (expressionService == null) {
+ handleFailedUpdate(update);
+ return;
+ }
+
+ final DsfExecutor dsfExecutor = getSession().getExecutor();
+
+ // Call IExpressions.getSubExpressions() to get an Iterable of IExpressionDMContext objects representing
+ // the sub-expressions of the expression represented by the current expression node.
+
+ final DataRequestMonitor<IExpressionDMContext[]> rm =
+ new ViewerDataRequestMonitor<IExpressionDMContext[]>(dsfExecutor, update) {
+ @Override
+ public void handleCompleted() {
+ if (!isSuccess()) {
+ handleFailedUpdate(update);
+ return;
+ }
+ fillUpdateWithVMCs(update, getData());
+ update.done();
+ }
+ };
+
+ // Make the asynchronous call to IExpressions.getSubExpressions(). The results are processed in the
+ // DataRequestMonitor.handleCompleted() above.
+
+ expressionService.getSubExpressions(expressionDMC, rm);
+ } else {
+ handleFailedUpdate(update);
+ }
+ }
+
+ private void getLocalsUpdateElementsInSessionThread(final IChildrenUpdate update) {
+
+ final IFrameDMContext frameDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IFrameDMContext.class);
+
+ // Get the services we need to use.
+
+ final IExpressions expressionService = getServicesTracker().getService(IExpressions.class);
+ final IStack stackFrameService = getServicesTracker().getService(IStack.class);
+
+ if ( frameDmc == null || expressionService == null || stackFrameService == null) {
+ handleFailedUpdate(update);
+ return;
+ }
+
+ final DsfExecutor dsfExecutor = getSession().getExecutor();
+
+ // Call IStack.getLocals() to get an array of IVariableDMContext objects representing the local
+ // variables in the stack frame represented by frameDmc.
+
+ final DataRequestMonitor<IVariableDMContext[]> rm =
+ new ViewerDataRequestMonitor<IVariableDMContext[]>(dsfExecutor, update) {
+ @Override
+ public void handleCompleted() {
+ if (!isSuccess()) {
+ handleFailedUpdate(update);
+ return;
+ }
+
+ // For each IVariableDMContext object returned by IStack.getLocals(), call
+ // MIStackFrameService.getModelData() to get the IVariableDMData object. This requires
+ // a MultiRequestMonitor object.
+
+ // First, get the data model context objects for the local variables.
+
+ IVariableDMContext[] localsDMCs = getData();
+
+ if (localsDMCs == null) {
+ handleFailedUpdate(update);
+ return;
+ }
+
+ if ( localsDMCs.length == 0 ) {
+ // There are no locals so just complete the request
+ update.done();
+ return;
+ }
+
+ // Create a List in which we store the DM data objects for the local variables. This is
+ // necessary because there is no MultiDataRequestMonitor. :)
+
+ final List<IVariableDMData> localsDMData = new ArrayList<IVariableDMData>();
+
+ // Create the MultiRequestMonitor to handle completion of the set of getModelData() calls.
+
+ final MultiRequestMonitor<DataRequestMonitor<IVariableDMData>> mrm =
+ new MultiRequestMonitor<DataRequestMonitor<IVariableDMData>>(dsfExecutor, null) {
+ @Override
+ public void handleCompleted() {
+ // Now that all the calls to getModelData() are complete, we create an
+ // IExpressionDMContext object for each local variable name, saving them all
+ // in an array.
+
+ if (!isSuccess()) {
+ handleFailedUpdate(update);
+ return;
+ }
+
+ IExpressionDMContext[] expressionDMCs = new IExpressionDMContext[localsDMData.size()];
+
+ int i = 0;
+
+ for (IVariableDMData localDMData : localsDMData) {
+ expressionDMCs[i++] = expressionService.createExpression(frameDmc, localDMData.getName());
+ }
+
+ // Lastly, we fill the update from the array of view model context objects
+ // that reference the ExpressionDMC objects for the local variables. This is
+ // the last code to run for a given call to updateElementsInSessionThread().
+ // We can now leave anonymous-inner-class hell.
+
+ fillUpdateWithVMCs(update, expressionDMCs);
+ update.done();
+ }
+ };
+
+ // Perform a set of getModelData() calls, one for each local variable's data model
+ // context object. In the handleCompleted() method of the DataRequestMonitor, add the
+ // IVariableDMData object to the localsDMData List for later processing (see above).
+
+ for (IVariableDMContext localDMC : localsDMCs) {
+ DataRequestMonitor<IVariableDMData> rm =
+ new ViewerDataRequestMonitor<IVariableDMData>(dsfExecutor, update) {
+ @Override
+ public void handleCompleted() {
+ localsDMData.add(getData());
+ mrm.requestMonitorDone(this);
+ }
+ };
+
+ mrm.add(rm);
+
+ getDMVMProvider().getModelData(VariableVMNode.this, update, stackFrameService, localDMC, rm, getExecutor());
+ }
+ }
+ };
+
+ // Make the asynchronous call to IStack.getLocals(). The results are processed in the
+ // DataRequestMonitor.handleCompleted() above.
+
+ stackFrameService.getLocals(frameDmc, rm);
+ }
+
+ //private final static int MAX_STRING_VALUE_LENGTH = 40;
+
+ public int getDeltaFlags(Object e) {
+ if ( e instanceof ISuspendedDMEvent ||
+ e instanceof IMemoryChangedEvent ||
+ e instanceof IExpressionChangedDMEvent ||
+ (e instanceof PropertyChangeEvent &&
+ ((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) )
+ {
+ // Create a delta that the whole register group has changed.
+ return IModelDelta.CONTENT;
+ }
+
+ return IModelDelta.NO_CHANGE;
+ }
+
+ public void buildDelta(final Object e, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor requestMonitor) {
+
+ // The following events can affect any expression's values,
+ // refresh the contents of the parent element (i.e. all the expressions).
+ if ( e instanceof ISuspendedDMEvent ||
+ e instanceof IMemoryChangedEvent ||
+ e instanceof IExpressionChangedDMEvent ||
+ (e instanceof PropertyChangeEvent &&
+ ((PropertyChangeEvent)e).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) )
+ {
+ // Create a delta that the whole register group has changed.
+ parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
+ }
+
+ requestMonitor.done();
+ }
+
+ public int getDeltaFlagsForExpression(IExpression expression, Object event) {
+ if ( event instanceof IExpressionChangedDMEvent ||
+ event instanceof IMemoryChangedEvent ||
+ (event instanceof PropertyChangeEvent &&
+ ((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) )
+ {
+ return IModelDelta.CONTENT;
+ }
+
+ if (event instanceof ISuspendedDMEvent)
+ {
+ return IModelDelta.CONTENT;
+ }
+
+ return IModelDelta.NO_CHANGE;
+ }
+
+ public void buildDeltaForExpression(IExpression expression, int elementIdx, Object event, VMDelta parentDelta,
+ TreePath path, RequestMonitor rm)
+ {
+ // Always refresh the contents of the view upon suspended event.
+ if (event instanceof ISuspendedDMEvent) {
+ parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT);
+ }
+
+ rm.done();
+ }
+
+ public void buildDeltaForExpressionElement(Object element, int elementIdx, Object event, VMDelta parentDelta,
+ RequestMonitor rm)
+ {
+ // The following events can affect expression values, refresh the state
+ // of the expression.
+ if ( event instanceof IExpressionChangedDMEvent ||
+ event instanceof IMemoryChangedEvent ||
+ (event instanceof PropertyChangeEvent &&
+ ((PropertyChangeEvent)event).getProperty() == IDebugVMConstants.CURRENT_FORMAT_STORAGE) )
+ {
+ parentDelta.addNode(element, IModelDelta.CONTENT);
+ }
+
+ rm.done();
+ }
+
+
+
+ /*
+ * (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$
+ }
+
+ private final String MEMENTO_NAME = "VARIABLE_MEMENTO_NAME"; //$NON-NLS-1$
+
+ public void compareElements(IElementCompareRequest[] requests) {
+
+ for ( IElementCompareRequest request : requests ) {
+
+ Object element = request.getElement();
+ IMemento memento = request.getMemento();
+ String mementoName = memento.getString(MEMENTO_NAME); //$NON-NLS-1$
+
+ if (mementoName != null) {
+ if (element instanceof IDMVMContext) {
+
+ IDMContext dmc = ((IDMVMContext)element).getDMContext();
+
+ if ( dmc instanceof IExpressionDMContext) {
+
+ String elementName = produceExpressionElementName( request.getPresentationContext().getId(), (IExpressionDMContext) dmc );
+ request.setEqual( elementName.equals( mementoName ) );
+ }
+ }
+ }
+ request.done();
+ }
+ }
+
+ /*
+ * (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 ) {
+
+ Object element = request.getElement();
+ IMemento memento = request.getMemento();
+
+ if (element instanceof IDMVMContext) {
+
+ IDMContext dmc = ((IDMVMContext)element).getDMContext();
+
+ if ( dmc instanceof IExpressionDMContext) {
+
+ String elementName = produceExpressionElementName( request.getPresentationContext().getId(), (IExpressionDMContext) dmc );
+ memento.putString(MEMENTO_NAME, elementName);
+ }
+ }
+ request.done();
+ }
+ }
+}
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
new file mode 100644
index 00000000000..b6424ae75cf
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/VariableVMProvider.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * 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.debug.ui.viewmodel.variable;
+
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.debug.service.ICachingService;
+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;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMAdapter;
+import org.eclipse.cdt.dsf.ui.viewmodel.IRootVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
+import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.RootDMVMNode;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.AutomaticUpdatePolicy;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.IVMUpdatePolicy;
+import org.eclipse.cdt.dsf.ui.viewmodel.update.ManualUpdatePolicy;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentation;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+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
+{
+ private IPropertyChangeListener fPreferencesListener = new IPropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ String property = event.getProperty();
+ if (property.equals(IDsfDebugUIConstants.PREF_WAIT_FOR_VIEW_UPDATE_AFTER_STEP_ENABLE)) {
+ IPreferenceStore store = DsfDebugUITools.getPreferenceStore();
+ setDelayEventHandleForViewUpdate(store.getBoolean(property));
+ }
+ }
+ };
+
+ private IPropertyChangeListener fPresentationContextListener = new IPropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ handleEvent(event);
+ }
+ };
+
+ public VariableVMProvider(AbstractVMAdapter adapter, IPresentationContext context, DsfSession session) {
+ super(adapter, context, session);
+
+ context.addPropertyChangeListener(fPresentationContextListener);
+
+ IPreferenceStore store = DsfDebugUITools.getPreferenceStore();
+ store.addPropertyChangeListener(fPreferencesListener);
+ setDelayEventHandleForViewUpdate(store.getBoolean(IDsfDebugUIConstants.PREF_WAIT_FOR_VIEW_UPDATE_AFTER_STEP_ENABLE));
+
+ /*
+ * Create the variable data access routines.
+ */
+ SyncVariableDataAccess varAccess = new SyncVariableDataAccess(session) ;
+
+ /*
+ * Create the top level node to deal with the root selection.
+ */
+ IRootVMNode rootNode = new RootDMVMNode(this);
+ setRootNode(rootNode);
+
+ /*
+ * Create the next level which represents members of structs/unions/enums and elements of arrays.
+ */
+ IVMNode subExpressioNode = new VariableVMNode(FormattedValuePreferenceStore.getDefault(), this, getSession(), varAccess);
+ addChildNodes(rootNode, new IVMNode[] { subExpressioNode });
+
+ // Configure the sub-expression node to be a child of itself. This way the content
+ // provider will recursively drill-down the variable hierarchy.
+ addChildNodes(subExpressioNode, new IVMNode[] { subExpressioNode });
+ }
+
+ @Override
+ public void dispose() {
+ DsfDebugUITools.getPreferenceStore().removePropertyChangeListener(fPreferencesListener);
+ getPresentationContext().removePropertyChangeListener(fPresentationContextListener);
+ super.dispose();
+ }
+
+ @Override
+ public IColumnPresentation createColumnPresentation(IPresentationContext context, Object element) {
+ return new VariableColumnPresentation();
+ }
+
+ @Override
+ public String getColumnPresentationId(IPresentationContext context, Object element) {
+ return VariableColumnPresentation.ID;
+ }
+
+ @Override
+ protected IVMUpdatePolicy[] createUpdateModes() {
+ return new IVMUpdatePolicy[] { new AutomaticUpdatePolicy(), new ManualUpdatePolicy(), new BreakpointHitUpdatePolicy() };
+ }
+
+ @Override
+ protected boolean canSkipHandlingEvent(Object newEvent, Object eventToSkip) {
+ // To optimize the performance of the view when stepping rapidly, skip all
+ // other events when a suspended event is received, including older suspended
+ // events.
+ return newEvent instanceof ISuspendedDMEvent;
+ }
+
+ @Override
+ public void refresh() {
+ super.refresh();
+ try {
+ getSession().getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ DsfServicesTracker tracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), getSession().getId());
+ IExpressions expressionsService = tracker.getService(IExpressions.class);
+ if (expressionsService instanceof ICachingService) {
+ ((ICachingService)expressionsService).flushCache(null);
+ }
+ tracker.dispose();
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ // Session disposed, ignore.
+ }
+ }
+}
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
new file mode 100644
index 00000000000..0b40d097c33
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/variable/messages.properties
@@ -0,0 +1,16 @@
+###############################################################################
+# 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
+# Wind River Systems - added Address
+###############################################################################
+
+VariableColumnPresentation_name=Name
+VariableColumnPresentation_type=Type
+VariableColumnPresentation_value=Value
+VariableColumnPresentation_address=Address

Back to the top