blob: 7eaa31ff96b37a67a07df77e18fb7ae13ebecae8 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006 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
* QNX Software Systems - Mikhail Khodjaiants - Registers View (Bug 53640)
*******************************************************************************/
package org.eclipse.debug.internal.ui.views.variables.details;
import java.util.Iterator;
import java.util.ResourceBundle;
import org.eclipse.core.commands.operations.IUndoContext;
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.core.runtime.jobs.Job;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IDebugElement;
import org.eclipse.debug.core.model.IExpression;
import org.eclipse.debug.core.model.IValue;
import org.eclipse.debug.core.model.IVariable;
import org.eclipse.debug.internal.ui.DebugPluginImages;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.internal.ui.IDebugHelpContextIds;
import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
import org.eclipse.debug.internal.ui.LazyModelPresentation;
import org.eclipse.debug.internal.ui.VariablesViewModelPresentation;
import org.eclipse.debug.internal.ui.actions.variables.details.DetailPaneAssignValueAction;
import org.eclipse.debug.internal.ui.actions.variables.details.DetailPaneMaxLengthAction;
import org.eclipse.debug.internal.ui.actions.variables.details.DetailPaneWordWrapAction;
import org.eclipse.debug.internal.ui.preferences.IDebugPreferenceConstants;
import org.eclipse.debug.internal.ui.views.variables.IndexedValuePartition;
import org.eclipse.debug.internal.ui.views.variables.StatusLineContributionItem;
import org.eclipse.debug.ui.IDebugModelPresentation;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.debug.ui.IDebugView;
import org.eclipse.debug.ui.IValueDetailListener;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.commands.ActionHandler;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.IFindReplaceTarget;
import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.IUndoManager;
import org.eclipse.jface.text.IUndoManagerExtension;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.console.actions.TextViewerAction;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.operations.OperationHistoryActionHandler;
import org.eclipse.ui.operations.RedoActionHandler;
import org.eclipse.ui.operations.UndoActionHandler;
import org.eclipse.ui.progress.WorkbenchJob;
import org.eclipse.ui.texteditor.FindReplaceAction;
import org.eclipse.ui.texteditor.IAbstractTextEditorHelpContextIds;
import org.eclipse.ui.texteditor.ITextEditorActionConstants;
import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds;
import com.ibm.icu.text.MessageFormat;
/**
* This detail pane uses a source viewer to display detailed information about the current
* selection. It incorporates a large number of actions into its context menu. It is the
* default detail pane.
*
* @see DefaultDetailPaneFactory
* @since 3.3
*
*/
public class DefaultDetailPane extends AbstractDetailPane implements IAdaptable, IPropertyChangeListener{
/**
* These are the IDs for the actions in the context menu
*/
protected static final String DETAIL_COPY_ACTION = ActionFactory.COPY.getId() + ".SourceDetailPane"; //$NON-NLS-1$
protected static final String DETAIL_SELECT_ALL_ACTION = IDebugView.SELECT_ALL_ACTION + ".SourceDetailPane"; //$NON-NLS-1$
protected static final String DETAIL_PASTE_ACTION = ActionFactory.PASTE.getId();
protected static final String DETAIL_CUT_ACTION = ActionFactory.CUT.getId();
protected static final String DETAIL_FIND_REPLACE_TEXT_ACTION = "FindReplaceText"; //$NON-NLS-1$
protected static final String DETAIL_CONTENT_ASSIST_ACTION = "ContentAssist"; //$NON-NLS-1$
protected static final String DETAIL_ASSIGN_VALUE_ACTION = "AssignValue"; //$NON-NLS-1$
protected static final String DETAIL_WORD_WRAP_ACTION = IDebugPreferenceConstants.PREF_DETAIL_PANE_WORD_WRAP;
protected static final String DETAIL_MAX_LENGTH_ACTION = "MaxLength"; //$NON-NLS-1$
/**
* The ID, name and description of this viewer are stored in contants so that the class
* does not have to be instantiated to access them.
*/
public static final String ID = DetailMessages.DefaultDetailPane_0;
public static final String NAME = DetailMessages.DefaultDetailPane_1;
public static final String DESCRIPTION = DetailMessages.DefaultDetailPane_57;
/**
* Data structure for the position label value.
*/
private static class PositionLabelValue {
public int fValue;
public String toString() {
return String.valueOf(fValue);
}
}
/**
* Internal interface for a cursor listener. I.e. aggregation
* of mouse and key listener.
* @since 3.0
*/
interface ICursorListener extends MouseListener, KeyListener {
}
/**
* Job to compute the details for a selection
*/
class DetailJob extends Job implements IValueDetailListener {
private IStructuredSelection fElements;
private IDebugModelPresentation fModel;
private boolean fFirst = true;
// whether a result was collected
private boolean fComputed = false;
private IProgressMonitor fMonitor;
public DetailJob(IStructuredSelection elements, IDebugModelPresentation model) {
super("compute variable details"); //$NON-NLS-1$
setSystem(true);
fElements = elements;
fModel = model;
}
/* (non-Javadoc)
* @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
*/
protected IStatus run(IProgressMonitor monitor) {
fMonitor = monitor;
Iterator iterator = fElements.iterator();
while (iterator.hasNext()) {
if (monitor.isCanceled()) {
break;
}
Object element = iterator.next();
IValue val = null;
if (element instanceof IVariable) {
try {
val = ((IVariable)element).getValue();
} catch (DebugException e) {
detailComputed(null, e.getStatus().getMessage());
}
} else if (element instanceof IExpression) {
val = ((IExpression)element).getValue();
}
if (val instanceof IndexedValuePartition) {
val = null;
}
if (val != null && !monitor.isCanceled()) {
fModel.computeDetail(val, this);
synchronized (this) {
try {
// wait for a max of 30 seconds for result, then cancel
wait(30000);
if (!fComputed) {
fMonitor.setCanceled(true);
}
} catch (InterruptedException e) {
break;
}
}
}
}
return Status.OK_STATUS;
}
/* (non-Javadoc)
* @see org.eclipse.core.runtime.jobs.Job#canceling()
*/
protected void canceling() {
super.canceling();
synchronized (this) {
notifyAll();
}
}
/* (non-Javadoc)
* @see org.eclipse.debug.ui.IValueDetailListener#detailComputed(org.eclipse.debug.core.model.IValue, java.lang.String)
*/
public void detailComputed(IValue value, final String result) {
synchronized (this) {
fComputed = true;
}
if (!fMonitor.isCanceled()) {
WorkbenchJob append = new WorkbenchJob("append details") { //$NON-NLS-1$
public IStatus runInUIThread(IProgressMonitor monitor) {
if (!fMonitor.isCanceled()) {
String insert = result;
int length = 0;
if (!fFirst) {
length = getDetailDocument().getLength();
}
if (length > 0) {
insert = "\n" + result; //$NON-NLS-1$
}
try {
int max = DebugUIPlugin.getDefault().getPreferenceStore().getInt(IInternalDebugUIConstants.PREF_MAX_DETAIL_LENGTH);
if (max > 0 && insert.length() > max) {
insert = insert.substring(0, max) + "..."; //$NON-NLS-1$
}
if (fFirst) {
getDetailDocument().set(insert);
fFirst = false;
} else {
getDetailDocument().replace(length, 0,insert);
}
} catch (BadLocationException e) {
DebugUIPlugin.log(e);
}
}
return Status.OK_STATUS;
}
};
append.setSystem(true);
append.schedule();
}
synchronized (this) {
notifyAll();
}
}
}
/**
* The model presentation used to produce the string details for a
* selected variable.
*/
private VariablesViewModelPresentation fModelPresentation;
private String fDebugModelIdentifier;
/**
* Controls the status line while the details area has focus.
* Displays the current cursor position in the text (line:character).
*/
private StatusLineContributionItem fStatusLineItem;
/**
* The source viewer in which the computed string detail
* of selected variables will be displayed.
*/
private SourceViewer fSourceViewer;
/**
* The last selection displayed in the source viewer.
*/
private IStructuredSelection fLastDisplayed = null;
/**
* Variables used to create the detailed information for a selection
*/
private IDocument fDetailDocument;
private DetailJob fDetailJob = null;
private final String fPositionLabelPattern = DetailMessages.DefaultDetailPane_56;
private final PositionLabelValue fLineLabel = new PositionLabelValue();
private final PositionLabelValue fColumnLabel = new PositionLabelValue();
private final Object[] fPositionLabelPatternArguments = new Object[] {
fLineLabel, fColumnLabel };
private ICursorListener fCursorListener;
/* (non-Javadoc)
* @see org.eclipse.debug.internal.ui.views.variables.details.AbstractDetailPane#init(org.eclipse.ui.IWorkbenchPartSite)
*/
public void init(IWorkbenchPartSite benchPartSite){
super.init(benchPartSite);
}
/* (non-Javadoc)
* @see org.eclipse.debug.ui.IDetailPane#createControl(org.eclipse.swt.widgets.Composite)
*/
public Control createControl(Composite parent) {
fModelPresentation = new VariablesViewModelPresentation();
createSourceViewer(parent);
createActions();
DebugUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this);
JFaceResources.getFontRegistry().addListener(this);
fStatusLineItem = new StatusLineContributionItem("ModeContributionItem"); //$NON-NLS-1$
IStatusLineManager manager= getViewSite().getActionBars().getStatusLineManager();
manager.add(fStatusLineItem);
return fSourceViewer.getControl();
}
/**
* Creates the source viewer in the given parent composite
*
* @param parent Parent composite to create the source viewer in
*/
private void createSourceViewer(Composite parent) {
// Create & configure a SourceViewer
fSourceViewer = new SourceViewer(parent, null, SWT.V_SCROLL | SWT.H_SCROLL);
fSourceViewer.setDocument(getDetailDocument());
fSourceViewer.getTextWidget().setFont(JFaceResources.getFont(IInternalDebugUIConstants.DETAIL_PANE_FONT));
getDetailDocument().addDocumentListener(new IDocumentListener() {
public void documentAboutToBeChanged(DocumentEvent event) {}
public void documentChanged(DocumentEvent event) {
updateSelectionDependentActions();
}
});
fSourceViewer.setEditable(false);
PlatformUI.getWorkbench().getHelpSystem().setHelp(fSourceViewer.getTextWidget(), IDebugHelpContextIds.DETAIL_PANE);
Control control = fSourceViewer.getControl();
GridData gd = new GridData(GridData.FILL_BOTH);
control.setLayoutData(gd);
// Add the selection listener so selection dependant actions get updated.
fSourceViewer.getSelectionProvider().addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
updateSelectionDependentActions();
}
});
// Add a focus listener to update actions when details area gains focus
fSourceViewer.getControl().addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
getViewSite().setSelectionProvider(fSourceViewer.getSelectionProvider());
setGlobalAction(IDebugView.SELECT_ALL_ACTION, getAction(DETAIL_SELECT_ALL_ACTION));
setGlobalAction(IDebugView.CUT_ACTION, getAction(DETAIL_CUT_ACTION));
setGlobalAction(IDebugView.COPY_ACTION, getAction(DETAIL_COPY_ACTION));
setGlobalAction(IDebugView.PASTE_ACTION, getAction(DETAIL_PASTE_ACTION));
setGlobalAction(IDebugView.FIND_ACTION, getAction(DETAIL_FIND_REPLACE_TEXT_ACTION));
IAction action = getAction(DETAIL_ASSIGN_VALUE_ACTION);
setGlobalAction(action.getActionDefinitionId(), action);
action = getAction(DETAIL_CONTENT_ASSIST_ACTION);
setGlobalAction(action.getActionDefinitionId(),action);
getViewSite().getActionBars().updateActionBars();
updateAction(DETAIL_FIND_REPLACE_TEXT_ACTION);
}
public void focusLost(FocusEvent e) {
getViewSite().setSelectionProvider(null);
setGlobalAction(IDebugView.SELECT_ALL_ACTION, null);
setGlobalAction(IDebugView.CUT_ACTION, null);
setGlobalAction(IDebugView.COPY_ACTION, null);
setGlobalAction(IDebugView.PASTE_ACTION, null);
setGlobalAction(IDebugView.FIND_ACTION, null);
setGlobalAction(getAction(DETAIL_ASSIGN_VALUE_ACTION).getActionDefinitionId(), null);
setGlobalAction(getAction(DETAIL_CONTENT_ASSIST_ACTION).getActionDefinitionId(), null);
getViewSite().getActionBars().updateActionBars();
}
});
fSourceViewer.getTextWidget().addMouseListener(getCursorListener());
fSourceViewer.getTextWidget().addKeyListener(getCursorListener());
// Add a context menu to the detail area
createDetailContextMenu(fSourceViewer.getTextWidget());
}
/**
* Creates the actions to add to the context menu
*/
private void createActions() {
TextViewerAction textAction= new TextViewerAction(fSourceViewer, ISourceViewer.CONTENTASSIST_PROPOSALS);
textAction.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
textAction.configureAction(DetailMessages.DefaultDetailPane_Co_ntent_Assist_3, "",""); //$NON-NLS-1$ //$NON-NLS-2$
textAction.setImageDescriptor(DebugPluginImages.getImageDescriptor(IDebugUIConstants.IMG_ELCL_CONTENT_ASSIST));
textAction.setHoverImageDescriptor(DebugPluginImages.getImageDescriptor(IDebugUIConstants.IMG_LCL_CONTENT_ASSIST));
textAction.setDisabledImageDescriptor(DebugPluginImages.getImageDescriptor(IDebugUIConstants.IMG_DLCL_CONTENT_ASSIST));
PlatformUI.getWorkbench().getHelpSystem().setHelp(textAction, IDebugHelpContextIds.DETAIL_PANE_CONTENT_ASSIST_ACTION);
setAction(DETAIL_CONTENT_ASSIST_ACTION, textAction);
ActionHandler actionHandler = new ActionHandler(textAction);
IHandlerService handlerService = (IHandlerService) getViewSite().getService(IHandlerService.class);
handlerService.activateHandler(textAction.getActionDefinitionId(), actionHandler);
textAction= new TextViewerAction(fSourceViewer, ITextOperationTarget.SELECT_ALL);
textAction.configureAction(DetailMessages.DefaultDetailPane_Select__All_5, "", ""); //$NON-NLS-1$ //$NON-NLS-2$
textAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.SELECT_ALL);
PlatformUI.getWorkbench().getHelpSystem().setHelp(textAction, IDebugHelpContextIds.DETAIL_PANE_SELECT_ALL_ACTION);
setAction(DETAIL_SELECT_ALL_ACTION, textAction);
textAction= new TextViewerAction(fSourceViewer, ITextOperationTarget.COPY);
textAction.configureAction(DetailMessages.DefaultDetailPane__Copy_8, "", ""); //$NON-NLS-1$ //$NON-NLS-2$
textAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.COPY);
PlatformUI.getWorkbench().getHelpSystem().setHelp(textAction, IDebugHelpContextIds.DETAIL_PANE_COPY_ACTION);
setAction(DETAIL_COPY_ACTION, textAction);
textAction= new TextViewerAction(fSourceViewer, ITextOperationTarget.CUT);
textAction.configureAction(DetailMessages.DefaultDetailPane_Cu_t_11, "", ""); //$NON-NLS-1$ //$NON-NLS-2$
textAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.CUT);
PlatformUI.getWorkbench().getHelpSystem().setHelp(textAction, IDebugHelpContextIds.DETAIL_PANE_CUT_ACTION);
setAction(DETAIL_CUT_ACTION, textAction);
textAction= new TextViewerAction(fSourceViewer, ITextOperationTarget.PASTE);
textAction.configureAction(DetailMessages.DefaultDetailPane__Paste_14, "", ""); //$NON-NLS-1$ //$NON-NLS-2$
textAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.PASTE);
PlatformUI.getWorkbench().getHelpSystem().setHelp(textAction, IDebugHelpContextIds.DETAIL_PANE_PASTE_ACTION);
setAction(ActionFactory.PASTE.getId(), textAction);
setSelectionDependantAction(DETAIL_COPY_ACTION);
setSelectionDependantAction(DETAIL_CUT_ACTION);
setSelectionDependantAction(DETAIL_PASTE_ACTION);
// TODO: Still using "old" resource access
ResourceBundle bundle= ResourceBundle.getBundle("org.eclipse.debug.internal.ui.views.variables.VariablesViewResourceBundleMessages"); //$NON-NLS-1$
IAction action = new FindReplaceAction(bundle, "find_replace_action_", getWorkbenchPartSite().getPart()); //$NON-NLS-1$
action.setActionDefinitionId(IWorkbenchActionDefinitionIds.FIND_REPLACE);
PlatformUI.getWorkbench().getHelpSystem().setHelp(action, IDebugHelpContextIds.DETAIL_PANE_FIND_REPLACE_ACTION);
setAction(DETAIL_FIND_REPLACE_TEXT_ACTION, action);
updateSelectionDependentActions();
action = new DetailPaneWordWrapAction(fSourceViewer);
setAction(DETAIL_WORD_WRAP_ACTION, action);
action = new DetailPaneMaxLengthAction(getWorkbenchPartSite().getShell());
setAction(DETAIL_MAX_LENGTH_ACTION,action);
action = new DetailPaneAssignValueAction(fSourceViewer,getViewSite());
setAction(DETAIL_ASSIGN_VALUE_ACTION, action);
}
/**
* Create the context menu particular to the detail pane. Note that anyone
* wishing to contribute an action to this menu must use
* <code>IDebugUIConstants.VARIABLE_VIEW_DETAIL_ID</code> as the
* <code>targetID</code> in the extension XML.
*/
protected void createDetailContextMenu(Control menuControl) {
MenuManager menuMgr= new MenuManager();
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager mgr) {
fillDetailContextMenu(mgr);
}
});
Menu menu= menuMgr.createContextMenu(menuControl);
menuControl.setMenu(menu);
getViewSite().registerContextMenu(IDebugUIConstants.VARIABLE_VIEW_DETAIL_ID, menuMgr, fSourceViewer.getSelectionProvider());
}
/**
* Adds items to the detail pane's context menu including any extension defined
* actions.
*
* @param menu The menu to add the item to.
*/
protected void fillDetailContextMenu(IMenuManager menu) {
menu.add(new Separator(IDebugUIConstants.VARIABLE_GROUP));
menu.add(getAction(DETAIL_ASSIGN_VALUE_ACTION));
menu.add(getAction(DETAIL_CONTENT_ASSIST_ACTION));
menu.add(new Separator());
menu.add(getAction(DETAIL_CUT_ACTION));
menu.add(getAction(DETAIL_COPY_ACTION));
menu.add(getAction(DETAIL_PASTE_ACTION));
menu.add(getAction(DETAIL_SELECT_ALL_ACTION));
menu.add(new Separator("FIND")); //$NON-NLS-1$
menu.add(getAction(DETAIL_FIND_REPLACE_TEXT_ACTION));
menu.add(new Separator());
menu.add(getAction(DETAIL_WORD_WRAP_ACTION));
menu.add(getAction(DETAIL_MAX_LENGTH_ACTION));
menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
}
/* (non-Javadoc)
* @see org.eclipse.debug.ui.IDetailPane#display(org.eclipse.jface.viewers.IStructuredSelection)
*/
public void display(IStructuredSelection selection) {
if (selection == null){
clearSourceViewer();
return;
}
fLastDisplayed = selection;
fSourceViewer.setEditable(true);
if (selection.isEmpty()){
clearSourceViewer();
return;
}
Object firstElement = selection.getFirstElement();
if (firstElement != null && firstElement instanceof IDebugElement) {
String modelID = ((IDebugElement)firstElement).getModelIdentifier();
setDebugModel(modelID);
}
IAction assignAction = getAction(DETAIL_ASSIGN_VALUE_ACTION);
if (assignAction instanceof DetailPaneAssignValueAction){
((DetailPaneAssignValueAction)assignAction).updateCurrentVariable(selection);
}
synchronized (this) {
if (fDetailJob != null) {
fDetailJob.cancel();
}
fDetailJob = new DetailJob(selection,fModelPresentation);
fDetailJob.schedule();
}
}
public boolean setFocus(){
if (fSourceViewer != null){
fSourceViewer.getTextWidget().setFocus();
return true;
}
return false;
}
/* (non-Javadoc)
* @see org.eclipse.debug.internal.ui.views.variables.details.AbstractDetailPane#dispose()
*/
public void dispose(){
super.dispose();
if (fDetailJob != null) fDetailJob.cancel();
if (fModelPresentation != null) fModelPresentation.dispose();
fDebugModelIdentifier = null; // Setting this to null makes sure the source viewer is reconfigured with the model presentation after disposal
if (fSourceViewer != null && fSourceViewer.getControl() != null) fSourceViewer.getControl().dispose();
disposeUndoRedoAction(ITextEditorActionConstants.UNDO);
disposeUndoRedoAction(ITextEditorActionConstants.REDO);
getViewSite().getActionBars().getStatusLineManager().remove(fStatusLineItem);
DebugUIPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this);
JFaceResources.getFontRegistry().removeListener(this);
}
/* (non-Javadoc)
* @see org.eclipse.debug.ui.IDetailPane#getDescription()
*/
public String getDescription() {
return DESCRIPTION;
}
/* (non-Javadoc)
* @see org.eclipse.debug.ui.IDetailPane#getID()
*/
public String getID() {
return ID;
}
/* (non-Javadoc)
* @see org.eclipse.debug.ui.IDetailPane#getName()
*/
public String getName() {
return NAME;
}
/* (non-Javadoc)
* @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
*/
public Object getAdapter(Class required) {
if (IFindReplaceTarget.class.equals(required)) {
return fSourceViewer.getFindReplaceTarget();
}
if (ITextViewer.class.equals(required)) {
return fSourceViewer;
}
return null;
}
/**
* Lazily instantiate and return a Document for the detail pane text viewer.
*/
protected IDocument getDetailDocument() {
if (fDetailDocument == null) {
fDetailDocument = new Document();
}
return fDetailDocument;
}
/**
* Clears the source viewer, removes all text.
*/
protected void clearSourceViewer(){
if (fDetailJob != null) {
fDetailJob.cancel();
}
fLastDisplayed = null;
fDetailDocument.set(""); //$NON-NLS-1$
fSourceViewer.setEditable(false);
}
/**
* Configures the details viewer for the debug model
* currently being displayed
*/
protected void configureDetailsViewer() {
LazyModelPresentation mp = (LazyModelPresentation)fModelPresentation.getPresentation(getDebugModel());
SourceViewerConfiguration svc = null;
if (mp != null) {
try {
svc = mp.newDetailsViewerConfiguration();
} catch (CoreException e) {
DebugUIPlugin.errorDialog(getViewSite().getShell(), DetailMessages.DefaultDetailPane_Error_1, DetailMessages.DefaultDetailPane_2, e);
}
}
if (svc == null) {
svc = new SourceViewerConfiguration();
fSourceViewer.setEditable(false);
}
fSourceViewer.unconfigure();
fSourceViewer.configure(svc);
//update actions that depend on the configuration of the source viewer
updateAction(DETAIL_CONTENT_ASSIST_ACTION);
updateAction(DETAIL_ASSIGN_VALUE_ACTION);
createUndoRedoActions();
}
/**
* @return The formatted string describing cursor position
*/
protected String getCursorPosition() {
if (fSourceViewer == null) {
return ""; //$NON-NLS-1$
}
StyledText styledText= fSourceViewer.getTextWidget();
int caret= styledText.getCaretOffset();
IDocument document= fSourceViewer.getDocument();
if (document == null) {
return ""; //$NON-NLS-1$
}
try {
int line= document.getLineOfOffset(caret);
int lineOffset= document.getLineOffset(line);
int tabWidth= styledText.getTabs();
int column= 0;
for (int i= lineOffset; i < caret; i++)
if ('\t' == document.getChar(i)) {
column += tabWidth - (tabWidth == 0 ? 0 : column % tabWidth);
} else {
column++;
}
fLineLabel.fValue= line + 1;
fColumnLabel.fValue= column + 1;
return MessageFormat.format(fPositionLabelPattern, fPositionLabelPatternArguments);
} catch (BadLocationException x) {
return ""; //$NON-NLS-1$
}
}
/**
* Returns this view's "cursor" listener to be installed on the view's
* associated details viewer. This listener is listening to key and mouse button events.
* It triggers the updating of the status line.
*
* @return the listener
*/
private ICursorListener getCursorListener() {
if (fCursorListener == null) {
fCursorListener= new ICursorListener() {
public void keyPressed(KeyEvent e) {
fStatusLineItem.setText(getCursorPosition());
}
public void keyReleased(KeyEvent e) {
}
public void mouseDoubleClick(MouseEvent e) {
}
public void mouseDown(MouseEvent e) {
}
public void mouseUp(MouseEvent e) {
fStatusLineItem.setText(getCursorPosition());
}
};
}
return fCursorListener;
}
/**
* Returns the identifier of the debug model being displayed
* in this view, or <code>null</code> if none.
*
* @return debug model identifier
*/
protected String getDebugModel() {
return fDebugModelIdentifier;
}
/**
* Sets the identifier of the debug model being displayed
* in this view, or <code>null</code> if none.
*
* @param id debug model identifier of the type of debug
* elements being displayed in this view
*/
protected void setDebugModel(String id) {
if (id != fDebugModelIdentifier) {
fDebugModelIdentifier = id;
configureDetailsViewer();
}
}
/**
* Creates this editor's undo/re-do actions.
* <p>
* Subclasses may override or extend.</p>
*
* @since 3.2
*/
protected void createUndoRedoActions() {
disposeUndoRedoAction(ITextEditorActionConstants.UNDO);
disposeUndoRedoAction(ITextEditorActionConstants.REDO);
IUndoContext undoContext= getUndoContext();
if (undoContext != null) {
// Use actions provided by global undo/re-do
// Create the undo action
OperationHistoryActionHandler undoAction= new UndoActionHandler(getViewSite(), undoContext);
PlatformUI.getWorkbench().getHelpSystem().setHelp(undoAction, IAbstractTextEditorHelpContextIds.UNDO_ACTION);
undoAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.UNDO);
setAction(ITextEditorActionConstants.UNDO, undoAction);
setGlobalAction(ITextEditorActionConstants.UNDO, undoAction);
// Create the re-do action.
OperationHistoryActionHandler redoAction= new RedoActionHandler(getViewSite(), undoContext);
PlatformUI.getWorkbench().getHelpSystem().setHelp(redoAction, IAbstractTextEditorHelpContextIds.REDO_ACTION);
redoAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.REDO);
setAction(ITextEditorActionConstants.REDO, redoAction);
setGlobalAction(ITextEditorActionConstants.REDO, redoAction);
getViewSite().getActionBars().updateActionBars();
}
}
/**
* Disposes of the action with the specified ID
*
* @param actionId the ID of the action to disposed
*/
protected void disposeUndoRedoAction(String actionId) {
OperationHistoryActionHandler action = (OperationHistoryActionHandler) getAction(actionId);
if (action != null) {
action.dispose();
setAction(actionId, null);
}
}
/**
* Returns this editor's viewer's undo manager undo context.
*
* @return the undo context or <code>null</code> if not available
* @since 3.2
*/
private IUndoContext getUndoContext() {
IUndoManager undoManager= fSourceViewer.getUndoManager();
if (undoManager instanceof IUndoManagerExtension)
return ((IUndoManagerExtension)undoManager).getUndoContext();
return null;
}
/* (non-Javadoc)
* @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
*/
public void propertyChange(PropertyChangeEvent event) {
String propertyName= event.getProperty();
if (propertyName.equals(IInternalDebugUIConstants.DETAIL_PANE_FONT)) {
fSourceViewer.getTextWidget().setFont(JFaceResources.getFont(IInternalDebugUIConstants.DETAIL_PANE_FONT));
} else if (propertyName.equals(IInternalDebugUIConstants.PREF_MAX_DETAIL_LENGTH)) {
display(fLastDisplayed);
} else if (propertyName.equals(IDebugPreferenceConstants.PREF_DETAIL_PANE_WORD_WRAP)) {
fSourceViewer.getTextWidget().setWordWrap(DebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IDebugPreferenceConstants.PREF_DETAIL_PANE_WORD_WRAP));
getAction(DETAIL_WORD_WRAP_ACTION).setChecked(DebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IDebugPreferenceConstants.PREF_DETAIL_PANE_WORD_WRAP));
}
}
}