diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/ExpressionInformationControlCreator.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/ExpressionInformationControlCreator.java
new file mode 100644
index 00000000000..c61b3863d6d
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/internal/ui/ExpressionInformationControlCreator.java
@@ -0,0 +1,441 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 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 - adapted for DSF
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.internal.ui;
+
+import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext;
+import org.eclipse.cdt.dsf.debug.ui.IDsfDebugUIConstants;
+import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.model.IVariable;
+import org.eclipse.debug.internal.ui.SWTFactory;
+import org.eclipse.debug.internal.ui.model.elements.ElementContentProvider;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerInputRequestor;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerInputUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdateListener;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.PresentationContext;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer;
+import org.eclipse.debug.internal.ui.viewers.model.provisional.ViewerInputService;
+import org.eclipse.debug.internal.ui.views.variables.details.DefaultDetailPane;
+import org.eclipse.debug.internal.ui.views.variables.details.DetailPaneProxy;
+import org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer;
+import org.eclipse.debug.ui.AbstractDebugView;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.jface.dialogs.IDialogSettings;
+import org.eclipse.jface.text.AbstractInformationControl;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlCreator;
+import org.eclipse.jface.text.IInformationControlExtension2;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredViewer;
+import org.eclipse.jface.viewers.TreeSelection;
+import org.eclipse.jface.viewers.ViewerFilter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Layout;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPartSite;
+
+/**
+ * Creates an information control to display an expression in a hover control.
+ *
This class is derivative work from JDT's ExpressionInformationControlCreator
.
+ *
+ * @noextend This class is not intended to be subclassed by clients.
+ *
+ * @since 2.1
+ */
+@SuppressWarnings("restriction")
+public class ExpressionInformationControlCreator implements IInformationControlCreator {
+
+ class ExpressionInformationControl extends AbstractInformationControl implements IInformationControlExtension2, IViewerInputRequestor {
+
+ /**
+ * Dialog setting key for height
+ */
+ private static final String HEIGHT = "HEIGHT"; //$NON-NLS-1$
+
+ /**
+ * Dialog setting key for width.
+ */
+ private static final String WIDTH = "WIDTH"; //$NON-NLS-1$
+
+ /**
+ * Dialog setting key for tree sash weight
+ */
+ private static final String SASH_WEIGHT_TREE = "SashWeightTree"; //$NON-NLS-1$
+
+ /**
+ * Dialog setting key for details sash weight
+ */
+ private static final String SASH_WEIGHT_DETAILS = "SashWeightDetails"; //$NON-NLS-1$
+
+ /**
+ * Variable to display.
+ */
+ private Object fVariable;
+
+ private TreeModelViewer fViewer;
+ private SashForm fSashForm;
+ private Composite fDetailPaneComposite;
+ private DetailPaneProxy fDetailPane;
+ private Tree fTree;
+
+ private ViewerInputService fInputService;
+
+ /**
+ * Creates the content for the root element of the tree viewer in the hover
+ */
+ private class TreeRoot extends ElementContentProvider {
+ @Override
+ protected int getChildCount(Object element, IPresentationContext context, IViewerUpdate monitor) throws CoreException {
+ return 1;
+ }
+ @Override
+ protected Object[] getChildren(Object parent, int index, int length, IPresentationContext context, IViewerUpdate monitor) throws CoreException {
+ return new Object[] { fVariable };
+ }
+ @Override
+ protected boolean supportsContextId(String id) {
+ return true;
+ }
+ }
+
+ /**
+ * Inner class implementing IDetailPaneContainer methods. Handles changes to detail
+ * pane and provides limited access to the detail pane proxy.
+ */
+ private class DetailPaneContainer implements IDetailPaneContainer {
+
+ /*
+ * @see org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer#getCurrentPaneID()
+ */
+ public String getCurrentPaneID() {
+ return fDetailPane.getCurrentPaneID();
+ }
+
+ /*
+ * @see org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer#getCurrentSelection()
+ */
+ public IStructuredSelection getCurrentSelection() {
+ return (IStructuredSelection)fViewer.getSelection();
+ }
+
+ /*
+ * @see org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer#refreshDetailPaneContents()
+ */
+ public void refreshDetailPaneContents() {
+ fDetailPane.display(getCurrentSelection());
+ }
+
+ /*
+ * @see org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer#getParentComposite()
+ */
+ public Composite getParentComposite() {
+ return fDetailPaneComposite;
+ }
+
+ /*
+ * @see org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer#getWorkbenchPartSite()
+ */
+ public IWorkbenchPartSite getWorkbenchPartSite() {
+ return null;
+ }
+
+ /*
+ * @see org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer#paneChanged(java.lang.String)
+ */
+ public void paneChanged(String newPaneID) {
+ if (DefaultDetailPane.ID.equals(newPaneID)){
+ fDetailPane.getCurrentControl().setBackground(getShell().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+ }
+ }
+
+ }
+
+ /**
+ * Constructs a new control in the given shell.
+ *
+ * @param parentShell shell
+ * @param resize whether resize is supported
+ */
+ ExpressionInformationControl(Shell parentShell, boolean resize) {
+ super(parentShell, resize);
+ create();
+ }
+
+ @Override
+ public Point computeSizeHint() {
+ IDialogSettings settings = getDialogSettings(false);
+ if (settings != null) {
+ int x = getIntSetting(settings, WIDTH);
+ if (x > 0) {
+ int y = getIntSetting(settings, HEIGHT);
+ if (y > 0) {
+ return new Point(x,y);
+ }
+ }
+ }
+ return super.computeSizeHint();
+ }
+
+ /**
+ * Returns the dialog settings for this hover or null
if none
+ *
+ * @param create whether to create the settings
+ */
+ private IDialogSettings getDialogSettings(boolean create) {
+ IDialogSettings settings = DsfUIPlugin.getDefault().getDialogSettings();
+ IDialogSettings section = settings.getSection(this.getClass().getName());
+ if (section == null & create) {
+ section = settings.addNewSection(this.getClass().getName());
+ }
+ return section;
+ }
+
+ /**
+ * Returns an integer value in the given dialog settings or -1 if none.
+ *
+ * @param settings dialog settings
+ * @param key key
+ * @return value or -1 if not present
+ */
+ private int getIntSetting(IDialogSettings settings, String key) {
+ try {
+ return settings.getInt(key);
+ } catch (NumberFormatException e) {
+ return -1;
+ }
+ }
+
+ @Override
+ public void dispose() {
+ persistSettings(getShell());
+ super.dispose();
+ }
+
+ /**
+ * Persists dialog settings.
+ *
+ * @param shell
+ */
+ private void persistSettings(Shell shell) {
+ if (shell != null && !shell.isDisposed()) {
+ if (isResizable()) {
+ IDialogSettings settings = getDialogSettings(true);
+ Point size = shell.getSize();
+ settings.put(WIDTH, size.x);
+ settings.put(HEIGHT, size.y);
+ int[] weights = fSashForm.getWeights();
+ settings.put(SASH_WEIGHT_TREE, weights[0]);
+ settings.put(SASH_WEIGHT_DETAILS, weights[1]);
+ }
+ }
+ }
+
+ @Override
+ public void setVisible(boolean visible) {
+ if (!visible) {
+ persistSettings(getShell());
+ }
+ super.setVisible(visible);
+ }
+
+ @Override
+ protected void createContent(Composite parent) {
+
+ fSashForm = new SashForm(parent, parent.getStyle());
+ fSashForm.setOrientation(SWT.VERTICAL);
+
+ // update presentation context
+ AbstractDebugView view = getViewToEmulate();
+ IPresentationContext context = new PresentationContext(IDsfDebugUIConstants.ID_EXPRESSION_HOVER);
+ if (view != null) {
+ // copy over properties
+ IPresentationContext copy = ((TreeModelViewer)view.getViewer()).getPresentationContext();
+ try {
+ String[] properties = copy.getProperties();
+ for (int i = 0; i < properties.length; i++) {
+ String key = properties[i];
+ context.setProperty(key, copy.getProperty(key));
+ }
+ } catch (NoSuchMethodError e) {
+ // ignore
+ }
+ }
+
+ fViewer = new TreeModelViewer(fSashForm, SWT.NO_TRIM | SWT.MULTI | SWT.VIRTUAL, context);
+ fViewer.setAutoExpandLevel(1);
+
+ if (view != null) {
+ // copy over filters
+ StructuredViewer structuredViewer = (StructuredViewer) view.getViewer();
+ if (structuredViewer != null) {
+ ViewerFilter[] filters = structuredViewer.getFilters();
+ for (int i = 0; i < filters.length; i++) {
+ fViewer.addFilter(filters[i]);
+ }
+ }
+ }
+ fInputService = new ViewerInputService(fViewer, this);
+
+ fDetailPaneComposite = SWTFactory.createComposite(fSashForm, 1, 1, GridData.FILL_BOTH);
+ Layout layout = fDetailPaneComposite.getLayout();
+ if (layout instanceof GridLayout) {
+ GridLayout gl = (GridLayout) layout;
+ gl.marginHeight = 0;
+ gl.marginWidth = 0;
+ }
+
+ fDetailPane = new DetailPaneProxy(new DetailPaneContainer());
+ fDetailPane.display(null); // Bring up the default pane so the user doesn't see an empty composite
+
+ fTree = fViewer.getTree();
+ fTree.addSelectionListener(new SelectionListener() {
+ public void widgetSelected(SelectionEvent e) {
+ fDetailPane.display((IStructuredSelection)fViewer.getSelection());
+ }
+ public void widgetDefaultSelected(SelectionEvent e) {}
+ });
+
+ initSashWeights();
+
+ // add update listener to auto-select and display details of root expression
+ fViewer.addViewerUpdateListener(new IViewerUpdateListener() {
+ public void viewerUpdatesComplete() {
+ }
+ public void viewerUpdatesBegin() {
+ }
+ public void updateStarted(IViewerUpdate update) {
+ }
+ public void updateComplete(IViewerUpdate update) {
+ if (update instanceof IChildrenUpdate) {
+ fViewer.removeViewerUpdateListener(this);
+ fViewer.getDisplay().timerExec(100, new Runnable() {
+ public void run() {
+ TreeSelection selection = new TreeSelection(fViewer.getTopElementPath());
+ fViewer.setSelection(selection);
+ fDetailPane.display(selection);
+ }});
+ }
+ }
+ });
+
+ setBackgroundColor(getShell().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+ }
+
+
+ /**
+ * Attempts to find an appropriate view to emulate, this will either be the
+ * variables view or the expressions view.
+ * @return a view to emulate or null
+ */
+ private AbstractDebugView getViewToEmulate() {
+ IWorkbenchPage page = DsfUIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ AbstractDebugView expressionsView = (AbstractDebugView) page.findView(IDebugUIConstants.ID_EXPRESSION_VIEW);
+ if (expressionsView != null && expressionsView.isVisible()) {
+ return expressionsView;
+ }
+ AbstractDebugView variablesView = (AbstractDebugView) page.findView(IDebugUIConstants.ID_VARIABLE_VIEW);
+ if (variablesView != null && variablesView.isVisible()) {
+ return variablesView;
+ }
+ if (expressionsView != null) {
+ return expressionsView;
+ }
+ return variablesView;
+ }
+
+ /**
+ * Initializes the sash form weights from the preference store (using default values if
+ * no sash weights were stored previously).
+ */
+ protected void initSashWeights(){
+ IDialogSettings settings = getDialogSettings(false);
+ if (settings != null) {
+ int tree = getIntSetting(settings, SASH_WEIGHT_TREE);
+ if (tree > 0) {
+ int details = getIntSetting(settings, SASH_WEIGHT_DETAILS);
+ if (details > 0) {
+ fSashForm.setWeights(new int[]{tree, details});
+ }
+ }
+ }
+ }
+
+ @Override
+ public void setBackgroundColor(Color background) {
+ super.setBackgroundColor(background);
+ fDetailPaneComposite.setBackground(background);
+ fTree.setBackground(background);
+ }
+
+ @Override
+ public void setFocus() {
+ super.setFocus();
+ fTree.setFocus();
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IInformationControlExtension#hasContents()
+ */
+ public boolean hasContents() {
+ return fVariable != null;
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IInformationControlExtension2#setInput(java.lang.Object)
+ */
+ public void setInput(Object input) {
+ if (input instanceof IExpressionDMContext) {
+ fVariable = input;
+ fInputService.resolveViewerInput(input);
+ } else if (input instanceof IVariable) {
+ fVariable = input;
+ fViewer.setInput(new TreeRoot());
+ }
+ }
+
+ @Override
+ public IInformationControlCreator getInformationPresenterControlCreator() {
+ return new ExpressionInformationControlCreator() {
+ @Override
+ public IInformationControl createInformationControl(Shell shell) {
+ return new ExpressionInformationControl(shell, true);
+ }
+ };
+ }
+
+ public void viewerInputComplete(IViewerInputUpdate update) {
+ fViewer.setInput(fVariable = update.getInputElement());
+ }
+
+ }
+
+ /*
+ * @see org.eclipse.jface.text.IInformationControlCreator#createInformationControl(org.eclipse.swt.widgets.Shell)
+ */
+ public IInformationControl createInformationControl(Shell parent) {
+ return new ExpressionInformationControl(parent, false);
+ }
+
+}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/AbstractDsfDebugTextHover.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/AbstractDsfDebugTextHover.java
index ee6668c8404..1d74b8d3eaa 100644
--- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/AbstractDsfDebugTextHover.java
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/AbstractDsfDebugTextHover.java
@@ -10,9 +10,13 @@
*******************************************************************************/
package org.eclipse.cdt.dsf.debug.ui;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+
import org.eclipse.cdt.debug.ui.editors.AbstractDebugTextHover;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Query;
+import org.eclipse.cdt.dsf.debug.internal.ui.ExpressionInformationControlCreator;
import org.eclipse.cdt.dsf.debug.service.IExpressions;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext;
@@ -24,13 +28,21 @@ import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.debug.core.model.IDebugModelProvider;
+import org.eclipse.jface.text.DefaultInformationControl;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlCreator;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextHoverExtension2;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.editors.text.EditorsUI;
/**
- * An implementation of AbstractDebugTextHover using DSF services.
+ * An implementation of AbstractDebugTextHover using DSF services
*
* @since 2.1
*/
-abstract public class AbstractDsfDebugTextHover extends AbstractDebugTextHover {
+abstract public class AbstractDsfDebugTextHover extends AbstractDebugTextHover implements ITextHoverExtension2 {
/**
* Returns the debug model ID that this debug text hover is to be used for.
@@ -121,4 +133,63 @@ abstract public class AbstractDsfDebugTextHover extends AbstractDebugTextHover {
return null;
}
+ /**
+ * Returns whether the expression explorer information control should be used.
+ * The default implementation returns false
.
+ */
+ protected boolean useExpressionExplorer() {
+ return false;
+ }
+
+ @Override
+ public IInformationControlCreator getHoverControlCreator() {
+ if (useExpressionExplorer()) {
+ return new ExpressionInformationControlCreator();
+ } else {
+ return new IInformationControlCreator() {
+ public IInformationControl createInformationControl(Shell parent) {
+ return new DefaultInformationControl(parent, EditorsUI.getTooltipAffordanceString());
+ }
+ };
+ }
+ }
+
+ /*
+ * @see org.eclipse.jface.text.ITextHoverExtension2#getHoverInfo2(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion)
+ */
+ public Object getHoverInfo2(ITextViewer textViewer, IRegion hoverRegion) {
+ final String simpleInfo = getHoverInfo(textViewer, hoverRegion);
+ if (!useExpressionExplorer() || simpleInfo == null) {
+ return simpleInfo;
+ }
+ // improved version using ExpressionInformationControlCreator
+ // see also getHoverControlCreator()
+ final String text;
+ text= getExpressionText(textViewer, hoverRegion);
+ if (text != null && text.length() > 0) {
+ final IFrameDMContext frameDmc = getFrame();
+ final DsfSession dsfSession = DsfSession.getSession(frameDmc.getSessionId());
+ Callable callable = new Callable() {
+ public IExpressionDMContext call() throws Exception {
+ DsfServicesTracker tracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), frameDmc.getSessionId());
+ try {
+ IExpressions expressions = tracker.getService(IExpressions.class);
+ if (expressions != null) {
+ return expressions.createExpression(frameDmc, text);
+ }
+ return null;
+ } finally {
+ tracker.dispose();
+ }
+ }
+ };
+ try {
+ return dsfSession.getExecutor().submit(callable).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/IDsfDebugUIConstants.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/IDsfDebugUIConstants.java
index b77138a5b3f..de4ddfa2f56 100644
--- 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2008 Wind River Systems and others.
+ * Copyright (c) 2006, 2009 Wind River Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -79,4 +79,11 @@ public interface IDsfDebugUIConstants {
* @since 2.0
*/
public static final String PREF_COLOR_STALE_DATA_BACKGROUND= PLUGIN_ID + ".staledata.background"; //$NON-NLS-1$
+
+ /**
+ * Presentation context id for the expression hover.
+ *
+ * @since 2.1
+ */
+ public static final String ID_EXPRESSION_HOVER= PLUGIN_ID + ".expression_hover"; //$NON-NLS-1$
}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProvider.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProvider.java
index 1f419e7b4eb..935fca4f2a9 100644
--- a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProvider.java
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/ExpressionVMProvider.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2008 Wind River Systems and others.
+ * Copyright (c) 2006, 2009 Wind River Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -19,6 +19,7 @@ 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.IExpressions.IExpressionDMContext;
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;
@@ -46,6 +47,7 @@ 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.IViewerInputUpdate;
import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
@@ -210,8 +212,13 @@ public class ExpressionVMProvider extends AbstractDMVMProvider
/*
* Now the Over-arching management node.
*/
- ExpressionManagerVMNode expressionManagerNode = new ExpressionManagerVMNode(this);
- addChildNodes(rootNode, new IVMNode[] {expressionManagerNode});
+ if (IDsfDebugUIConstants.ID_EXPRESSION_HOVER.equals(getPresentationContext().getId())) {
+ SingleExpressionVMNode expressionManagerNode = new SingleExpressionVMNode(this);
+ addChildNodes(rootNode, new IVMNode[] { expressionManagerNode });
+ } else {
+ 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.
@@ -372,4 +379,20 @@ public class ExpressionVMProvider extends AbstractDMVMProvider
// Session disposed, ignore.
}
}
+
+ @Override
+ public void update(IViewerInputUpdate update) {
+ if (IDsfDebugUIConstants.ID_EXPRESSION_HOVER.equals(getPresentationContext().getId())) {
+ Object input = update.getElement();
+ if (input instanceof IExpressionDMContext) {
+ IExpressionDMContext dmc = (IExpressionDMContext) input;
+ SingleExpressionVMNode vmNode = (SingleExpressionVMNode) getChildVMNodes(getRootVMNode())[0];
+ vmNode.setExpression(dmc);
+ update.setInputElement(vmNode.createVMContext(dmc));
+ update.done();
+ return;
+ }
+ }
+ super.update(update);
+ }
}
diff --git a/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/SingleExpressionVMNode.java b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/SingleExpressionVMNode.java
new file mode 100644
index 00000000000..46e8744698b
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf.ui/src/org/eclipse/cdt/dsf/debug/ui/viewmodel/expression/SingleExpressionVMNode.java
@@ -0,0 +1,327 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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.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.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.ExpressionVMProvider;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.ExpressionsChangedEvent;
+import org.eclipse.cdt.dsf.debug.ui.viewmodel.expression.InvalidExpressionVMContext;
+import org.eclipse.cdt.dsf.ui.concurrent.ViewerCountingRequestMonitor;
+import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMContext;
+import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
+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.IDMVMContext;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.model.IDebugTarget;
+import org.eclipse.debug.core.model.IExpression;
+import org.eclipse.debug.core.model.IValue;
+import org.eclipse.debug.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.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.jface.viewers.TreePath;
+
+/**
+ * A VM node for displaying a single expression in the expression hover.
+ */
+public class SingleExpressionVMNode extends AbstractDMVMNode implements IElementLabelProvider {
+
+ private static class RootDMVMContext extends AbstractVMContext implements IDMVMContext {
+ private final IDMContext fDmc;
+ public RootDMVMContext(IVMNode node, IDMContext dmc) {
+ super(node);
+ fDmc = dmc;
+ }
+ public IDMContext getDMContext() {
+ return fDmc;
+ }
+ @SuppressWarnings("rawtypes")
+ @Override
+ 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(fDmc)) {
+ return fDmc;
+ } else {
+ return fDmc.getAdapter(adapter);
+ }
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof RootDMVMContext)) return false;
+ RootDMVMContext otherVmc = (RootDMVMContext)other;
+ return getVMNode().equals(otherVmc.getVMNode()) &&
+ fDmc.equals(otherVmc.fDmc);
+ }
+
+ @Override
+ public int hashCode() {
+ return getVMNode().hashCode() + fDmc.hashCode();
+ }
+
+ }
+
+ private static class SimpleExpression implements IExpression {
+ private String fExpressionText;
+ SimpleExpression(String text) {
+ fExpressionText = text;
+ }
+ public void dispose() {
+ }
+ public IDebugTarget getDebugTarget() {
+ return null;
+ }
+ public String getExpressionText() {
+ return fExpressionText;
+ }
+ public IValue getValue() {
+ return null;
+ }
+ public ILaunch getLaunch() {
+ return null;
+ }
+ public String getModelIdentifier() {
+ return null;
+ }
+ @SuppressWarnings("rawtypes")
+ public Object getAdapter(Class adapter) {
+ return null;
+ }
+
+ }
+
+ private static class SingleExpressionManager {
+ private static final IExpression[] NO_EXPRESSIONS = {};
+ IExpression fExpression;
+ public IExpression[] getExpressions() {
+ if (fExpression != null) {
+ return new IExpression[] { fExpression };
+ }
+ return NO_EXPRESSIONS;
+ }
+ public void setExpression(IExpression expression) {
+ fExpression = expression;
+ }
+
+ }
+
+ /** Local reference to the expression manager */
+ private final SingleExpressionManager fManager;
+
+ public SingleExpressionVMNode(ExpressionVMProvider provider) {
+ super(provider, provider.getSession(), IExpressionDMContext.class);
+ fManager = new SingleExpressionManager();
+ }
+
+ @Override
+ public String toString() {
+ return "SingleExpressionVMNode"; //$NON-NLS-1$
+ }
+
+ private ExpressionVMProvider getExpressionVMProvider() {
+ return (ExpressionVMProvider)getVMProvider();
+ }
+
+ @Override
+ 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();
+ }
+ }
+
+ @Override
+ 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);
+ update.done();
+ }
+ }
+
+ @Override
+ 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