blob: 8e0d68736793909cf986cc2787f95a44a7920a1d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005 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
*******************************************************************************/
package org.eclipse.debug.internal.ui.views.memory;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.StringTokenizer;
import org.eclipse.core.runtime.CoreException;
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.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IDebugEventSetListener;
import org.eclipse.debug.core.IMemoryBlockListener;
import org.eclipse.debug.core.model.IDebugElement;
import org.eclipse.debug.core.model.IMemoryBlock;
import org.eclipse.debug.core.model.IMemoryBlockExtension;
import org.eclipse.debug.core.model.IMemoryBlockRetrieval;
import org.eclipse.debug.core.model.IMemoryBlockRetrievalExtension;
import org.eclipse.debug.core.model.ITerminate;
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.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugUIConstants;
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.IMemoryRenderingType;
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.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.part.PageBook;
import org.eclipse.ui.progress.UIJob;
public class AddMemoryBlocksComposite implements ISelectionListener, IDebugEventSetListener{
private IViewPart fViewPart;
private PageBook fComposite;
private AddMemoryBlockPage fExtendedPage;
private AddMemoryBlockPage fSimplePage;
private class AddMemoryBlockPage implements IMemoryBlockListener
{
private Composite fPageComposite;
private Combo fExpression;
private Text fLengthTxt;
private Button fAddButton;
private boolean fShowLength;
private AddMemoryBlockPage(boolean createLengthFields)
{
fShowLength= createLengthFields;
createPage(fComposite, createLengthFields);
}
private Control createPage(Composite parent, boolean createLengthFields) {
Composite composite = new Composite(parent, SWT.FILL);
fPageComposite = composite;
GridLayout addLayout = new GridLayout();
if (createLengthFields)
addLayout.numColumns = 3;
else
addLayout.numColumns = 2;
addLayout.makeColumnsEqualWidth = false;
composite.setLayout(addLayout);
Label expr = new Label(composite, SWT.NONE);
expr.setText(DebugUIMessages.AddMemoryBlocksComposite_0);
GridData data = new GridData();
data.grabExcessHorizontalSpace = false;
data.grabExcessVerticalSpace = false;
data.verticalAlignment = SWT.CENTER;
data.horizontalAlignment = SWT.LEFT;
expr.setLayoutData(data);
if (createLengthFields)
{
Label length = new Label(composite, SWT.NONE);
length.setText(DebugUIMessages.AddMemoryBlocksComposite_1);
data = new GridData();
data.grabExcessHorizontalSpace = false;
data.grabExcessVerticalSpace = false;
data.verticalAlignment = SWT.CENTER;
data.horizontalAlignment = SWT.LEFT;
length.setLayoutData(data);
}
new Label(composite, SWT.NONE);
fExpression = new Combo(composite, SWT.NONE);
data = new GridData();
data.grabExcessHorizontalSpace = true;
data.grabExcessVerticalSpace = false;
data.horizontalAlignment = SWT.FILL;
data.verticalAlignment = SWT.BOTTOM;
fExpression.setLayoutData(data);
fExpression.addSelectionListener(new SelectionAdapter()
{
public void widgetDefaultSelected(SelectionEvent e)
{
if (validate())
addMemoryBlocks();
}
});
// fill history
fillHistory();
if (createLengthFields)
{
fLengthTxt = new Text(composite, SWT.BORDER | SWT.SINGLE);
data = new GridData();
data.grabExcessHorizontalSpace = true;
data.grabExcessVerticalSpace = false;
data.horizontalAlignment = SWT.FILL;
data.verticalAlignment = SWT.BOTTOM;
fLengthTxt.setLayoutData(data);
fLengthTxt.addSelectionListener(new SelectionAdapter()
{
public void widgetDefaultSelected(SelectionEvent e)
{
if (validate())
addMemoryBlocks();
}
});
}
fAddButton = new Button(composite, SWT.NONE);
fAddButton.setImage(DebugUITools.getImage(IInternalDebugUIConstants.IMG_ELCL_MONITOR_EXPRESSION));
fAddButton.setToolTipText(DebugUIMessages.AddMemoryBlocksComposite_2);
data = new GridData();
data.grabExcessHorizontalSpace = false;
data.grabExcessVerticalSpace = false;
data.verticalAlignment = SWT.TOP;
fAddButton.setLayoutData(data);
fAddButton.addSelectionListener(new SelectionAdapter()
{
public void widgetSelected(SelectionEvent e)
{
addMemoryBlocks();
}
});
return composite;
}
private void fillHistory() {
String[] history = MemoryViewUtil.getHistory();
if (history.length > 0)
{
String txt = fExpression.getText();
fExpression.removeAll();
for(int j=0; j<history.length; j++) {
fExpression.add(history[j]);
}
fExpression.setText(txt);
}
}
private void addMemoryBlocks()
{
IAdaptable debugContext = DebugUITools.getDebugContext();
if (debugContext == null)
return;
IDebugElement elm = null;
if (debugContext instanceof IDebugElement)
elm = (IDebugElement)debugContext;
if (elm == null)
return;
IMemoryBlockRetrieval standardMemRetrieval = (IMemoryBlockRetrieval)elm.getAdapter(IMemoryBlockRetrieval.class);
if (standardMemRetrieval == null)
standardMemRetrieval = elm.getDebugTarget();
if (standardMemRetrieval == null)
return;
// get expression entered in combo
String input = fExpression.getText();
ArrayList expressions = new ArrayList();
if (input.length() == 0)
{
expressions.add(""); //$NON-NLS-1$
}
else
{
StringTokenizer tokenizer = new StringTokenizer(input, ","); //$NON-NLS-1$
while (tokenizer.hasMoreTokens())
{
expressions.add(tokenizer.nextToken());
}
}
boolean error = false;
String[] expressionsArray = (String[])expressions.toArray(new String[expressions.size()]);
for (int i=0; i<expressionsArray.length; i++)
{
String expression = expressionsArray[i].trim();
MemoryViewUtil.addHistory(expression);
try {
if (standardMemRetrieval instanceof IMemoryBlockRetrievalExtension)
{
// if the debug session supports IMemoryBlockExtensionRetrieval
IMemoryBlockRetrievalExtension memRetrieval = (IMemoryBlockRetrievalExtension)standardMemRetrieval;
// get extended memory block with the expression entered
IMemoryBlockExtension memBlock = memRetrieval.getExtendedMemoryBlock(expression, elm);
// add block to memory block manager
if (memBlock != null)
{
IMemoryBlock[] memArray = new IMemoryBlock[]{memBlock};
MemoryView view = getMemoryView();
if (view != null)
view.registerMemoryBlocks(memArray);
MemoryViewUtil.getMemoryBlockManager().addMemoryBlocks(memArray);
addDefaultRenderings(memBlock);
}
else
{
error = true;
// open error if it failed to retrieve a memory block
MemoryViewUtil.openError(DebugUIMessages.AddMemoryBlockAction_title, DebugUIMessages.AddMemoryBlockAction_noMemoryBlock, null);
}
}
else
{
// if the debug session does not support IMemoryBlockExtensionRetrieval
expression = expression.toUpperCase();
String hexPrefix = "0X"; //$NON-NLS-1$
if (expression.startsWith(hexPrefix))
{
expression = expression.substring(hexPrefix.length());
}
// convert the expression to an address
BigInteger address = new BigInteger(expression, 16);
long longAddress = address.longValue();
// get the length of memory to block
String strLength = fLengthTxt.getText();
long length = Long.parseLong(strLength);
// must monitor at least one line
if (length <= 0)
{
error = true;
String message = DebugUIMessages.AddMemoryBlockAction_failed + "\n" + DebugUIMessages.AddMemoryBlockAction_input_invalid; //$NON-NLS-1$
MemoryViewUtil.openError(DebugUIMessages.AddMemoryBlockAction_title, message, null);
continue;
}
// get standard memory block
IMemoryBlock memBlock = standardMemRetrieval.getMemoryBlock(longAddress, length);
// make sure the memory block returned is not an instance of IMemoryBlockExtension
if (memBlock instanceof IMemoryBlockExtension)
{
Status status = new Status(IStatus.WARNING, DebugUIPlugin.getUniqueIdentifier(), 0,
"IMemoryBlockRetrieval returns IMemoryBlockExtension. This may result in unexpected behavior.", null); //$NON-NLS-1$
DebugUIPlugin.log(status);
}
if (memBlock != null)
{
// add memory block to memory block manager
IMemoryBlock[] memArray = new IMemoryBlock[]{memBlock};
MemoryView view = getMemoryView();
if (view != null)
view.registerMemoryBlocks(memArray);
MemoryViewUtil.getMemoryBlockManager().addMemoryBlocks(memArray);
addDefaultRenderings(memBlock);
}
else
{
error = true;
// otherwise open up an error doalog
MemoryViewUtil.openError(DebugUIMessages.AddMemoryBlockAction_title, DebugUIMessages.AddMemoryBlockAction_noMemoryBlock, null);
}
}
} catch (DebugException e1) {
error = true;
MemoryViewUtil.openError(DebugUIMessages.AddMemoryBlockAction_title, DebugUIMessages.AddMemoryBlockAction_failed, e1);
}
catch(NumberFormatException e2)
{
error = true;
String message = DebugUIMessages.AddMemoryBlockAction_failed + "\n" + DebugUIMessages.AddMemoryBlockAction_input_invalid; //$NON-NLS-1$
MemoryViewUtil.openError(DebugUIMessages.AddMemoryBlockAction_title, message, null);
}
}
if (!error)
{
fExpression.setText(""); //$NON-NLS-1$
if (fShowLength)
fLengthTxt.setText(""); //$NON-NLS-1$
}
}
private void becomesVisible()
{
}
private void becomesHidden()
{
}
private Control getControl()
{
return fPageComposite;
}
private boolean validate()
{
if (fAddButton.isEnabled())
{
if (fShowLength)
{
if (fExpression.getText() != null &&
fLengthTxt.getText() != null)
{
if (fLengthTxt.getText().length() > 0)
return true;
}
return false;
}
if (fExpression.getText() != null)
return true;
return false;
}
return false;
}
private void update(ISelection selection)
{
if (MemoryViewUtil.isValidSelection(selection))
fAddButton.setEnabled(true);
else
fAddButton.setEnabled(false);
}
public void memoryBlocksAdded(IMemoryBlock[] memory) {
// history has changed if a new memory block is added
fillHistory();
}
public void memoryBlocksRemoved(IMemoryBlock[] memory) {
}
}
/**
* @param viewPart
*/
public AddMemoryBlocksComposite(IViewPart viewPart)
{
fViewPart = viewPart;
}
public Control createComposite(Composite parent)
{
fComposite = new PageBook(parent, SWT.FILL);
GridData pagebookData = new GridData();
pagebookData.grabExcessHorizontalSpace = true;
pagebookData.grabExcessVerticalSpace = false;
pagebookData.horizontalAlignment = SWT.FILL;
pagebookData.verticalAlignment = SWT.TOP;
fComposite.setLayoutData(pagebookData);
fExtendedPage = new AddMemoryBlockPage(false);
fSimplePage = new AddMemoryBlockPage(true);
showPageWithLength(false);
IAdaptable debugContext = DebugUITools.getDebugContext();
if (debugContext != null)
{
ISelection sel = new StructuredSelection(debugContext);
update(sel);
}
else
update(StructuredSelection.EMPTY);
fViewPart.getViewSite().getPage().addSelectionListener(IDebugUIConstants.ID_DEBUG_VIEW, this);
DebugPlugin.getDefault().addDebugEventListener(this);
DebugPlugin.getDefault().getMemoryBlockManager().addListener(fExtendedPage);
DebugPlugin.getDefault().getMemoryBlockManager().addListener(fSimplePage);
return fComposite;
}
public void showPageWithLength(boolean showLengthFields)
{
if (showLengthFields)
{
fComposite.showPage(fSimplePage.getControl());
fExtendedPage.becomesHidden();
fSimplePage.becomesVisible();
}
else
{
fComposite.showPage(fExtendedPage.getControl());
fSimplePage.becomesHidden();
fExtendedPage.becomesVisible();
}
}
public void dispose()
{
fViewPart.getViewSite().getPage().removeSelectionListener(IDebugUIConstants.ID_DEBUG_VIEW, this);
DebugPlugin.getDefault().removeDebugEventListener(this);
DebugPlugin.getDefault().getMemoryBlockManager().removeListener(fExtendedPage);
DebugPlugin.getDefault().getMemoryBlockManager().removeListener(fSimplePage);
}
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
update(selection);
}
public void update(ISelection selection) {
if (selection instanceof IStructuredSelection)
{
Object obj = ((IStructuredSelection)selection).getFirstElement();
if (obj == null)
{
fExtendedPage.fAddButton.setEnabled(false);
fSimplePage.fAddButton.setEnabled(false);
return;
}
fExtendedPage.update(selection);
fSimplePage.update(selection);
if (obj instanceof IDebugElement)
{
IDebugElement elm = (IDebugElement)obj;
IMemoryBlockRetrieval retrieval = (IMemoryBlockRetrieval)elm.getAdapter(IMemoryBlockRetrieval.class);
if (retrieval == null)
retrieval = elm.getDebugTarget();
// watch expression can have null debug target
if (retrieval == null)
{
return;
}
if (!(retrieval instanceof IMemoryBlockRetrievalExtension))
showPageWithLength(true);
else
showPageWithLength(false);
}
}
}
private MemoryView getMemoryView()
{
if (fViewPart instanceof MemoryView)
return (MemoryView)fViewPart;
return null;
}
private void addDefaultRenderings(IMemoryBlock memoryBlock)
{
IMemoryRenderingType primaryType = DebugUITools.getMemoryRenderingManager().getPrimaryRenderingType(memoryBlock);
IMemoryRenderingType renderingTypes[] = DebugUITools.getMemoryRenderingManager().getDefaultRenderingTypes(memoryBlock);
// create primary rendering
try {
if (primaryType != null)
{
createRenderingInContainer(memoryBlock, primaryType, IDebugUIConstants.ID_RENDERING_VIEW_PANE_1);
}
else if (renderingTypes.length > 0)
{
primaryType = renderingTypes[0];
createRenderingInContainer(memoryBlock, renderingTypes[0], IDebugUIConstants.ID_RENDERING_VIEW_PANE_1);
}
} catch (CoreException e1) {
DebugUIPlugin.log(e1);
}
for (int i = 0; i<renderingTypes.length; i++)
{
try {
boolean create = true;
if (primaryType != null)
{
if (primaryType.getId().equals(renderingTypes[i].getId()))
create = false;
}
if (create)
createRenderingInContainer(memoryBlock, renderingTypes[i], IDebugUIConstants.ID_RENDERING_VIEW_PANE_2);
} catch (CoreException e) {
DebugUIPlugin.log(e);
}
}
}
/**
* @param memoryBlock
* @param primaryType
* @throws CoreException
*/
private void createRenderingInContainer(IMemoryBlock memoryBlock, IMemoryRenderingType primaryType, String paneId) throws CoreException {
IMemoryRendering rendering = primaryType.createRendering();
IMemoryRenderingContainer container = ((IMemoryRenderingSite)getMemoryView()).getContainer(paneId);
rendering.init(container, memoryBlock);
container.addMemoryRendering(rendering);
}
public void handleDebugEvents(DebugEvent[] events) {
for (int i=0; i<events.length; i++)
{
if (events[i].getKind() == DebugEvent.TERMINATE &&
events[i].getSource() instanceof ITerminate)
{
IAdaptable context = DebugUITools.getDebugContext();
if (context != null && context instanceof IDebugElement)
{
IDebugElement elm = (IDebugElement)context;
if (elm.getDebugTarget().isDisconnected() ||
elm.getDebugTarget().isTerminated())
{
// causes action to disable
UIJob job = new UIJob("Update") { //$NON-NLS-1$
public IStatus runInUIThread(IProgressMonitor monitor) {
// updating actions need to run on UI thread
update(StructuredSelection.EMPTY);
return Status.OK_STATUS;
}};
job.setSystem(true);
job.schedule();
}
}
}
}
}
}