blob: 998525c3643ba461be0e870605e1bef222ca8ddd [file] [log] [blame]
/**********************************************************************
Copyright (c) 2000, 2002 IBM Corp. 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 implementation
**********************************************************************/
package org.eclipse.ui.texteditor;
import java.lang.reflect.InvocationTargetException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.IPluginDescriptor;
import org.eclipse.core.runtime.IPluginPrerequisite;
import org.eclipse.core.runtime.IPluginRegistry;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ST;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.custom.VerifyKeyListener;
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.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ST;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.custom.VerifyKeyListener;
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.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ST;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.custom.VerifyKeyListener;
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.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.jface.action.Action;
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.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IFindReplaceTarget;
import org.eclipse.jface.text.IFindReplaceTargetExtension;
import org.eclipse.jface.text.IMarkRegionTarget;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.IRewriteTarget;
import org.eclipse.jface.text.ITextInputListener;
import org.eclipse.jface.text.ITextListener;
import org.eclipse.jface.text.ITextOperationTarget;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.ITextViewerExtension;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.TextEvent;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.IVerticalRuler;
import org.eclipse.jface.text.source.IVerticalRulerExtension;
import org.eclipse.jface.text.source.IVerticalRulerInfo;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.text.source.SourceViewerConfiguration;
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.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorActionBarContributor;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IKeyBindingService;
import org.eclipse.ui.INavigationLocation;
import org.eclipse.ui.INavigationLocationProvider;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IReusableEditor;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.help.WorkbenchHelp;
import org.eclipse.ui.internal.ActionDescriptor;
import org.eclipse.ui.internal.EditorPluginAction;
import org.eclipse.ui.internal.KeyBindingService;
import org.eclipse.ui.internal.actions.gestures.Capture;
import org.eclipse.ui.internal.actions.gestures.CaptureListener;
import org.eclipse.ui.internal.actions.gestures.Gesture;
import org.eclipse.ui.internal.actions.gestures.Util;
import org.eclipse.ui.internal.texteditor.EditPosition;
import org.eclipse.ui.internal.texteditor.TextEditorPlugin;
import org.eclipse.ui.internal.texteditor.EditPosition;
import org.eclipse.ui.internal.texteditor.TextEditorPlugin;
import org.eclipse.ui.part.EditorActionBarContributor;
import org.eclipse.ui.part.EditorPart;
/**
* Abstract base implementation of a text editor.
* <p>
* Subclasses are responsible for configuring the editor appropriately.
* The standard text editor, <code>TextEditor</code>, is one such example.
* </p>
* <p>
* If a subclass calls <code>setEditorContextMenuId</code> the arguments is
* used as the id under which the editor's context menu is registered for extensions.
* If no id is set, the context menu is registered under <b>[editor_id].EditorContext</b>
* whereby [editor_id] is replaced with the editor's part id. If the editor is instructed to
* run in version 1.0 context menu registration compatibility mode, the latter form of the
* registration even happens if a context menu id has been set via <code>setEditorContextMenuId</code>.
* If no id is set while in compatibility mode, the menu is registered under
* <code>DEFAULT_EDITOR_CONTEXT_MENU_ID</code>.
* </p>
* <p>
* If a subclass calls <code>setRulerContextMenuId</code> the arguments is
* used as the id under which the ruler's context menu is registered for extensions.
* If no id is set, the context menu is registered under <b>[editor_id].RulerContext</b>
* whereby [editor_id] is replaced with the editor's part id. If the editor is instructed to
* run in version 1.0 context menu registration compatibility mode, the latter form of the
* registration even happens if a context menu id has been set via <code>setRulerContextMenuId</code>.
* If no id is set while in compatibility mode, the menu is registered under
* <code>DEFAULT_RULER_CONTEXT_MENU_ID</code>.
* </p>
*
* @see org.eclipse.ui.editors.text.TextEditor
*/
public abstract class AbstractTextEditor extends EditorPart implements ITextEditor, IReusableEditor, ITextEditorExtension, ITextEditorExtension2, INavigationLocationProvider {
/**
* Tag used in xml configuration files to specify editor action contributions.
* Current value: <code>editorContribution</code>
* @since 2.0
*/
private static final String TAG_CONTRIBUTION_TYPE= "editorContribution"; //$NON-NLS-1$
/**
* The text input listener.
*/
private static class TextInputListener implements ITextInputListener {
/** Indicates whether the editor input changed during the process of state validation. */
public boolean inputChanged;
/** Detector for editor input changes during the process of state validation. */
public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {}
public void inputDocumentChanged(IDocument oldInput, IDocument newInput) { inputChanged= true; }
}
/**
* Internal element state listener.
*/
class ElementStateListener implements IElementStateListener, IElementStateListenerExtension {
/**
* Internal <code>VerifyListener</code> for performing the state validation of the
* editor input in case of the first attempted manipulation via typing on the keyboard.
* @since 2.0
*/
class Validator implements VerifyListener {
/*
* @see VerifyListener#verifyText(VerifyEvent)
*/
public void verifyText(VerifyEvent e) {
if (! validateEditorInputState())
e.doit= false;
}
};
/**
* The listener's validator.
* @since 2.0
*/
private Validator fValidator;
/*
* @see IElementStateListenerExtension#elementStateValidationChanged(Object, boolean)
* @since 2.0
*/
public void elementStateValidationChanged(Object element, boolean isStateValidated) {
if (element != null && element.equals(getEditorInput())) {
enableSanityChecking(true);
if (isStateValidated && fValidator != null) {
ISourceViewer viewer= getSourceViewer();
if (viewer != null) {
StyledText textWidget= viewer.getTextWidget();
if (textWidget != null && !textWidget.isDisposed())
textWidget.removeVerifyListener(fValidator);
fValidator= null;
}
} else if (!isStateValidated && fValidator == null) {
ISourceViewer viewer= getSourceViewer();
if (viewer != null) {
StyledText textWidget= viewer.getTextWidget();
if (textWidget != null && !textWidget.isDisposed()) {
fValidator= new Validator();
textWidget.addVerifyListener(fValidator);
}
}
}
}
}
/*
* @see IElementStateListener#elementDirtyStateChanged
*/
public void elementDirtyStateChanged(Object element, boolean isDirty) {
if (element != null && element.equals(getEditorInput())) {
enableSanityChecking(true);
firePropertyChange(PROP_DIRTY);
}
}
/*
* @see IElementStateListener#elementContentAboutToBeReplaced
*/
public void elementContentAboutToBeReplaced(Object element) {
if (element != null && element.equals(getEditorInput())) {
enableSanityChecking(true);
rememberSelection();
resetHighlightRange();
}
}
/*
* @see IElementStateListener#elementContentReplaced
*/
public void elementContentReplaced(Object element) {
if (element != null && element.equals(getEditorInput())) {
enableSanityChecking(true);
firePropertyChange(PROP_DIRTY);
restoreSelection();
}
}
/*
* @see IElementStateListener#elementDeleted
*/
public void elementDeleted(Object deletedElement) {
if (deletedElement != null && deletedElement.equals(getEditorInput())) {
enableSanityChecking(true);
close(false);
}
}
/*
* @see IElementStateListener#elementMoved
*/
public void elementMoved(Object originalElement, Object movedElement) {
if (originalElement != null && originalElement.equals(getEditorInput())) {
enableSanityChecking(true);
if (!canHandleMove((IEditorInput) originalElement, (IEditorInput) movedElement)) {
close(true);
return;
}
if (movedElement == null || movedElement instanceof IEditorInput) {
rememberSelection();
IDocumentProvider d= getDocumentProvider();
IDocument changed= null;
if (isDirty())
changed= d.getDocument(getEditorInput());
setInput((IEditorInput) movedElement);
if (changed != null) {
d.getDocument(getEditorInput()).set(changed.get());
validateState(getEditorInput());
updateStatusField(ITextEditorActionConstants.STATUS_CATEGORY_ELEMENT_STATE);
}
restoreSelection();
}
}
}
/*
* @see IElementStateListenerExtension#elementStateChanging(Object)
* @since 2.0
*/
public void elementStateChanging(Object element) {
if (element != null && element.equals(getEditorInput()))
enableSanityChecking(false);
}
/*
* @see IElementStateListenerExtension#elementStateChangeFailed(Object)
* @since 2.0
*/
public void elementStateChangeFailed(Object element) {
if (element != null && element.equals(getEditorInput()))
enableSanityChecking(true);
}
};
/**
* Internal text listener for updating all content dependent
* actions. The updating is done asynchronously.
*/
class TextListener implements ITextListener {
/** The posted updater code. */
private Runnable fRunnable= new Runnable() {
public void run() {
if (fSourceViewer != null) {
// check whether editor has not been disposed yet
updateContentDependentActions();
// remember the last edit position
if (isDirty()) {
ISelection sel= getSelectionProvider().getSelection();
IEditorInput input= getEditorInput();
Position pos= null;
if (sel instanceof ITextSelection) {
int offset= ((ITextSelection)sel).getOffset();
int length= ((ITextSelection)sel).getLength();
pos= new Position(offset, length);
try {
getDocumentProvider().getDocument(input).addPosition(pos);
} catch (BadLocationException ex) {
// pos is null
}
}
TextEditorPlugin.getDefault().setLastEditPosition(new EditPosition(input, getEditorSite().getId(), getSelectionProvider().getSelection(), pos));
}
}
}
};
/** Display used for posting the updater code. */
private Display fDisplay;
/*
* @see ITextListener#textChanged(TextEvent)
*/
public void textChanged(TextEvent event) {
/*
* Also works for text events which do not base on a DocumentEvent.
* This way, if the visible document of the viewer changes, all content
* dependent actions are updated as well.
*/
if (fDisplay == null)
fDisplay= getSite().getShell().getDisplay();
fDisplay.asyncExec(fRunnable);
}
};
/**
* Compare configuration elements according to the prerequisite relation
* of their defining plug-ins.
* @since 2.0
*/
static class ConfigurationElementComparator implements Comparator {
/*
* @see Comparator#compare(Object, Object)
* @since 2.0
*/
public int compare(Object object0, Object object1) {
IConfigurationElement element0= (IConfigurationElement)object0;
IConfigurationElement element1= (IConfigurationElement)object1;
if (dependsOn(element0, element1))
return -1;
if (dependsOn(element1, element0))
return +1;
return 0;
}
/**
* Returns whether one configuration element depends on the other element. Does this by
* checking the dependency chain of the defining plugins.
*
* @param element0 the first element
* @param element1 the second element
* @return <code>true</code> if <code>element0</code> depends on <code>element1</code>.
* @since 2.0
*/
private static boolean dependsOn(IConfigurationElement element0, IConfigurationElement element1) {
IPluginDescriptor descriptor0= element0.getDeclaringExtension().getDeclaringPluginDescriptor();
IPluginDescriptor descriptor1= element1.getDeclaringExtension().getDeclaringPluginDescriptor();
return dependsOn(descriptor0, descriptor1);
}
/**
* Returns whether one plugin depends on the other plugin.
*
* @param descriptor0 descriptor of the first plugin
* @param descriptor1 descriptor of the second plugin
* @return <code>true</code> if <code>descriptor0</code> depends on <code>descriptor1</code>.
* @since 2.0
*/
private static boolean dependsOn(IPluginDescriptor descriptor0, IPluginDescriptor descriptor1) {
IPluginRegistry registry= Platform.getPluginRegistry();
IPluginPrerequisite[] prerequisites= descriptor0.getPluginPrerequisites();
for (int i= 0; i < prerequisites.length; i++) {
IPluginPrerequisite prerequisite= prerequisites[i];
String id= prerequisite.getUniqueIdentifier();
IPluginDescriptor descriptor= registry.getPluginDescriptor(id);
if (descriptor != null && (descriptor.equals(descriptor1) || dependsOn(descriptor, descriptor1)))
return true;
}
return false;
}
}
/**
* Internal property change listener for handling changes in the editor's preferences.
*/
class PropertyChangeListener implements IPropertyChangeListener {
/*
* @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
*/
public void propertyChange(PropertyChangeEvent event) {
handlePreferenceStoreChanged(event);
}
};
/**
* Internal key verify listener for triggering action activation codes.
*/
class ActivationCodeTrigger implements VerifyKeyListener {
/** Indicates whether this trigger has been installed. */
private boolean fIsInstalled= false;
/**
* The key binding service to use.
* @since 2.0
*/
private IKeyBindingService fKeyBindingService;
/*
* @see VerifyKeyListener#verifyKey(VerifyEvent)
*/
public void verifyKey(VerifyEvent event) {
ActionActivationCode code= null;
int size= fActivationCodes.size();
for (int i= 0; i < size; i++) {
code= (ActionActivationCode) fActivationCodes.get(i);
if (code.matches(event)) {
IAction action= getAction(code.fActionId);
if (action != null) {
if (action instanceof IUpdate)
((IUpdate) action).update();
if (!action.isEnabled() && action instanceof IReadOnlyDependent) {
IReadOnlyDependent dependent= (IReadOnlyDependent) action;
boolean writable= dependent.isEnabled(true);
if (writable) {
event.doit= false;
return;
}
} else if (action.isEnabled()) {
event.doit= false;
action.run();
return;
}
}
}
}
if (fKeyBindingService.processKey(event))
event.doit= false;
}
/**
* Installs this trigger on the editor's text widget.
* @since 2.0
*/
public void install() {
if (!fIsInstalled) {
if (fSourceViewer instanceof ITextViewerExtension) {
ITextViewerExtension e= (ITextViewerExtension) fSourceViewer;
e.prependVerifyKeyListener(this);
} else {
StyledText text= fSourceViewer.getTextWidget();
text.addVerifyKeyListener(this);
}
fKeyBindingService= getEditorSite().getKeyBindingService();
fKeyBindingService.enable(true);
fIsInstalled= true;
}
}
/**
* Uninstalls this trigger from the editor's text widget.
* @since 2.0
*/
public void uninstall() {
if (fIsInstalled) {
if (fSourceViewer instanceof ITextViewerExtension) {
ITextViewerExtension e= (ITextViewerExtension) fSourceViewer;
e.removeVerifyKeyListener(this);
} else if (fSourceViewer != null) {
StyledText text= fSourceViewer.getTextWidget();
if (text != null && !text.isDisposed())
text.removeVerifyKeyListener(fActivationCodeTrigger);
}
fIsInstalled= false;
fKeyBindingService= null;
}
}
/**
* Registers the given action for key activation.
* @param action the action to be registered
* @since 2.0
*/
public void registerActionForKeyActivation(IAction action) {
if (action.getActionDefinitionId() != null)
fKeyBindingService.registerAction(action);
}
/**
* The given action is no longer available for key activation
* @param action the action to be unregistered
* @since 2.0
*/
public void unregisterActionFromKeyActivation(IAction action) {
// No such action available on the service
}
};
/**
* Representation of action activation codes.
*/
static class ActionActivationCode {
public String fActionId;
public char fCharacter;
public int fKeyCode= -1;
public int fStateMask= SWT.DEFAULT;
/**
* Creates a new action activation code for the given action id.
* @param actionId the action id
*/
public ActionActivationCode(String actionId) {
fActionId= actionId;
}
/**
* Returns <code>true</code> if this activation code matches the given verify event.
* @param event the event to test for matching
*/
public boolean matches(VerifyEvent event) {
return (event.character == fCharacter &&
(fKeyCode == -1 || event.keyCode == fKeyCode) &&
(fStateMask == SWT.DEFAULT || event.stateMask == fStateMask));
}
};
/**
* Internal part and shell activation listener for triggering state validation.
* @since 2.0
*/
class ActivationListener extends ShellAdapter implements IPartListener {
/** Cache of the active workbench part. */
private IWorkbenchPart fActivePart;
/** Indicates whether activation handling is currently be done. */
private boolean fIsHandlingActivation= false;
/*
* @see IPartListener#partActivated(IWorkbenchPart)
*/
public void partActivated(IWorkbenchPart part) {
fActivePart= part;
handleActivation();
}
/*
* @see IPartListener#partBroughtToTop(IWorkbenchPart)
*/
public void partBroughtToTop(IWorkbenchPart part) {
}
/*
* @see IPartListener#partClosed(IWorkbenchPart)
*/
public void partClosed(IWorkbenchPart part) {
}
/*
* @see IPartListener#partDeactivated(IWorkbenchPart)
*/
public void partDeactivated(IWorkbenchPart part) {
fActivePart= null;
}
/*
* @see IPartListener#partOpened(IWorkbenchPart)
*/
public void partOpened(IWorkbenchPart part) {
}
/*
* @see ShellListener#shellActivated(ShellEvent)
*/
public void shellActivated(ShellEvent e) {
/*
* Workaround for problem described in
* http://dev.eclipse.org/bugs/show_bug.cgi?id=11731
* Will be removed when SWT has solved the problem.
*/
e.widget.getDisplay().asyncExec(new Runnable() {
public void run() {
handleActivation();
}
});
}
/**
* Handles the activation triggering a element state check in the editor.
*/
private void handleActivation() {
if (fIsHandlingActivation)
return;
if (fActivePart == AbstractTextEditor.this) {
fIsHandlingActivation= true;
try {
safelySanityCheckState(getEditorInput());
} finally {
fIsHandlingActivation= false;
}
}
}
};
/**
* Internal interface for a cursor listener. I.e. aggregation
* of mouse and key listener.
* @since 2.0
*/
interface ICursorListener extends MouseListener, KeyListener {
};
/**
* Maps an action definition id to an StyledText action.
* @since 2.0
*/
static class IdMapEntry {
/** The action id */
private String fActionId;
/** The StyledText action */
private int fAction;
/**
* Creates a new mapping.
* @param actionId the action id
* @param action the StyledText action
*/
public IdMapEntry(String actionId, int action) {
fActionId= actionId;
fAction= action;
}
/**
* Returns the action id.
* @return the action id
*/
public String getActionId() {
return fActionId;
}
/**
* Returns the action
* @return the action
*/
public int getAction() {
return fAction;
}
};
/**
* Internal action to scroll the editor's viewer by a specified number of lines.
* @since 2.0
*/
class ScrollLinesAction extends Action {
/** Number of lines to scroll. */
private int fScrollIncrement;
/**
* Creates a new scroll action that scroll the given number of lines. If the
* increment is &lt 0, it's scrolling up, if &gt 0 it's scrolling down.
* @param scrollIncrement the number of lines to scroll
*/
public ScrollLinesAction(int scrollIncrement) {
fScrollIncrement= scrollIncrement;
}
/*
* @see IAction#run()
*/
public void run() {
ISourceViewer viewer= getSourceViewer();
int topIndex= viewer.getTopIndex();
int newTopIndex= Math.max(0, topIndex + fScrollIncrement);
viewer.setTopIndex(newTopIndex);
}
};
/**
* @since 2.1
*/
class ToggleInsertModeAction extends TextNavigationAction {
public ToggleInsertModeAction(StyledText textWidget) {
super(textWidget, ST.TOGGLE_OVERWRITE);
}
/*
* @see org.eclipse.jface.action.IAction#run()
*/
public void run() {
super.run();
fOverwriting= !fOverwriting;
handleInsertModeChanged();
}
};
/**
* This action implements smart end.
* Instead of going to the end of a line it does the following:
* - if smart home/end is enabled and the caret is before the line's last non-whitespace and then the caret is moved directly after it
* - if the caret is after last non-whitespace the caret is moved at the end of the line
* - if the caret is at the end of the line the caret is moved directly after the line's last non-whitespace character
* @since 2.1
*/
class LineEndAction extends TextNavigationAction {
private boolean fDoSelect;
public LineEndAction(StyledText textWidget, boolean doSelect) {
super(textWidget, ST.LINE_END);
fDoSelect= doSelect;
}
/*
* @see org.eclipse.jface.action.IAction#run()
*/
public void run() {
boolean isSmartHomeEndEnabled= false;
IPreferenceStore store= getPreferenceStore();
if (store != null)
isSmartHomeEndEnabled= store.getBoolean(AbstractTextEditor.PREFERENCE_NAVIGATION_SMART_HOME_END);
StyledText st= getSourceViewer().getTextWidget();
if (st == null || st.isDisposed())
return;
int caretOffset= st.getCaretOffset();
int lineNumber= st.getLineAtOffset(caretOffset);
int lineOffset= st.getOffsetAtLine(lineNumber);
int lineLength;
try {
int caretOffsetInDocument= caretOffset + getSourceViewer().getVisibleRegion().getOffset();
lineLength= getSourceViewer().getDocument().getLineInformationOfOffset(caretOffsetInDocument).getLength();
} catch (BadLocationException ex) {
return;
}
int lineEndOffset= lineOffset + lineLength;
String line= ""; //$NON-NLS-1$
if (lineLength > 0)
line= st.getText(lineOffset, lineOffset + lineLength - 1);
int i= lineLength - 1;
while (i > -1 && Character.isWhitespace(line.charAt(i))) {
i--;
}
if (i == -1)
i= lineLength;
else
i++;
// Remember current selection
Point oldSelection= st.getSelection();
// Compute new caret position
int newCaretOffset= -1;
if (caretOffset == lineEndOffset)
// from end of line to end of text
newCaretOffset= lineOffset + i;
else if (isSmartHomeEndEnabled && caretOffset - lineOffset < i)
// to end of text
newCaretOffset= lineOffset + i;
else if (caretOffset < lineEndOffset)
// to end of line
newCaretOffset= lineEndOffset;
if (newCaretOffset == -1)
// do nothing
return;
st.setCaretOffset(newCaretOffset);
if (fDoSelect) {
if (caretOffset < oldSelection.y)
st.setSelection(oldSelection.y, newCaretOffset);
else
st.setSelection(oldSelection.x, newCaretOffset);
} else
st.setSelection(newCaretOffset);
// send selection changed event
Event event= new Event();
event.x= st.getSelection().x;
event.y= st.getSelection().y;
st.notifyListeners(SWT.Selection, event);
}
};
/**
* This action implements smart home.
* Instead of going to the start of a line it does the following:
* - if smart home/end is enabled and the caret is after the line's first non-whitespace then the caret is moved directly before it
* - if the caret is before the line's first non-whitespace the caret is moved to the beginning of the line
* - if the caret is at the beginning of the line the caret is moved directly before the line's first non-whitespace character
* @since 2.1
*/
class LineStartAction extends TextNavigationAction {
private boolean fDoSelect;
public LineStartAction(StyledText textWidget, boolean doSelect) {
super(textWidget, ST.LINE_START);
fDoSelect= doSelect;
}
/*
* @see org.eclipse.jface.action.IAction#run()
*/
public void run() {
boolean isSmartHomeEndEnabled= false;
IPreferenceStore store= getPreferenceStore();
if (store != null)
isSmartHomeEndEnabled= store.getBoolean(AbstractTextEditor.PREFERENCE_NAVIGATION_SMART_HOME_END);
StyledText st= getSourceViewer().getTextWidget();
if (st == null || st.isDisposed())
return;
int caretOffset= st.getCaretOffset();
int lineNumber= st.getLineAtOffset(caretOffset);
int lineOffset= st.getOffsetAtLine(lineNumber);
int lineLength;
try {
int caretOffsetInDocument= caretOffset + getSourceViewer().getVisibleRegion().getOffset();
lineLength= getSourceViewer().getDocument().getLineInformationOfOffset(caretOffsetInDocument).getLength();
} catch (BadLocationException ex) {
return;
}
String line= ""; //$NON-NLS-1$
if (lineLength > 0)
line= st.getText(lineOffset, lineOffset + lineLength - 1);
int i= 0;
while (i < lineLength && Character.isWhitespace(line.charAt(i)))
i++;
if (i == lineLength)
i= 0;
// Remember current selection
Point oldSelection= st.getSelection();
// Compute new caret position
int newCaretOffset= -1;
if (caretOffset == lineOffset)
// from start to beginning of text
newCaretOffset= lineOffset + i;
else if (isSmartHomeEndEnabled && caretOffset - lineOffset > i)
// to beginning of text
newCaretOffset= lineOffset + i;
else if (caretOffset > lineOffset)
// to beginning if line
newCaretOffset= lineOffset;
if (newCaretOffset == -1)
// do nothing
return;
st.setCaretOffset(newCaretOffset);
if (fDoSelect) {
if (caretOffset < oldSelection.y)
st.setSelection(oldSelection.y, newCaretOffset);
else
st.setSelection(oldSelection.x, newCaretOffset);
} else
st.setSelection(newCaretOffset);
// send selection changed event
Event event= new Event();
event.x= st.getSelection().x;
event.y= st.getSelection().y;
st.notifyListeners(SWT.Selection, event);
}
};
/**
* Internal action to show the editor's ruler context menu (accessibility).
* @since 2.0
*/
class ShowRulerContextMenuAction extends Action {
/*
* @see IAction#run()
*/
public void run() {
if (fSourceViewer == null)
return;
StyledText text= fSourceViewer.getTextWidget();
if (text == null || text.isDisposed())
return;
Point location= text.getLocationAtOffset(text.getCaretOffset());
location.x= 0;
if (fVerticalRuler instanceof IVerticalRulerExtension)
((IVerticalRulerExtension) fVerticalRuler).setLocationOfLastMouseButtonActivity(location.x, location.y);
location= text.toDisplay(location);
fRulerContextMenu.setLocation(location.x, location.y);
fRulerContextMenu.setVisible(true);
}
};
/**
* Editor specific selection provider which wraps the source viewer's selection provider.
*
*/
class SelectionProvider implements ISelectionProvider {
/*
* @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(ISelectionChangedListener)
*/
public void addSelectionChangedListener(ISelectionChangedListener listener) {
if (fSourceViewer != null)
fSourceViewer.getSelectionProvider().addSelectionChangedListener(listener);
}
/*
* @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
*/
public ISelection getSelection() {
return doGetSelection();
}
/*
* @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(ISelectionChangedListener)
*/
public void removeSelectionChangedListener(ISelectionChangedListener listener) {
if (fSourceViewer != null)
fSourceViewer.getSelectionProvider().removeSelectionChangedListener(listener);
}
/*
* @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(ISelection)
*/
public void setSelection(ISelection selection) {
doSetSelection(selection);
}
};
/** Key used to look up font preference */
public final static String PREFERENCE_FONT= JFaceResources.TEXT_FONT;
/**
* Key used to look up foreground color preference
* Value: <code>AbstractTextEditor.Color.Foreground</code>
* @since 2.0
*/
public final static String PREFERENCE_COLOR_FOREGROUND= "AbstractTextEditor.Color.Foreground"; //$NON-NLS-1$
/**
* Key used to look up background color preference
* Value: <code>AbstractTextEditor.Color.Background</code>
* @since 2.0
*/
public final static String PREFERENCE_COLOR_BACKGROUND= "AbstractTextEditor.Color.Background"; //$NON-NLS-1$
/**
* Key used to look up foreground color system default preference
* Value: <code>AbstractTextEditor.Color.Foreground.SystemDefault</code>
* @since 2.0
*/
public final static String PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT= "AbstractTextEditor.Color.Foreground.SystemDefault"; //$NON-NLS-1$
/**
* Key used to look up background color system default preference
* Value: <code>AbstractTextEditor.Color.Background.SystemDefault</code>
* @since 2.0
*/
public final static String PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT= "AbstractTextEditor.Color.Background.SystemDefault"; //$NON-NLS-1$
/**
* Key used to look up find scope background color preference
* Value: <code>AbstractTextEditor.Color.FindScope</code>
* @since 2.0
*/
public final static String PREFERENCE_COLOR_FIND_SCOPE= "AbstractTextEditor.Color.FindScope"; //$NON-NLS-1$
/**
* Key used to look up smart home/end preference
* Value: <code>AbstractTextEditor.Navigation.SmartHomeEnd</code>
* @since 2.1
*/
public final static String PREFERENCE_NAVIGATION_SMART_HOME_END= "AbstractTextEditor.Navigation.SmartHomeEnd"; //$NON-NLS-1$
/** Menu id for the editor context menu. */
public final static String DEFAULT_EDITOR_CONTEXT_MENU_ID= "#EditorContext"; //$NON-NLS-1$
/** Menu id for the ruler context menu. */
public final static String DEFAULT_RULER_CONTEXT_MENU_ID= "#RulerContext"; //$NON-NLS-1$
/** The width of the vertical ruler */
protected final static int VERTICAL_RULER_WIDTH= 12;
/**
* The complete mapping between action definition ids used by eclipse and StyledText actions.
* @since 2.0
*/
protected final static IdMapEntry[] ACTION_MAP= new IdMapEntry[] {
// navigation
new IdMapEntry(ITextEditorActionDefinitionIds.LINE_UP, ST.LINE_UP),
new IdMapEntry(ITextEditorActionDefinitionIds.LINE_DOWN, ST.LINE_DOWN),
new IdMapEntry(ITextEditorActionDefinitionIds.LINE_START, ST.LINE_START),
new IdMapEntry(ITextEditorActionDefinitionIds.LINE_END, ST.LINE_END),
new IdMapEntry(ITextEditorActionDefinitionIds.COLUMN_PREVIOUS, ST.COLUMN_PREVIOUS),
new IdMapEntry(ITextEditorActionDefinitionIds.COLUMN_NEXT, ST.COLUMN_NEXT),
new IdMapEntry(ITextEditorActionDefinitionIds.PAGE_UP, ST.PAGE_UP),
new IdMapEntry(ITextEditorActionDefinitionIds.PAGE_DOWN, ST.PAGE_DOWN),
new IdMapEntry(ITextEditorActionDefinitionIds.WORD_PREVIOUS, ST.WORD_PREVIOUS),
new IdMapEntry(ITextEditorActionDefinitionIds.WORD_NEXT, ST.WORD_NEXT),
new IdMapEntry(ITextEditorActionDefinitionIds.TEXT_START, ST.TEXT_START),
new IdMapEntry(ITextEditorActionDefinitionIds.TEXT_END, ST.TEXT_END),
new IdMapEntry(ITextEditorActionDefinitionIds.WINDOW_START, ST.WINDOW_START),
new IdMapEntry(ITextEditorActionDefinitionIds.WINDOW_END, ST.WINDOW_END),
// selection
new IdMapEntry(ITextEditorActionDefinitionIds.SELECT_LINE_UP, ST.SELECT_LINE_UP),
new IdMapEntry(ITextEditorActionDefinitionIds.SELECT_LINE_DOWN, ST.SELECT_LINE_DOWN),
new IdMapEntry(ITextEditorActionDefinitionIds.SELECT_LINE_START, ST.SELECT_LINE_START),
new IdMapEntry(ITextEditorActionDefinitionIds.SELECT_LINE_END, ST.SELECT_LINE_END),
new IdMapEntry(ITextEditorActionDefinitionIds.SELECT_COLUMN_PREVIOUS, ST.SELECT_COLUMN_PREVIOUS),
new IdMapEntry(ITextEditorActionDefinitionIds.SELECT_COLUMN_NEXT, ST.SELECT_COLUMN_NEXT),
new IdMapEntry(ITextEditorActionDefinitionIds.SELECT_PAGE_UP, ST.SELECT_PAGE_UP),
new IdMapEntry(ITextEditorActionDefinitionIds.SELECT_PAGE_DOWN, ST.SELECT_PAGE_DOWN),
new IdMapEntry(ITextEditorActionDefinitionIds.SELECT_WORD_PREVIOUS, ST.SELECT_WORD_PREVIOUS),
new IdMapEntry(ITextEditorActionDefinitionIds.SELECT_WORD_NEXT, ST.SELECT_WORD_NEXT),
new IdMapEntry(ITextEditorActionDefinitionIds.SELECT_TEXT_START, ST.SELECT_TEXT_START),
new IdMapEntry(ITextEditorActionDefinitionIds.SELECT_TEXT_END, ST.SELECT_TEXT_END),
new IdMapEntry(ITextEditorActionDefinitionIds.SELECT_WINDOW_START, ST.SELECT_WINDOW_START),
new IdMapEntry(ITextEditorActionDefinitionIds.SELECT_WINDOW_END, ST.SELECT_WINDOW_END),
// modification
new IdMapEntry(ITextEditorActionDefinitionIds.CUT, ST.CUT),
new IdMapEntry(ITextEditorActionDefinitionIds.COPY, ST.COPY),
new IdMapEntry(ITextEditorActionDefinitionIds.PASTE, ST.PASTE),
new IdMapEntry(ITextEditorActionDefinitionIds.DELETE_PREVIOUS, ST.DELETE_PREVIOUS),
new IdMapEntry(ITextEditorActionDefinitionIds.DELETE_NEXT, ST.DELETE_NEXT),
// miscellaneous
new IdMapEntry(ITextEditorActionDefinitionIds.TOGGLE_OVERWRITE, ST.TOGGLE_OVERWRITE)
};
private final String fReadOnlyLabel = EditorMessages.getString("Editor.statusline.state.readonly.label"); //$NON-NLS-1$
private final String fWritableLabel = EditorMessages.getString("Editor.statusline.state.writable.label"); //$NON-NLS-1$
private final String fInsertModeLabel = EditorMessages.getString("Editor.statusline.mode.insert.label"); //$NON-NLS-1$
private final String fOverwriteModeLabel = EditorMessages.getString("Editor.statusline.mode.overwrite.label"); //$NON-NLS-1$
private static class PositionLabelValue {
public int fValue;
public String toString() {
return String.valueOf(fValue);
}
};
/** The error message shown in the status line in case of failed information look up. */
protected final String fErrorLabel= EditorMessages.getString("Editor.statusline.error.label"); //$NON-NLS-1$
private final String fPositionLabelPattern= EditorMessages.getString("Editor.statusline.position.pattern"); //$NON-NLS-1$
private final PositionLabelValue fLineLabel= new PositionLabelValue();
private final PositionLabelValue fColumnLabel= new PositionLabelValue();
private final Object[] fPositionLabelPatternArguments= new Object[] { fLineLabel, fColumnLabel };
/** The editor's internal document provider */
private IDocumentProvider fInternalDocumentProvider;
/** The editor's external document provider */
private IDocumentProvider fExternalDocumentProvider;
/** The editor's preference store */
private IPreferenceStore fPreferenceStore;
/** The editor's range indicator */
private Annotation fRangeIndicator;
/** The editor's source viewer configuration */
private SourceViewerConfiguration fConfiguration;
/** The editor's source viewer */
private ISourceViewer fSourceViewer;
/** The editor's selection provider */
private SelectionProvider fSelectionProvider= new SelectionProvider();
/** The editor's font */
private Font fFont;
/**
* The editor's foreground color
* @since 2.0
*/
private Color fForegroundColor;
/**
* The editor's background color
* @since 2.0
*/
private Color fBackgroundColor;
/**
* The find scope's highlight color
* @since 2.0
*/
private Color fFindScopeHighlightColor;
/** The editor's status line */
private IEditorStatusLine fEditorStatusLine;
/** The editor's vertical ruler */
private IVerticalRuler fVerticalRuler;
/** The editor's context menu id */
private String fEditorContextMenuId;
/** The ruler's context menu id */
private String fRulerContextMenuId;
/** The editor's help context id */
private String fHelpContextId;
/** The editor's presentation mode */
private boolean fShowHighlightRangeOnly;
/** The actions registered with the editor */
private Map fActions= new HashMap(10);
/** The actions marked as selection dependent */
private List fSelectionActions= new ArrayList(5);
/** The actions marked as content dependent */
private List fContentActions= new ArrayList(5);
/**
* The actions marked as property dependent
* @since 2.0
*/
private List fPropertyActions= new ArrayList(5);
/**
* The actions marked as state dependent
* @since 2.0
*/
private List fStateActions= new ArrayList(5);
/** The editor's action activation codes */
private List fActivationCodes= new ArrayList(2);
/** The verify key listener for activation code triggering */
private ActivationCodeTrigger fActivationCodeTrigger= new ActivationCodeTrigger();
/** Context menu listener */
private IMenuListener fMenuListener;
/** Vertical ruler mouse listener */
private MouseListener fMouseListener;
/** Selection changed listener */
private ISelectionChangedListener fSelectionChangedListener;
/** Title image to be disposed */
private Image fTitleImage;
/** The text context menu to be disposed */
private Menu fTextContextMenu;
/** The ruler context menu to be disposed */
private Menu fRulerContextMenu;
/** The editor's element state listener */
private IElementStateListener fElementStateListener= new ElementStateListener();
/** The editor's text input listener. */
private TextInputListener fTextInputListener= new TextInputListener();
/** The editor's text listener */
private ITextListener fTextListener= new TextListener();
/** The editor's property change listener */
private IPropertyChangeListener fPropertyChangeListener= new PropertyChangeListener();
/**
* The editor's activation listener
* @since 2.0
*/
private ActivationListener fActivationListener= new ActivationListener();
/**
* The map of the editor's status fields
* @since 2.0
*/
private Map fStatusFields;
/**
* The editor's cursor listener
* @since 2.0
*/
private ICursorListener fCursorListener;
/**
* The editor's insert mode
* @since 2.0
*/
private boolean fOverwriting= false;
/**
* The editor's remembered text selection
* @since 2.0
*/
private ISelection fRememberedSelection;
/**
* Indicates whether the editor runs in 1.0 context menu registration compatibility mode
* @since 2.0
*/
private boolean fCompatibilityMode= true;
/**
* The number of reentrances into error correction code while saving
* @since 2.0
*/
private int fErrorCorrectionOnSave;
/**
* The delete line target.
*/
private DeleteLineTarget fDeleteLineTarget;
/**
* The incremental find target
* @since 2.0
*/
private IncrementalFindTarget fIncrementalFindTarget;
/**
* The mark region target
* @since 2.0
*/
private IMarkRegionTarget fMarkRegionTarget;
/**
* Cached modification stamp of the editor's input
* @since 2.0
*/
private long fModificationStamp= -1;
/**
* Ruler context menu listeners.
* @since 2.0
*/
private List fRulerContextMenuListeners= new ArrayList();
/**
* Indicates whether sanity checking in enabled.
* @since 2.0
*/
private boolean fIsSanityCheckEnabled= true;
/**
* Creates a new text editor. If not explicitly set, this editor uses
* a <code>SourceViewerConfiguration</code> to configure its
* source viewer. This viewer does not have a range indicator installed,
* nor any menu id set. By default, the created editor runs in 1.0 context
* menu registration compatibility mode.
*/
protected AbstractTextEditor() {
super();
fEditorContextMenuId= null;
fRulerContextMenuId= null;
fHelpContextId= null;
}
/*
* @see ITextEditor#getDocumentProvider
*/
public IDocumentProvider getDocumentProvider() {
if (fInternalDocumentProvider != null)
return fInternalDocumentProvider;
return fExternalDocumentProvider;
}
/**
* Returns the editor's range indicator.
*
* @return the editor's range indicator
*/
protected final Annotation getRangeIndicator() {
return fRangeIndicator;
}
/**
* Returns the editor's source viewer configuration.
*
* @return the editor's source viewer configuration
*/
protected final SourceViewerConfiguration getSourceViewerConfiguration() {
return fConfiguration;
}
/**
* Returns the editor's source viewer.
*
* @return the editor's source viewer
*/
protected final ISourceViewer getSourceViewer() {
return fSourceViewer;
}
/**
* Returns the editor's vertical ruler.
*
* @return the editor's vertical ruler
*/
protected final IVerticalRuler getVerticalRuler() {
return fVerticalRuler;
}
/**
* Returns the editor's context menu id.
*
* @return the editor's context menu id
*/
protected final String getEditorContextMenuId() {
return fEditorContextMenuId;
}
/**
* Returns the ruler's context menu id.
*
* @return the ruler's context menu id
*/
protected final String getRulerContextMenuId() {
return fRulerContextMenuId;
}
/**
* Returns the editor's help context id.
*
* @return the editor's help context id
*/
protected final String getHelpContextId() {
return fHelpContextId;
}
/**
* Returns this editor's preference store.
*
* @return this editor's preference store
*/
protected final IPreferenceStore getPreferenceStore() {
return fPreferenceStore;
}
/**
* Sets this editor's document provider. This method must be
* called before the editor's control is created.
*
* @param provider the document provider
*/
protected void setDocumentProvider(IDocumentProvider provider) {
Assert.isNotNull(provider);
fInternalDocumentProvider= provider;
}
/**
* Sets this editor's source viewer configuration used to configure its
* internal source viewer. This method must be called before the editor's
* control is created. If not, this editor uses a <code>SourceViewerConfiguration</code>.
*
* @param configuration the source viewer configuration object
*/
protected void setSourceViewerConfiguration(SourceViewerConfiguration configuration) {
Assert.isNotNull(configuration);
fConfiguration= configuration;
}
/**
* Sets the annotation which this editor uses to represent the highlight
* range if the editor is configured to show the entire document. If the
* range indicator is not set, this editor uses a <code>DefaultRangeIndicator</code>.
*
* @param rangeIndicator the annotation
*/
protected void setRangeIndicator(Annotation rangeIndicator) {
Assert.isNotNull(rangeIndicator);
fRangeIndicator= rangeIndicator;
}
/**
* Sets this editor's context menu id.
*
* @param contextMenuId the context menu id
*/
protected void setEditorContextMenuId(String contextMenuId) {
Assert.isNotNull(contextMenuId);
fEditorContextMenuId= contextMenuId;
}
/**
* Sets the ruler's context menu id.
*
* @param contextMenuId the context menu id
*/
protected void setRulerContextMenuId(String contextMenuId) {
Assert.isNotNull(contextMenuId);
fRulerContextMenuId= contextMenuId;
}
/**
* Sets the context menu registration 1.0 compatibility mode. (See class
* description for more details.)
*
* @param compatible <code>true</code> if compatibility mode is enabled
* @since 2.0
*/
protected final void setCompatibilityMode(boolean compatible) {
fCompatibilityMode= compatible;
}
/**
* Sets the editor's help context id.
*
* @param helpContextId the help context id
*/
protected void setHelpContextId(String helpContextId) {
Assert.isNotNull(helpContextId);
fHelpContextId= helpContextId;
}
/**
* Sets this editor's preference store. This method must be
* called before the editor's control is created.
*
* @param store the new preference store
*/
protected void setPreferenceStore(IPreferenceStore store) {
if (fPreferenceStore != null)
fPreferenceStore.removePropertyChangeListener(fPropertyChangeListener);
fPreferenceStore= store;
if (fPreferenceStore != null)
fPreferenceStore.addPropertyChangeListener(fPropertyChangeListener);
}
/*
* @see ITextEditor#isEditable
*/
public boolean isEditable() {
IDocumentProvider provider= getDocumentProvider();
if (provider instanceof IDocumentProviderExtension) {
IDocumentProviderExtension extension= (IDocumentProviderExtension) provider;
return extension.isModifiable(getEditorInput());
}
return false;
}
/*
* @see ITextEditor#getSelectionProvider
*/
public ISelectionProvider getSelectionProvider() {
return fSelectionProvider;
}
/**
* Remembers the current selection of this editor. This method is called when, e.g.,
* the content of the editor is about to be reverted to the saved state. This method
* remembers the selection in a semantic format, i.e., in a format which allows to
* restore the selection even if the originally selected text is no longer part of the
* editor's content.<p>
* Subclasses should implement this method including all necessary state. This
* default implementation remembers the textual range only and is thus purely
* syntactic.
*
* @see #restoreSelection
* @since 2.0
*/
protected void rememberSelection() {
fRememberedSelection= doGetSelection();
}
/**
* Returns the current selection.
* @return ISelection
*/
protected ISelection doGetSelection() {
ISelectionProvider sp= null;
if (fSourceViewer != null)
sp= fSourceViewer.getSelectionProvider();
return (sp == null ? null : sp.getSelection());
}
/**
* Restores a selection previously remembered by <code>rememberSelection</code>.
* Subclasses may reimplement this method and thereby semantically adapt the
* remembered selection. This default implementation just selects the
* remembered textual range.
*
* @see #rememberSelection
* @since 2.0
*/
protected void restoreSelection() {
doSetSelection(fRememberedSelection);
fRememberedSelection= null;
}
/**
* Sets the given selection.
* @param selection
*/
protected void doSetSelection(ISelection selection) {
if (selection instanceof ITextSelection) {
ITextSelection textSelection= (ITextSelection) selection;
selectAndReveal(textSelection.getOffset(), textSelection.getLength());
}
}
/**
* Creates and returns the listener on this editor'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 (getEditorContextMenuId().equals(id)) {
setFocus();
editorContextMenuAboutToShow(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(ITextEditorActionConstants.RULER_DOUBLE_CLICK);
}
}
public void mouseDown(MouseEvent e) {
StyledText text= fSourceViewer.getTextWidget();
if (text != null && !text.isDisposed()) {
Display display= text.getDisplay();
Point location= display.getCursorLocation();
fRulerContextMenu.setLocation(location.x, location.y);
}
}
};
}
return fMouseListener;
}
/**
* Returns this editor's selection changed listener to be installed
* on the editor's source viewer.
*
* @return the listener
*/
protected final ISelectionChangedListener getSelectionChangedListener() {
if (fSelectionChangedListener == null) {
fSelectionChangedListener= new ISelectionChangedListener() {
private Runnable fRunnable= new Runnable() {
public void run() {
// check whether editor has not been disposed yet
if (fSourceViewer != null) {
updateSelectionDependentActions();
}
}
};
private Display fDisplay;
public void selectionChanged(SelectionChangedEvent event) {
if (fDisplay == null)
fDisplay= getSite().getShell().getDisplay();
fDisplay.asyncExec(fRunnable);
handleCursorPositionChanged();
}
};
}
return fSelectionChangedListener;
}
/**
* Returns this editor's "cursor" listener to be installed on the editor's
* source viewer. This listener is listening to key and mouse button events.
* It triggers the updating of the status line by calling
* <code>handleCursorPositionChanged()</code>.
*
* @return the listener
* @since 2.0
*/
protected final ICursorListener getCursorListener() {
if (fCursorListener == null) {
fCursorListener= new ICursorListener() {
public void keyPressed(KeyEvent e) {
handleCursorPositionChanged();
}
public void keyReleased(KeyEvent e) {
}
public void mouseDoubleClick(MouseEvent e) {
}
public void mouseDown(MouseEvent e) {
}
public void mouseUp(MouseEvent e) {
handleCursorPositionChanged();
}
};
}
return fCursorListener;
}
/*
* @see IEditorPart#init
*/
public void init(IEditorSite site, IEditorInput input) throws PartInitException {
setSite(site);
try {
doSetInput(input);
} catch (CoreException x) {
throw new PartInitException(x.getStatus());
}
IWorkbenchWindow window= getSite().getWorkbenchWindow();
window.getPartService().addPartListener(fActivationListener);
window.getShell().addShellListener(fActivationListener);
}
/**
* Creates the vertical ruler to be used by this editor.
* Subclasses may re-implement this method.
*
* @return the vertical ruler
*/
protected IVerticalRuler createVerticalRuler() {
return new VerticalRuler(VERTICAL_RULER_WIDTH);
}
/**
* Creates the source viewer to be used by this editor.
* Subclasses may re-implement this method.
*
* @param parent the parent control
* @param ruler the vertical ruler
* @param styles style bits
* @return the source viewer
*/
protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) {
return new SourceViewer(parent, ruler, styles);
}
/**
* The <code>AbstractTextEditor</code> implementation of this
* <code>IWorkbenchPart</code> method creates the vertical ruler and
* source viewer. Subclasses may extend.
*/
public void createPartControl(Composite parent) {
fVerticalRuler= createVerticalRuler();
int styles= SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION;
fSourceViewer= createSourceViewer(parent, fVerticalRuler, styles);
if (fConfiguration == null)
fConfiguration= new SourceViewerConfiguration();
fSourceViewer.configure(fConfiguration);
if (fRangeIndicator != null)
fSourceViewer.setRangeIndicator(fRangeIndicator);
fSourceViewer.addTextListener(fTextListener);
getSelectionProvider().addSelectionChangedListener(getSelectionChangedListener());
initializeViewerFont(fSourceViewer);
initializeViewerColors(fSourceViewer);
initializeFindScopeColor(fSourceViewer);
StyledText styledText= fSourceViewer.getTextWidget();
final Map gestureMap = new HashMap();
gestureMap.put("E", "org.eclipse.ui.navigate.forwardHistory");
gestureMap.put("N", "org.eclipse.ui.file.save");
gestureMap.put("NW", "org.eclipse.ui.file.saveAll");
gestureMap.put("S", "org.eclipse.ui.file.close");
gestureMap.put("SW", "org.eclipse.ui.file.closeAll");
gestureMap.put("W", "org.eclipse.ui.navigate.backwardHistory");
gestureMap.put("EN", "org.eclipse.ui.edit.copy");
gestureMap.put("ES", "org.eclipse.ui.edit.paste");
gestureMap.put("EW", "org.eclipse.ui.edit.cut");
Capture capture = Capture.create();
capture.setControl(styledText);
capture.addCaptureListener(new CaptureListener() {
public void gesture(Gesture gesture) {
if (gesture.getPen() == 3) {
String actionId = (String) gestureMap.get(Util.recognize(gesture.getPoints(), 20));
if (actionId != null) {
IKeyBindingService keyBindingService = getEditorSite().getKeyBindingService();
if (keyBindingService instanceof KeyBindingService) {
IAction action = ((KeyBindingService) keyBindingService).getAction(actionId);
if (action != null) {
if (action instanceof IUpdate)
((IUpdate) action).update();
if (action.isEnabled())
action.run();
}
}
return;
}
fTextContextMenu.setVisible(true);
}
};
});
styledText.addMouseListener(getCursorListener());
styledText.addKeyListener(getCursorListener());
if (getHelpContextId() != null)
WorkbenchHelp.setHelp(styledText, getHelpContextId());
String id= fEditorContextMenuId != null ? fEditorContextMenuId : DEFAULT_EDITOR_CONTEXT_MENU_ID;
MenuManager manager= new MenuManager(id, id);
manager.setRemoveAllWhenShown(true);
manager.addMenuListener(getContextMenuListener());
fTextContextMenu= manager.createContextMenu(styledText);
//styledText.setMenu(fTextContextMenu);
if (fEditorContextMenuId != null)
getSite().registerContextMenu(fEditorContextMenuId, manager, getSelectionProvider());
else if (fCompatibilityMode)
getSite().registerContextMenu(DEFAULT_EDITOR_CONTEXT_MENU_ID, manager, getSelectionProvider());
if ((fEditorContextMenuId != null && fCompatibilityMode) || fEditorContextMenuId == null) {
String partId= getSite().getId();
if (partId != null)
getSite().registerContextMenu(partId + ".EditorContext", manager, getSelectionProvider()); //$NON-NLS-1$
}
if (fEditorContextMenuId == null)
fEditorContextMenuId= DEFAULT_EDITOR_CONTEXT_MENU_ID;
id= fRulerContextMenuId != null ? fRulerContextMenuId : DEFAULT_RULER_CONTEXT_MENU_ID;
manager= new MenuManager(id, id);
manager.setRemoveAllWhenShown(true);
manager.addMenuListener(getContextMenuListener());
Control rulerControl= fVerticalRuler.getControl();
fRulerContextMenu= manager.createContextMenu(rulerControl);
rulerControl.setMenu(fRulerContextMenu);
rulerControl.addMouseListener(getRulerMouseListener());
if (fRulerContextMenuId != null)
getSite().registerContextMenu(fRulerContextMenuId, manager, getSelectionProvider());
else if (fCompatibilityMode)
getSite().registerContextMenu(DEFAULT_RULER_CONTEXT_MENU_ID, manager, getSelectionProvider());
if ((fRulerContextMenuId != null && fCompatibilityMode) || fRulerContextMenuId == null) {
String partId= getSite().getId();
if (partId != null)
getSite().registerContextMenu(partId + ".RulerContext", manager, getSelectionProvider()); //$NON-NLS-1$
}
if (fRulerContextMenuId == null)
fRulerContextMenuId= DEFAULT_RULER_CONTEXT_MENU_ID;
getSite().setSelectionProvider(getSelectionProvider());
fActivationCodeTrigger.install();
createNavigationActions();
createAccessibilityActions();
createActions();
initializeSourceViewer(getEditorInput());
}
/**
* Initializes the given viewer's font.
*
* @param viewer the viewer
* @since 2.0
*/
private void initializeViewerFont(ISourceViewer viewer) {
IPreferenceStore store= getPreferenceStore();
if (store != null) {
FontData data= null;
if (store.contains(PREFERENCE_FONT) && !store.isDefault(PREFERENCE_FONT))
data= PreferenceConverter.getFontData(store, PREFERENCE_FONT);
else
data= PreferenceConverter.getDefaultFontData(store, PREFERENCE_FONT);
if (data != null) {
Font font= new Font(viewer.getTextWidget().getDisplay(), data);
setFont(viewer, font);
if (fFont != null)
fFont.dispose();
fFont= font;
return;
}
}
// if all the preferences failed
setFont(viewer, JFaceResources.getTextFont());
}
/**
* Sets the font for the given viewer sustaining selection and scroll position.
*
* @param sourceViewer the source viewer
* @param font the font
* @since 2.0
*/
private void setFont(ISourceViewer sourceViewer, Font font) {
if (sourceViewer.getDocument() != null) {
Point selection= sourceViewer.getSelectedRange();
int topIndex= sourceViewer.getTopIndex();
StyledText styledText= sourceViewer.getTextWidget();
Control parent= styledText;
if (sourceViewer instanceof ITextViewerExtension) {
ITextViewerExtension extension= (ITextViewerExtension) sourceViewer;
parent= extension.getControl();
}
parent.setRedraw(false);
styledText.setFont(font);
if (fVerticalRuler instanceof IVerticalRulerExtension) {
IVerticalRulerExtension e= (IVerticalRulerExtension) fVerticalRuler;
e.setFont(font);
}
sourceViewer.setSelectedRange(selection.x , selection.y);
sourceViewer.setTopIndex(topIndex);
if (parent instanceof Composite) {
Composite composite= (Composite) parent;
composite.layout(true);
}
parent.setRedraw(true);
} else {
StyledText styledText= sourceViewer.getTextWidget();
styledText.setFont(font);
if (fVerticalRuler instanceof IVerticalRulerExtension) {
IVerticalRulerExtension e= (IVerticalRulerExtension) fVerticalRuler;
e.setFont(font);
}
}
}
/**
* Creates a color from the information stored in the given preference store.
* Returns <code>null</code> if there is no such information available.
*
* @param store the store to read from
* @param key the key used for the lookup in the preference store
* @param display the display used create the color
* @return the created color according to the specification in the preference store
* @since 2.0
*/
private Color createColor(IPreferenceStore store, String key, Display display) {
RGB rgb= null;
if (store.contains(key)) {
if (store.isDefault(key))
rgb= PreferenceConverter.getDefaultColor(store, key);
else
rgb= PreferenceConverter.getColor(store, key);
if (rgb != null)
return new Color(display, rgb);
}
return null;
}
/**
* Initializes the given viewer's colors.
*
* @param viewer the viewer to be initialized
* @since 2.0
*/
private void initializeViewerColors(ISourceViewer viewer) {
IPreferenceStore store= getPreferenceStore();
if (store != null) {
StyledText styledText= viewer.getTextWidget();
// ----------- foreground color --------------------
Color color= store.getBoolean(PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT)
? null
: createColor(store, PREFERENCE_COLOR_FOREGROUND, styledText.getDisplay());
styledText.setForeground(color);
if (fForegroundColor != null)
fForegroundColor.dispose();
fForegroundColor= color;
// ---------- background color ----------------------
color= store.getBoolean(PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT)
? null
: createColor(store, PREFERENCE_COLOR_BACKGROUND, styledText.getDisplay());
styledText.setBackground(color);
if (fBackgroundColor != null)
fBackgroundColor.dispose();
fBackgroundColor= color;
}
}
/**
* Initializes the background color used for highlighting the document ranges
* defining search scopes.
* @param viewer the viewer to initialize
* @since 2.0
*/
private void initializeFindScopeColor(ISourceViewer viewer) {
IPreferenceStore store= getPreferenceStore();
if (store != null) {
StyledText styledText= viewer.getTextWidget();
Color color= createColor(store, PREFERENCE_COLOR_FIND_SCOPE, styledText.getDisplay());
IFindReplaceTarget target= viewer.getFindReplaceTarget();
if (target != null && target instanceof IFindReplaceTargetExtension)
((IFindReplaceTargetExtension) target).setScopeHighlightColor(color);
if (fFindScopeHighlightColor != null)
fFindScopeHighlightColor.dispose();
fFindScopeHighlightColor= color;
}
}
/**
* Initializes the editor's source viewer based on the given editor input.
*
* @param input the editor input to be used to initialize the source viewer
*/
private void initializeSourceViewer(IEditorInput input) {
IAnnotationModel model= getDocumentProvider().getAnnotationModel(input);
IDocument document= getDocumentProvider().getDocument(input);
if (document != null) {
fSourceViewer.setDocument(document, model);
fSourceViewer.setEditable(isEditable());
fSourceViewer.showAnnotations(model != null);
}
if (fElementStateListener instanceof IElementStateListenerExtension) {
IElementStateListenerExtension extension= (IElementStateListenerExtension) fElementStateListener;
extension.elementStateValidationChanged(input, false);
}
}
/**
* Initializes the editor's title based on the given editor input.
*
* @param input the editor input to be used
*/
private void initializeTitle(IEditorInput input) {
Image oldImage= fTitleImage;
fTitleImage= null;
String title= ""; //$NON-NLS-1$
if (input != null) {
IEditorRegistry editorRegistry = getEditorSite().getPage().getWorkbenchWindow().getWorkbench().getEditorRegistry();
IEditorDescriptor editorDesc= editorRegistry.findEditor(getSite().getId());
ImageDescriptor imageDesc= editorDesc != null ? editorDesc.getImageDescriptor() : null;
fTitleImage= imageDesc != null ? imageDesc.createImage() : null;
title= input.getName();
}
setTitleImage(fTitleImage);
setTitle(title);
firePropertyChange(PROP_DIRTY);
if (oldImage != null && !oldImage.isDisposed())
oldImage.dispose();
}
/**
* If there is no implicit document provider set, the external one is
* re-initialized based on the given editor input.
*
* @param input the editor input.
*/
private void updateDocumentProvider(IEditorInput input) {
if (getDocumentProvider() != null)
getDocumentProvider().removeElementStateListener(fElementStateListener);
if (fInternalDocumentProvider == null)
fExternalDocumentProvider= DocumentProviderRegistry.getDefault().getDocumentProvider(input);
if (getDocumentProvider() != null)
getDocumentProvider().addElementStateListener(fElementStateListener);
}
/**
* Internal <code>setInput</code> method.
*
* @param input the input to be set
* @exception CoreException if input cannot be connected to the document provider
*/
protected void doSetInput(IEditorInput input) throws CoreException {
if (input == null)
close(isSaveOnCloseNeeded());
else {
IEditorInput oldInput= getEditorInput();
if (oldInput != null)
getDocumentProvider().disconnect(oldInput);
super.setInput(input);
updateDocumentProvider(input);
IDocumentProvider provider= getDocumentProvider();
if (provider == null) {
IStatus s= new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.OK, EditorMessages.getString("Editor.error.no_provider"), null); //$NON-NLS-1$
throw new CoreException(s);
}
provider.connect(input);
initializeTitle(input);
if (fSourceViewer != null)
initializeSourceViewer(input);
updateStatusField(ITextEditorActionConstants.STATUS_CATEGORY_ELEMENT_STATE);
}
}
/*
* @see EditorPart#setInput
*/
public final void setInput(IEditorInput input) {
try {
doSetInput(input);
} catch (CoreException x) {
String title= EditorMessages.getString("Editor.error.setinput.title"); //$NON-NLS-1$
String msg= EditorMessages.getString("Editor.error.setinput.message"); //$NON-NLS-1$
Shell shell= getSite().getShell();
ErrorDialog.openError(shell, title, msg, x.getStatus());
}
}
/*
* @see ITextEditor#close
*/
public void close(final boolean save) {
enableSanityChecking(false);
Display display= getSite().getShell().getDisplay();
display.asyncExec(new Runnable() {
public void run() {
if (fSourceViewer != null) {
// check whether editor has not been disposed yet
getSite().getPage().closeEditor(AbstractTextEditor.this, save);
}
}
});
}
/**
* The <code>AbstractTextEditor</code> implementation of this
* <code>IWorkbenchPart</code> method may be extended by subclasses.
* Subclasses must call <code>super.dispose()</code>.
*/
public void dispose() {
if (fActivationListener != null) {
IWorkbenchWindow window= getSite().getWorkbenchWindow();
window.getPartService().removePartListener(fActivationListener);
Shell shell= window.getShell();
if (shell != null && !shell.isDisposed())
shell.removeShellListener(fActivationListener);
fActivationListener= null;
}
if (fTitleImage != null) {
fTitleImage.dispose();
fTitleImage= null;
}
if (fFont != null) {
fFont.dispose();
fFont= null;
}
if (fPropertyChangeListener != null) {
if (fPreferenceStore != null) {
fPreferenceStore.removePropertyChangeListener(fPropertyChangeListener);
fPreferenceStore= null;
}
fPropertyChangeListener= null;
}
if (fActivationCodeTrigger != null) {
fActivationCodeTrigger.uninstall();
fActivationCodeTrigger= null;
}
IDocumentProvider provider= getDocumentProvider();
if (provider != null) {
IEditorInput input= getEditorInput();
if (input != null)
provider.disconnect(input);
if (fElementStateListener != null) {
provider.removeElementStateListener(fElementStateListener);
fElementStateListener= null;
}
fInternalDocumentProvider= null;
fExternalDocumentProvider= null;
}
if (fSourceViewer != null) {
if (fTextListener != null) {
fSourceViewer.removeTextListener(fTextListener);
fTextListener= null;
}
fTextInputListener= null;
fSelectionProvider= null;
fSourceViewer= null;
}
if (fTextContextMenu != null) {
fTextContextMenu.dispose();
fTextContextMenu= null;
}
if (fRulerContextMenu != null) {
fRulerContextMenu.dispose();
fRulerContextMenu= null;
}
if (fActions != null) {
fActions.clear();
fActions= null;
}
if (fSelectionActions != null) {
fSelectionActions.clear();
fSelectionActions= null;
}
if (fContentActions != null) {
fContentActions.clear();
fContentActions= null;
}
if (fPropertyActions != null) {
fPropertyActions.clear();
fPropertyActions= null;
}
if (fStateActions != null) {
fStateActions.clear();
fStateActions= null;
}
if (fActivationCodes != null) {
fActivationCodes.clear();
fActivationCodes= null;
}
if (fEditorStatusLine != null)
fEditorStatusLine= null;
super.setInput(null);
super.dispose();
}
/**
* Determines whether the given preference change affects the editor's
* presentation. This implementation always returns <code>false</code>.
* May be reimplemented by subclasses.
*
* @param event the event which should be investigated
* @return <code>true</code> if the event describes a preference change affecting the editor's presentation
* @since 2.0
*/
protected boolean affectsTextPresentation(PropertyChangeEvent event) {
return false;
}
/**
* Handles a property change event describing a change
* of the editor's preference store and updates the preference
* related editor properties.
*
* @param event the property change event
*/
protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
if (fSourceViewer == null)
return;
String property= event.getProperty();
if (PREFERENCE_FONT.equals(property)) {
initializeViewerFont(fSourceViewer);
} else if (PREFERENCE_COLOR_FOREGROUND.equals(property) || PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT.equals(property) ||
PREFERENCE_COLOR_BACKGROUND.equals(property) || PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT.equals(property))
{
initializeViewerColors(fSourceViewer);
} else if (PREFERENCE_COLOR_FIND_SCOPE.equals(property)) {
initializeFindScopeColor(fSourceViewer);
}
if (affectsTextPresentation(event))
fSourceViewer.invalidateTextPresentation();
}
/**
* Handles an external change of the editor's input element.
*/
protected void handleEditorInputChanged() {
String title;
String msg;
Shell shell= getSite().getShell();
IDocumentProvider provider= getDocumentProvider();
if (provider == null) {
// fix for http://dev.eclipse.org/bugs/show_bug.cgi?id=15066
close(false);
return;
}
IEditorInput input= getEditorInput();
if (provider.isDeleted(input)) {
if (isSaveAsAllowed()) {
title= EditorMessages.getString("Editor.error.activated.deleted.save.title"); //$NON-NLS-1$
msg= EditorMessages.getString("Editor.error.activated.deleted.save.message"); //$NON-NLS-1$
String[] buttons= {
EditorMessages.getString("Editor.error.activated.deleted.save.button.save"), //$NON-NLS-1$
EditorMessages.getString("Editor.error.activated.deleted.save.button.close"), //$NON-NLS-1$
};
MessageDialog dialog= new MessageDialog(shell, title, null, msg, MessageDialog.QUESTION, buttons, 0);
if (dialog.open() == 0) {
NullProgressMonitor pm= new NullProgressMonitor();
performSaveAs(pm);
if (pm.isCanceled())
handleEditorInputChanged();
} else {
close(false);
}
} else {
title= EditorMessages.getString("Editor.error.activated.deleted.close.title"); //$NON-NLS-1$
msg= EditorMessages.getString("Editor.error.activated.deleted.close.message"); //$NON-NLS-1$
if (MessageDialog.openConfirm(shell, title, msg))
close(false);
}
} else {
title= EditorMessages.getString("Editor.error.activated.outofsync.title"); //$NON-NLS-1$
msg= EditorMessages.getString("Editor.error.activated.outofsync.message"); //$NON-NLS-1$
if (MessageDialog.openQuestion(shell, title, msg)) {
try {
if (provider instanceof IDocumentProviderExtension) {
IDocumentProviderExtension extension= (IDocumentProviderExtension) provider;
extension.synchronize(input);
} else {
doSetInput(input);
}
} catch (CoreException x) {
title= EditorMessages.getString("Editor.error.refresh.outofsync.title"); //$NON-NLS-1$
msg= EditorMessages.getString("Editor.error.refresh.outofsync.message"); //$NON-NLS-1$
ErrorDialog.openError(shell, title, msg, x.getStatus());
}
}
// // disabled because of http://bugs.eclipse.org/bugs/show_bug.cgi?id=15166
// else {
// markEditorAsDirty();
// }
}
}
/**
* Marks this editor and its editor input as dirty.
* @since 2.0
*/
private void markEditorAsDirty() {
if (isDirty())
return;
IDocumentProvider provider= getDocumentProvider();
if (provider instanceof IDocumentProviderExtension) {
provider.removeElementStateListener(fElementStateListener);
try {
IDocumentProviderExtension extension= (IDocumentProviderExtension) provider;
extension.setCanSaveDocument(getEditorInput());
firePropertyChange(PROP_DIRTY);
} finally {
provider.addElementStateListener(fElementStateListener);
}
}
}
/**
* The <code>AbstractTextEditor</code> implementation of this
* <code>IEditorPart</code> method calls <code>oerformSaveAs</code>.
* Subclasses may reimplement.
*/
public void doSaveAs() {
/*
* 1GEUSSR: ITPUI:ALL - User should never loose changes made in the editors.
* Changed Behavior to make sure that if called inside a regular save (because
* of deletion of input element) there is a way to report back to the caller.
*/
performSaveAs(new NullProgressMonitor());
}
/**
* Performs a save as and reports the result state back to the
* given progress monitor. This default implementation does nothing.
* Subclasses may reimplement.
*
* @param progressMonitor the progress monitor for communicating result state or <code>null</code>
*/
protected void performSaveAs(IProgressMonitor progressMonitor) {
}
/**
* The <code>AbstractTextEditor</code> implementation of this
* <code>IEditorPart</code> method may be extended by subclasses.
*/
public void doSave(IProgressMonitor progressMonitor) {
IDocumentProvider p= getDocumentProvider();
if (p == null)
return;
if (p.isDeleted(getEditorInput())) {
if (isSaveAsAllowed()) {
/*
* 1GEUSSR: ITPUI:ALL - User should never loose changes made in the editors.
* Changed Behavior to make sure that if called inside a regular save (because
* of deletion of input element) there is a way to report back to the caller.
*/
performSaveAs(progressMonitor);
} else {
Shell shell= getSite().getShell();
String title= EditorMessages.getString("Editor.error.save.deleted.title"); //$NON-NLS-1$
String msg= EditorMessages.getString("Editor.error.save.deleted.message"); //$NON-NLS-1$
MessageDialog.openError(shell, title, msg);
}
} else {
performSaveOperation(createSaveOperation(false), progressMonitor);
}
}
/**
* Enables/Disabled sanity checking.
* @param enable <code>true</code> if santity checking should be enabled, <code>false</code> otherwise
* @since 2.0
*/
protected void enableSanityChecking(boolean enable) {
synchronized (this) {
fIsSanityCheckEnabled= enable;
}
}
/**
* Checks the state of the given editor input if sanity checking is enabled.
* @param input the editor input whose state is to be checked
* @since 2.0
*/
protected void safelySanityCheckState(IEditorInput input) {
boolean enabled= false;
synchronized (this) {
enabled= fIsSanityCheckEnabled;
}
if (enabled)
sanityCheckState(input);
}
/**
* Checks the state of the given editor input.
* @param input the editor input whose state is to be checked
* @since 2.0
*/
protected void sanityCheckState(IEditorInput input) {
IDocumentProvider p= getDocumentProvider();
if (p == null)
return;
if (fModificationStamp == -1)
fModificationStamp= p.getSynchronizationStamp(input);
long stamp= p.getModificationStamp(input);
if (stamp != fModificationStamp) {
fModificationStamp= stamp;
if (stamp != p.getSynchronizationStamp(input))
handleEditorInputChanged();
}
updateState(getEditorInput());
updateStatusField(ITextEditorActionConstants.STATUS_CATEGORY_ELEMENT_STATE);
}
/**
* Validates the state of the given editor input. The predominate intent
* of this method is to take any action propably necessary to ensure that
* the input can persistently be changed.
*
* @param input the input to be validated
* @since 2.0
*/
protected void validateState(IEditorInput input) {
IDocumentProvider provider= getDocumentProvider();
if (! (provider instanceof IDocumentProviderExtension))
return;
IDocumentProviderExtension extension= (IDocumentProviderExtension) provider;
boolean wasReadOnly= isEditorInputReadOnly();
try {
extension.validateState(input, getSite().getShell());
} catch (CoreException exception) {
// for backward compatibility only
if (exception instanceof ValidateStateException) {
if (fSourceViewer != null)
fSourceViewer.setEditable(isEditable());
if (wasReadOnly != isEditorInputReadOnly())
updateStateDependentActions();
}
ILog log= Platform.getPlugin(PlatformUI.PLUGIN_ID).getLog();
log.log(exception.getStatus());
Shell shell= getSite().getShell();
String title= EditorMessages.getString("Editor.error.validateEdit.title"); //$NON-NLS-1$
String msg= EditorMessages.getString("Editor.error.validateEdit.message"); //$NON-NLS-1$
ErrorDialog.openError(shell, title, msg, exception.getStatus());
return;
}
if (fSourceViewer != null)
fSourceViewer.setEditable(isEditable());
if (wasReadOnly != isEditorInputReadOnly())
updateStateDependentActions();
}
/*
* @see org.eclipse.ui.texteditor.ITextEditorExtension2.validateEditorInputState()
*/
public boolean validateEditorInputState() {
ISourceViewer viewer= getSourceViewer();
fTextInputListener.inputChanged= false;
viewer.addTextInputListener(fTextInputListener);
try {
IEditorInput input= getEditorInput();
validateState(input);
sanityCheckState(input);
return !isEditorInputReadOnly() && !fTextInputListener.inputChanged;
} finally {
viewer.removeTextInputListener(fTextInputListener);
}
}
/**
* Updates the state of the given editor input such as read-only flag etc.
*
* @param input the input to be validated
* @since 2.0
*/
protected void updateState(IEditorInput input) {
IDocumentProvider provider= getDocumentProvider();
if (provider instanceof IDocumentProviderExtension) {
IDocumentProviderExtension extension= (IDocumentProviderExtension) provider;
try {
boolean wasReadOnly= isEditorInputReadOnly();
extension.updateStateCache(input);
if (fSourceViewer != null)
fSourceViewer.setEditable(isEditable());
if (wasReadOnly != isEditorInputReadOnly())
updateStateDependentActions();
} catch (CoreException x) {
ILog log= Platform.getPlugin(PlatformUI.PLUGIN_ID).getLog();
log.log(x.getStatus());
}
}
}
/**
* Creates a workspace modify operation which saves the content of the editor
* to the editor's input element. <code>overwrite</code> indicates whether
* the editor input element may be overwritten if necessary. Clients may
* reimplement this method.
*
* @param overwrite indicates whether or not overwrititng is allowed
* @return the save operation
*/
protected WorkspaceModifyOperation createSaveOperation(final boolean overwrite) {
return new WorkspaceModifyOperation() {
public void execute(final IProgressMonitor monitor) throws CoreException {
IEditorInput input= getEditorInput();
getDocumentProvider().saveDocument(monitor, input, getDocumentProvider().getDocument(input), overwrite);
}
};
}
/**
* Performs the given save operation and handles errors appropriatly.
*
* @param operation the operation to be performed
* @param progressMonitor the monitor in which to run the operation
*/
protected void performSaveOperation(WorkspaceModifyOperation operation, IProgressMonitor progressMonitor) {
IDocumentProvider provider= getDocumentProvider();
try {
provider.aboutToChange(getEditorInput());
operation.run(progressMonitor);
editorSaved();
} catch (InterruptedException x) {
} catch (InvocationTargetException x) {
Throwable t= x.getTargetException();
if (t instanceof CoreException)
handleExceptionOnSave((CoreException) t, progressMonitor);
else {
Shell shell= getSite().getShell();
String title= EditorMessages.getString("Editor.error.save.title"); //$NON-NLS-1$
String msg= EditorMessages.getString("Editor.error.save.message"); //$NON-NLS-1$
MessageDialog.openError(shell, title, msg + t.getMessage());
}
} finally {
provider.changed(getEditorInput());
}
}
/**
* Handles the given exception. If the exception reports an out-of-sync
* situation, this is reported to the user. Otherwise, the exception
* is generically reported.
*
* @param exception the exception to handle
* @param progressMonitor the progress monitor
*/
protected void handleExceptionOnSave(CoreException exception, IProgressMonitor progressMonitor) {
try {
++ fErrorCorrectionOnSave;
Shell shell= getSite().getShell();
IDocumentProvider p= getDocumentProvider();
long modifiedStamp= p.getModificationStamp(getEditorInput());
long synchStamp= p.getSynchronizationStamp(getEditorInput());
if (fErrorCorrectionOnSave == 1 && modifiedStamp != synchStamp) {
String title= EditorMessages.getString("Editor.error.save.outofsync.title"); //$NON-NLS-1$
String msg= EditorMessages.getString("Editor.error.save.outofsync.message"); //$NON-NLS-1$
if (MessageDialog.openQuestion(shell, title, msg))
performSaveOperation(createSaveOperation(true), progressMonitor);
else {
/*
* 1GEUPKR: ITPJUI:ALL - Loosing work with simultaneous edits
* Set progress monitor to canceled in order to report back
* to enclosing operations.
*/
if (progressMonitor != null)
progressMonitor.setCanceled(true);
}
} else {
String title= EditorMessages.getString("Editor.error.save.title"); //$NON-NLS-1$
String msg= EditorMessages.getString("Editor.error.save.message"); //$NON-NLS-1$
ErrorDialog.openError(shell, title, msg, exception.getStatus());
/*
* 1GEUPKR: ITPJUI:ALL - Loosing work with simultaneous edits
* Set progress monitor to canceled in order to report back
* to enclosing operations.
*/
if (progressMonitor != null)
progressMonitor.setCanceled(true);
}
} finally {
-- fErrorCorrectionOnSave;
}
}
/**
* The <code>AbstractTextEditor</code> implementation of this
* <code>IEditorPart</code> method returns <code>false</code>. Subclasses
* may override.
*/
public boolean isSaveAsAllowed() {
return false;
}
/*
* @see IEditorPart#isSaveOnCloseNeeded()
*/
public boolean isSaveOnCloseNeeded() {
IDocumentProvider p= getDocumentProvider();
return p == null ? false : p.mustSaveDocument(getEditorInput());
}
/*
* @see IEditorPart#isDirty
*/
public boolean isDirty() {
IDocumentProvider p= getDocumentProvider();
return p == null ? false : p.canSaveDocument(getEditorInput());
}
/**
* The <code>AbstractTextEditor</code> implementation of this
* <code>ITextEditor</code> method may be extended by subclasses.
*/
public void doRevertToSaved() {
IDocumentProvider p= getDocumentProvider();
if (p == null)
return;
try {
p.resetDocument(getEditorInput());
IAnnotationModel model= p.getAnnotationModel(getEditorInput());
if (model instanceof AbstractMarkerAnnotationModel) {
AbstractMarkerAnnotationModel markerModel= (AbstractMarkerAnnotationModel) model;
markerModel.resetMarkers();
}
firePropertyChange(PROP_DIRTY);
} catch (CoreException x) {
String title= EditorMessages.getString("Editor.error.revert.title"); //$NON-NLS-1$
String msg= EditorMessages.getString("Editor.error.revert.message"); //$NON-NLS-1$
Shell shell= getSite().getShell();
ErrorDialog.openError(shell, title, msg, x.getStatus());
}
}
/*
* @see ITextEditor#setAction
*/
public void setAction(String actionID, IAction action) {
Assert.isNotNull(actionID);
if (action == null) {
action= (IAction) fActions.remove(actionID);
if (action != null)
fActivationCodeTrigger.unregisterActionFromKeyActivation(action);
} else {
fActions.put(actionID, action);
fActivationCodeTrigger.registerActionForKeyActivation(action);
}
}
/*
* @see ITextEditor#setActionActivationCode(String, char, int, int)
*/
public void setActionActivationCode(String actionID, char activationCharacter, int activationKeyCode, int activationStateMask) {
Assert.isNotNull(actionID);
ActionActivationCode found= findActionActivationCode(actionID);
if (found == null) {
found= new ActionActivationCode(actionID);
fActivationCodes.add(found);
}
found.fCharacter= activationCharacter;
found.fKeyCode= activationKeyCode;
found.fStateMask= activationStateMask;
}
/**
* Returns the activation code registered for the specified action.
*
* @param actionID the action id
* @return the registered activation code or <code>null</code> if no code has been installed
*/
private ActionActivationCode findActionActivationCode(String actionID) {
int size= fActivationCodes.size();
for (int i= 0; i < size; i++) {
ActionActivationCode code= (ActionActivationCode) fActivationCodes.get(i);
if (actionID.equals(code.fActionId))
return code;
}
return null;
}
/*
* @see ITextEditor#removeActionActivationCode(String)
*/
public void removeActionActivationCode(String actionID) {
Assert.isNotNull(actionID);
ActionActivationCode code= findActionActivationCode(actionID);
if (code != null)
fActivationCodes.remove(code);
}
/*
* @see ITextEditor#getAction
*/
public IAction getAction(String actionID) {
Assert.isNotNull(actionID);
IAction action= (IAction) fActions.get(actionID);
if (action == null) {
action= findContributedAction(actionID);
if (action != null)
setAction(actionID, action);
}
return action;
}
/**
* Returns the action with the given action id that has been contributed via xml to this editor.
* The lookup honors the dependencies of plugins.
*
* @param actionID the action id to look up
* @return the action that has been contributed
* @since 2.0
*/
private IAction findContributedAction(String actionID) {
IExtensionPoint extensionPoint= Platform.getPluginRegistry().getExtensionPoint(PlatformUI.PLUGIN_ID, "editorActions"); //$NON-NLS-1$
if (extensionPoint != null) {
IConfigurationElement[] elements= extensionPoint.getConfigurationElements();
List actions= new ArrayList();
for (int i= 0; i < elements.length; i++) {
IConfigurationElement element= elements[i];
if (TAG_CONTRIBUTION_TYPE.equals(element.getName())) {
if (!getSite().getId().equals(element.getAttribute("targetID"))) //$NON-NLS-1$
continue;
IConfigurationElement[] children= element.getChildren("action"); //$NON-NLS-1$
for (int j= 0; j < children.length; j++) {
IConfigurationElement child= children[j];
if (actionID.equals(child.getAttribute("actionID"))) //$NON-NLS-1$
actions.add(child);
}
}
}
Collections.sort(actions, new ConfigurationElementComparator());
if (actions.size() != 0) {
IConfigurationElement element= (IConfigurationElement) actions.get(0);
String defId = element.getAttribute(ActionDescriptor.ATT_DEFINITION_ID);
return new EditorPluginAction(element, "class", this,defId); //$NON-NLS-1$
}
}
return null;
}
/**
* Updates the specified action by calling <code>IUpdate.update</code>
* if applicable.
*
* @param actionId the action id
*/
private void updateAction(String actionId) {
Assert.isNotNull(actionId);
if (fActions != null) {
IAction action= (IAction) fActions.get(actionId);
if (action instanceof IUpdate)
((IUpdate) action).update();
}
}
/**
* Marks or unmarks the given action to be updated on text selection changes.
*
* @param actionId the action id
* @param mark <code>true</code> if the action is selection dependent
*/
public void markAsSelectionDependentAction(String actionId, boolean mark) {
Assert.isNotNull(actionId);
if (mark) {
if (!fSelectionActions.contains(actionId))
fSelectionActions.add(actionId);
} else
fSelectionActions.remove(actionId);
}
/**
* Marks or unmarks the given action to be updated on content changes.
*
* @param actionId the action id
* @param mark <code>true</code> if the action is content dependent
*/
public void markAsContentDependentAction(String actionId, boolean mark) {
Assert.isNotNull(actionId);
if (mark) {
if (!fContentActions.contains(actionId))
fContentActions.add(actionId);
} else
fContentActions.remove(actionId);
}
/**
* Marks or unmarks the given action to be updated on property changes.
*
* @param actionId the action id
* @param mark <code>true</code> if the action is property dependent
* @since 2.0
*/
public void markAsPropertyDependentAction(String actionId, boolean mark) {
Assert.isNotNull(actionId);
if (mark) {
if (!fPropertyActions.contains(actionId))
fPropertyActions.add(actionId);
} else
fPropertyActions.remove(actionId);
}
/**
* Marks or unmarks the given action to be updated on state changes.
*
* @param actionId the action id
* @param mark <code>true</code> if the action is state dependent
* @since 2.0
*/
public void markAsStateDependentAction(String actionId, boolean mark) {
Assert.isNotNull(actionId);
if (mark) {
if (!fStateActions.contains(actionId))
fStateActions.add(actionId);
} else
fStateActions.remove(actionId);
}
/**
* Updates all selection dependent actions.
*/
protected void updateSelectionDependentActions() {
if (fSelectionActions != null) {
Iterator e= fSelectionActions.iterator();
while (e.hasNext())
updateAction((String) e.next());
}
}
/**
* Updates all content dependent actions.
*/
protected void updateContentDependentActions() {
if (fContentActions != null) {
Iterator e= fContentActions.iterator();
while (e.hasNext())
updateAction((String) e.next());
}
}
/**
* Updates all property dependent actions.
* @since 2.0
*/
protected void updatePropertyDependentActions() {
if (fPropertyActions != null) {
Iterator e= fPropertyActions.iterator();
while (e.hasNext())
updateAction((String) e.next());
}
}
/**
* Updates all state dependent actions.
* @since 2.0
*/
protected void updateStateDependentActions() {
if (fStateActions != null) {
Iterator e= fStateActions.iterator();
while (e.hasNext())
updateAction((String) e.next());
}
}
/**
* Creates action entries for all SWT StyledText actions as defined in
* <code>org.eclipse.swt.custom.ST</code>. Overwrites and
* extends the list of these actions afterwards.
* <p>
* Subclasses may extend.
* </p>
* @since 2.0
*/
protected void createNavigationActions() {
IAction action;
StyledText textWidget= getSourceViewer().getTextWidget();
for (int i= 0; i < ACTION_MAP.length; i++) {
IdMapEntry entry= (IdMapEntry) ACTION_MAP[i];
action= new TextNavigationAction(textWidget, entry.getAction());
action.setActionDefinitionId(entry.getActionId());
setAction(entry.getActionId(), action);
}
action= new ToggleInsertModeAction(textWidget);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.TOGGLE_OVERWRITE);
setAction(ITextEditorActionDefinitionIds.TOGGLE_OVERWRITE, action);
action= new ScrollLinesAction(-1);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.SCROLL_LINE_UP);
setAction(ITextEditorActionDefinitionIds.SCROLL_LINE_UP, action);
action= new ScrollLinesAction(1);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.SCROLL_LINE_DOWN);
setAction(ITextEditorActionDefinitionIds.SCROLL_LINE_DOWN, action);
action= new LineEndAction(textWidget, false);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.LINE_END);
setAction(ITextEditorActionDefinitionIds.LINE_END, action);
action= new LineStartAction(textWidget, false);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.LINE_START);
setAction(ITextEditorActionDefinitionIds.LINE_START, action);
action= new LineEndAction(textWidget, true);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_LINE_END);
setAction(ITextEditorActionDefinitionIds.SELECT_LINE_END, action);
action= new LineStartAction(textWidget, true);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_LINE_START);
setAction(ITextEditorActionDefinitionIds.SELECT_LINE_START, action);
setActionActivationCode(ITextEditorActionDefinitionIds.LINE_END, (char) 0, SWT.END, SWT.NONE);
setActionActivationCode(ITextEditorActionDefinitionIds.LINE_START, (char) 0, SWT.HOME, SWT.NONE);
setActionActivationCode(ITextEditorActionDefinitionIds.SELECT_LINE_END, (char) 0, SWT.END, SWT.SHIFT);
setActionActivationCode(ITextEditorActionDefinitionIds.SELECT_LINE_START, (char) 0, SWT.HOME, SWT.SHIFT);
}
/**
* Creates this editor's accessibility actions.
* @since 2.0
*/
private void createAccessibilityActions() {
IAction action= new ShowRulerContextMenuAction();
action.setActionDefinitionId(ITextEditorActionDefinitionIds.SHOW_RULER_CONTEXT_MENU);
setAction(ITextEditorActionDefinitionIds.SHOW_RULER_CONTEXT_MENU, action);
}
/**
* Creates this editor's standard actions and connects them with the global
* workbench actions.
* <p>
* Subclasses may extend.
* </p>
*/
protected void createActions() {
ResourceAction action;
action= new TextOperationAction(EditorMessages.getResourceBundle(), "Editor.Undo.", this, ITextOperationTarget.UNDO); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.UNDO_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.UNDO);
setAction(ITextEditorActionConstants.UNDO, action);
action= new TextOperationAction(EditorMessages.getResourceBundle(), "Editor.Redo.", this, ITextOperationTarget.REDO); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.REDO_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.REDO);
setAction(ITextEditorActionConstants.REDO, action);
action= new TextOperationAction(EditorMessages.getResourceBundle(), "Editor.Cut.", this, ITextOperationTarget.CUT); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.CUT_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.CUT);
setAction(ITextEditorActionConstants.CUT, action);
action= new TextOperationAction(EditorMessages.getResourceBundle(), "Editor.Copy.", this, ITextOperationTarget.COPY, true); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.COPY_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.COPY);
setAction(ITextEditorActionConstants.COPY, action);
action= new TextOperationAction(EditorMessages.getResourceBundle(), "Editor.Paste.", this, ITextOperationTarget.PASTE); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.PASTE_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.PASTE);
setAction(ITextEditorActionConstants.PASTE, action);
action= new TextOperationAction(EditorMessages.getResourceBundle(), "Editor.Delete.", this, ITextOperationTarget.DELETE); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.DELETE_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.DELETE);
setAction(ITextEditorActionConstants.DELETE, action);
action= new DeleteLineAction(EditorMessages.getResourceBundle(), "Editor.DeleteLine.", this, DeleteLineAction.WHOLE); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.DELETE_LINE_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.DELETE_LINE);
setAction(ITextEditorActionConstants.DELETE_LINE, action);
action= new DeleteLineAction(EditorMessages.getResourceBundle(), "Editor.DeleteLineToBeginning.", this, DeleteLineAction.TO_BEGINNING); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.DELETE_LINE_TO_BEGINNING_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.DELETE_LINE_TO_BEGINNING);
setAction(ITextEditorActionConstants.DELETE_LINE_TO_BEGINNING, action);
action= new DeleteLineAction(EditorMessages.getResourceBundle(), "Editor.DeleteLineToEnd.", this, DeleteLineAction.TO_END); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.DELETE_LINE_TO_END_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.DELETE_LINE_TO_END);
setAction(ITextEditorActionConstants.DELETE_LINE_TO_END, action);
action= new MarkAction(EditorMessages.getResourceBundle(), "Editor.SetMark.", this, MarkAction.SET_MARK); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.SET_MARK_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.SET_MARK);
setAction(ITextEditorActionConstants.SET_MARK, action);
action= new MarkAction(EditorMessages.getResourceBundle(), "Editor.ClearMark.", this, MarkAction.CLEAR_MARK); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.CLEAR_MARK_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.CLEAR_MARK);
setAction(ITextEditorActionConstants.CLEAR_MARK, action);
action= new MarkAction(EditorMessages.getResourceBundle(), "Editor.SwapMark.", this, MarkAction.SWAP_MARK); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.SWAP_MARK_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.SWAP_MARK);
setAction(ITextEditorActionConstants.SWAP_MARK, action);
action= new TextOperationAction(EditorMessages.getResourceBundle(), "Editor.SelectAll.", this, ITextOperationTarget.SELECT_ALL, true); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.SELECT_ALL_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.SELECT_ALL);
setAction(ITextEditorActionConstants.SELECT_ALL, action);
action= new ShiftAction(EditorMessages.getResourceBundle(), "Editor.ShiftRight.", this, ITextOperationTarget.SHIFT_RIGHT); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.SHIFT_RIGHT_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.SHIFT_RIGHT);
setAction(ITextEditorActionConstants.SHIFT_RIGHT, action);
action= new ShiftAction(EditorMessages.getResourceBundle(), "Editor.ShiftLeft.", this, ITextOperationTarget.SHIFT_LEFT); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.SHIFT_LEFT_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.SHIFT_LEFT);
setAction(ITextEditorActionConstants.SHIFT_LEFT, action);
action= new TextOperationAction(EditorMessages.getResourceBundle(), "Editor.Print.", this, ITextOperationTarget.PRINT, true); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.PRINT_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.PRINT);
setAction(ITextEditorActionConstants.PRINT, action);
action= new FindReplaceAction(EditorMessages.getResourceBundle(), "Editor.FindReplace.", this); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.FIND_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.FIND_REPLACE);
setAction(ITextEditorActionConstants.FIND, action);
action= new FindNextAction(EditorMessages.getResourceBundle(), "Editor.FindNext.", this, true); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.FIND_NEXT_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.FIND_NEXT);
setAction(ITextEditorActionConstants.FIND_NEXT, action);
action= new FindNextAction(EditorMessages.getResourceBundle(), "Editor.FindPrevious.", this, false); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.FIND_PREVIOUS_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.FIND_PREVIOUS);
setAction(ITextEditorActionConstants.FIND_PREVIOUS, action);
action= new IncrementalFindAction(EditorMessages.getResourceBundle(), "Editor.FindIncremental.", this, true); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.FIND_INCREMENTAL_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.FIND_INCREMENTAL);
setAction(ITextEditorActionConstants.FIND_INCREMENTAL, action);
action= new IncrementalFindAction(EditorMessages.getResourceBundle(), "Editor.FindIncrementalReverse.", this, false); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.FIND_INCREMENTAL_REVERSE_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.FIND_INCREMENTAL_REVERSE);
setAction(ITextEditorActionConstants.FIND_INCREMENTAL_REVERSE, action);
action= new AddMarkerAction(EditorMessages.getResourceBundle(), "Editor.AddBookmark.", this, IMarker.BOOKMARK, true); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.BOOKMARK_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.ADD_BOOKMARK);
setAction(ITextEditorActionConstants.BOOKMARK, action);
// FIXME: need another way to contribute this action
// action= new AddTaskAction(EditorMessages.getResourceBundle(), "Editor.AddTask.", this); //$NON-NLS-1$
// action.setHelpContextId(IAbstractTextEditorHelpContextIds.ADD_TASK_ACTION);
// action.setActionDefinitionId(ITextEditorActionDefinitionIds.ADD_TASK);
// setAction(ITextEditorActionConstants.ADD_TASK, action);
action= new SaveAction(EditorMessages.getResourceBundle(), "Editor.Save.", this); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.SAVE_ACTION);
// action.setActionDefinitionId(ITextEditorActionDefinitionIds.SAVE);
setAction(ITextEditorActionConstants.SAVE, action);
action= new RevertToSavedAction(EditorMessages.getResourceBundle(), "Editor.Revert.", this); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.REVERT_TO_SAVED_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.REVERT_TO_SAVED);
setAction(ITextEditorActionConstants.REVERT_TO_SAVED, action);
action= new GotoLineAction(EditorMessages.getResourceBundle(), "Editor.GotoLine.", this); //$NON-NLS-1$
action.setHelpContextId(IAbstractTextEditorHelpContextIds.GOTO_LINE_ACTION);
action.setActionDefinitionId(ITextEditorActionDefinitionIds.LINE_GOTO);
setAction(ITextEditorActionConstants.GOTO_LINE, action);
markAsContentDependentAction(ITextEditorActionConstants.UNDO, true);
markAsContentDependentAction(ITextEditorActionConstants.REDO, true);
markAsContentDependentAction(ITextEditorActionConstants.FIND, true);
markAsContentDependentAction(ITextEditorActionConstants.FIND_NEXT, true);
markAsContentDependentAction(ITextEditorActionConstants.FIND_PREVIOUS, true);
markAsContentDependentAction(ITextEditorActionConstants.FIND_INCREMENTAL, true);
markAsContentDependentAction(ITextEditorActionConstants.FIND_INCREMENTAL_REVERSE, true);
markAsSelectionDependentAction(ITextEditorActionConstants.CUT, true);
markAsSelectionDependentAction(ITextEditorActionConstants.COPY, true);
markAsSelectionDependentAction(ITextEditorActionConstants.PASTE, true);
markAsSelectionDependentAction(ITextEditorActionConstants.DELETE, true);
markAsSelectionDependentAction(ITextEditorActionConstants.SHIFT_RIGHT, true);
markAsSelectionDependentAction(ITextEditorActionConstants.SHIFT_LEFT, true);
markAsPropertyDependentAction(ITextEditorActionConstants.REVERT_TO_SAVED, true);
markAsStateDependentAction(ITextEditorActionConstants.UNDO, true);
markAsStateDependentAction(ITextEditorActionConstants.REDO, true);
markAsStateDependentAction(ITextEditorActionConstants.CUT, true);
markAsStateDependentAction(ITextEditorActionConstants.PASTE, true);
markAsStateDependentAction(ITextEditorActionConstants.DELETE, true);
markAsStateDependentAction(ITextEditorActionConstants.SHIFT_RIGHT, true);
markAsStateDependentAction(ITextEditorActionConstants.SHIFT_LEFT, true);
markAsStateDependentAction(ITextEditorActionConstants.FIND, true);
markAsStateDependentAction(ITextEditorActionConstants.DELETE_LINE, true);
markAsStateDependentAction(ITextEditorActionConstants.DELETE_LINE_TO_BEGINNING, true);
markAsStateDependentAction(ITextEditorActionConstants.DELETE_LINE_TO_END, true);
setActionActivationCode(ITextEditorActionConstants.SHIFT_RIGHT,'\t', -1, SWT.NONE);
setActionActivationCode(ITextEditorActionConstants.SHIFT_LEFT, '\t', -1, SWT.SHIFT);
}
/**
* 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);
}
}
/**
* 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 a new group after the specified group.
* @param menu the menu to add the new group to
* @param existingGroup the group after which to insert the new group
* @param newGroup the new group
*/
protected final void addGroup(IMenuManager menu, String existingGroup, String newGroup) {
IMenuManager subMenu= menu.findMenuUsingPath(existingGroup);
if (subMenu != null)
subMenu.add(new Separator(newGroup));
else
menu.appendToGroup(existingGroup, new Separator(newGroup));
}
/**
* Sets up the ruler context menu before it is made visible.
* <p>
* Subclasses may extend to add other actions.
* </p>
*
* @param menu the menu
*/
protected void rulerContextMenuAboutToShow(IMenuManager menu) {
for (Iterator i = fRulerContextMenuListeners.iterator(); i.hasNext();)
((IMenuListener) i.next()).menuAboutToShow(menu);
addAction(menu, ITextEditorActionConstants.RULER_MANAGE_BOOKMARKS);
addAction(menu, ITextEditorActionConstants.RULER_MANAGE_TASKS);
menu.add(new Separator(ITextEditorActionConstants.GROUP_REST));
menu.add(new Separator(ITextEditorActionConstants.MB_ADDITIONS));
}
/**
* Sets up this editor's context menu before it is made visible.
* <p>
* Subclasses may extend to add other actions.
* </p>
*
* @param menu the menu
*/
protected void editorContextMenuAboutToShow(IMenuManager menu) {
menu.add(new Separator(ITextEditorActionConstants.GROUP_UNDO));
menu.add(new Separator(ITextEditorActionConstants.GROUP_COPY));
menu.add(new Separator(ITextEditorActionConstants.GROUP_PRINT));
menu.add(new Separator(ITextEditorActionConstants.GROUP_EDIT));
menu.add(new Separator(ITextEditorActionConstants.GROUP_FIND));
menu.add(new Separator(ITextEditorActionConstants.GROUP_ADD));
menu.add(new Separator(ITextEditorActionConstants.GROUP_REST));
menu.add(new Separator(ITextEditorActionConstants.MB_ADDITIONS));
menu.add(new Separator(ITextEditorActionConstants.GROUP_SAVE));
if (isEditable()) {
addAction(menu, ITextEditorActionConstants.GROUP_UNDO, ITextEditorActionConstants.UNDO);
addAction(menu, ITextEditorActionConstants.GROUP_UNDO, ITextEditorActionConstants.REVERT_TO_SAVED);
addAction(menu, ITextEditorActionConstants.GROUP_COPY, ITextEditorActionConstants.CUT);
addAction(menu, ITextEditorActionConstants.GROUP_COPY, ITextEditorActionConstants.COPY);
addAction(menu, ITextEditorActionConstants.GROUP_COPY, ITextEditorActionConstants.PASTE);
addAction(menu, ITextEditorActionConstants.GROUP_SAVE, ITextEditorActionConstants.SAVE);
} else {
addAction(menu, ITextEditorActionConstants.GROUP_COPY, ITextEditorActionConstants.COPY);
}
}
/**
* Returns the status line manager of this editor.
* @return the status line manager of this editor
* @since 2.0
*/
private IStatusLineManager getStatusLineManager() {
IEditorActionBarContributor contributor= getEditorSite().getActionBarContributor();
if (!(contributor instanceof EditorActionBarContributor))
return null;
IActionBars actionBars= ((EditorActionBarContributor) contributor).getActionBars();
if (actionBars == null)
return null;
return actionBars.getStatusLineManager();
}
/*
* @see IAdaptable#getAdapter(Class)
*/
public Object getAdapter(Class required) {
if (IEditorStatusLine.class.equals(required)) {
if (fEditorStatusLine == null) {
IStatusLineManager statusLineManager= getStatusLineManager();
ISelectionProvider selectionProvider= getSelectionProvider();
if (statusLineManager != null && selectionProvider != null)
fEditorStatusLine= new EditorStatusLine(statusLineManager, selectionProvider);
}
return fEditorStatusLine;
}
if (IVerticalRulerInfo.class.equals(required)) {
if (fVerticalRuler instanceof IVerticalRulerInfo)
return fVerticalRuler;
}
if (IMarkRegionTarget.class.equals(required)) {
if (fMarkRegionTarget == null) {
IStatusLineManager manager= getStatusLineManager();
if (manager != null)
fMarkRegionTarget= (fSourceViewer == null ? null : new MarkRegionTarget(fSourceViewer, manager));
}
return fMarkRegionTarget;
}
if (DeleteLineTarget.class.equals(required)){
if (fDeleteLineTarget == null) {
fDeleteLineTarget = new DeleteLineTarget(fSourceViewer);
}
return fDeleteLineTarget;
}
if (IncrementalFindTarget.class.equals(required)) {
if (fIncrementalFindTarget == null) {
IStatusLineManager manager= getStatusLineManager();
if (manager != null)
fIncrementalFindTarget= (fSourceViewer == null ? null : new IncrementalFindTarget(fSourceViewer, manager));
}
return fIncrementalFindTarget;
}
if (IFindReplaceTarget.class.equals(required)) {
IFindReplaceTarget target= (fSourceViewer == null ? null : fSourceViewer.getFindReplaceTarget());
if (target != null && target instanceof IFindReplaceTargetExtension)
((IFindReplaceTargetExtension) target).setScopeHighlightColor(fFindScopeHighlightColor);
return target;
}
if (ITextOperationTarget.class.equals(required))
return (fSourceViewer == null ? null : fSourceViewer.getTextOperationTarget());
if (IRewriteTarget.class.equals(required)) {
if (fSourceViewer instanceof ITextViewerExtension) {
ITextViewerExtension extension= (ITextViewerExtension) fSourceViewer;
return extension.getRewriteTarget();
}
return null;
}
return super.getAdapter(required);
}
/*
* @see IDesktopPart#setFocus()
*/
public void setFocus() {
if (fSourceViewer != null && fSourceViewer.getTextWidget() != null)
fSourceViewer.getTextWidget().setFocus();
}
/**
* If the editor can be saved all marker ranges have been changed according to
* the text manipulations. However, those changes are not yet propagated to the
* marker manager. Thus, when opening a marker, the marker's position in the editor
* must be determined as it might differ from the position stated in the marker.
* @param marker the marker to go to
* @see EditorPart#gotoMarker
*/
public void gotoMarker(IMarker marker) {
if (fSourceViewer == null)
return;
int start= MarkerUtilities.getCharStart(marker);
int end= MarkerUtilities.getCharEnd(marker);
if (start < 0 || end < 0) {
// there is only a line number
int line= MarkerUtilities.getLineNumber(marker);
if (line > -1) {
// marker line numbers are 1-based
-- line;
try {
IDocument document= getDocumentProvider().getDocument(getEditorInput());
selectAndReveal(document.getLineOffset(line), document.getLineLength(line));
} catch (BadLocationException x) {
// marker refers to invalid text position -> do nothing
}
}
} else {
// look up the current range of the marker when the document has been edited
IAnnotationModel model= getDocumentProvider().getAnnotationModel(getEditorInput());
if (model instanceof AbstractMarkerAnnotationModel) {
AbstractMarkerAnnotationModel markerModel= (AbstractMarkerAnnotationModel) model;
Position pos= markerModel.getMarkerPosition(marker);
if (pos == null || pos.isDeleted()) {
// do nothing if position has been deleted
return;
}
start= pos.getOffset();
end= pos.getOffset() + pos.getLength();
}
IDocument document= getDocumentProvider().getDocument(getEditorInput());
int length= document.getLength();
if (end - 1 < length && start < length)
selectAndReveal(start, end - start);
}
}
/*
* @see ITextEditor#showsHighlightRangeOnly
*/
public boolean showsHighlightRangeOnly() {
return fShowHighlightRangeOnly;
}
/*
* @see ITextEditor#showHighlightRangeOnly
*/
public void showHighlightRangeOnly(boolean showHighlightRangeOnly) {
fShowHighlightRangeOnly= showHighlightRangeOnly;
}
/*
* @see ITextEditor#setHighlightRange
*/
public void setHighlightRange(int start, int length, boolean moveCursor) {
if (fSourceViewer == null)
return;
if (fShowHighlightRangeOnly) {
if (moveCursor) {
IRegion visibleRegion= fSourceViewer.getVisibleRegion();
if (start != visibleRegion.getOffset() || length != visibleRegion.getLength())
fSourceViewer.setVisibleRegion(start, length);
}
} else {
IRegion rangeIndication= fSourceViewer.getRangeIndication();
if (rangeIndication == null || start != rangeIndication.getOffset() || length != rangeIndication.getLength())
fSourceViewer.setRangeIndication(start, length, moveCursor);
}
}
/*
* @see ITextEditor#getHighlightRange
*/
public IRegion getHighlightRange() {
if (fSourceViewer == null)
return null;
if (fShowHighlightRangeOnly)
return fSourceViewer.getVisibleRegion();
return fSourceViewer.getRangeIndication();
}
/*
* @see ITextEditor#resetHighlightRange
*/
public void resetHighlightRange() {
if (fSourceViewer == null)
return;
if (fShowHighlightRangeOnly)
fSourceViewer.resetVisibleRegion();
else
fSourceViewer.removeRangeIndication();
}
/**
* Adjusts the highlight range so that at least the specified range
* is highlighted. <p>
* Subclasses may re-implement this method.
*
* @param offset the offset of the range which at least should be highlighted
* @param length the length of the range which at least should be highlighted
*/
protected void adjustHighlightRange(int offset, int length) {
if (fSourceViewer == null)
return;
if (!fSourceViewer.overlapsWithVisibleRegion(offset, length))
fSourceViewer.resetVisibleRegion();
}
/*
* @see ITextEditor#selectAndReveal
*/
public void selectAndReveal(int start, int length) {
if (fSourceViewer == null)
return;
ISelection selection= getSelectionProvider().getSelection();
if (selection instanceof TextSelection) {
TextSelection textSelection= (TextSelection) selection;
if (textSelection.getOffset() != 0 || textSelection.getLength() != 0)
markInNavigationHistory();
}
StyledText widget= fSourceViewer.getTextWidget();
widget.setRedraw(false);
{
adjustHighlightRange(start, length);
fSourceViewer.revealRange(start, length);
fSourceViewer.setSelectedRange(start, length);
markInNavigationHistory();
}
widget.setRedraw(true);
}
/*
* @see org.eclipse.ui.INavigationLocationProvider#createNavigationLocation()
* 2.1 - WORK_IN_PROGRESS do not use.
*/
public INavigationLocation createEmptyNavigationLocation() {
return new TextSelectionNavigationLocation(this, false);
}
/*
* @see org.eclipse.ui.INavigationLocationProvider#createNavigationLocation()
* 2.1 - WORK_IN_PROGRESS do not use.
*/
public INavigationLocation createNavigationLocation() {
return new TextSelectionNavigationLocation(this, true);
}
/**
* Writes a check mark of the given situation into the navigation history.
* 2.1 - WORK_IN_PROGRESS do not use.
*/
protected void markInNavigationHistory() {
IWorkbenchPage page= getEditorSite().getPage();
page.getNavigationHistory().markLocation(this);
}
/**
* Subclasses may extend.
* 2.1 - WORK_IN_PROGRESS do not use.
*/
protected void editorSaved() {
IWorkbenchPage page= getEditorSite().getPage();
INavigationLocation[] locations= page.getNavigationHistory().getLocations();
IEditorInput input= getEditorInput();
for (int i= 0; i < locations.length; i++) {
if (locations[i] instanceof TextSelectionNavigationLocation) {
if(input.equals(locations[i].getInput())) {
TextSelectionNavigationLocation location= (TextSelectionNavigationLocation) locations[i];
location.partSaved(this);
}
}
}
}
/*
* @see EditorPart#firePropertyChange
*/
protected void firePropertyChange(int property) {
super.firePropertyChange(property);
updatePropertyDependentActions();
}
/*
* @see ITextEditorExtension#setStatusField(IStatusField, String)
* @since 2.0
*/
public void setStatusField(IStatusField field, String category) {
Assert.isNotNull(category);
if (field != null) {
if (fStatusFields == null)
fStatusFields= new HashMap(3);
fStatusFields.put(category, field);
updateStatusField(category);
} else if (fStatusFields != null)
fStatusFields.remove(category);
}
/**
* Returns the current status field for the given status category.
*
* @param category the status category
* @return the current status field for the given status category.
* @since 2.0
*/
protected IStatusField getStatusField(String category) {
if (category != null && fStatusFields != null)
return (IStatusField) fStatusFields.get(category);
return null;
}
/**
* Returns whether this editor is in overwrite or insert mode.
*
* @return <code>true</code> if in insert mode, <code>false</code> for overwrite mode
* @since 2.0
*/
protected boolean isInInsertMode() {
return !fOverwriting;
}
/**
* Handles a potential change of the cursor position. Subclasses may extend.
* @since 2.0
*/
protected void handleCursorPositionChanged() {
updateStatusField(ITextEditorActionConstants.STATUS_CATEGORY_INPUT_POSITION);
}
/**
* Handles a change of the editor's insert mode. Subclasses may extend.
* @since 2.0
*/
protected void handleInsertModeChanged() {
updateStatusField(ITextEditorActionConstants.STATUS_CATEGORY_INPUT_MODE);
}
/**
* Updates the status fields for the given category.
* @param category
* @since 2.0
*/
protected void updateStatusField(String category) {
if (category == null)
return;
IStatusField field= getStatusField(category);
if (field != null) {
String text= null;
if (ITextEditorActionConstants.STATUS_CATEGORY_INPUT_POSITION.equals(category))
text= getCursorPosition();
else if (ITextEditorActionConstants.STATUS_CATEGORY_ELEMENT_STATE.equals(category))
text= isEditorInputReadOnly() ? fReadOnlyLabel : fWritableLabel;
else if (ITextEditorActionConstants.STATUS_CATEGORY_INPUT_MODE.equals(category))
text= isInInsertMode() ? fInsertModeLabel : fOverwriteModeLabel;
field.setText(text == null ? fErrorLabel : text);
}
}
/**
* Updates all status fields.
* @since 2.0
*/
protected void updateStatusFields() {
if (fStatusFields != null) {
Iterator e= fStatusFields.keySet().iterator();
while (e.hasNext())
updateStatusField((String) e.next());
}
}
/**
* Returns a description of the cursor position.
* @return a description of the cursor position
* @since 2.0
*/
protected String getCursorPosition() {
if (fSourceViewer == null)
return fErrorLabel;
StyledText styledText= fSourceViewer.getTextWidget();
int offset= fSourceViewer.getVisibleRegion().getOffset();
int caret= offset + styledText.getCaretOffset();
IDocument document= fSourceViewer.getDocument();
if (document == null)
return fErrorLabel;
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 - (column % tabWidth);
else
column++;
fLineLabel.fValue= line + 1;
fColumnLabel.fValue= column + 1;
return MessageFormat.format(fPositionLabelPattern, fPositionLabelPatternArguments);
} catch (BadLocationException x) {
return fErrorLabel;
}
}
/*
* @see ITextEditorExtension#isEditorInputReadOnly()
* @since 2.0
*/
public boolean isEditorInputReadOnly() {
IDocumentProvider provider= getDocumentProvider();
if (provider instanceof IDocumentProviderExtension) {
IDocumentProviderExtension extension= (IDocumentProviderExtension) provider;
return extension.isReadOnly(getEditorInput());
}
return true;
}
/*
* @see ITextEditorExtension2#isEditorInputModifiable()
* @since 2.1
*/
public boolean isEditorInputModifiable() {
IDocumentProvider provider= getDocumentProvider();
if (provider instanceof IDocumentProviderExtension) {
IDocumentProviderExtension extension= (IDocumentProviderExtension) provider;
return extension.isModifiable(getEditorInput());
}
return true;
}
/*
* @see ITextEditorExtension#addRulerContextMenuListener(IMenuListener)
* @since 2.0
*/
public void addRulerContextMenuListener(IMenuListener listener) {
fRulerContextMenuListeners.add(listener);
}
/*
* @see ITextEditorExtension#removeRulerContextMenuListener(IMenuListener)
* @since 2.0
*/
public void removeRulerContextMenuListener(IMenuListener listener) {
fRulerContextMenuListeners.remove(listener);
}
/**
* Returns wether this editor can handle the move of the original element
* so that it ends up being the moved element. By default this method returns
* <code>true</code>. Subclasses may reimplement.
* @param originalElement the original element
* @param movedElement the moved element
* @since 2.0
*/
protected boolean canHandleMove(IEditorInput originalElement, IEditorInput movedElement) {
return true;
}
}