blob: ae5006cc17a77abb65870f5616b93b6e084491cb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2018 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* WindRiver - Bug 192028 [Memory View] Memory view does not
* display memory blocks that do not reference IDebugTarget
* ARM - Bug 192028 [Memory View] Memory view does not
* display memory blocks that do not reference IDebugTarget
* WindRiver - Bug 216509 [Memory View] typo, s/isMeomryBlockRemoved/isMemoryBlockRemoved
* Wind River Systems - Ted Williams - [Memory View] Memory View: Workflow Enhancements (Bug 215432)
*******************************************************************************/
package org.eclipse.debug.internal.ui.views.memory;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;
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.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.model.IMemoryBlock;
import org.eclipse.debug.core.model.IMemoryBlockRetrieval;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.internal.ui.views.memory.renderings.CreateRendering;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.contexts.DebugContextEvent;
import org.eclipse.debug.ui.memory.IMemoryRendering;
import org.eclipse.debug.ui.memory.IMemoryRenderingContainer;
import org.eclipse.debug.ui.memory.IMemoryRenderingSite;
import org.eclipse.debug.ui.memory.IMemoryRenderingSynchronizationService;
import org.eclipse.debug.ui.memory.IResettableMemoryRendering;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.resource.ColorRegistry;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabFolder2Adapter;
import org.eclipse.swt.custom.CTabFolderEvent;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPreferenceConstants;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.progress.UIJob;
/**
* Represents a rendering view pane in the Memory View. This hosts the memory
* view tabs in the view.
*
* @since 3.1
*
*/
public class RenderingViewPane extends AbstractMemoryViewPane implements IMemoryRenderingContainer {
public static final String RENDERING_VIEW_PANE_ID = DebugUIPlugin.getUniqueIdentifier() + ".MemoryView.RenderingViewPane"; //$NON-NLS-1$
private Hashtable<IMemoryBlock, CTabFolder> fTabFolderForMemoryBlock = new Hashtable<>();
private Hashtable<CTabFolder, IMemoryBlock> fMemoryBlockFromTabFolder = new Hashtable<>();
private ViewPaneRenderingMgr fRenderingMgr;
private IMemoryRenderingSite fRenderingSite;
private Set<IMemoryRendering> fAddedRenderings = new HashSet<>();
private Set<IMemoryBlock> fAddedMemoryBlocks = new HashSet<>();
private boolean fCanAddRendering = true;
private boolean fCanRemoveRendering = true;
/**
* @param parent is the view hosting this view pane
* @param paneId is the identifier assigned by the Memory View
*
* Pane id is assigned with the following format. Rendering view
* pane created has its id assigned to
* org.eclipse.debug.ui.MemoryView.RenderingViewPane.#. # is a
* number indicating the order of which the rendering view pane
* is created. First rendering view pane created will have its id
* assigned to
* org.eclipse.debug.ui.MemoryView.RenderingViewPane.1. Second
* rendering view pane created will have its id assigned to
* org.eclipse.debug.ui.MemoryView.RenderingViewPane.2. and so
* on. View pane are created from left to right by the Memory
* View.
*
*/
public RenderingViewPane(IViewPart parent) {
super(parent);
if (parent instanceof IMemoryRenderingSite) {
fRenderingSite = (IMemoryRenderingSite) parent;
} else {
DebugUIPlugin.logErrorMessage("Parent for the rendering view pane is invalid."); //$NON-NLS-1$
}
}
/*
* (non-Javadoc)
* @see
* org.eclipse.debug.internal.core.memory.IMemoryBlockListener#MemoryBlockAdded
* (org.eclipse.debug.core.model.IMemoryBlock)
*/
@Override
public void memoryBlocksAdded(final IMemoryBlock[] memoryBlocks) {
Display.getDefault().asyncExec(() -> {
if (isDisposed()) {
return;
}
// check condition before doing anything
if (memoryBlocks == null || memoryBlocks.length <= 0) {
return;
}
for (int i = 0; i < memoryBlocks.length; i++) {
IMemoryBlock memory = memoryBlocks[i];
if (!fTabFolderForMemoryBlock.containsKey(memory)) {
createFolderForMemoryBlock(memory);
}
fAddedMemoryBlocks.add(memory);
updateToolBarActionsEnablement();
}
});
}
/*
* (non-Javadoc)
* @see org.eclipse.debug.internal.core.memory.IMemoryBlockListener#
* MemoryBlockRemoved(org.eclipse.debug.core.model.IMemoryBlock)
*/
@Override
public void memoryBlocksRemoved(final IMemoryBlock[] memoryBlocks) {
Display.getDefault().asyncExec(() -> {
for (int j = 0; j < memoryBlocks.length; j++) {
IMemoryBlock mbRemoved = memoryBlocks[j];
if (fTabFolderForMemoryBlock == null) {
return;
}
// get all renderings from this memory block and remove them
// from the view
IMemoryRendering[] renderings = fRenderingMgr.getRenderingsFromMemoryBlock(mbRemoved);
for (int k = 0; k < renderings.length; k++) {
removeMemoryRendering(renderings[k]);
}
// remove a the tab folder if the memory block is removed
CTabFolder tabFolder = fTabFolderForMemoryBlock.get(mbRemoved);
if (tabFolder == null) {
continue;
}
fTabFolderForMemoryBlock.remove(mbRemoved);
fMemoryBlockFromTabFolder.remove(tabFolder);
IMemoryBlockRetrieval retrieve = MemoryViewUtil.getMemoryBlockRetrieval(mbRemoved);
if (retrieve != null) {
if (fTabFolderForDebugView.contains(tabFolder)) {
fTabFolderForDebugView.remove(MemoryViewUtil.getHashCode(retrieve));
}
}
if (!tabFolder.isDisposed()) {
// dispose all view tabs belonging to the tab folder
CTabItem[] items = tabFolder.getItems();
for (int i = 0; i < items.length; i++) {
disposeTab(items[i]);
}
// dispose the tab folder
tabFolder.dispose();
// if this is the top control
if (tabFolder == fStackLayout.topControl) {
// if memory view is visible and have a selection
// follow memory view's selection
ISelection selection = DebugUIPlugin.getActiveWorkbenchWindow().getSelectionService()
.getSelection(IDebugUIConstants.ID_MEMORY_VIEW);
IMemoryBlock mbToSelect = getMemoryBlock(selection);
if (mbToSelect != null) {
// memory view may not have got the event and is
// still displaying
// the deleted memory block
if (mbToSelect != mbRemoved) {
handleMemoryBlockSelection(null, mbToSelect);
} else if ((MemoryViewUtil.getMemoryBlockManager().getMemoryBlocks(retrieve).length > 0)) {
mbToSelect = MemoryViewUtil.getMemoryBlockManager().getMemoryBlocks(retrieve)[0];
handleMemoryBlockSelection(null, mbToSelect);
} else {
emptyFolder();
}
} else if (MemoryViewUtil.getMemoryBlockManager().getMemoryBlocks(retrieve).length > 0) { // get
// to
// the
// next
// folder
mbToSelect = MemoryViewUtil.getMemoryBlockManager().getMemoryBlocks(retrieve)[0];
handleMemoryBlockSelection(null, mbToSelect);
} else {
emptyFolder();
}
}
// if not the top control
// no need to do anything
}
fAddedMemoryBlocks.remove(mbRemoved);
updateToolBarActionsEnablement();
}
});
}
/*
* (non-Javadoc)
* @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.
* IWorkbenchPart, org.eclipse.jface.viewers.ISelection)
*/
@Override
public void selectionChanged(final IWorkbenchPart part, final ISelection selection) {
if (isDisposed()) {
return;
}
// do not schedule job if any of these conditions are true
if (part == RenderingViewPane.this) {
return;
}
if (!(selection instanceof IStructuredSelection)) {
return;
}
if (selection == AbstractMemoryViewPane.EMPTY) {
return;
}
UIJob job = new UIJob("RenderingViewPane selectionChanged") { //$NON-NLS-1$
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
try {
if (isDisposed()) {
return Status.OK_STATUS;
}
if (selection.isEmpty()) {
// if the event comes from Memory View
// pick empty tab folder as the memory view is no longer
// displaying anything
if (part.getSite().getId().equals(IDebugUIConstants.ID_MEMORY_VIEW)) {
if (part == getMemoryRenderingSite().getSite().getPart()) {
IMemoryViewTab lastViewTab = getTopMemoryTab();
if (lastViewTab != null) {
lastViewTab.setEnabled(false);
}
emptyFolder();
}
}
// do not do anything if there is no selection
// In the case when a debug adpater fires a debug event
// incorrectly, Launch View sets
// selection to nothing. If the view tab is disabled, it
// erases all the "delta" information
// in the content. This may not be desirable as it will
// cause memory to show up as
// unchanged when it's actually changed. Do not disable
// the view tab until there is a
// valid selection.
return Status.OK_STATUS;
}
// back up current view tab
IMemoryViewTab lastViewTab = getTopMemoryTab();
if (!(selection instanceof IStructuredSelection)) {
return Status.OK_STATUS;
}
Object elem = ((IStructuredSelection) selection).getFirstElement();
if (elem instanceof IMemoryBlock) {
// if the selection event comes from this view
if (part == getMemoryRenderingSite()) {
// find the folder associated with the given
// IMemoryBlockRetrieval
IMemoryBlock memBlock = (IMemoryBlock) elem;
// should never get here... added code for safety
if (fTabFolderForMemoryBlock == null) {
if (lastViewTab != null) {
lastViewTab.setEnabled(false);
}
emptyFolder();
return Status.OK_STATUS;
}
handleMemoryBlockSelection(lastViewTab, memBlock);
}
}
} catch (SWTException se) {
DebugUIPlugin.log(se);
}
return Status.OK_STATUS;
}
};
job.setSystem(true);
job.schedule();
}
public void handleMemoryBlockSelection(final IMemoryViewTab lastViewTab, final IMemoryBlock memBlock) {
// Do not check if the debug target of mb is removed
// We should not get into this method if the debug target of the memory
// block is terminated
// Memory Block Manager gets the terminate event and would have removed
// all memory blocks
// associated with the debug target
// Therefore, we will never try to set a selection to a memory block
// whose target is terminated
// check current memory block
CTabFolder currentFolder = (CTabFolder) fStackLayout.topControl;
if (currentFolder != null && !currentFolder.isDisposed()) {
IMemoryBlock currentBlk = fMemoryBlockFromTabFolder.get(currentFolder);
if (currentBlk != null) {
if (currentBlk == memBlock) {
return;
}
}
}
if (getTopMemoryTab() != null) {
if (getTopMemoryTab().getRendering().getMemoryBlock() == memBlock) {
return;
}
}
// if we've got a tabfolder to go with the IMemoryBlock, display
// it
if (fTabFolderForMemoryBlock.containsKey(memBlock)) {
if (fStackLayout.topControl != fTabFolderForMemoryBlock.get(memBlock)) {
setTabFolder(fTabFolderForMemoryBlock.get(memBlock));
fViewPaneCanvas.layout();
}
} else { // otherwise, add a new one
CTabFolder folder = createTabFolder(fViewPaneCanvas);
fTabFolderForMemoryBlock.put(memBlock, folder);
fMemoryBlockFromTabFolder.put(folder, memBlock);
setTabFolder(fTabFolderForMemoryBlock.get(memBlock));
fViewPaneCanvas.layout();
fAddedMemoryBlocks.add(memBlock);
newCreateRenderingForFolder(memBlock, folder);
}
// restore view tabs
IMemoryRendering[] renderings = fRenderingMgr.getRenderingsFromMemoryBlock(memBlock);
CTabFolder toDisplay = (CTabFolder) fStackLayout.topControl;
// if only CreateRendering is present, restore renderings
if (isRestoreViewTabs(toDisplay)) {
restoreViewTabs(renderings);
}
// disable last view tab as it becomes hidden
IMemoryViewTab newViewTab = getTopMemoryTab();
if (lastViewTab != null && lastViewTab != newViewTab) {
lastViewTab.setEnabled(false);
}
if (newViewTab != null) {
// if new view tab is not already enabled, enable it
if (!newViewTab.isEnabled()) {
// if the view tab is visible, enable it
if (fVisible) {
newViewTab.setEnabled(fVisible);
}
}
}
IMemoryViewTab viewTab = getTopMemoryTab();
if (viewTab != null) {
setRenderingSelection(viewTab.getRendering());
}
// set toolbar actions enabled/disabled
updateToolBarActionsEnablement();
}
private boolean isRestoreViewTabs(CTabFolder folder) {
if (canAddRendering()) {
return (folder.getItemCount() == 1 && getTopMemoryTab().getRendering() instanceof CreateRendering);
} else {
return (folder.getItemCount() == 0);
}
}
private int getIndexOfCreateRenderingTab(CTabFolder folder) {
for (int i = 0; i < folder.getItemCount(); i++) {
if (folder.getItem(i).getData() instanceof MemoryViewTab && ((MemoryViewTab) folder.getItem(i).getData()).getRendering() instanceof CreateRendering) {
return i;
}
}
return -1;
}
public void memoryBlockRenderingAdded(final IMemoryRendering rendering) {
Display.getDefault().asyncExec(() -> {
if (isDisposed()) {
return;
}
if (fAddedRenderings.contains(rendering)) {
return;
}
IMemoryBlock memoryblk = rendering.getMemoryBlock();
CTabFolder tabFolder = fTabFolderForMemoryBlock.get(memoryblk);
if (tabFolder == null) {
tabFolder = createFolderForMemoryBlock(memoryblk);
}
if (tabFolder == fStackLayout.topControl) {
// disable current view tab
if (getTopMemoryTab() != null) {
deactivateRendering(getTopMemoryTab());
getTopMemoryTab().setEnabled(false);
}
}
fAddedRenderings.add(rendering);
int index = getIndexOfCreateRenderingTab(tabFolder);
if (index < 0) {
index = 0;
}
CTabItem tab = createTab(tabFolder, index);
MemoryViewTab viewTab = new MemoryViewTab(tab, rendering, getInstance());
tabFolder.setSelection(tabFolder.indexOf(tab));
if (tabFolder == fStackLayout.topControl) {
setRenderingSelection(viewTab.getRendering());
// disable top view tab if the view pane is not visible
IMemoryViewTab top = getTopMemoryTab();
if (top != null) {
top.setEnabled(fVisible);
}
} else {
deactivateRendering(viewTab);
viewTab.setEnabled(false);
}
updateToolBarActionsEnablement();
});
}
/*
* (non-Javadoc)
* @see org.eclipse.debug.internal.core.memory.IMemoryRenderingListener#
* MemoryBlockRenderingRemoved
* (org.eclipse.debug.internal.core.memory.IMemoryRendering)
*/
public void memoryBlockRenderingRemoved(final IMemoryRendering rendering) {
final IMemoryBlock memory = rendering.getMemoryBlock();
// need to run the following code on the UI Thread to avoid invalid
// thread access exception
Display.getDefault().asyncExec(() -> {
if (!fAddedRenderings.contains(rendering)) {
return;
}
fAddedRenderings.remove(rendering);
CTabFolder tabFolder = (CTabFolder) fStackLayout.topControl;
if (tabFolder.isDisposed()) {
return;
}
CTabItem[] tabs = tabFolder.getItems();
boolean foundTab = false;
for (int i1 = 0; i1 < tabs.length; i1++) {
IMemoryViewTab viewTab1 = (IMemoryViewTab) tabs[i1].getData();
if (tabs[i1].isDisposed()) {
continue;
}
if (viewTab1.getRendering().getMemoryBlock() == memory) {
if (viewTab1.getRendering() == rendering) {
foundTab = true;
disposeTab(tabs[i1]);
break;
}
}
}
// if a tab is not found in the current top control
// this deletion is a result of a debug target termination
// find memory from other folder and dispose the view tab
if (!foundTab) {
Enumeration<CTabFolder> enumeration = fTabFolderForMemoryBlock.elements();
while (enumeration.hasMoreElements()) {
CTabFolder otherTabFolder = enumeration.nextElement();
tabs = otherTabFolder.getItems();
IMemoryViewTab viewTab2 = null;
for (int i2 = 0; i2 < tabs.length; i2++) {
viewTab2 = (IMemoryViewTab) tabs[i2].getData();
if (viewTab2.getRendering().getMemoryBlock() == memory) {
if (viewTab2.getRendering() == rendering) {
foundTab = true;
disposeTab(tabs[i2]);
break;
}
}
}
}
}
IMemoryViewTab top = getTopMemoryTab();
// update selection
if (top != null) {
setRenderingSelection(top.getRendering());
}
updateToolBarActionsEnablement();
});
}
/**
* @param viewTab
*/
protected void setRenderingSelection(IMemoryRendering rendering) {
if (rendering != null) {
fSelectionProvider.setSelection(new StructuredSelection(rendering));
}
}
private void restoreViewTabs(IMemoryRendering[] renderings) {
for (int i = 0; i < renderings.length; i++) {
memoryBlockRenderingAdded(renderings[i]);
}
}
private void handleDebugElementSelection(final IMemoryViewTab lastViewTab, final IAdaptable element) {
// get current memory block retrieval and debug target
IMemoryBlockRetrieval currentRetrieve = null;
// get tab folder
CTabFolder tabFolder = (CTabFolder) fStackLayout.topControl;
// get memory block
IMemoryBlock currentBlock = fMemoryBlockFromTabFolder.get(tabFolder);
if (currentBlock != null) {
currentRetrieve = MemoryViewUtil.getMemoryBlockRetrieval(currentBlock);
// backup current retrieve and tab folder
if (currentRetrieve != null && tabFolder != null) {
fTabFolderForDebugView.put(MemoryViewUtil.getHashCode(currentRetrieve), tabFolder);
}
}
// find the folder associated with the given IMemoryBlockRetrieval
IMemoryBlockRetrieval retrieve = MemoryViewUtil.getMemoryBlockRetrieval(element);
// if debug target has changed
// switch to that tab folder
if (retrieve != null && retrieve != currentRetrieve) {
Integer key = MemoryViewUtil.getHashCode(retrieve);
CTabFolder folder = fTabFolderForDebugView.get(key);
if (folder != null) {
setTabFolder(folder);
fTabFolderForDebugView.put(key, folder);
fViewPaneCanvas.layout();
} else {
// find out if there is any memory block for this debug target
// and set up tab folder for the memory blocks
IMemoryBlock blocks[] = MemoryViewUtil.getMemoryBlockManager().getMemoryBlocks(retrieve);
if (blocks.length > 0) {
handleMemoryBlockSelection(null, blocks[0]);
} else {
emptyFolder();
fTabFolderForDebugView.put(key, fEmptyTabFolder);
fViewPaneCanvas.layout();
}
}
}
// disable last view tab as it becomes hidden
IMemoryViewTab newViewTab = getTopMemoryTab();
if (lastViewTab != null && lastViewTab != newViewTab) {
lastViewTab.setEnabled(false);
}
if (newViewTab != null) {
// if new view tab is not already enabled, enable it
if (!newViewTab.isEnabled()) {
// if the view tab is visible, enable it
if (fVisible) {
newViewTab.setEnabled(fVisible);
}
}
// should only change selection if the new view tab is different
if (lastViewTab != newViewTab) {
setRenderingSelection(newViewTab.getRendering());
}
}
// set toolbar actions enabled/disabled
updateToolBarActionsEnablement();
}
@Override
protected void addListeners() {
super.addListeners();
// must directly listen for selection events from parent's selection
// provider
// to ensure that we get the selection event from the tree viewer pane
// even
// if the view does not have focuse
fParent.getSite().getSelectionProvider().addSelectionChangedListener(this);
}
@Override
protected void removeListeners() {
super.removeListeners();
fParent.getSite().getSelectionProvider().removeSelectionChangedListener(this);
}
/*
* (non-Javadoc)
* @see
* org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt
* .events.SelectionEvent)
*/
@Override
public void widgetSelected(SelectionEvent e) {
if (getTopMemoryTab() == null) {
return;
}
IMemoryRendering rendering = getTopMemoryTab().getRendering();
if (rendering != null) {
fSelectionProvider.setSelection(new StructuredSelection(rendering));
}
}
/*
* (non-Javadoc)
* @see
* org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse
* .swt.events.SelectionEvent)
*/
@Override
public void widgetDefaultSelected(SelectionEvent e) {
}
@Override
public Object getCurrentSelection() {
if (getTopMemoryTab() != null) {
if (getTopMemoryTab().getRendering() != null) {
return getTopMemoryTab().getRendering();
}
}
return null;
}
/*
* (non-Javadoc)
* @see com.ibm.debug.extended.ui.IMemoryView#getAllViewTabs()
*/
@Override
public IMemoryViewTab[] getAllViewTabs() {
// otherwise, find the view tab to display
CTabFolder folder = (CTabFolder) fStackLayout.topControl;
CTabItem[] items = folder.getItems();
IMemoryViewTab[] viewTabs = new IMemoryViewTab[folder.getItemCount()];
for (int i = 0; i < items.length; i++) {
viewTabs[i] = (IMemoryViewTab) items[i].getData();
}
return viewTabs;
}
/*
* (non-Javadoc)
* @see
* com.ibm.debug.extended.ui.IMemoryView#moveToTop(com.ibm.debug.extended
* .ui.IMemoryViewTab)
*/
@Override
public void moveToTop(IMemoryViewTab viewTab) {
IMemoryViewTab lastViewTab = getTopMemoryTab();
if (viewTab == lastViewTab) {
return;
}
// otherwise, find the view tab to display
CTabFolder folder = (CTabFolder) fStackLayout.topControl;
CTabItem[] items = folder.getItems();
for (int i = 0; i < items.length; i++) {
IMemoryViewTab tab = (IMemoryViewTab) items[i].getData();
if (viewTab == tab) {
boolean isEnabled = lastViewTab.isEnabled();
// switch to that viewTab
lastViewTab.setEnabled(false);
folder.setSelection(i);
setRenderingSelection(tab.getRendering());
getTopMemoryTab().setEnabled(isEnabled && fVisible);
break;
}
}
}
private CTabFolder createTabFolder(Composite parent) {
CTabFolder folder = new CTabFolder(parent, SWT.NO_REDRAW_RESIZE | SWT.NO_TRIM | SWT.FLAT);
ColorRegistry reg = JFaceResources.getColorRegistry();
Color c1 = reg.get("org.eclipse.ui.workbench.ACTIVE_TAB_BG_START"), //$NON-NLS-1$
c2 = reg.get("org.eclipse.ui.workbench.ACTIVE_TAB_BG_END"); //$NON-NLS-1$
folder.setSelectionBackground(new Color[] { c1, c2 }, new int[] { 100 }, true);
folder.setSelectionForeground(reg.get("org.eclipse.ui.workbench.ACTIVE_TAB_TEXT_COLOR")); //$NON-NLS-1$
folder.setSimple(PlatformUI.getPreferenceStore().getBoolean(IWorkbenchPreferenceConstants.SHOW_TRADITIONAL_STYLE_TABS));
folder.setBorderVisible(true);
folder.setFont(fViewPaneCanvas.getFont());
folder.addCTabFolder2Listener(new CTabFolder2Adapter() {
@Override
public void close(CTabFolderEvent event) {
if (event.item.getData() instanceof MemoryViewTab) {
RenderingViewPane.this.removeMemoryRendering(((MemoryViewTab) event.item.getData()).getRendering());
}
event.doit = false;
}
});
return folder;
}
@Override
public void restoreViewPane() {
// get current selection from memory view
ISelection selection = null;
if (fParent.getSite().getSelectionProvider() != null) {
selection = fParent.getSite().getSelectionProvider().getSelection();
}
IMemoryBlock memoryBlock = null;
if (selection != null) {
memoryBlock = getMemoryBlock(selection);
}
if (memoryBlock == null) {
// get selection from this view
selection = fSelectionProvider.getSelection();
if (MemoryViewUtil.isValidSelection(selection)) {
Object elem = ((IStructuredSelection) selection).getFirstElement();
if (!(elem instanceof IMemoryBlock)) {
return;
}
memoryBlock = (IMemoryBlock) elem;
}
}
if (memoryBlock == null) {
// get a memory block from current debug context
IAdaptable context = DebugUITools.getPartDebugContext(fParent.getSite());
if (context != null) {
IMemoryBlockRetrieval retrieval = MemoryViewUtil.getMemoryBlockRetrieval(context);
if (retrieval != null) {
IMemoryBlock[] blocks = DebugPlugin.getDefault().getMemoryBlockManager().getMemoryBlocks(retrieval);
if (blocks.length > 0) {
memoryBlock = blocks[0];
}
}
}
}
if (memoryBlock != null) {
if (!fTabFolderForMemoryBlock.containsKey(memoryBlock)) {
// create tab folder if a tab folder does not already exist
// for the memory block
CTabFolder folder = createTabFolder(fViewPaneCanvas);
fTabFolderForMemoryBlock.put(memoryBlock, folder);
fMemoryBlockFromTabFolder.put(folder, memoryBlock);
setTabFolder(fTabFolderForMemoryBlock.get(memoryBlock));
IMemoryBlockRetrieval retrieval = MemoryViewUtil.getMemoryBlockRetrieval(memoryBlock);
if (retrieval != null) {
fTabFolderForDebugView.put(MemoryViewUtil.getHashCode(retrieval), fTabFolderForMemoryBlock.get(memoryBlock));
} else {
DebugUIPlugin.logErrorMessage("Memory block retrieval for memory block is null."); //$NON-NLS-1$
}
fViewPaneCanvas.layout();
fAddedMemoryBlocks.add(memoryBlock);
// every time we create a folder, we have to create a
// CreateRendering
newCreateRenderingForFolder(memoryBlock, folder);
}
if (fTabFolderForMemoryBlock.containsKey(memoryBlock)) {
CTabFolder toDisplay = fTabFolderForMemoryBlock.get(memoryBlock);
if (toDisplay != null) {
setTabFolder(toDisplay);
IMemoryBlockRetrieval retrieval = MemoryViewUtil.getMemoryBlockRetrieval(memoryBlock);
if (retrieval != null) {
fTabFolderForDebugView.put(MemoryViewUtil.getHashCode(retrieval), toDisplay);
} else {
DebugUIPlugin.logErrorMessage("Memory block retrieval is null for memory block."); //$NON-NLS-1$
}
fViewPaneCanvas.layout();
// restore view tabs
IMemoryRendering[] renderings = fRenderingMgr.getRenderingsFromMemoryBlock(memoryBlock);
// if only CreateRendering is present, restore renderings
if (isRestoreViewTabs(toDisplay)) {
restoreViewTabs(renderings);
}
}
}
// disable current storag block
IMemoryViewTab top = getTopMemoryTab();
if (top != null) {
top.setEnabled(fVisible);
}
}
}
@Override
public void dispose() {
super.dispose();
fTabFolderForMemoryBlock.clear();
fTabFolderForMemoryBlock = null;
fMemoryBlockFromTabFolder.clear();
fMemoryBlockFromTabFolder = null;
fRenderingMgr.dispose();
fRenderingMgr = null;
fAddedMemoryBlocks.clear();
fAddedRenderings.clear();
}
public Control createViewPane(Composite parent, String paneId, String label, boolean canAddRendering, boolean canRemoveRendering) {
return doCreateViewPane(parent, paneId, label, canAddRendering, canRemoveRendering);
}
@Override
public Control createViewPane(Composite parent, String paneId, String label) {
return doCreateViewPane(parent, paneId, label, true, true);
}
/**
* @param parent
* @param paneId
* @param label
* @param canAddRendering
* @param canRemoveRendering
* @return
*/
private Control doCreateViewPane(Composite parent, String paneId, String label, boolean canAddRendering, boolean canRemoveRendering) {
Control control = super.createViewPane(parent, paneId, label);
fCanAddRendering = canAddRendering;
fCanRemoveRendering = canRemoveRendering;
fRenderingMgr = new ViewPaneRenderingMgr(this);
PlatformUI.getWorkbench().getHelpSystem().setHelp(parent, IDebugUIConstants.PLUGIN_ID + ".MemoryRenderingView_context"); //$NON-NLS-1$
return control;
}
@Override
public IAction[] getActions() {
return new IAction[0];
}
// enable/disable toolbar action
protected void updateToolBarActionsEnablement() {
}
/*
* (non-Javadoc)
* @see
* org.eclipse.debug.internal.ui.views.memory.AbstractMemoryViewPane#emptyFolder
* ()
*/
@Override
protected void emptyFolder() {
super.emptyFolder();
updateToolBarActionsEnablement();
fSelectionProvider.setSelection(AbstractMemoryViewPane.EMPTY);
}
/*
* (non-Javadoc)
* @see org.eclipse.debug.internal.ui.views.memory.IRenderingViewPane#
* addMemoryRendering
* (org.eclipse.debug.internal.ui.views.memory.IMemoryRendering)
*/
@Override
public void addMemoryRendering(IMemoryRendering rendering) {
if (rendering == null) {
return;
}
memoryBlockRenderingAdded(rendering);
fRenderingMgr.addMemoryBlockRendering(rendering);
}
/*
* (non-Javadoc)
* @see org.eclipse.debug.internal.ui.views.memory.IRenderingViewPane#
* removeMemoryRendering
* (org.eclipse.debug.internal.ui.views.memory.IMemoryRendering)
*/
@Override
public void removeMemoryRendering(IMemoryRendering rendering) {
if (rendering == null) {
return;
}
memoryBlockRenderingRemoved(rendering);
if (fRenderingMgr != null) {
fRenderingMgr.removeMemoryBlockRendering(rendering);
}
}
private RenderingViewPane getInstance() {
return this;
}
private IMemoryBlock getMemoryBlock(ISelection selection) {
if (!(selection instanceof IStructuredSelection)) {
return null;
}
// only single selection of PICLDebugElements is allowed for this action
if (selection.isEmpty() || ((IStructuredSelection) selection).size() > 1) {
return null;
}
Object elem = ((IStructuredSelection) selection).getFirstElement();
if (elem instanceof IMemoryBlock) {
return (IMemoryBlock) elem;
} else if (elem instanceof IMemoryRendering) {
return ((IMemoryRendering) elem).getMemoryBlock();
} else {
return null;
}
}
private void deactivateRendering(IMemoryViewTab viewTab) {
if (viewTab == null) {
return;
}
if (!viewTab.isDisposed()) {
viewTab.getRendering().deactivated();
}
}
/*
* (non-Javadoc)
* @see org.eclipse.debug.internal.ui.views.memory.IRenderingViewPane#
* getMemoryRenderingSite()
*/
@Override
public IMemoryRenderingSite getMemoryRenderingSite() {
return fRenderingSite;
}
/*
* (non-Javadoc)
* @see org.eclipse.debug.ui.memory.IMemoryRenderingContainer#getId()
*/
@Override
public String getId() {
return getPaneId();
}
/*
* (non-Javadoc)
* @see
* org.eclipse.debug.ui.memory.IMemoryRenderingContainer#getRenderings()
*/
@Override
public IMemoryRendering[] getRenderings() {
return fRenderingMgr.getRenderings();
}
/*
* (non-Javadoc)
* @see
* org.eclipse.debug.ui.memory.IMemoryRenderingContainer#getActiveRendering
* ()
*/
@Override
public IMemoryRendering getActiveRendering() {
if (getTopMemoryTab() == null) {
return null;
}
return getTopMemoryTab().getRendering();
}
/**
* Reset the memory renderings within this view pane.
*
* @param memoryBlock - reset renderings associated with the given memory
* block
* @param resetVisible - reset what's currently visible if the parameter is
* true. Otherwise, the view pane will reset all renderings
* associated with the given memory block.
*/
public void resetRenderings(IMemoryBlock memoryBlock, boolean resetVisible) {
// if we only reset what's visible and the view pane is not visible
// do nothing.
if (resetVisible && !isVisible()) {
return;
}
if (resetVisible) {
IMemoryRendering rendering = getActiveRendering();
if (rendering != null) {
if (rendering.getMemoryBlock() == memoryBlock) {
if (rendering instanceof IResettableMemoryRendering) {
IResettableMemoryRendering resettableRendering = (IResettableMemoryRendering) rendering;
try {
resettableRendering.resetRendering();
} catch (DebugException e) {
// do not pop up error message
// error message is annoying where there are
// multiple rendering
// panes and renderings to reset
}
}
}
}
} else {
// get all renderings associated with the given memory block
IMemoryRendering[] renderings = fRenderingMgr.getRenderingsFromMemoryBlock(memoryBlock);
// back up current synchronization provider
IMemoryRendering originalProvider = null;
IMemoryRenderingSynchronizationService service = getMemoryRenderingSite().getSynchronizationService();
if (service != null) {
originalProvider = service.getSynchronizationProvider();
}
for (int i = 0; i < renderings.length; i++) {
if (renderings[i] instanceof IResettableMemoryRendering) {
try {
// This is done to allow user to select multiple memory
// monitors and
// reset their renderings.
// In this case, a hidden rendering will not be the sync
// provider to the sync
// service. When the reset happens, the top visible
// address and selected
// address is not updated in the sync service. When the
// rendering later
// becomes visible, the rendering gets the sync info
// from the sync service
// and will try to sync up with old information, giving
// user the impression
// that the rendering was never reset. By forcing the
// rendering that we
// are trying to reset as the synchronization provider,
// we ensure that
// the rendering is able to update its sync info even
// though the rendering
// is currently hidden.
if (service != null) {
service.setSynchronizationProvider(renderings[i]);
}
((IResettableMemoryRendering) renderings[i]).resetRendering();
} catch (DebugException e) {
// do not pop up error message
// error message is annoying where there are multiple
// rendering
// panes and renderings to reset
}
}
}
// restore synchronization provider
if (service != null) {
service.setSynchronizationProvider(originalProvider);
}
}
}
public void showCreateRenderingTab() {
IMemoryRendering activeRendering = RenderingViewPane.this.getActiveRendering();
if (activeRendering == null) {
return;
}
IMemoryBlock memoryblk = activeRendering.getMemoryBlock();
final CTabFolder tabFolder = fTabFolderForMemoryBlock.get(memoryblk);
if (tabFolder != null) {
Display.getDefault().asyncExec(() -> {
int index = getIndexOfCreateRenderingTab(tabFolder);
if (index >= 0) {
tabFolder.setSelection(index);
}
});
}
}
public void contextActivated(final ISelection selection) {
UIJob job = new UIJob("contextActivated") { //$NON-NLS-1$
@Override
public IStatus runInUIThread(IProgressMonitor monitor) {
if (isDisposed()) {
return Status.OK_STATUS;
}
IMemoryViewTab lastViewTab = getTopMemoryTab();
if (MemoryViewUtil.isValidSelection(selection)) {
if (!(selection instanceof IStructuredSelection)) {
return Status.OK_STATUS;
}
Object elem = ((IStructuredSelection) selection).getFirstElement();
if (elem instanceof IAdaptable) {
handleDebugElementSelection(lastViewTab, (IAdaptable) elem);
}
} else {
if (lastViewTab != null) {
lastViewTab.setEnabled(false);
}
if (fStackLayout.topControl != fEmptyTabFolder) {
emptyFolder();
}
}
return Status.OK_STATUS;
}
};
job.setSystem(true);
job.schedule();
}
/**
* @param memory
*/
private CTabFolder createFolderForMemoryBlock(IMemoryBlock memory) {
CTabFolder folder = createTabFolder(fViewPaneCanvas);
fTabFolderForMemoryBlock.put(memory, folder);
fMemoryBlockFromTabFolder.put(folder, memory);
IMemoryBlockRetrieval retrieval = MemoryViewUtil.getMemoryBlockRetrieval(memory);
if (retrieval != null) {
fTabFolderForDebugView.put(MemoryViewUtil.getHashCode(retrieval), folder);
} else {
DebugUIPlugin.logErrorMessage("Memory block retrieval for memory block is null"); //$NON-NLS-1$
}
newCreateRenderingForFolder(memory, folder);
return folder;
}
private void newCreateRenderingForFolder(IMemoryBlock memory, CTabFolder folder) {
if (!canAddRendering()) {
return;
}
CTabItem newItem = new CTabItem(folder, SWT.NONE);
CreateRendering rendering = new CreateRendering(getInstance());
rendering.init(getInstance(), memory);
new MemoryViewTab(newItem, rendering, getInstance());
folder.setSelection(0);
}
/*
* (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());
}
}
/**
* @return whether this container allows user to add rendering manually
* @since 3.4
*/
public boolean canAddRendering() {
return fCanAddRendering;
}
/**
* @return whether this container allows user to remove rendering manually
* @since 3.4
*/
public boolean canRemoveRendering() {
return fCanRemoveRendering;
}
/**
* @param tabFolder
* @param index
* @return
*/
private CTabItem createTab(CTabFolder tabFolder, int index) {
int swtStyle = SWT.CLOSE;
if (!canRemoveRendering()) {
swtStyle = SWT.NONE;
}
CTabItem tab = new CTabItem(tabFolder, swtStyle, index);
return tab;
}
}