blob: b3bb3513fd6807684f01750349b62d80378cc2d6 [file] [log] [blame]
/*
*(c) Copyright QNX Software Systems Ltd. 2002.
* All Rights Reserved.
*
*/
package org.eclipse.cdt.debug.internal.ui.views.memory;
import org.eclipse.cdt.debug.core.CDebugModel;
import org.eclipse.cdt.debug.core.ICMemoryManager;
import org.eclipse.cdt.debug.core.model.IFormattedMemoryBlock;
import org.eclipse.cdt.debug.internal.ui.CDebugUIUtils;
import org.eclipse.cdt.debug.internal.ui.preferences.ICDebugPreferenceConstants;
import org.eclipse.cdt.debug.ui.CDebugUIPlugin;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
/**
*
* The tab content in the memory view.
*
* @since Jul 25, 2002
*/
public class MemoryControlArea extends Composite implements ITextOperationTarget
{
private MemoryView fMemoryView;
private MemoryPresentation fPresentation;
private int fIndex = 0;
private ICMemoryManager fMemoryManager = null;
private Text fAddressText;
private Button fEvaluateButton;
private MemoryText fMemoryText;
private int fFormat = ICMemoryManager.MEMORY_FORMAT_HEX;
private int fWordSize = ICMemoryManager.MEMORY_SIZE_BYTE;
private int fNumberOfRows = 40;
private int fNumberOfColumns = 16;
private char fPaddingChar = '.';
/**
* Constructor for MemoryControlArea.
* @param parent
* @param style
*/
public MemoryControlArea( Composite parent, int style, int index, MemoryView view )
{
super( parent, style );
fMemoryView = view;
GridLayout layout = new GridLayout();
layout.marginHeight = 0;
layout.marginWidth = 0;
GridData gridData = new GridData( GridData.FILL_BOTH |
GridData.GRAB_HORIZONTAL |
GridData.GRAB_VERTICAL );
setLayout( layout );
setLayoutData( gridData );
setIndex( index );
fPresentation = createPresentation();
fAddressText = createAddressText( this );
fMemoryText = createMemoryText( this, style, fPresentation );
setDefaultPreferences();
updateToolTipText();
}
private void setDefaultPreferences()
{
char[] paddingCharStr = CDebugUIPlugin.getDefault().getPreferenceStore().getString( ICDebugPreferenceConstants.PREF_MEMORY_PADDING_CHAR ).toCharArray();
setPaddingChar( ( paddingCharStr.length > 0 ) ? paddingCharStr[0] : '.' );
fPresentation.setDisplayAscii( CDebugUIPlugin.getDefault().getPreferenceStore().getBoolean( ICDebugPreferenceConstants.PREF_MEMORY_SHOW_ASCII ) );
}
private MemoryPresentation createPresentation()
{
return new MemoryPresentation();
}
public MemoryPresentation getPresentation()
{
return fPresentation;
}
private Text createAddressText( Composite parent )
{
Composite composite = new Composite( parent, SWT.NONE );
composite.setLayout( new GridLayout( 3, false ) );
composite.setLayoutData( new GridData( GridData.FILL_HORIZONTAL ) );
// create label
Label label = new Label( composite, SWT.RIGHT );
label.setText( "Address: " );
label.pack();
// create address text
Text text = new Text( composite, SWT.BORDER );
text.setLayoutData( new GridData( GridData.FILL_HORIZONTAL ) );
text.addTraverseListener( new TraverseListener()
{
public void keyTraversed( TraverseEvent e )
{
if ( e.detail == SWT.TRAVERSE_RETURN && e.stateMask == 0 )
{
e.doit = false;
handleAddressEnter();
}
}
} );
text.addFocusListener( new FocusListener()
{
public void focusGained( FocusEvent e )
{
getMemoryView().updateObjects();
}
public void focusLost( FocusEvent e )
{
getMemoryView().updateObjects();
}
} );
text.addModifyListener( new ModifyListener()
{
public void modifyText( ModifyEvent e )
{
handleAddressModification();
}
} );
text.addKeyListener( new KeyListener()
{
public void keyPressed( KeyEvent e )
{
getMemoryView().updateObjects();
}
public void keyReleased( KeyEvent e )
{
getMemoryView().updateObjects();
}
} );
text.addMouseListener( new MouseListener()
{
public void mouseDoubleClick( MouseEvent e )
{
getMemoryView().updateObjects();
}
public void mouseDown( MouseEvent e )
{
getMemoryView().updateObjects();
}
public void mouseUp( MouseEvent e )
{
getMemoryView().updateObjects();
}
} );
fEvaluateButton = new Button( composite, SWT.PUSH );
fEvaluateButton.setText( "Evaluate" );
fEvaluateButton.setToolTipText( "Evaluate expression to address" );
fEvaluateButton.addSelectionListener( new SelectionAdapter()
{
public void widgetSelected( SelectionEvent e )
{
evaluateAddressExpression();
}
} );
return text;
}
private MemoryText createMemoryText( Composite parent,
int styles,
MemoryPresentation presentation )
{
return new MemoryText( parent, SWT.BORDER | SWT.HIDE_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL, presentation );
}
protected void handleAddressEnter()
{
if ( getMemoryManager() != null )
{
String address = fAddressText.getText().trim();
try
{
removeBlock();
if ( address.length() > 0 )
{
createBlock( address );
}
}
catch( DebugException e )
{
CDebugUIPlugin.errorDialog( "Unable to get memory block.", e.getStatus() );
}
refresh();
getMemoryView().updateObjects();
}
}
public void propertyChange( PropertyChangeEvent event )
{
if ( event.getProperty().equals( ICDebugPreferenceConstants.MEMORY_BACKGROUND_RGB ) )
{
fMemoryText.setBackgroundColor();
}
else if ( event.getProperty().equals( ICDebugPreferenceConstants.MEMORY_FOREGROUND_RGB ) )
{
fMemoryText.setForegroundColor();
}
else if ( event.getProperty().equals( ICDebugPreferenceConstants.MEMORY_FONT ) )
{
fMemoryText.changeFont();
}
else if ( event.getProperty().equals( ICDebugPreferenceConstants.MEMORY_ADDRESS_RGB ) )
{
fMemoryText.setAddressColor();
}
else if ( event.getProperty().equals( ICDebugPreferenceConstants.MEMORY_CHANGED_RGB ) )
{
fMemoryText.setChangedColor();
}
else if ( event.getProperty().equals( ICDebugPreferenceConstants.MEMORY_DIRTY_RGB ) )
{
fMemoryText.setDirtyColor();
}
else if ( event.getProperty().equals( ICDebugPreferenceConstants.PREF_MEMORY_PADDING_CHAR ) )
{
String paddingCharString = (String)event.getNewValue();
setPaddingChar( ( paddingCharString.length() > 0 ) ? paddingCharString.charAt( 0 ) : '.' );
refresh();
}
}
public void setInput( Object input )
{
setMemoryManager( ( input instanceof ICMemoryManager ) ? (ICMemoryManager)input : null );
getPresentation().setMemoryBlock( getMemoryBlock() );
setState();
refresh();
}
protected void refresh()
{
fAddressText.setText( ( getPresentation() != null ) ? getPresentation().getAddressExpression() : "" );
fMemoryText.refresh();
getMemoryView().updateObjects();
updateToolTipText();
}
protected void setMemoryManager( ICMemoryManager mm )
{
fMemoryManager = mm;
}
protected ICMemoryManager getMemoryManager()
{
return fMemoryManager;
}
protected IFormattedMemoryBlock getMemoryBlock()
{
return ( getMemoryManager() != null ) ? getMemoryManager().getBlock( getIndex() ) : null;
}
protected int getIndex()
{
return fIndex;
}
protected void setIndex( int index )
{
fIndex = index;
}
private void createBlock( String address ) throws DebugException
{
if ( getMemoryManager() != null )
{
getMemoryManager().setBlockAt( getIndex(),
CDebugModel.createFormattedMemoryBlock( (IDebugTarget)getMemoryManager().getAdapter( IDebugTarget.class ),
address,
getFormat(),
getWordSize(),
getNumberOfRows(),
getNumberOfColumns(),
getPaddingChar() ) );
getMemoryBlock().setFrozen( !CDebugUIPlugin.getDefault().getPreferenceStore().getBoolean( ICDebugPreferenceConstants.PREF_MEMORY_AUTO_REFRESH ) );
getPresentation().setMemoryBlock( getMemoryBlock() );
}
setMemoryTextState();
updateToolTipText();
}
private void removeBlock() throws DebugException
{
if ( getMemoryManager() != null )
{
getMemoryManager().removeBlock( getIndex() );
getPresentation().setMemoryBlock( null );
}
setMemoryTextState();
updateToolTipText();
}
public int getFormat()
{
return fFormat;
}
public int getNumberOfColumns()
{
return fNumberOfColumns;
}
public int getNumberOfRows()
{
return fNumberOfRows;
}
public char getPaddingChar()
{
return fPaddingChar;
}
public int getWordSize()
{
return fWordSize;
}
public void setFormat(int format)
{
fFormat = format;
}
public void setNumberOfColumns( int numberOfColumns )
{
fNumberOfColumns = numberOfColumns;
}
public void setNumberOfRows( int numberOfRows )
{
fNumberOfRows = numberOfRows;
}
public void setPaddingChar( char paddingChar )
{
fPaddingChar = paddingChar;
if ( getMemoryBlock() != null )
{
try
{
getMemoryBlock().reformat( getMemoryBlock().getFormat(),
getMemoryBlock().getWordSize(),
getMemoryBlock().getNumberOfRows(),
getMemoryBlock().getNumberOfColumns(),
fPaddingChar );
}
catch( DebugException e )
{
// ignore
}
}
}
public void setWordSize( int wordSize )
{
fWordSize = wordSize;
}
private void enableAddressText( boolean enable )
{
fAddressText.setEnabled( enable );
}
protected void setState()
{
enableAddressText( getMemoryManager() != null );
setMemoryTextState();
}
private void setMemoryTextState()
{
fMemoryText.setEditable( getMemoryManager() != null && getMemoryBlock() != null );
}
protected MemoryText getMemoryText()
{
return fMemoryText;
}
protected void clear()
{
fAddressText.setText( "" );
handleAddressEnter();
updateToolTipText();
}
/**
* @see org.eclipse.swt.widgets.Widget#dispose()
*/
public void dispose()
{
if ( getPresentation() != null )
{
getPresentation().dispose();
}
super.dispose();
}
protected String getTitle()
{
if ( getParent() instanceof CTabFolder )
{
CTabItem[] tabItems = ((CTabFolder)getParent()).getItems();
return tabItems[fIndex].getText();
}
return "";
}
protected void setTitle( String title )
{
if ( getParent() instanceof CTabFolder )
{
CTabItem[] tabItems = ((CTabFolder)getParent()).getItems();
tabItems[fIndex].setText( title );
}
}
protected void setTabItemToolTipText( String text )
{
String newText = replaceMnemonicCharacters( text );
if ( getParent() instanceof CTabFolder )
{
CTabItem[] tabItems = ((CTabFolder)getParent()).getItems();
tabItems[fIndex].setToolTipText( "Memory View " + (fIndex + 1) + ( ( newText.length() > 0 ) ? ( ": " + newText ) : "" ) );
}
}
protected void refreshMemoryBlock()
{
if ( getMemoryBlock() != null )
{
try
{
getMemoryBlock().refresh();
}
catch( DebugException e )
{
CDebugUIPlugin.errorDialog( "Unable to refresh memory.", e.getStatus() );
}
}
}
private void updateToolTipText()
{
setTabItemToolTipText( fAddressText.getText().trim() );
}
private String replaceMnemonicCharacters( String text )
{
StringBuffer sb = new StringBuffer( text.length() );
for ( int i = 0; i < text.length(); ++i )
{
char ch = text.charAt( i );
sb.append( ch );
if ( ch == '&' )
{
sb.append( ch );
}
}
return sb.toString();
}
protected void handleAddressModification()
{
fEvaluateButton.setEnabled( fAddressText.getText().trim().length() > 0 );
}
protected void evaluateAddressExpression()
{
if ( getMemoryManager() != null )
{
if ( getMemoryBlock() == null )
{
String expression = fAddressText.getText().trim();
try
{
removeBlock();
if ( expression.length() > 0 )
{
createBlock( expression );
}
}
catch( DebugException e )
{
CDebugUIPlugin.errorDialog( "Unable to get memory block.", e.getStatus() );
}
}
if ( getMemoryBlock() != null )
{
fAddressText.setText( CDebugUIUtils.toHexAddressString( getMemoryBlock().getStartAddress() ) );
handleAddressEnter();
}
}
}
/* (non-Javadoc)
* @see org.eclipse.jface.text.ITextOperationTarget#canDoOperation(int)
*/
public boolean canDoOperation( int operation )
{
switch( operation )
{
case CUT:
case COPY:
return ( fAddressText != null && fAddressText.isFocusControl() && fAddressText.isEnabled() && fAddressText.getSelectionCount() > 0 );
case PASTE:
case SELECT_ALL:
return ( fAddressText != null && fAddressText.isFocusControl() && fAddressText.isEnabled() );
}
return false;
}
/* (non-Javadoc)
* @see org.eclipse.jface.text.ITextOperationTarget#doOperation(int)
*/
public void doOperation( int operation )
{
switch( operation )
{
case CUT:
fAddressText.cut();
break;
case COPY:
fAddressText.copy();
break;
case PASTE:
fAddressText.paste();
break;
case SELECT_ALL:
fAddressText.selectAll();
break;
}
}
protected MemoryView getMemoryView()
{
return fMemoryView;
}
}