blob: 2bcbaaf289ef4bc80935d15eb1bf248f9afc54b6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.debug.internal.ui.views.memory;
import java.util.Enumeration;
import java.util.Hashtable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.debug.core.model.IDebugElement;
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.core.memory.IMemoryBlockListener;
import org.eclipse.debug.internal.core.memory.IMemoryRenderingInfo;
import org.eclipse.debug.internal.core.memory.MemoryBlockManager;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.ui.IDebugUIConstants;
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.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.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.help.WorkbenchHelp;
public abstract class AbstractMemoryViewPane implements IMemoryBlockListener, ISelectionListener, SelectionListener, IMemoryView, ISelectionChangedListener{
private static final String VIEW_TAB_FACTORY = "viewTabFactory"; //$NON-NLS-1$
private static final String RENDERER = "renderer"; //$NON-NLS-1$
protected Composite fViewPaneCanvas;
protected StackLayout fStackLayout;
private ViewTabEnablementManager fViewTabEnablementManager;
protected TabFolder fEmptyTabFolder;
protected Hashtable fTabFolderForDebugView;
protected Hashtable fMenuMgr;
protected boolean fVisible;
protected Hashtable fRenderingInfoTable;
protected IMemoryBlockRetrieval fKey; // store the key for current tab folder
protected ViewPaneSelectionProvider fSelectionProvider;
private IViewPart fParent;
public AbstractMemoryViewPane(IViewPart parent)
{
super();
fParent = parent;
}
/**
* Create the content of the view pane
* @param parent
* @return the control of the view pane
*/
public Control createViewPane(Composite parent)
{
WorkbenchHelp.setHelp(parent, IDebugUIConstants.PLUGIN_ID + ".MemoryView_context"); //$NON-NLS-1$
fSelectionProvider = new ViewPaneSelectionProvider();
// view pane overall canvas
Composite canvas = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.makeColumnsEqualWidth = false;
layout.numColumns = 1;
layout.marginHeight = 0;
layout.marginWidth = 0;
GridData data = new GridData();
data.grabExcessHorizontalSpace = true;
data.grabExcessVerticalSpace = true;
data.verticalAlignment = SWT.BEGINNING;
data.horizontalAlignment = SWT.BEGINNING;
canvas.setLayout(layout);
canvas.setLayoutData(data);
// memory view area
Composite memoryViewAreaParent = canvas;
Composite subCanvas = new Composite(memoryViewAreaParent, SWT.NONE);
fViewPaneCanvas = subCanvas;
fStackLayout = new StackLayout();
GridData memoryAreaData = new GridData();
memoryAreaData.grabExcessHorizontalSpace = true;
memoryAreaData.grabExcessVerticalSpace = true;
memoryAreaData.verticalAlignment = SWT.FILL;
memoryAreaData.horizontalAlignment = SWT.FILL;
fViewPaneCanvas.setLayout(fStackLayout);
fViewPaneCanvas.setLayoutData(memoryAreaData);
fViewTabEnablementManager = new ViewTabEnablementManager();
fEmptyTabFolder = new TabFolder(fViewPaneCanvas, SWT.NULL);
setTabFolder(fEmptyTabFolder);
fTabFolderForDebugView = new Hashtable(3);
fMenuMgr = new Hashtable();
addListeners();
// check current selection and create folder if something is already selected from debug view
ISelection selection = DebugUIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection(IDebugUIConstants.ID_DEBUG_VIEW);
if (MemoryViewUtil.isValidSelection(selection))
{
createFolder(selection);
}
fVisible = true;
return canvas;
}
protected void addListeners()
{
MemoryBlockManager.getMemoryBlockManager().addListener(this);
DebugUIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getSelectionService().addSelectionListener(IDebugUIConstants.ID_DEBUG_VIEW, this);
DebugUIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getSelectionService().addSelectionListener(this);
}
protected void removeListeners()
{
MemoryBlockManager.getMemoryBlockManager().removeListener(this);
DebugUIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getSelectionService().removeSelectionListener(IDebugUIConstants.ID_DEBUG_VIEW, this);
DebugUIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getSelectionService().removeSelectionListener(this);
if (fStackLayout.topControl != null)
{
TabFolder old = (TabFolder)fStackLayout.topControl;
if (!old.isDisposed())
{
old.removeSelectionListener(this);
old.removeSelectionListener(fViewTabEnablementManager);
}
}
}
protected void setTabFolder(TabFolder folder)
{
if (fStackLayout.topControl != null)
{
TabFolder old = (TabFolder)fStackLayout.topControl;
if (!old.isDisposed())
{
old.removeSelectionListener(this);
old.removeSelectionListener(fViewTabEnablementManager);
}
}
fStackLayout.topControl = folder;
if (folder.getItemCount() > 0)
{
TabItem[] selectedItem = folder.getSelection();
if (selectedItem.length > 0)
{
fSelectionProvider.setSelection(new StructuredSelection(getCurrentSelection()));
}
}
else
{
fSelectionProvider.setSelection(new StructuredSelection());
}
folder.addSelectionListener(this);
folder.addSelectionListener(fViewTabEnablementManager);
}
private void createFolder(ISelection selection)
{
if (!(selection instanceof IStructuredSelection))
return;
//only single selection of PICLDebugElements is allowed for this action
if (selection == null || selection.isEmpty() || ((IStructuredSelection)selection).size() > 1)
{
return;
}
Object elem = ((IStructuredSelection)selection).getFirstElement();
// if not debug element
if (!(elem instanceof IDebugElement))
return;
IDebugTarget debugTarget = ((IDebugElement)elem).getDebugTarget();
IMemoryBlockRetrieval memRetrieval =(IMemoryBlockRetrieval) ((IDebugElement)elem).getAdapter(IMemoryBlockRetrieval.class);
if (memRetrieval == null)
{
// if debug element returns null from getAdapter, assume its debug target is going to retrieve memory blocks
memRetrieval = debugTarget;
}
//if we've got a tabfolder to go with the IMemoryBlockRetrieval, display it
if (fTabFolderForDebugView.containsKey(memRetrieval)) {
if (fStackLayout.topControl != (TabFolder)fTabFolderForDebugView.get(memRetrieval)) {
setTabFolder((TabFolder)fTabFolderForDebugView.get(memRetrieval));
fViewPaneCanvas.layout();
}
} else { //otherwise, add a new one
fTabFolderForDebugView.put(memRetrieval, new TabFolder(fViewPaneCanvas, SWT.NULL));
setTabFolder((TabFolder)fTabFolderForDebugView.get(memRetrieval));
fViewPaneCanvas.layout();
}
}
public IMemoryViewTab getTopMemoryTab() {
if (fStackLayout.topControl instanceof TabFolder)
{
TabFolder folder = (TabFolder)fStackLayout.topControl;
if (!folder.isDisposed())
{
int index = folder.getSelectionIndex();
if (index >= 0) {
TabItem tab = folder.getItem(index);
return (IMemoryViewTab)tab.getData();
}
}
}
return null;
}
protected MenuManager createContextMenuManager() {
MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
IMemoryViewTab top = getTopMemoryTab();
if (top != null)
{
top.fillContextMenu(manager);
}
manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
}
});
// register a context menu manager, use its pane id as the menu id
fParent.getSite().registerContextMenu(getPaneId(), menuMgr, fSelectionProvider);
return menuMgr;
}
protected IMemoryViewTabFactory getViewTabFactory(String renderingId)
{
if (fRenderingInfoTable == null)
fRenderingInfoTable = new Hashtable();
IMemoryRenderingInfo info;
info = (IMemoryRenderingInfo)fRenderingInfoTable.get(renderingId);
// ask manager for new info
if (info == null)
{
info = MemoryBlockManager.getMemoryRenderingManager().getRenderingInfo(renderingId);
fRenderingInfoTable.put(renderingId, info);
}
if (info == null)
return null;
IConfigurationElement element = info.getPropertyConfigElement(VIEW_TAB_FACTORY);
if (element == null)
return null;
try {
if (element != null)
{
// create the view tab factory
Object obj = element.createExecutableExtension("value"); //$NON-NLS-1$
if (obj instanceof IMemoryViewTabFactory)
return (IMemoryViewTabFactory)obj;
return null;
}
return null;
} catch (CoreException e1) {
return null;
}
}
/**
* @param renderingId
* @return the renderer for the rendering
*/
protected AbstractMemoryRenderer getRenderer(String renderingId){
if (fRenderingInfoTable == null)
fRenderingInfoTable = new Hashtable();
IMemoryRenderingInfo info;
info = (IMemoryRenderingInfo)fRenderingInfoTable.get(renderingId);
// ask manager for new info
if (info == null)
{
info = MemoryBlockManager.getMemoryRenderingManager().getRenderingInfo(renderingId);
fRenderingInfoTable.put(renderingId, info);
}
if (info == null)
return null;
IConfigurationElement element = info.getPropertyConfigElement(RENDERER);
if (element == null)
return null;
try {
if (element != null)
{
// create the view tab factory
Object obj = element.createExecutableExtension("value"); //$NON-NLS-1$
if (obj instanceof AbstractMemoryRenderer)
return (AbstractMemoryRenderer)obj;
return null;
}
return null;
} catch (CoreException e1) {
return null;
}
}
protected void disposeViewTab(IMemoryViewTab viewTab, TabItem tabItem)
{
if (viewTab == null)
return;
// get menu manager and clean up
IMenuManager menuMgr = (IMenuManager)fMenuMgr.get(viewTab);
if (menuMgr != null)
{
menuMgr.dispose();
}
viewTab.dispose();
if (tabItem == null)
return;
// dispose the tab item in case the view tab has not
// cleaned up the tab item
if (!tabItem.isDisposed())
{
tabItem.dispose();
}
}
protected void emptyFolder()
{
setTabFolder(fEmptyTabFolder);
if (!fViewPaneCanvas.isDisposed()) {
fViewPaneCanvas.layout();
}
}
public void addSelectionListener(ISelectionChangedListener listener)
{
fSelectionProvider.addSelectionChangedListener(listener);
}
public void removeSelctionListener(ISelectionChangedListener listener)
{
fSelectionProvider.removeSelectionChangedListener(listener);
}
public ISelectionProvider getSelectionProvider()
{
return fSelectionProvider;
}
public void dispose()
{
removeListeners();
// dispose empty folders
fEmptyTabFolder.dispose();
// dispose all other folders
try {
if (fTabFolderForDebugView != null) {
Enumeration enumeration = fTabFolderForDebugView.elements();
while (enumeration.hasMoreElements())
{
TabFolder tabFolder = (TabFolder)enumeration.nextElement();
if (tabFolder.isDisposed())
continue;
// if tab folder is not empty, dipose view tabs
TabItem[] tabs = tabFolder.getItems();
for (int i=0; i<tabs.length; i++)
{
IMemoryViewTab viewTab = (IMemoryViewTab)tabs[i].getData();
if (!tabs[i].isDisposed())
disposeViewTab(viewTab, tabs[i]);
}
tabFolder.dispose();
}
// set to null so that clean up is only done once
fTabFolderForDebugView.clear();
fTabFolderForDebugView = null;
}
} catch (Exception e) {
DebugUIPlugin.logErrorMessage("Exception occurred when the Memory View is disposed."); //$NON-NLS-1$
}
}
public void setVisible(boolean visible)
{
fVisible = visible;
IMemoryViewTab currentTab = getTopMemoryTab();
if (currentTab != null)
currentTab.setEnabled(visible);
}
public void selectionChanged(SelectionChangedEvent event) {
ISelection selection = event.getSelection();
selectionChanged(fParent,selection);
fSelectionProvider.setSelection(selection);
}
/* (non-Javadoc)
* @see org.eclipse.debug.internal.core.memory.IMemoryBlockListener#MemoryBlockAdded(org.eclipse.debug.core.model.IMemoryBlock)
*/
abstract public void MemoryBlockAdded(IMemoryBlock memory);
/* (non-Javadoc)
* @see org.eclipse.debug.internal.core.memory.IMemoryBlockListener#MemoryBlockRemoved(org.eclipse.debug.core.model.IMemoryBlock)
*/
abstract public void MemoryBlockRemoved(final IMemoryBlock memory);
/* (non-Javadoc)
* @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection)
*/
abstract public void selectionChanged(IWorkbenchPart part, ISelection selection);
/**
* @return current selection from the view pane
*/
abstract public Object getCurrentSelection();
/**
* @return the unique identifier of the view pane
*/
abstract public String getPaneId();
/**
* retore the view pane based on current selection from the debug view
* and the memory blocks and renderings currently exist
*/
abstract public void restoreViewPane();
/**
* @return actions to be contributed to the view pane's toolbar
*/
abstract IAction[] getActions();
}