/******************************************************************************* * Copyright (c) 2004, 2017 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 * WindRiver - Bug 192028 [Memory View] Memory view does not * display memory blocks that do not reference IDebugTarget * *******************************************************************************/ package org.eclipse.debug.internal.ui.views.memory; import java.util.ArrayList; 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.debug.core.DebugEvent; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.IDebugEventSetListener; import org.eclipse.debug.core.IMemoryBlockListener; import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.core.model.IMemoryBlock; import org.eclipse.debug.core.model.IMemoryBlockRetrieval; import org.eclipse.debug.internal.ui.DebugPluginImages; import org.eclipse.debug.internal.ui.DebugUIMessages; import org.eclipse.debug.internal.ui.DebugUIPlugin; import org.eclipse.debug.internal.ui.IInternalDebugUIConstants; import org.eclipse.debug.internal.ui.memory.provisional.MemoryViewPresentationContext; import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.debug.ui.contexts.DebugContextEvent; import org.eclipse.debug.ui.contexts.IDebugContextListener; import org.eclipse.debug.ui.memory.IMemoryRendering; import org.eclipse.debug.ui.memory.IMemoryRenderingContainer; import org.eclipse.debug.ui.memory.IMemoryRenderingSite; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; 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.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredViewer; import org.eclipse.swt.SWT; 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.ISelectionListener; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.progress.UIJob; /** * Tree viewer for memory blocks */ public class MemoryBlocksTreeViewPane implements ISelectionListener, ISelectionChangedListener, IMemoryViewPane, IMemoryRenderingContainer { public static final String PANE_ID = DebugUIPlugin.getUniqueIdentifier() + ".MemoryView.MemoryBlocksTreeViewPane"; //$NON-NLS-1$ private IViewPart fParent; private IPresentationContext fPresentationContext; private MemoryViewTreeViewer fTreeViewer; protected IMemoryBlockRetrieval fRetrieval; private ViewPaneSelectionProvider fSelectionProvider; private AddMemoryBlockAction fAddMemoryBlockAction; private IAction fRemoveMemoryBlockAction; private IAction fRemoveAllMemoryBlocksAction; private String fPaneId; private boolean fVisible = true; private TreeViewPaneContextListener fDebugContextListener; private ViewPaneEventHandler fEvtHandler; private String fLabel; class TreeViewerRemoveMemoryBlocksAction extends Action { TreeViewerRemoveMemoryBlocksAction() { super(); setText(DebugUIMessages.RemoveMemoryBlockAction_title); setToolTipText(DebugUIMessages.RemoveMemoryBlockAction_tooltip); setImageDescriptor(DebugPluginImages.getImageDescriptor(IInternalDebugUIConstants.IMG_ELCL_REMOVE_MEMORY)); setHoverImageDescriptor(DebugPluginImages.getImageDescriptor(IInternalDebugUIConstants.IMG_LCL_REMOVE_MEMORY)); setDisabledImageDescriptor(DebugPluginImages.getImageDescriptor(IInternalDebugUIConstants.IMG_DLCL_REMOVE_MEMORY)); PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IDebugUIConstants.PLUGIN_ID + ".RemoveMemoryBlockAction_context"); //$NON-NLS-1$ setEnabled(true); } /* * (non-Javadoc) * @see org.eclipse.jface.action.IAction#run() */ @Override public void run() { ISelection selected = fTreeViewer.getSelection(); if (selected != null && selected instanceof IStructuredSelection) { Object[] selectedMemBlks = ((IStructuredSelection) selected).toArray(); ArrayList<Object> memoryBlocks = new ArrayList<Object>(); for (int i = 0; i < selectedMemBlks.length; i++) { if (selectedMemBlks[i] instanceof IMemoryBlock) { memoryBlocks.add(selectedMemBlks[i]); } } DebugPlugin.getDefault().getMemoryBlockManager().removeMemoryBlocks(memoryBlocks.toArray(new IMemoryBlock[memoryBlocks.size()])); } } } class TreeViewerRemoveAllMemoryBlocksAction extends Action { TreeViewerRemoveAllMemoryBlocksAction() { super(); setText(DebugUIMessages.MemoryBlocksTreeViewPane_2); setToolTipText(DebugUIMessages.MemoryBlocksTreeViewPane_2); setImageDescriptor(DebugPluginImages.getImageDescriptor(IInternalDebugUIConstants.IMG_ELCL_REMOVE_ALL)); setHoverImageDescriptor(DebugPluginImages.getImageDescriptor(IInternalDebugUIConstants.IMG_ELCL_REMOVE_ALL)); setDisabledImageDescriptor(DebugPluginImages.getImageDescriptor(IInternalDebugUIConstants.IMG_DLCL_REMOVE_ALL)); PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IDebugUIConstants.PLUGIN_ID + ".RemoveAllMemoryBlocksAction_context"); //$NON-NLS-1$ } /* * (non-Javadoc) * @see org.eclipse.jface.action.IAction#run() */ @Override public void run() { IWorkbenchWindow window = DebugUIPlugin.getActiveWorkbenchWindow(); if (window == null) { return; } boolean proceed = MessageDialog.openQuestion(window.getShell(), DebugUIMessages.MemoryBlocksTreeViewPane_0, DebugUIMessages.MemoryBlocksTreeViewPane_1); // if (proceed) { IMemoryBlock[] memoryBlocks = DebugPlugin.getDefault().getMemoryBlockManager().getMemoryBlocks(fRetrieval); DebugPlugin.getDefault().getMemoryBlockManager().removeMemoryBlocks(memoryBlocks); } } } class ViewPaneEventHandler implements IMemoryBlockListener, IDebugEventSetListener { private boolean fDisposed = false; public ViewPaneEventHandler() { DebugPlugin.getDefault().getMemoryBlockManager().addListener(this); DebugPlugin.getDefault().addDebugEventListener(this); } /* * (non-Javadoc) * @see org.eclipse.jface.viewers.IContentProvider#dispose() */ public void dispose() { fDisposed = true; DebugPlugin.getDefault().getMemoryBlockManager().removeListener(this); DebugPlugin.getDefault().removeDebugEventListener(this); } /* * (non-Javadoc) * @see org.eclipse.debug.internal.core.memory.IMemoryBlockListener# * MemoryBlockAdded(org.eclipse.debug.core.model.IMemoryBlock) */ @Override public void memoryBlocksAdded(final IMemoryBlock[] memory) { // if the content provider is disposed, do not handle event if (fDisposed) { return; } updateActionsEnablement(); } /* * (non-Javadoc) * @see org.eclipse.debug.internal.core.memory.IMemoryBlockListener# * MemoryBlockRemoved(org.eclipse.debug.core.model.IMemoryBlock) */ @Override public void memoryBlocksRemoved(final IMemoryBlock[] memory) { if (fDisposed) { return; } updateActionsEnablement(); } /* * (non-Javadoc) * @see * org.eclipse.debug.internal.ui.views.memory.BasicDebugViewContentProvider * #doHandleDebugEvent(org.eclipse.debug.core.DebugEvent) */ protected void doHandleDebugEvent(DebugEvent event) { // if the view is disposed, do not handle event if (fDisposed) { return; } if (event.getKind() == DebugEvent.TERMINATE) { // should only handle the terminate event if the target is // terminated if (event.getSource() instanceof IDebugTarget) { IMemoryBlockRetrieval srcRetrieval = MemoryViewUtil.getMemoryBlockRetrieval(event.getSource()); if (srcRetrieval == fRetrieval) { // #setInput must be done on the UI thread UIJob job = new UIJob("setInput") { //$NON-NLS-1$ @Override public IStatus runInUIThread(IProgressMonitor monitor) { // if viewpane is disposed, do not handle event if (fTreeViewer.getContentProvider() == null) { return Status.OK_STATUS; } fTreeViewer.setInput(null); return Status.OK_STATUS; } }; job.setSystem(true); job.schedule(); } } } } @Override public void handleDebugEvents(DebugEvent[] events) { for (int i = 0; i < events.length; i++) { doHandleDebugEvent(events[i]); } } } class TreeViewPaneContextListener implements IDebugContextListener { public void contextActivated(ISelection selection) { if (selection.isEmpty() && fRetrieval != null) { fRetrieval = null; if (fTreeViewer != null && fTreeViewer.getContentProvider() != null) { fTreeViewer.setInput(fRetrieval); } updateActionsEnablement(); return; } if (selection instanceof IStructuredSelection) { Object obj = ((IStructuredSelection) selection).getFirstElement(); if (obj instanceof IAdaptable) { IAdaptable context = (IAdaptable) obj; IMemoryBlockRetrieval retrieval = MemoryViewUtil.getMemoryBlockRetrieval(context); if (retrieval != null && fTreeViewer != null && (retrieval != fRetrieval || retrieval != fTreeViewer.getInput()) && fTreeViewer.getContentProvider() != null) { // set new setting fRetrieval = retrieval; fTreeViewer.setInput(fRetrieval); } updateActionsEnablement(); } } } /* * (non-Javadoc) * @see * org.eclipse.debug.internal.ui.contexts.provisional.IDebugContextListener * #contextEvent(org.eclipse.debug.internal.ui.contexts.provisional. * DebugContextEvent) */ @Override public void debugContextChanged(DebugContextEvent event) { if ((event.getFlags() & DebugContextEvent.ACTIVATED) > 0) { contextActivated(event.getContext()); } } } public MemoryBlocksTreeViewPane(IViewPart parent) { fParent = parent; fSelectionProvider = new ViewPaneSelectionProvider(); } @Override public Control createViewPane(Composite parent, String paneId, String label) { fPaneId = paneId; int style = SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.VIRTUAL; fLabel = label; IMemoryRenderingSite site = getMemoryRenderingSite(); fPresentationContext = new MemoryViewPresentationContext(site, this, null); fTreeViewer = new MemoryViewTreeViewer(parent, style, fPresentationContext); IAdaptable context = DebugUITools.getPartDebugContext(fParent.getSite()); IMemoryBlockRetrieval retrieval = MemoryViewUtil.getMemoryBlockRetrieval(context); if (retrieval != null) { fTreeViewer.setInput(retrieval); } fRetrieval = retrieval; fParent.getViewSite().getSelectionProvider().addSelectionChangedListener(this); fParent.getViewSite().getPage().addSelectionListener(this); fDebugContextListener = new TreeViewPaneContextListener(); DebugUITools.addPartDebugContextListener(fParent.getSite(), fDebugContextListener); fTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { ISelection treeSelected = event.getSelection(); fSelectionProvider.setSelection(treeSelected); } }); updateRetrieval(); fEvtHandler = new ViewPaneEventHandler(); // create context menu MenuManager mgr = createContextMenuManager(); Menu menu = mgr.createContextMenu(fTreeViewer.getControl()); fTreeViewer.getControl().setMenu(menu); GridData data = new GridData(); data.grabExcessHorizontalSpace = true; data.grabExcessVerticalSpace = true; data.horizontalAlignment = SWT.FILL; data.verticalAlignment = SWT.FILL; fTreeViewer.getControl().setLayoutData(data); updateActionsEnablement(); return fTreeViewer.getControl(); } /** * */ private void updateRetrieval() { Object context = DebugUITools.getPartDebugContext(fParent.getSite()); fRetrieval = MemoryViewUtil.getMemoryBlockRetrieval(context); } protected MenuManager createContextMenuManager() { MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$ menuMgr.setRemoveAllWhenShown(true); menuMgr.addMenuListener(new IMenuListener() { @Override public void menuAboutToShow(IMenuManager manager) { manager.add(fAddMemoryBlockAction); manager.add(fRemoveMemoryBlockAction); manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); } }); // register a context menu manager, use its pane id as the menu id fParent.getSite().registerContextMenu(getId(), menuMgr, fSelectionProvider); return menuMgr; } @Override public void dispose() { fParent.getViewSite().getSelectionProvider().removeSelectionChangedListener(this); fParent.getViewSite().getPage().removeSelectionListener(this); fAddMemoryBlockAction.dispose(); DebugUITools.removePartDebugContextListener(fParent.getSite(), fDebugContextListener); fEvtHandler.dispose(); fPresentationContext.dispose(); } /* * (non-Javadoc) * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui. * IWorkbenchPart, org.eclipse.jface.viewers.ISelection) */ @Override public void selectionChanged(IWorkbenchPart part, ISelection selection) { if (selection instanceof IStructuredSelection) { Object obj = ((IStructuredSelection) selection).getFirstElement(); if (obj instanceof IMemoryBlock) { // if the selection event comes from this view if (part == fParent) { // do not change selection if the selection is already // correct ISelection treeSel = fTreeViewer.getSelection(); if (treeSel instanceof IStructuredSelection) { if (((IStructuredSelection) treeSel).getFirstElement() == obj) { return; } } // remove itself as selection listener when handling // selection changed event removeSelctionListener(this); fTreeViewer.setSelection(selection); // remove itself as selection listener when handling // selection changed event addSelectionListener(this); } } } } @Override public String getId() { return fPaneId; } /* * (non-Javadoc) * @see * org.eclipse.debug.internal.ui.views.memory.IMemoryViewPane#getActions() */ @Override public IAction[] getActions() { if (fAddMemoryBlockAction == null) { fAddMemoryBlockAction = new RetargetAddMemoryBlockAction((IMemoryRenderingSite) fParent); } if (fRemoveMemoryBlockAction == null) { fRemoveMemoryBlockAction = new TreeViewerRemoveMemoryBlocksAction(); } if (fRemoveAllMemoryBlocksAction == null) { fRemoveAllMemoryBlocksAction = new TreeViewerRemoveAllMemoryBlocksAction(); } updateActionsEnablement(); return new IAction[] { fAddMemoryBlockAction, fRemoveMemoryBlockAction, fRemoveAllMemoryBlocksAction }; } /* * (non-Javadoc) * @see org.eclipse.debug.internal.ui.views.memory.IMemoryViewPane# * addSelectionListener(org.eclipse.jface.viewers.ISelectionChangedListener) */ @Override public void addSelectionListener(ISelectionChangedListener listener) { if (fSelectionProvider == null) { fSelectionProvider = new ViewPaneSelectionProvider(); } fSelectionProvider.addSelectionChangedListener(listener); } /* * (non-Javadoc) * @see org.eclipse.debug.internal.ui.views.memory.IMemoryViewPane# * removeSelctionListener * (org.eclipse.jface.viewers.ISelectionChangedListener) */ @Override public void removeSelctionListener(ISelectionChangedListener listener) { if (fSelectionProvider == null) { return; } fSelectionProvider.removeSelectionChangedListener(listener); } /* * (non-Javadoc) * @see org.eclipse.debug.internal.ui.views.memory.IMemoryViewPane# * getSelectionProvider() */ @Override public ISelectionProvider getSelectionProvider() { return fSelectionProvider; } /* * (non-Javadoc) * @see * org.eclipse.debug.internal.ui.views.memory.IMemoryViewPane#restoreViewPane * () */ @Override public void restoreViewPane() { updateRetrieval(); updateActionsEnablement(); } /* * (non-Javadoc) * @see * org.eclipse.debug.internal.ui.views.memory.IMemoryViewPane#getControl() */ @Override public Control getControl() { return fTreeViewer.getControl(); } /* * (non-Javadoc) * @see * org.eclipse.debug.internal.ui.views.memory.IMemoryViewPane#setVisible * (boolean) */ @Override public void setVisible(boolean visible) { if (fVisible != visible) { fVisible = visible; if (fVisible) { fTreeViewer.refresh(); fTreeViewer.getControl().setFocus(); } } } /* * (non-Javadoc) * @see * org.eclipse.debug.internal.ui.views.memory.IMemoryViewPane#isVisible() */ @Override public boolean isVisible() { return fVisible; } private void updateActionsEnablement() { if (fRemoveMemoryBlockAction == null) { return; } if (fRemoveAllMemoryBlocksAction == null) { return; } if (fRetrieval != null) { IMemoryBlock[] memBlocks = DebugPlugin.getDefault().getMemoryBlockManager().getMemoryBlocks(fRetrieval); if (memBlocks.length > 0) { fRemoveMemoryBlockAction.setEnabled(true); fRemoveAllMemoryBlocksAction.setEnabled(true); } else { fRemoveMemoryBlockAction.setEnabled(false); fRemoveAllMemoryBlocksAction.setEnabled(false); } } else { fRemoveMemoryBlockAction.setEnabled(false); fRemoveAllMemoryBlocksAction.setEnabled(false); } } @Override public void selectionChanged(SelectionChangedEvent event) { // only handle selection changed from parent's selection provider if (event.getSource() == fParent.getSite().getSelectionProvider()) { MemoryBlocksTreeViewPane.this.selectionChanged(fParent, event.getSelection()); } } public StructuredViewer getViewer() { return fTreeViewer; } @Override public IMemoryRenderingSite getMemoryRenderingSite() { if (fParent instanceof IMemoryRenderingSite) { return (IMemoryRenderingSite) fParent; } return null; } @Override public void addMemoryRendering(IMemoryRendering rendering) { // do nothing } @Override public void removeMemoryRendering(IMemoryRendering rendering) { // do nothing } @Override public IMemoryRendering[] getRenderings() { return new IMemoryRendering[0]; } @Override public IMemoryRendering getActiveRendering() { return null; } @Override public String getLabel() { return fLabel; } }