diff options
author | John Cortell | 2010-05-13 19:43:47 +0000 |
---|---|---|
committer | John Cortell | 2010-05-13 19:43:47 +0000 |
commit | 5a1558ddd2630730da44eef58d5e69e2548e945a (patch) | |
tree | 6366c5616c7b6eee3a32ae2abafe85d523e952fc /memory | |
parent | 6a61597cf9b81dc6f17126bbbfcccc4f8ee9d3c1 (diff) | |
download | org.eclipse.cdt-5a1558ddd2630730da44eef58d5e69e2548e945a.tar.gz org.eclipse.cdt-5a1558ddd2630730da44eef58d5e69e2548e945a.tar.xz org.eclipse.cdt-5a1558ddd2630730da44eef58d5e69e2548e945a.zip |
Bug 309032: Need APIs to support memory pages (or memory spaces)
Diffstat (limited to 'memory')
4 files changed, 401 insertions, 191 deletions
diff --git a/memory/org.eclipse.cdt.debug.ui.memory.memorybrowser/META-INF/MANIFEST.MF b/memory/org.eclipse.cdt.debug.ui.memory.memorybrowser/META-INF/MANIFEST.MF index 4a4f0adff6a..e2a08fc607d 100644 --- a/memory/org.eclipse.cdt.debug.ui.memory.memorybrowser/META-INF/MANIFEST.MF +++ b/memory/org.eclipse.cdt.debug.ui.memory.memorybrowser/META-INF/MANIFEST.MF @@ -9,7 +9,9 @@ Bundle-Localization: plugin Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, org.eclipse.debug.core;bundle-version="3.5.0", - org.eclipse.debug.ui;bundle-version="3.5.0" + org.eclipse.debug.ui;bundle-version="3.5.0", + org.eclipse.cdt.debug.core;bundle-version="7.0.0", + org.eclipse.cdt.debug.ui;bundle-version="7.0.0" Bundle-RequiredExecutionEnvironment: J2SE-1.5 Bundle-ActivationPolicy: lazy Export-Package: org.eclipse.cdt.debug.ui.memory.memorybrowser diff --git a/memory/org.eclipse.cdt.debug.ui.memory.memorybrowser/src/org/eclipse/cdt/debug/ui/memory/memorybrowser/MemoryBrowser.java b/memory/org.eclipse.cdt.debug.ui.memory.memorybrowser/src/org/eclipse/cdt/debug/ui/memory/memorybrowser/MemoryBrowser.java index a1c6a996c3f..e106f7b64de 100644 --- a/memory/org.eclipse.cdt.debug.ui.memory.memorybrowser/src/org/eclipse/cdt/debug/ui/memory/memorybrowser/MemoryBrowser.java +++ b/memory/org.eclipse.cdt.debug.ui.memory.memorybrowser/src/org/eclipse/cdt/debug/ui/memory/memorybrowser/MemoryBrowser.java @@ -15,9 +15,14 @@ package org.eclipse.cdt.debug.ui.memory.memorybrowser; import java.lang.reflect.Type; import java.math.BigInteger; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; +import java.util.Map; +import org.eclipse.cdt.debug.core.model.provisional.IMemoryRenderingViewportProvider; +import org.eclipse.cdt.debug.core.model.provisional.IMemorySpaceAwareMemoryBlockRetrieval; +import org.eclipse.cdt.debug.internal.core.CRequest; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; @@ -62,6 +67,7 @@ import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.util.SafeRunnable; import org.eclipse.jface.viewers.IBasicPropertyConstants; +import org.eclipse.jface.viewers.ILabelDecorator; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; @@ -81,6 +87,7 @@ import org.eclipse.swt.graphics.Color; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; +import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; @@ -110,40 +117,77 @@ import org.eclipse.ui.progress.WorkbenchJob; @SuppressWarnings("restriction") public class MemoryBrowser extends ViewPart implements IDebugContextListener, IMemoryRenderingSite, IDebugEventSetListener { - public static final String ID = "org.eclipse.cdt.debug.ui.memory.memorybrowser.MemoryBrowser"; //$NON-NLS-1$ - protected StackLayout fStackLayout; private Composite fRenderingsComposite; - private HashMap<Object,CTabFolder> fContextFolders = new HashMap<Object,CTabFolder> (); private GoToAddressBarWidget fGotoAddressBar; private Control fGotoAddressBarControl; - - // revisit; see bug 307023 - // private Combo fGotoAddressSpaceControl; - + private Combo fGotoMemorySpaceControl; private Label fUnsupportedLabel; private Composite fMainComposite; private String defaultRenderingTypeId = null; + + /** + * Every memory retrieval object is given its own tab folder. Typically all + * elements of a "process" (process, threads, frames) have the same + * retrieval object. + */ + private Map<IMemoryBlockRetrieval,CTabFolder> fContextFolders = new HashMap<IMemoryBlockRetrieval,CTabFolder> (); - private ArrayList<IMemoryRenderingContainer> fCurrentContainers = new ArrayList<IMemoryRenderingContainer>(); + private List<IMemoryRenderingContainer> fCurrentContainers = new ArrayList<IMemoryRenderingContainer>(); - private final static String KEY_RENDERING = "RENDERING"; //$NON-NLS-1$ private final static String KEY_CONTEXT = "CONTEXT"; //$NON-NLS-1$ - private final static String KEY_MEMORY_BLOCK = "MEMORY"; //$NON-NLS-1$ - private final static String KEY_RETRIEVAL = "RETRIEVAL"; //$NON-NLS-1$ private final static String KEY_CONTAINER = "CONTAINER"; //$NON-NLS-1$ + private final static String KEY_RENDERING_TYPE = "RENDERING_TYPE"; //$NON-NLS-1$ + + /** + * Property we attach to a CTabItem to track the retrieval object we use to + * create memory blocks on the tab's behalf. Value is an + * {@link IMemoryBlockRetrieval} + */ + private final static String KEY_RETRIEVAL = "RETRIEVAL"; //$NON-NLS-1$ + + /** + * Property we attach to a CTabItem to track the memory space it's + * associated with. Value is a memory space ID (String), or null if n/a + */ + private final static String KEY_MEMORY_SPACE = "MEMORY_SPACE"; //$NON-NLS-1$ + + /** + * Property we attach to a CTabItem to track what renderings have been + * created on its behalf. There will be more than one rendering if the + * backend supports memory spaces, there is more than one such space, and + * the user has viewed memory in multiple memory spaces within that tab. + * The value is a map of memory-space-ID==>IMemoryRendering. + */ + private final static String KEY_RENDERINGS = "RENDERINGS"; //$NON-NLS-1$ + + /** + * Property we attach to a CTabItem to track the active rendering in the + * tab. The value is an IMemoryRendering. + */ + private final static String KEY_RENDERING = "RENDERING"; //$NON-NLS-1$ - // revisit; see bug 307023 - // private final static String KEY_ADDRESS_SPACE_PREFIXES = "ADDRESSSPACEPREFIXES"; //$NON-NLS-1$ + /** + * Property we attach to a CTabItem to track what memory blocks have been + * created on its behalf. There can be multiple when dealing with memory + * spaces, for the same reasons there can be multiple renderings. There is a + * 1:1:1 association between rendering, block and memory space. The value is + * a list of IMemoryBlockExtension + */ + private final static String KEY_MEMORY_BLOCKS = "MEMORY_BLOCKS"; //$NON-NLS-1$ - public static final String PREF_DEFAULT_RENDERING = "org.eclipse.cdt.debug.ui.memory.memorybrowser.defaultRendering"; //$NON-NLS-1$ + public static final String PREF_DEFAULT_RENDERING = "org.eclipse.cdt.debug.ui.memory.memorybrowser.defaultRendering"; //$NON-NLS-1$ + + /** + * The text we use in the combobox to represent no memory space specification + */ + private static final String NA_MEMORY_SPACE_ID = " -----"; public MemoryBrowser() { } - public Control getControl() - { + public Control getControl() { return fMainComposite; } @@ -180,9 +224,7 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM layout.spacing = 0; fMainComposite.setLayout(layout); - // revisit; see bug 307023 - //fGotoAddressSpaceControl = new Combo(fMainComposite, SWT.DROP_DOWN | SWT.READ_ONLY); - + fGotoMemorySpaceControl = new Combo(fMainComposite, SWT.DROP_DOWN | SWT.READ_ONLY); fGotoAddressBar = new GoToAddressBarWidget(); fGotoAddressBarControl = fGotoAddressBar.createControl(fMainComposite); @@ -210,9 +252,7 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM FormData data = new FormData(); data.top = new FormAttachment(0); - // revisit; see bug 307023 - //data.left = new FormAttachment(fGotoAddressSpaceControl); - data.left = new FormAttachment(0); + data.left = new FormAttachment(fGotoMemorySpaceControl); data.right = new FormAttachment(100); fGotoAddressBarControl.setLayoutData(data); @@ -300,7 +340,7 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM for (DebugEvent event: events) { Object source = event.getSource(); if (event.getKind() == DebugEvent.TERMINATE && source instanceof IMemoryBlockRetrieval) { - releaseTabFolder(source); + releaseTabFolder((IMemoryBlockRetrieval)source); } } } @@ -321,55 +361,67 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM return null; } - private void handleUnsupportedSelection() - { + private void handleUnsupportedSelection() { fStackLayout.topControl = fUnsupportedLabel; fGotoAddressBarControl.setVisible(false); - - // revisit; see bug 307023 - //fGotoAddressSpaceControl.setVisible(false); + fGotoMemorySpaceControl.setVisible(false); } - private void performGo(boolean inNewTab) - { - performGo(inNewTab, fGotoAddressBar.getExpressionText(), (short)0); + private void performGo(boolean inNewTab) { + // Index zero is the 'auto' (n/a) memory space entry + String memorySpace = null; + if (fGotoMemorySpaceControl.isVisible() && (fGotoMemorySpaceControl.getSelectionIndex() != 0)) { + memorySpace = fGotoMemorySpaceControl.getText(); + assert (memorySpace != null) && (memorySpace.length() > 0); + } + + String expression = fGotoAddressBar.getExpressionText(); + if (expression.length() > 0) { + performGo(inNewTab, fGotoAddressBar.getExpressionText(), memorySpace); + } } - public void performGo(boolean inNewTab, final String expression, short memoryPage) - { + public void performGo(boolean inNewTab, final String expression, final String memorySpaceId) { final CTabFolder activeFolder = (CTabFolder) fStackLayout.topControl; - if(activeFolder != null) - { + if (activeFolder != null) { final IMemoryBlockRetrieval retrieval = (IMemoryBlockRetrieval) activeFolder.getData(KEY_RETRIEVAL); final Object context = activeFolder.getData(KEY_CONTEXT); - if(inNewTab || activeFolder.getSelection() == null) - { - CTabItem item = createTab(activeFolder, activeFolder.getSelectionIndex() + 1); - populateTabWithRendering(item, retrieval, context); - setTabFolder(retrieval, activeFolder); + CTabItem item = activeFolder.getSelection(); + if (inNewTab || item == null) { + item = createTab(activeFolder, activeFolder.getSelectionIndex() + 1); + populateTabWithRendering(item, retrieval, context, memorySpaceId); + + fContextFolders.put(retrieval, activeFolder); activeFolder.setSelection(item); getSite().getSelectionProvider().setSelection(new StructuredSelection(item.getData(KEY_RENDERING))); } - final IRepositionableMemoryRendering rendering = (IRepositionableMemoryRendering) activeFolder.getSelection().getData(KEY_RENDERING); - final String gotoExpression = getAddressSpacePrefix() + expression; - - if(retrieval instanceof IMemoryBlockRetrievalExtension) - { - new Thread() - { - public void run() - { + IRepositionableMemoryRendering rendering = (IRepositionableMemoryRendering) activeFolder.getSelection().getData(KEY_RENDERING); + IMemoryRenderingContainer container = (IMemoryRenderingContainer)item.getData(KEY_CONTAINER); + String oldMemorySpaceId = (String)activeFolder.getSelection().getData(KEY_MEMORY_SPACE); + assert oldMemorySpaceId == null || !oldMemorySpaceId.equals(NA_MEMORY_SPACE_ID) : "should be null reference, not 'auto'"; + if ((oldMemorySpaceId != null && !oldMemorySpaceId.equals(memorySpaceId)) + || (oldMemorySpaceId == null && memorySpaceId != null)) { + updateTabWithRendering(item, retrieval, container, context, memorySpaceId); + activeFolder.setSelection(item); + getSite().getSelectionProvider().setSelection(new StructuredSelection(item.getData(KEY_RENDERING))); + rendering = (IRepositionableMemoryRendering) activeFolder.getSelection().getData(KEY_RENDERING); + } + final IRepositionableMemoryRendering renderingFinal = rendering; + if (retrieval instanceof IMemoryBlockRetrievalExtension) { + new Thread() { + public void run() { try { - BigInteger newBase = getExpressionAddress(retrieval, gotoExpression, context); - if(((IMemoryBlockExtension) rendering.getMemoryBlock()).supportBaseAddressModification()) - ((IMemoryBlockExtension) rendering.getMemoryBlock()).setBaseAddress(newBase); - rendering.goToAddress(newBase); + BigInteger newBase = getExpressionAddress(retrieval, expression, context, memorySpaceId); + IMemoryBlockExtension block = (IMemoryBlockExtension) renderingFinal.getMemoryBlock(); + if (block.supportBaseAddressModification()) { + block.setBaseAddress(newBase); + } + renderingFinal.goToAddress(newBase); runOnUIThread(new Runnable(){ - public void run() - { - updateLabel(activeFolder.getSelection(), rendering); + public void run() { + updateLabel(activeFolder.getSelection(), renderingFinal); } }); } catch (DebugException e1) { @@ -380,68 +432,59 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM } } } - - private String getAddressSpacePrefix() - { - // revisit; see bug 307023 -// if(fGotoAddressSpaceControl.isVisible()) -// { -// String prefixes[] = (String[]) fGotoAddressSpaceControl.getData(KEY_ADDRESS_SPACE_PREFIXES); -// if(prefixes != null && prefixes.length > 0) -// { -// return prefixes[fGotoAddressSpaceControl.getSelectionIndex()]; -// } -// } - return ""; - } - -// MemoryBrowser.FailedToGoToAddressTitle=Unable to Go To specified address -// MemoryBrowser.UnableToEvaluateAddress - private void updateLabel(CTabItem tab, IMemoryRendering rendering) - { - String label = null; - - // This is a hack and needs to be revisited. -// -// // would like to avoid using reflection -// try { -// Method m = rendering.getControl().getClass().getMethod("getViewportStartAddress", new Class[0]); //$NON-NLS-1$ -// if(m != null) -// label = "0x" + ((BigInteger) m.invoke(rendering.getControl(), new Object[0])).toString(16).toUpperCase(); //$NON-NLS-1$ -// } -// catch (Exception e) -// { -// } + private void updateLabel(CTabItem tab, IMemoryRendering rendering) { + // The default is to use the label provided by the base rendering + // interface. + String label = rendering.getLabel(); - if(label == null) - label = rendering.getLabel(); + // We create all memory blocks using address 0 regardless of where the + // user wants to see memory. We then go-to the requested location. So, + // if we rely on the default rendering label, all tabs will show + // address zero, which will be confusing. To avoid this, the rendering + // object should implement this interface that allows us to get to the + // first address being shown. We'll use that for the label + if (rendering instanceof IMemoryRenderingViewportProvider) { + BigInteger viewportAddress = ((IMemoryRenderingViewportProvider)rendering).getViewportAddress(); + + // The base label generation puts the rendering type name in "<>" and + // appends it to the label. Fish that out + String renderingType = null; + int i = label.indexOf('<'); + if (i >= 0) { + renderingType = label.substring(i); + } + + label = null; + + // If a memory space is involved, we want to include its ID in the label + String memorySpaceID = (String)tab.getData(KEY_MEMORY_SPACE); + if (memorySpaceID != null) { + IMemoryBlockRetrieval retrieval = (IMemoryBlockRetrieval) tab.getParent().getData(KEY_RETRIEVAL); + if (retrieval instanceof IMemorySpaceAwareMemoryBlockRetrieval) { + label = ((IMemorySpaceAwareMemoryBlockRetrieval)retrieval).encodeAddress("0x" + viewportAddress.toString(16), memorySpaceID); + } + } + if (label == null) { + label = "0x" + viewportAddress.toString(16) + ' ' + renderingType; + } + + // Allow the memory block to customize the label. The platform's + // Memory view support this (it was done in the call to + // rendering.getLabel() above) + IMemoryBlock block = rendering.getMemoryBlock(); + ILabelDecorator labelDec = (ILabelDecorator)block.getAdapter(ILabelDecorator.class); + if (labelDec != null) { + String newLabel = labelDec.decorateText(label, rendering); + if (newLabel != null) { + label = newLabel; + } + } + } tab.setText(label); } - /** - * fetch memory spaces for a given IMemoryBlockRetrieval - * @param retrieval memory block retrieval. - * @return two arrays, the first containing memory space mnemonics, the second containing associated expression prefixes - */ - // revisit; see bug 307023 -// private String[][] getAddressSpaces(IMemoryBlockRetrieval retrieval) -// { -// // would like to avoid using reflection, but necessary interface additions should live in platform to avoid introducing dependencies. -// -// String[][] addressSpaceTitles = new String[0][0]; -// try { -// Method m = retrieval.getClass().getMethod("getAddressSpaces", new Class[0]); //$NON-NLS-1$ -// if(m != null) -// addressSpaceTitles = (String[][]) m.invoke(retrieval, new Object[0]); -// } -// catch (Exception e) -// { -// } -// return addressSpaceTitles; -// } - private CTabFolder createTabFolder(Composite parent) { final CTabFolder folder = new CTabFolder(parent, SWT.NO_REDRAW_RESIZE | SWT.NO_TRIM | SWT.FLAT); @@ -475,6 +518,19 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM return folder; } + // these utility methods allow us restrict the scope of the unavoidable @SuppressWarnings + + @SuppressWarnings("unchecked") + private static Map<String, IMemoryRendering> getRenderings(CTabItem tabItem) { + return (Map<String, IMemoryRendering>)tabItem.getData(KEY_RENDERINGS); + } + + @SuppressWarnings("unchecked") + private static List<IMemoryBlockExtension> getMemoryBlocks(CTabItem tabItem) { + return (List<IMemoryBlockExtension>)tabItem.getData(KEY_MEMORY_BLOCKS); + } + + /** * dispose rendering resources associated with the tab item * @param item @@ -485,24 +541,31 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM IMemoryRenderingContainer container = (IMemoryRenderingContainer) item.getData(KEY_CONTAINER); fCurrentContainers.remove( container ); - IMemoryRendering rendering = (IMemoryRendering) item.getData(KEY_RENDERING); - // always deactivate rendering before disposing it. - if ( rendering != null ) { + Map<String, IMemoryRendering> map = getRenderings(item); + Collection<IMemoryRendering> renderings = map.values(); + for (IMemoryRendering rendering : renderings) { + // always deactivate rendering before disposing it. rendering.deactivated(); rendering.dispose(); } - IMemoryBlockExtension block = (IMemoryBlockExtension) item.getData(KEY_MEMORY_BLOCK); - try { - if (block != null) + map.clear(); + + List<IMemoryBlockExtension> blocks = getMemoryBlocks(item); + for (IMemoryBlockExtension block : blocks) { + try { block.dispose(); - } catch (DebugException e) { - MemoryBrowserPlugin.getDefault().getLog().log(new Status(Status.ERROR, MemoryBrowserPlugin.PLUGIN_ID, "Could not dispose memory block", e)); //$NON-NLS-1$ - } + } catch (DebugException e) { + MemoryBrowserPlugin.getDefault().getLog().log(new Status(Status.ERROR, MemoryBrowserPlugin.PLUGIN_ID, "Could not dispose memory block", e)); //$NON-NLS-1$ + } + } + blocks.clear(); } private CTabItem createTab(CTabFolder tabFolder, int index) { int swtStyle = SWT.CLOSE; CTabItem tab = new CTabItem(tabFolder, swtStyle, index); + tab.setData(KEY_RENDERINGS, new HashMap<String, IMemoryRendering>()); + tab.setData(KEY_MEMORY_BLOCKS, new ArrayList<IMemoryBlock>()); return tab; } @@ -544,7 +607,6 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM } manager.add(sub); - manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); } @@ -601,44 +663,83 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM public void debugContextChanged(DebugContextEvent event) { handleDebugContextChanged(((StructuredSelection) event.getContext()).getFirstElement()); } + + private class GetMemorySpacesRequest extends CRequest implements IMemorySpaceAwareMemoryBlockRetrieval.GetMemorySpacesRequest { + String [] fMemorySpaces; + public String[] getMemorySpaces() { + return fMemorySpaces; + } + public void setMemorySpaces(String[] memorySpaceIds) { + fMemorySpaces = memorySpaceIds; + } + } - public void handleDebugContextChanged(Object context) { + public void handleDebugContextChanged(final Object context) { if(defaultRenderingTypeId == null) return; if(context instanceof IAdaptable) { IAdaptable adaptable = (IAdaptable) context; - IMemoryBlockRetrieval retrieval = ((IMemoryBlockRetrieval) adaptable.getAdapter(IMemoryBlockRetrieval.class)); + final IMemoryBlockRetrieval retrieval = ((IMemoryBlockRetrieval) adaptable.getAdapter(IMemoryBlockRetrieval.class)); ILaunch launch = ((ILaunch) adaptable.getAdapter(ILaunch.class)); - if(retrieval != null && launch != null && !launch.isTerminated()) - { - fGotoAddressBarControl.setVisible(true); + if(retrieval != null && launch != null && !launch.isTerminated()) { + if (retrieval instanceof IMemorySpaceAwareMemoryBlockRetrieval) { + ((IMemorySpaceAwareMemoryBlockRetrieval)retrieval).getMemorySpaces(context, new GetMemorySpacesRequest(){ + public void done() { + updateTab(retrieval, context, isSuccess() ? getMemorySpaces() : new String[0]); + } + }); + } + else { + updateTab(retrieval, context, new String[0]); + } + } + else { + handleUnsupportedSelection(); + } + + fGotoMemorySpaceControl.pack(true); + fStackLayout.topControl.getParent().layout(true); + } + } - // revisit; see bug 307023 -// String addressSpaces[][] = getAddressSpaces(retrieval); -// if(addressSpaces.length > 0) -// { -// fGotoAddressSpaceControl.setVisible(true); -// fGotoAddressSpaceControl.setItems(addressSpaces[0]); -// fGotoAddressSpaceControl.setData(KEY_ADDRESS_SPACE_PREFIXES, addressSpaces[1]); -// } -// else -// fGotoAddressSpaceControl.setVisible(false); - - CTabFolder tabFolder = getTabFolder(retrieval); - if(tabFolder != null) - { + /** + * Called to update the tab once the asynchronous query for memory spaces + * has returned a result. + * + * @param retrieval + * the retrieval object associated with the newly active debug + * context + * @param context + * the newly active context + * @param memorySpaces + * the memory spaces, if applicable. Otherwise an empty array. + */ + private void updateTab(final IMemoryBlockRetrieval retrieval, final Object context, final String[] memorySpaces) { + // GUI activity must be on the main thread + runOnUIThread(new Runnable(){ + public void run() { + if (fGotoAddressBarControl.isDisposed()) { + return; + } + + fGotoAddressBarControl.setVisible(true); + + // If we've already created a tab folder for this retrieval + // object, bring it to the forefront. Otherwise create the + // folder. + CTabFolder tabFolder = fContextFolders.get(retrieval); + if(tabFolder != null) { fStackLayout.topControl = tabFolder; } - else - { - tabFolder = this.createTabFolder(fRenderingsComposite); - tabFolder.addSelectionListener(new SelectionListener() - { + else { + tabFolder = createTabFolder(fRenderingsComposite); + tabFolder.addSelectionListener(new SelectionListener() { public void widgetDefaultSelected(SelectionEvent e) {} public void widgetSelected(SelectionEvent e) { + updateMemorySpaceControlSelection((CTabItem)e.item); getSite().getSelectionProvider().setSelection(new StructuredSelection(((CTabItem) e.item).getData(KEY_RENDERING))); } }); @@ -646,24 +747,76 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM tabFolder.setData(KEY_RETRIEVAL, retrieval); CTabItem item = createTab(tabFolder, 0); - populateTabWithRendering(item, retrieval, context); - setTabFolder(retrieval, tabFolder); - - fStackLayout.topControl = getTabFolder(retrieval); + populateTabWithRendering(item, retrieval, context, null); + fContextFolders.put(retrieval, tabFolder); + fStackLayout.topControl = tabFolder; } // update debug context to the new selection tabFolder.setData(KEY_CONTEXT, context); + + + final CTabFolder activeFolder = tabFolder; + if (!activeFolder.equals(tabFolder)) { + return; + } + + CTabItem tabItem = activeFolder.getSelection(); + if (tabItem != null) { + if(memorySpaces.length > 0) { + fGotoMemorySpaceControl.setVisible(true); + fGotoMemorySpaceControl.setItems(memorySpaces); + + // the n/a entry; don't think this needs to be translated + fGotoMemorySpaceControl.add(NA_MEMORY_SPACE_ID, 0); //$NON-NLS-1$ + } + else { + fGotoMemorySpaceControl.setVisible(false); + fGotoMemorySpaceControl.setItems(new String[0]); + } + + updateMemorySpaceControlSelection(tabItem); + } + fStackLayout.topControl.getParent().layout(true); } - else - { - handleUnsupportedSelection(); - } + }); + } - // revisit; see bug 307023 - //fGotoAddressSpaceControl.pack(true); - - fStackLayout.topControl.getParent().layout(true); + /** + * Update the selection in the memory space combobox to reflect the memory + * space being shown in the given tab + * + * @param item + * the active tab + */ + private void updateMemorySpaceControlSelection(CTabItem item) { + String[] memorySpaces = fGotoMemorySpaceControl.getItems(); + if (memorySpaces.length > 0 ) { + // Don't assume that the memory space previously set in the tab + // is one of the ones now available. If it isn't, then select + // the first available one and update the tab data + boolean foundIt = false; + String currentMemorySpace = (String) item.getData(KEY_MEMORY_SPACE); + if (currentMemorySpace != null) { + assert currentMemorySpace.length() > 0; + for (String memorySpace : memorySpaces) { + if (memorySpace.equals(currentMemorySpace)) { + foundIt = true; + fGotoMemorySpaceControl.setText(currentMemorySpace); + break; + } + } + } + if (!foundIt) { + fGotoMemorySpaceControl.select(0); + item.setData(KEY_MEMORY_SPACE, null); + } + fGotoMemorySpaceControl.setVisible(true); + } + else { + fGotoMemorySpaceControl.setVisible(false); } + fGotoMemorySpaceControl.getParent().layout(true); + } private String getDefaultRenderingTypeId() @@ -678,14 +831,12 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM store.setValue(PREF_DEFAULT_RENDERING, defaultRenderingTypeId); } - private void populateTabWithRendering(final CTabItem tab, final IMemoryBlockRetrieval retrieval, Object context) - { + private void populateTabWithRendering(final CTabItem tab, final IMemoryBlockRetrieval retrieval, Object context, String memorySpaceId) { IMemoryRenderingType type = DebugUITools.getMemoryRenderingManager().getRenderingType(getDefaultRenderingTypeId()); try { final IMemoryRendering rendering = type.createRendering(); - IMemoryRenderingContainer container = new IMemoryRenderingContainer() - { + IMemoryRenderingContainer container = new IMemoryRenderingContainer() { public void addMemoryRendering(IMemoryRendering rendering) {} public IMemoryRendering getActiveRendering() { @@ -712,16 +863,19 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM }; - IMemoryBlock block = createMemoryBlock(retrieval, "0", context); //$NON-NLS-1$ + IMemoryBlockExtension block = createMemoryBlock(retrieval, "0", context, memorySpaceId); //$NON-NLS-1$ fCurrentContainers.add(container); rendering.init(container, block); rendering.createControl(tab.getParent()); tab.setControl(rendering.getControl()); tab.getParent().setSelection(0); + getRenderings(tab).put(memorySpaceId, rendering); tab.setData(KEY_RENDERING, rendering); + tab.setData(KEY_MEMORY_SPACE, memorySpaceId); tab.setData(KEY_CONTAINER, container); - tab.setData(KEY_MEMORY_BLOCK, block); + getMemoryBlocks(tab).add(block); + tab.setData(KEY_RENDERING_TYPE, type); getSite().getSelectionProvider().setSelection(new StructuredSelection(tab.getData(KEY_RENDERING))); updateLabel(tab, rendering); @@ -748,19 +902,60 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM } } - private CTabFolder getTabFolder(Object context) - { - return fContextFolders.get(context); + private void updateTabWithRendering(final CTabItem tab, final IMemoryBlockRetrieval retrieval, IMemoryRenderingContainer container, Object context, String memorySpaceId) { + IMemoryRenderingType type = (IMemoryRenderingType)tab.getData(KEY_RENDERING_TYPE); + if (type == null) { + type = DebugUITools.getMemoryRenderingManager().getRenderingType(getDefaultRenderingTypeId()); + } + try { + Map<String, IMemoryRendering> renderings = getRenderings(tab); + + // Note: memorySpaceId can be null. In that case, there will just be + // one rendering in the tab + IMemoryRendering rendering = renderings.get(memorySpaceId); + if (rendering == null) { + // No rendering yet. Create one. + final IMemoryRendering newRendering = type.createRendering(); + IMemoryBlockExtension block = createMemoryBlock(retrieval, "0", context, memorySpaceId); //$NON-NLS-1$ + newRendering.init(container, block); + getMemoryBlocks(tab).add(block); + renderings.put(memorySpaceId, newRendering); + newRendering.createControl(tab.getParent()); + newRendering.addPropertyChangeListener(new IPropertyChangeListener() { + public void propertyChange(final PropertyChangeEvent event) { + WorkbenchJob job = new WorkbenchJob("MemoryBrowser PropertyChanged") { //$NON-NLS-1$ + public IStatus runInUIThread(IProgressMonitor monitor) { + if(tab.isDisposed()) + return Status.OK_STATUS; + + if (event.getProperty().equals(IBasicPropertyConstants.P_TEXT)) + updateLabel(tab, newRendering); + return Status.OK_STATUS; + } + }; + job.setSystem(true); + job.schedule(); + } + }); + rendering = newRendering; + } + tab.setControl(rendering.getControl()); + tab.getParent().setSelection(0); + tab.setData(KEY_RENDERING, rendering); + tab.setData(KEY_MEMORY_SPACE, memorySpaceId); + tab.setData(KEY_CONTAINER, container); + tab.setData(KEY_RENDERING_TYPE, type); + getSite().getSelectionProvider().setSelection(new StructuredSelection(tab.getData(KEY_RENDERING))); + updateLabel(tab, rendering); + fStackLayout.topControl.getParent().layout(true); + } catch (CoreException e) { + MemoryBrowserPlugin.getDefault().getLog().log(new Status(Status.ERROR, MemoryBrowserPlugin.PLUGIN_ID, "", e)); //$NON-NLS-1$ + } } - - private CTabFolder setTabFolder(Object context, CTabFolder folder) - { - return fContextFolders.put(context, folder); - } - - private void releaseTabFolder(final Object context) + + private void releaseTabFolder(final IMemoryBlockRetrieval retrieval) { - final CTabFolder folder = getTabFolder(context); + final CTabFolder folder = fContextFolders.get(retrieval); if(folder != null) { Runnable run = new Runnable() { @@ -768,7 +963,7 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM for(CTabItem tab : folder.getItems()) { disposeTab(tab); } - fContextFolders.remove(context); + fContextFolders.remove(retrieval); folder.dispose(); if (fStackLayout.topControl.equals(folder)) { @@ -821,17 +1016,22 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM * @param expression expression to be evaluated to an addressL * @param context context for evaluating the expression. This is typically * a debug element. + * @param memorySpaceID a memory space identifier, or null if n/a * @return a memory block based on the given expression and context * @throws DebugException if unable to retrieve the specified memory */ - private IMemoryBlockExtension createMemoryBlock(IMemoryBlockRetrieval retrieval, String expression, Object context) throws DebugException { + private IMemoryBlockExtension createMemoryBlock(IMemoryBlockRetrieval retrieval, String expression, Object context, String memorySpaceID) throws DebugException { IMemoryBlockExtension block = null; - if(retrieval instanceof IAdaptable) - { - IMemoryBlockRetrievalExtension retrievalExtension = (IMemoryBlockRetrievalExtension) - ((IAdaptable) retrieval).getAdapter(IMemoryBlockRetrievalExtension.class); - if(retrievalExtension != null) - block = retrievalExtension.getExtendedMemoryBlock(expression, context); //$NON-NLS-1$ + if(retrieval instanceof IAdaptable) { + IMemoryBlockRetrievalExtension retrievalExtension = (IMemoryBlockRetrievalExtension)((IAdaptable) retrieval).getAdapter(IMemoryBlockRetrievalExtension.class); + if (retrievalExtension != null) { + if (retrievalExtension instanceof IMemorySpaceAwareMemoryBlockRetrieval) { + block = ((IMemorySpaceAwareMemoryBlockRetrieval)retrievalExtension).getMemoryBlock(expression, context, memorySpaceID); + } + else { + block = retrievalExtension.getExtendedMemoryBlock(expression, context); + } + } } if ( block == null ) { throw new DebugException(new Status(Status.ERROR, MemoryBrowserPlugin.PLUGIN_ID, "Extended Memory Block could not be obtained")); //$NON-NLS-1$ @@ -847,9 +1047,9 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM * @return BigInteger address of the expression * @throws DebugException */ - private BigInteger getExpressionAddress(IMemoryBlockRetrieval retrieval, String expression, Object context) throws DebugException { + private BigInteger getExpressionAddress(IMemoryBlockRetrieval retrieval, String expression, Object context, String memorySpaceId) throws DebugException { // Until 257842 issue is solved this is done via IMemoryBlockRetrievalExtension API. - IMemoryBlockExtension newBlock = createMemoryBlock(retrieval, expression, context); + IMemoryBlockExtension newBlock = createMemoryBlock(retrieval, expression, context, memorySpaceId); BigInteger address = newBlock.getBigBaseAddress(); newBlock.dispose(); return address; @@ -862,9 +1062,8 @@ public class MemoryBrowser extends ViewPart implements IDebugContextListener, IM * @param runnable * the runnable to execute */ - private void runOnUIThread(final Runnable runnable) - { - if (Display.getCurrent() != null) { + private void runOnUIThread(final Runnable runnable) { + if (Display.getCurrent() != null) { runnable.run(); } else { diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/META-INF/MANIFEST.MF b/memory/org.eclipse.cdt.debug.ui.memory.traditional/META-INF/MANIFEST.MF index afe55dce916..9de58377e45 100644 --- a/memory/org.eclipse.cdt.debug.ui.memory.traditional/META-INF/MANIFEST.MF +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/META-INF/MANIFEST.MF @@ -10,7 +10,8 @@ Require-Bundle: org.eclipse.debug.core, org.eclipse.swt, org.eclipse.jface, org.eclipse.ui, - org.eclipse.search;bundle-version="3.4.0" + org.eclipse.search;bundle-version="3.4.0", + org.eclipse.cdt.debug.core;bundle-version="7.0.0" Bundle-ActivationPolicy: lazy Bundle-Activator: org.eclipse.cdt.debug.ui.memory.traditional.TraditionalRenderingPlugin Bundle-Vendor: %providerName diff --git a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRendering.java b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRendering.java index 8b78eca15af..1fa1a2e1eab 100644 --- a/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRendering.java +++ b/memory/org.eclipse.cdt.debug.ui.memory.traditional/src/org/eclipse/cdt/debug/ui/memory/traditional/TraditionalRendering.java @@ -14,6 +14,7 @@ package org.eclipse.cdt.debug.ui.memory.traditional; import java.lang.reflect.Method; import java.math.BigInteger; +import org.eclipse.cdt.debug.core.model.provisional.IMemoryRenderingViewportProvider; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.Command; import org.eclipse.core.commands.ExecutionEvent; @@ -83,7 +84,7 @@ import org.eclipse.ui.progress.UIJob; */ @SuppressWarnings("restriction") -public class TraditionalRendering extends AbstractMemoryRendering implements IRepositionableMemoryRendering, IResettableMemoryRendering +public class TraditionalRendering extends AbstractMemoryRendering implements IRepositionableMemoryRendering, IResettableMemoryRendering, IMemoryRenderingViewportProvider { protected Rendering fRendering; protected Action displayEndianBigAction; @@ -1264,6 +1265,13 @@ public class TraditionalRendering extends AbstractMemoryRendering implements IRe public void resetRendering() throws DebugException { fRendering.gotoAddress(fRendering.fBaseAddress); } + + /* (non-Javadoc) + * @see org.eclipse.cdt.debug.internal.core.model.provisional.IMemoryRenderingViewportProvider#getViewportAddress() + */ + public BigInteger getViewportAddress() { + return fRendering.getViewportStartAddress(); + } } class CopyAction extends Action |