| /******************************************************************************* |
| * Copyright (c) 2004, 2006 QNX Software Systems 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: |
| * QNX Software Systems - Initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.cdt.debug.internal.ui.views.disassembly; |
| |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| import org.eclipse.cdt.debug.core.CDebugCorePlugin; |
| import org.eclipse.cdt.debug.core.ICDebugConstants; |
| import org.eclipse.cdt.debug.core.model.ICStackFrame; |
| import org.eclipse.cdt.debug.core.model.IDisassembly; |
| import org.eclipse.cdt.debug.internal.ui.ICDebugHelpContextIds; |
| import org.eclipse.cdt.debug.internal.ui.IInternalCDebugUIConstants; |
| import org.eclipse.cdt.debug.internal.ui.actions.CBreakpointPropertiesRulerAction; |
| import org.eclipse.cdt.debug.internal.ui.actions.EnableDisableBreakpointRulerAction; |
| import org.eclipse.cdt.debug.internal.ui.actions.ToggleBreakpointRulerAction; |
| import org.eclipse.cdt.debug.internal.ui.views.AbstractDebugEventHandler; |
| import org.eclipse.cdt.debug.internal.ui.views.AbstractDebugEventHandlerView; |
| import org.eclipse.cdt.debug.internal.ui.views.IDebugExceptionHandler; |
| import org.eclipse.cdt.debug.ui.CDebugUIPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IAdaptable; |
| 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.IThread; |
| import org.eclipse.debug.ui.DebugUITools; |
| 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.IToolBarManager; |
| import org.eclipse.jface.action.MenuManager; |
| import org.eclipse.jface.action.Separator; |
| import org.eclipse.jface.preference.IPreferenceStore; |
| import org.eclipse.jface.resource.JFaceResources; |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.IRegion; |
| import org.eclipse.jface.text.Position; |
| import org.eclipse.jface.text.TextPresentation; |
| import org.eclipse.jface.text.source.IAnnotationAccess; |
| import org.eclipse.jface.text.source.IAnnotationModel; |
| import org.eclipse.jface.text.source.IOverviewRuler; |
| import org.eclipse.jface.text.source.ISharedTextColors; |
| import org.eclipse.jface.text.source.ISourceViewer; |
| import org.eclipse.jface.text.source.IVerticalRuler; |
| import org.eclipse.jface.text.source.OverviewRuler; |
| import org.eclipse.jface.text.source.SourceViewer; |
| import org.eclipse.jface.text.source.VerticalRuler; |
| import org.eclipse.jface.util.Assert; |
| import org.eclipse.jface.util.IPropertyChangeListener; |
| import org.eclipse.jface.util.PropertyChangeEvent; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.jface.viewers.Viewer; |
| import org.eclipse.swt.custom.StyleRange; |
| import org.eclipse.swt.custom.StyledText; |
| import org.eclipse.swt.events.MouseEvent; |
| import org.eclipse.swt.events.MouseListener; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Menu; |
| import org.eclipse.ui.IEditorInput; |
| import org.eclipse.ui.INullSelectionListener; |
| import org.eclipse.ui.ISelectionListener; |
| import org.eclipse.ui.IViewPart; |
| import org.eclipse.ui.IWorkbenchActionConstants; |
| import org.eclipse.ui.IWorkbenchPart; |
| import org.eclipse.ui.editors.text.EditorsUI; |
| import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; |
| import org.eclipse.ui.texteditor.AnnotationPreference; |
| import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess; |
| import org.eclipse.ui.texteditor.DefaultRangeIndicator; |
| import org.eclipse.ui.texteditor.ITextEditorActionConstants; |
| import org.eclipse.ui.texteditor.IUpdate; |
| import org.eclipse.ui.texteditor.MarkerAnnotationPreferences; |
| import org.eclipse.ui.texteditor.SourceViewerDecorationSupport; |
| |
| /** |
| * This view shows disassembly for a particular stack frame. |
| */ |
| public class DisassemblyView extends AbstractDebugEventHandlerView |
| implements ISelectionListener, |
| INullSelectionListener, |
| IPropertyChangeListener, |
| IDebugExceptionHandler, |
| IDisassemblyListener { |
| |
| /** |
| * Creates and returns the listener on this view's context menus. |
| * |
| * @return the menu listener |
| */ |
| protected final IMenuListener getContextMenuListener() { |
| if ( fMenuListener == null ) { |
| fMenuListener = new IMenuListener() { |
| |
| public void menuAboutToShow( IMenuManager menu ) { |
| String id = menu.getId(); |
| if ( getRulerContextMenuId().equals( id ) ) { |
| setFocus(); |
| rulerContextMenuAboutToShow( menu ); |
| } |
| else if ( getViewContextMenuId().equals( id ) ) { |
| setFocus(); |
| viewContextMenuAboutToShow( menu ); |
| } |
| } |
| }; |
| } |
| return fMenuListener; |
| } |
| |
| /** |
| * Creates and returns the listener on this editor's vertical ruler. |
| * |
| * @return the mouse listener |
| */ |
| protected final MouseListener getRulerMouseListener() { |
| if ( fMouseListener == null ) { |
| fMouseListener = new MouseListener() { |
| |
| private boolean fDoubleClicked = false; |
| |
| private void triggerAction( String actionID ) { |
| IAction action = getAction( actionID ); |
| if ( action != null ) { |
| if ( action instanceof IUpdate ) |
| ((IUpdate)action).update(); |
| if ( action.isEnabled() ) |
| action.run(); |
| } |
| } |
| |
| public void mouseUp( MouseEvent e ) { |
| setFocus(); |
| if ( 1 == e.button && !fDoubleClicked ) |
| triggerAction( ITextEditorActionConstants.RULER_CLICK ); |
| fDoubleClicked = false; |
| } |
| |
| public void mouseDoubleClick( MouseEvent e ) { |
| if ( 1 == e.button ) { |
| fDoubleClicked = true; |
| triggerAction( IInternalCDebugUIConstants.ACTION_TOGGLE_BREAKPOINT ); |
| } |
| } |
| |
| public void mouseDown( MouseEvent e ) { |
| StyledText text = getSourceViewer().getTextWidget(); |
| if ( text != null && !text.isDisposed() ) { |
| Display display = text.getDisplay(); |
| Point location = display.getCursorLocation(); |
| getRulerContextMenu().setLocation( location.x, location.y ); |
| } |
| } |
| }; |
| } |
| return fMouseListener; |
| } |
| |
| /** |
| * The width of the vertical ruler. |
| */ |
| private final static int VERTICAL_RULER_WIDTH = 12; |
| |
| /** |
| * Preference key for highlighting current line. |
| */ |
| private final static String CURRENT_LINE = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE; |
| |
| /** |
| * Preference key for highlight color of current line. |
| */ |
| private final static String CURRENT_LINE_COLOR = AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE_COLOR; |
| |
| /** |
| * The view's context menu id. |
| */ |
| private String fViewContextMenuId; |
| |
| /** |
| * The ruler's context menu id. |
| */ |
| private String fRulerContextMenuId; |
| |
| /** |
| * The vertical ruler. |
| */ |
| private IVerticalRuler fVerticalRuler; |
| |
| /** |
| * The overview ruler. |
| */ |
| private IOverviewRuler fOverviewRuler; |
| |
| /** |
| * The last stack frame for which the disassembly storage has |
| * been requested. |
| */ |
| protected ICStackFrame fLastStackFrame = null; |
| |
| /** |
| * Helper for managing the decoration support of this view's viewer. |
| */ |
| private SourceViewerDecorationSupport fSourceViewerDecorationSupport; |
| |
| /** |
| * Helper for accessing annotation from the perspective of this view. |
| */ |
| private IAnnotationAccess fAnnotationAccess; |
| |
| /** |
| * The annotation preferences. |
| */ |
| private MarkerAnnotationPreferences fAnnotationPreferences; |
| |
| /** |
| * Disassembly document provider. |
| */ |
| private DisassemblyDocumentProvider fDocumentProvider; |
| |
| /** |
| * Current instruction pointer nnotation. |
| */ |
| private DisassemblyInstructionPointerAnnotation fInstrPointerAnnotation; |
| |
| /** |
| * Context menu listener. |
| */ |
| private IMenuListener fMenuListener; |
| |
| /** |
| * Vertical ruler mouse listener. |
| */ |
| private MouseListener fMouseListener; |
| |
| /** |
| * The ruler context menu to be disposed. |
| */ |
| private Menu fRulerContextMenu; |
| |
| /** |
| * The text context menu to be disposed. |
| */ |
| private Menu fTextContextMenu; |
| |
| /** |
| * The actions registered with the view. |
| */ |
| private Map fActions = new HashMap( 10 ); |
| |
| /** |
| * Constructor for DisassemblyView. |
| */ |
| public DisassemblyView() { |
| super(); |
| setViewContextMenuId( "#DisassemblyViewContext" ); //$NON-NLS-1$ |
| setRulerContextMenuId( "#DisassemblyViewRulerContext" ); //$NON-NLS-1$ |
| fAnnotationPreferences = new MarkerAnnotationPreferences(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.AbstractDebugView#createViewer(org.eclipse.swt.widgets.Composite) |
| */ |
| protected Viewer createViewer( Composite parent ) { |
| fVerticalRuler = createVerticalRuler(); |
| fOverviewRuler = createOverviewRuler( getSharedColors() ); |
| |
| SourceViewer viewer = createSourceViewer( parent, fVerticalRuler, getOverviewRuler() ); |
| viewer.configure( new DisassemblyViewerConfiguration() ); |
| getSourceViewerDecorationSupport( viewer ); |
| |
| getEditorPreferenceStore().addPropertyChangeListener( this ); |
| CDebugUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener( this ); |
| getSite().getPage().addSelectionListener( IDebugUIConstants.ID_DEBUG_VIEW, this ); |
| getSite().setSelectionProvider( viewer.getSelectionProvider() ); |
| setEventHandler( createEventHandler() ); |
| |
| viewer.setDocument( getDocumentProvider().getDocument( DisassemblyEditorInput.EMPTY_EDITOR_INPUT ), getDocumentProvider().getAnnotationModel( null ) ); |
| |
| resetViewerInput(); |
| |
| return viewer; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.AbstractDebugView#createActions() |
| */ |
| protected void createActions() { |
| IAction action; |
| IVerticalRuler ruler = getVerticalRuler(); |
| action= new ToggleBreakpointRulerAction( this, ruler ); |
| setAction( IInternalCDebugUIConstants.ACTION_TOGGLE_BREAKPOINT, action ); |
| action= new EnableDisableBreakpointRulerAction( this, ruler ); |
| setAction( IInternalCDebugUIConstants.ACTION_ENABLE_DISABLE_BREAKPOINT, action ); |
| action= new CBreakpointPropertiesRulerAction( this, ruler ); |
| setAction( IInternalCDebugUIConstants.ACTION_BREAKPOINT_PROPERTIES, action ); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.AbstractDebugView#getHelpContextId() |
| */ |
| protected String getHelpContextId() { |
| return ICDebugHelpContextIds.DISASSEMBLY_VIEW; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.AbstractDebugView#fillContextMenu(org.eclipse.jface.action.IMenuManager) |
| */ |
| protected void fillContextMenu( IMenuManager menu ) { |
| menu.add( new Separator( IWorkbenchActionConstants.MB_ADDITIONS ) ); |
| updateObjects(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.AbstractDebugView#configureToolBar(org.eclipse.jface.action.IToolBarManager) |
| */ |
| protected void configureToolBar( IToolBarManager tbm ) { |
| // TODO Auto-generated method stub |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection) |
| */ |
| public void selectionChanged( IWorkbenchPart part, ISelection selection ) { |
| if ( !isAvailable() || !isVisible() ) |
| return; |
| if ( selection == null ) |
| resetViewerInput(); |
| else if ( selection instanceof IStructuredSelection ) |
| computeInput( (IStructuredSelection)selection ); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent) |
| */ |
| public void propertyChange( PropertyChangeEvent event ) { |
| String propertyName = event.getProperty(); |
| if ( IInternalCDebugUIConstants.DISASSEMBLY_SOURCE_LINE_COLOR.equals( propertyName ) ) { |
| IEditorInput input = getInput(); |
| if ( input instanceof DisassemblyEditorInput ) |
| getSourceViewer().changeTextPresentation( createTextPresentation( ((DisassemblyEditorInput)input).getSourceRegions() ), true ); |
| } |
| else if ( IInternalCDebugUIConstants.DISASSEMBLY_FONT.equals( propertyName ) ) { |
| getSourceViewer().getTextWidget().setFont( JFaceResources.getFont( IInternalCDebugUIConstants.DISASSEMBLY_FONT ) ); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.internal.ui.views.IDebugExceptionHandler#handleException(org.eclipse.debug.core.DebugException) |
| */ |
| public void handleException( DebugException e ) { |
| showMessage( e.getMessage() ); |
| } |
| |
| /** |
| * Creates the vertical ruler to be used by this view. |
| * |
| * @return the vertical ruler |
| */ |
| protected IVerticalRuler createVerticalRuler() { |
| IVerticalRuler ruler = new VerticalRuler( VERTICAL_RULER_WIDTH, getAnnotationAccess() ); |
| return ruler; |
| } |
| |
| private IOverviewRuler createOverviewRuler( ISharedTextColors sharedColors ) { |
| IOverviewRuler ruler = new OverviewRuler( getAnnotationAccess(), VERTICAL_RULER_WIDTH, sharedColors ); |
| Iterator e = fAnnotationPreferences.getAnnotationPreferences().iterator(); |
| while( e.hasNext() ) { |
| AnnotationPreference preference = (AnnotationPreference)e.next(); |
| if ( preference.contributesToHeader() ) |
| ruler.addHeaderAnnotationType( preference.getAnnotationType() ); |
| } |
| return ruler; |
| } |
| |
| /** |
| * Creates the source viewer to be used by this view. |
| * |
| * @param parent the parent control |
| * @param ruler the vertical ruler |
| * @param styles style bits |
| * @return the source viewer |
| */ |
| private SourceViewer createSourceViewer( Composite parent, IVerticalRuler vertRuler, IOverviewRuler ovRuler ) { |
| DisassemblyViewer viewer = new DisassemblyViewer( parent, vertRuler, ovRuler ); |
| viewer.setRangeIndicator( new DefaultRangeIndicator() ); |
| JFaceResources.getFontRegistry().addListener( this ); |
| JFaceResources.getColorRegistry().addListener( this ); |
| return viewer; |
| } |
| |
| protected SourceViewer getSourceViewer() { |
| return (SourceViewer)getViewer(); |
| } |
| |
| /** |
| * Creates this view's event handler. |
| * |
| * @return an event handler |
| */ |
| protected AbstractDebugEventHandler createEventHandler() { |
| return new DisassemblyViewEventHandler( this ); |
| } |
| |
| protected void computeInput( IStructuredSelection ssel ) { |
| SourceViewer viewer = getSourceViewer(); |
| if ( viewer == null ) |
| return; |
| |
| fLastStackFrame = null; |
| if ( ssel != null && ssel.size() == 1 ) { |
| Object element = ssel.getFirstElement(); |
| if ( element instanceof ICStackFrame ) { |
| fLastStackFrame = (ICStackFrame)element; |
| IEditorInput input = getInput(); |
| if ( input instanceof DisassemblyEditorInput && |
| !((DisassemblyEditorInput)input).contains( (ICStackFrame)element ) ) |
| setViewerInput( DisassemblyEditorInput.PENDING_EDITOR_INPUT ); |
| computeInput( input, (ICStackFrame)element, this ); |
| return; |
| } |
| } |
| resetViewerInput(); |
| } |
| |
| public void setViewerInput( IEditorInput input ) { |
| SourceViewer viewer = getSourceViewer(); |
| if ( viewer == null ) |
| return; |
| |
| if ( input == null ) |
| input = DisassemblyEditorInput.EMPTY_EDITOR_INPUT; |
| |
| IEditorInput current = getInput(); |
| if ( current != null && current.equals( input ) ) { |
| updateObjects(); |
| return; |
| } |
| |
| setInput( input ); |
| showViewer(); |
| try { |
| getDocumentProvider().connect( input ); |
| } |
| catch( CoreException e ) { |
| // never happens |
| } |
| getSourceViewer().setDocument( getDocumentProvider().getDocument( input ), |
| getDocumentProvider().getAnnotationModel( input ) ); |
| if ( input instanceof DisassemblyEditorInput ) { |
| // Workaround for bug #69728 |
| IRegion[] sourceRegions = ((DisassemblyEditorInput)input).getSourceRegions(); |
| if ( sourceRegions.length > 0 ) { |
| getSourceViewer().changeTextPresentation( createTextPresentation( sourceRegions ), true ); |
| } |
| } |
| updateObjects(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.IWorkbenchPart#dispose() |
| */ |
| public void dispose() { |
| getSite().getPage().removeSelectionListener( IDebugUIConstants.ID_DEBUG_VIEW, this ); |
| JFaceResources.getFontRegistry().removeListener( this ); |
| JFaceResources.getColorRegistry().removeListener( this ); |
| getEditorPreferenceStore().removePropertyChangeListener( this ); |
| CDebugUIPlugin.getDefault().getPreferenceStore().removePropertyChangeListener( this ); |
| |
| if ( fSourceViewerDecorationSupport != null ) { |
| fSourceViewerDecorationSupport.dispose(); |
| fSourceViewerDecorationSupport = null; |
| } |
| |
| if ( fDocumentProvider != null ) { |
| fDocumentProvider.dispose(); |
| fDocumentProvider = null; |
| } |
| |
| if ( fActions != null ) { |
| fActions.clear(); |
| fActions = null; |
| } |
| |
| super.dispose(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.internal.ui.views.disassembly.IDisassemblyListener#inputComputed(org.eclipse.cdt.debug.core.model.ICStackFrame, org.eclipse.core.runtime.IStatus, org.eclipse.ui.IEditorInput) |
| */ |
| public void inputComputed( final ICStackFrame frame, final IStatus status, final IEditorInput input ) { |
| Runnable runnable = new Runnable() { |
| public void run() { |
| if ( isAvailable() ) { |
| if ( fLastStackFrame != null && fLastStackFrame.equals( frame ) ) { |
| fLastStackFrame = null; |
| if ( !status.isOK() ) { |
| setInput( null ); |
| getViewer().setInput( null ); |
| showMessage( status.getMessage() ); |
| return; |
| } |
| } |
| if ( input != null ) { |
| setViewerInput( input ); |
| selectAndReveal( frame, input ); |
| } |
| else { |
| resetViewerInput(); |
| } |
| } |
| } |
| }; |
| asyncExec( runnable ); |
| } |
| |
| /** |
| * Asynchronousy computes the editor input for the given stack frame. |
| * |
| * @param current the current editor input |
| * @param frame the stack frame for which the input is required |
| * @param listener the listener to be notified when the computation is completed |
| */ |
| public void computeInput( final Object current, |
| final ICStackFrame frame, |
| final IDisassemblyListener listener ) { |
| Runnable runnable = new Runnable() { |
| public void run() { |
| IStatus status = Status.OK_STATUS; |
| IEditorInput input = null; |
| if ( current instanceof DisassemblyEditorInput && |
| ((DisassemblyEditorInput)current).contains( frame ) ) { |
| input = (IEditorInput)current; |
| } |
| else { |
| try { |
| input = DisassemblyEditorInput.create( frame ); |
| } |
| catch( DebugException e ) { |
| status = new Status( IStatus.ERROR, |
| CDebugUIPlugin.getUniqueIdentifier(), |
| 0, |
| e.getMessage(), |
| null ); |
| } |
| |
| } |
| listener.inputComputed( frame, status, input ); |
| } |
| }; |
| DebugPlugin.getDefault().asyncExec( runnable ); |
| } |
| |
| protected void selectAndReveal( ICStackFrame frame, IEditorInput input ) { |
| IRegion region = getLineInformation( frame, input ); |
| if ( region != null ) { |
| int start = region.getOffset(); |
| int length = region.getLength(); |
| StyledText widget = getSourceViewer().getTextWidget(); |
| widget.setRedraw( false ); |
| { |
| getSourceViewer().revealRange( start, length ); |
| getSourceViewer().setSelectedRange( start, 0 ); |
| } |
| widget.setRedraw( true ); |
| setInstructionPointer( frame, start, length, getDocumentProvider().getAnnotationModel( input ) ); |
| } |
| } |
| |
| /** |
| * Returns the line information for the given line in the given editor |
| */ |
| private IRegion getLineInformation( ICStackFrame frame, IEditorInput input ) { |
| if ( input instanceof DisassemblyEditorInput ) { |
| int line = ((DisassemblyEditorInput)input).getInstructionLine( frame.getAddress() ); |
| if ( line > 0 ) { |
| try { |
| return getSourceViewer().getDocument().getLineInformation( --line ); |
| } |
| catch( BadLocationException e1 ) { |
| } |
| } |
| } |
| return null; |
| } |
| |
| public IEditorInput getInput() { |
| if ( getSourceViewer() != null ) { |
| Object input = getSourceViewer().getInput(); |
| if ( input instanceof IEditorInput ) |
| return (IEditorInput)input; |
| } |
| return null; |
| } |
| |
| protected void setInput( IEditorInput input ) { |
| getSourceViewer().setInput( input ); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) |
| */ |
| public void createPartControl( Composite parent ) { |
| super.createPartControl( parent ); |
| createViewContextMenu(); |
| createRulerContextMenu(); |
| if ( fSourceViewerDecorationSupport != null ) |
| fSourceViewerDecorationSupport.install( getEditorPreferenceStore() ); |
| } |
| |
| /** |
| * Returns the source viewer decoration support. |
| * |
| * @return the source viewer decoration support |
| */ |
| protected SourceViewerDecorationSupport getSourceViewerDecorationSupport( ISourceViewer viewer ) { |
| if ( fSourceViewerDecorationSupport == null ) { |
| fSourceViewerDecorationSupport = new SourceViewerDecorationSupport( viewer, getOverviewRuler(), getAnnotationAccess(), getSharedColors() ); |
| configureSourceViewerDecorationSupport( fSourceViewerDecorationSupport ); |
| } |
| return fSourceViewerDecorationSupport; |
| } |
| |
| /** |
| * Creates the annotation access for this view. |
| * |
| * @return the created annotation access |
| */ |
| private IAnnotationAccess createAnnotationAccess() { |
| return new DefaultMarkerAnnotationAccess(); |
| } |
| |
| /** |
| * Configures the decoration support for this view's the source viewer. |
| */ |
| private void configureSourceViewerDecorationSupport( SourceViewerDecorationSupport support ) { |
| Iterator e = fAnnotationPreferences.getAnnotationPreferences().iterator(); |
| while( e.hasNext() ) |
| support.setAnnotationPreference( (AnnotationPreference)e.next() ); |
| support.setCursorLinePainterPreferenceKeys( CURRENT_LINE, CURRENT_LINE_COLOR ); |
| } |
| |
| /** |
| * Returns the annotation access. |
| * |
| * @return the annotation access |
| */ |
| private IAnnotationAccess getAnnotationAccess() { |
| if ( fAnnotationAccess == null ) |
| fAnnotationAccess = createAnnotationAccess(); |
| return fAnnotationAccess; |
| } |
| |
| private ISharedTextColors getSharedColors() { |
| ISharedTextColors sharedColors = CDebugUIPlugin.getDefault().getSharedTextColors(); |
| return sharedColors; |
| } |
| |
| private IPreferenceStore getEditorPreferenceStore() { |
| return EditorsUI.getPreferenceStore(); |
| } |
| |
| public DisassemblyDocumentProvider getDocumentProvider() { |
| if ( this.fDocumentProvider == null ) |
| this.fDocumentProvider = new DisassemblyDocumentProvider(); |
| return this.fDocumentProvider; |
| } |
| |
| protected void setInstructionPointer( ICStackFrame frame, int start, int length, IAnnotationModel model ) { |
| Assert.isNotNull( model ); |
| boolean tos = isTopStackFrame( frame ); |
| DisassemblyInstructionPointerAnnotation instPtrAnnotation = new DisassemblyInstructionPointerAnnotation( frame, tos ); |
| Position position = new Position( start, length ); |
| DisassemblyInstructionPointerAnnotation oldPointer = getCurrentInstructionPointer(); |
| if ( oldPointer != null ) |
| model.removeAnnotation( oldPointer ); |
| model.addAnnotation( instPtrAnnotation, position ); |
| setCurrentInstructionPointer( instPtrAnnotation ); |
| } |
| |
| private boolean isTopStackFrame( ICStackFrame stackFrame ) { |
| IThread thread = stackFrame.getThread(); |
| boolean tos = false; |
| try { |
| tos = stackFrame.equals( thread.getTopStackFrame() ); |
| } |
| catch( DebugException e ) { |
| } |
| return tos; |
| } |
| |
| private DisassemblyInstructionPointerAnnotation getCurrentInstructionPointer() { |
| return fInstrPointerAnnotation; |
| } |
| |
| private void setCurrentInstructionPointer( DisassemblyInstructionPointerAnnotation instrPointer ) { |
| fInstrPointerAnnotation = instrPointer; |
| } |
| |
| protected void removeCurrentInstructionPointer( IAnnotationModel model ) { |
| Assert.isNotNull( model ); |
| DisassemblyInstructionPointerAnnotation instrPointer = getCurrentInstructionPointer(); |
| if ( instrPointer != null ) { |
| model.removeAnnotation( instrPointer ); |
| setCurrentInstructionPointer( null ); |
| } |
| } |
| |
| protected void resetViewerInput() { |
| SourceViewer viewer = getSourceViewer(); |
| if ( viewer == null ) |
| return; |
| |
| IEditorInput input = DisassemblyEditorInput.EMPTY_EDITOR_INPUT; |
| setInput( input ); |
| showViewer(); |
| try { |
| getDocumentProvider().connect( input ); |
| } |
| catch( CoreException e ) { |
| // never happens |
| } |
| IAnnotationModel model = getDocumentProvider().getAnnotationModel( input ); |
| getSourceViewer().setDocument( getDocumentProvider().getDocument( input ), model ); |
| removeCurrentInstructionPointer( model ); |
| |
| updateObjects(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.AbstractDebugView#becomesHidden() |
| */ |
| protected void becomesHidden() { |
| selectionChanged( null, new StructuredSelection() ); |
| super.becomesHidden(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.AbstractDebugView#becomesVisible() |
| */ |
| protected void becomesVisible() { |
| super.becomesVisible(); |
| IViewPart part = getSite().getPage().findView( IDebugUIConstants.ID_DEBUG_VIEW ); |
| if ( part != null ) { |
| ISelection selection = getSite().getPage().getSelection( IDebugUIConstants.ID_DEBUG_VIEW ); |
| selectionChanged( part, selection ); |
| } |
| } |
| |
| /** |
| * Returns the overview ruler. |
| * |
| * @return the overview ruler |
| */ |
| private IOverviewRuler getOverviewRuler() { |
| if ( fOverviewRuler == null ) |
| fOverviewRuler = createOverviewRuler( getSharedColors() ); |
| return fOverviewRuler; |
| } |
| |
| protected String getRulerContextMenuId() { |
| return this.fRulerContextMenuId; |
| } |
| |
| private void setRulerContextMenuId( String rulerContextMenuId ) { |
| Assert.isNotNull( rulerContextMenuId ); |
| this.fRulerContextMenuId = rulerContextMenuId; |
| } |
| |
| protected String getViewContextMenuId() { |
| return this.fViewContextMenuId; |
| } |
| |
| private void setViewContextMenuId( String viewContextMenuId ) { |
| Assert.isNotNull( viewContextMenuId ); |
| this.fViewContextMenuId = viewContextMenuId; |
| } |
| |
| /** |
| * Sets up the ruler context menu before it is made visible. |
| * |
| * @param menu the menu |
| */ |
| protected void rulerContextMenuAboutToShow( IMenuManager menu ) { |
| menu.add( new Separator( ITextEditorActionConstants.GROUP_REST ) ); |
| menu.add( new Separator( IWorkbenchActionConstants.MB_ADDITIONS ) ); |
| addAction( menu, IInternalCDebugUIConstants.ACTION_TOGGLE_BREAKPOINT ); |
| addAction( menu, IInternalCDebugUIConstants.ACTION_ENABLE_DISABLE_BREAKPOINT ); |
| addAction( menu, IInternalCDebugUIConstants.ACTION_BREAKPOINT_PROPERTIES ); |
| } |
| |
| /** |
| * Sets up the view context menu before it is made visible. |
| * |
| * @param menu the menu |
| */ |
| protected void viewContextMenuAboutToShow( IMenuManager menu ) { |
| menu.add( new Separator( ITextEditorActionConstants.GROUP_REST ) ); |
| menu.add( new Separator( IWorkbenchActionConstants.MB_ADDITIONS ) ); |
| } |
| |
| /** |
| * Convenience method to add the action installed under the given action id to the specified group of the menu. |
| * @param menu the menu to add the action to |
| * @param group the group in the menu |
| * @param actionId the id of the action to add |
| */ |
| protected final void addAction( IMenuManager menu, String group, String actionId ) { |
| IAction action = getAction( actionId ); |
| if ( action != null ) { |
| if ( action instanceof IUpdate ) |
| ((IUpdate)action).update(); |
| IMenuManager subMenu = menu.findMenuUsingPath( group ); |
| if ( subMenu != null ) |
| subMenu.add( action ); |
| else |
| menu.appendToGroup( group, action ); |
| } |
| } |
| |
| /** |
| * Convenience method to add the action installed under the given action id to the given menu. |
| * @param menu the menu to add the action to |
| * @param actionId the id of the action to be added |
| */ |
| protected final void addAction( IMenuManager menu, String actionId ) { |
| IAction action = getAction( actionId ); |
| if ( action != null ) { |
| if ( action instanceof IUpdate ) |
| ((IUpdate)action).update(); |
| menu.add( action ); |
| } |
| } |
| |
| protected Menu getRulerContextMenu() { |
| return this.fRulerContextMenu; |
| } |
| |
| private void setRulerContextMenu( Menu rulerContextMenu ) { |
| this.fRulerContextMenu = rulerContextMenu; |
| } |
| |
| private void createViewContextMenu() { |
| String id = getViewContextMenuId(); |
| MenuManager manager = new MenuManager( id, id ); |
| manager.setRemoveAllWhenShown( true ); |
| manager.addMenuListener( getContextMenuListener() ); |
| StyledText styledText = getSourceViewer().getTextWidget(); |
| setTextContextMenu( manager.createContextMenu( styledText ) ); |
| styledText.setMenu( getTextContextMenu() ); |
| |
| // register the context menu such that other plugins may contribute to it |
| if ( getSite() != null ) { |
| getSite().registerContextMenu( id, manager, getSourceViewer() ); |
| } |
| } |
| |
| private void createRulerContextMenu() { |
| String id = getRulerContextMenuId(); |
| MenuManager manager = new MenuManager( id, id ); |
| manager.setRemoveAllWhenShown( true ); |
| manager.addMenuListener( getContextMenuListener() ); |
| Control rulerControl = fVerticalRuler.getControl(); |
| setRulerContextMenu( manager.createContextMenu( rulerControl ) ); |
| rulerControl.setMenu( getRulerContextMenu() ); |
| rulerControl.addMouseListener( getRulerMouseListener() ); |
| |
| if ( getSite() != null ) { |
| getSite().registerContextMenu( id, manager, getSourceViewer() ); |
| } |
| } |
| |
| private Menu getTextContextMenu() { |
| return this.fTextContextMenu; |
| } |
| |
| private void setTextContextMenu( Menu textContextMenu ) { |
| this.fTextContextMenu = textContextMenu; |
| } |
| |
| public void setAction( String actionID, IAction action ) { |
| Assert.isNotNull( actionID ); |
| if ( action == null ) { |
| action = (IAction)fActions.remove( actionID ); |
| } |
| else { |
| fActions.put( actionID, action ); |
| } |
| } |
| |
| public IAction getAction( String actionID ) { |
| Assert.isNotNull( actionID ); |
| return (IAction)fActions.get( actionID ); |
| } |
| |
| private IVerticalRuler getVerticalRuler() { |
| return this.fVerticalRuler; |
| } |
| |
| private TextPresentation createTextPresentation( IRegion[] regions ) { |
| TextPresentation p = new TextPresentation(); |
| for ( int i = 0; i < regions.length; ++i ) { |
| p.addStyleRange( new StyleRange( regions[i].getOffset(), |
| regions[i].getLength(), |
| CDebugUIPlugin.getPreferenceColor( IInternalCDebugUIConstants.DISASSEMBLY_SOURCE_LINE_COLOR ), |
| null ) ); |
| } |
| return p; |
| } |
| |
| protected void refresh( IDisassembly disassembly ) { |
| if ( !(getInput() instanceof DisassemblyEditorInput) || !disassembly.equals( ((DisassemblyEditorInput)getInput()).getDisassembly() ) ) |
| return; |
| resetViewerInput(); |
| if ( !isAvailable() || !isVisible() ) |
| return; |
| IAdaptable context = DebugUITools.getDebugContext(); |
| if ( context instanceof ICStackFrame ) { |
| fLastStackFrame = (ICStackFrame)context; |
| IEditorInput input = getInput(); |
| if ( input instanceof DisassemblyEditorInput ) |
| setViewerInput( DisassemblyEditorInput.PENDING_EDITOR_INPUT ); |
| computeInput( input, (ICStackFrame)context, this ); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.part.PageBookView#partActivated(org.eclipse.ui.IWorkbenchPart) |
| */ |
| public void partActivated( IWorkbenchPart part ) { |
| if ( this.equals( part ) ) { |
| CDebugCorePlugin.getDefault().getPluginPreferences().setValue( ICDebugConstants.PREF_INSTRUCTION_STEP_MODE_ON, true ); |
| } |
| super.partActivated( part ); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.part.PageBookView#partDeactivated(org.eclipse.ui.IWorkbenchPart) |
| */ |
| public void partDeactivated( IWorkbenchPart part ) { |
| if ( this.equals( part ) ) { |
| CDebugCorePlugin.getDefault().getPluginPreferences().setValue( ICDebugConstants.PREF_INSTRUCTION_STEP_MODE_ON, false ); |
| } |
| super.partDeactivated( part ); |
| } |
| } |