Java tutorial
/* * Copyright (c) 2014 Peter Palaga. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.l2x6.eircc.ui.editor; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.action.GroupMarker; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceConverter; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.DocumentEvent; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocumentListener; import org.eclipse.jface.text.IFindReplaceTarget; import org.eclipse.jface.text.IFindReplaceTargetExtension; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ISelectionValidator; import org.eclipse.jface.text.ITextOperationTarget; import org.eclipse.jface.text.ITextSelection; import org.eclipse.jface.text.ITextViewerExtension; import org.eclipse.jface.text.ITextViewerExtension5; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.hyperlink.HyperlinkManager; import org.eclipse.jface.text.revisions.RevisionInformation; import org.eclipse.jface.text.source.Annotation; import org.eclipse.jface.text.source.IAnnotationAccess; import org.eclipse.jface.text.source.IAnnotationModel; import org.eclipse.jface.text.source.IOverviewRuler; import org.eclipse.jface.text.source.ISharedTextColors; import org.eclipse.jface.text.source.ISourceViewer; import org.eclipse.jface.text.source.OverviewRuler; import org.eclipse.jface.text.source.SourceViewerConfiguration; import org.eclipse.jface.viewers.IPostSelectionProvider; 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.jface.viewers.StructuredSelection; import org.eclipse.jface.window.IShellProvider; import org.eclipse.swt.SWT; 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.VerifyEvent; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; 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.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IKeyBindingService; import org.eclipse.ui.IMemento; import org.eclipse.ui.INavigationLocation; import org.eclipse.ui.INavigationLocationProvider; import org.eclipse.ui.IPersistableEditor; import org.eclipse.ui.IReusableEditor; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.IWorkbenchCommandConstants; import org.eclipse.ui.dialogs.PropertyDialogAction; import org.eclipse.ui.internal.editors.text.EditorsPlugin; import org.eclipse.ui.internal.texteditor.NLSUtility; import org.eclipse.ui.part.EditorPart; import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; import org.eclipse.ui.texteditor.AnnotationPreference; import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess; import org.eclipse.ui.texteditor.FindNextAction; import org.eclipse.ui.texteditor.FindReplaceAction; import org.eclipse.ui.texteditor.GotoAnnotationAction; import org.eclipse.ui.texteditor.GotoLineAction; import org.eclipse.ui.texteditor.IAbstractTextEditorHelpContextIds; import org.eclipse.ui.texteditor.IDocumentProvider; import org.eclipse.ui.texteditor.IEditorStatusLine; import org.eclipse.ui.texteditor.IReadOnlyDependent; import org.eclipse.ui.texteditor.IStatusField; import org.eclipse.ui.texteditor.ITextEditor; import org.eclipse.ui.texteditor.ITextEditorActionConstants; import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds; import org.eclipse.ui.texteditor.ITextEditorExtension; import org.eclipse.ui.texteditor.ITextEditorExtension4; import org.eclipse.ui.texteditor.IUpdate; import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds; import org.eclipse.ui.texteditor.IncrementalFindAction; import org.eclipse.ui.texteditor.MarkerAnnotationPreferences; import org.eclipse.ui.texteditor.MoveLinesAction; import org.eclipse.ui.texteditor.RecenterAction; import org.eclipse.ui.texteditor.ResourceAction; import org.eclipse.ui.texteditor.ShowWhitespaceCharactersAction; import org.eclipse.ui.texteditor.SourceViewerDecorationSupport; import org.eclipse.ui.texteditor.TextOperationAction; import org.eclipse.ui.texteditor.TextSelectionNavigationLocation; import org.l2x6.eircc.ui.IrcUiMessages; /** * @author <a href="mailto:ppalaga@redhat.com">Peter Palaga</a> */ @SuppressWarnings({ "deprecation", "restriction" }) public abstract class AbstractIrcEditor extends EditorPart implements ITextEditor, IReusableEditor, ITextEditorExtension, ITextEditorExtension4, INavigationLocationProvider, IPersistableEditor { /** * Internal implementation class for a change listener. * * @since 3.0 */ protected abstract class AbstractSelectionChangedListener implements ISelectionChangedListener { /** * Installs this selection changed listener with the given selection * provider. If the selection provider is a post selection provider, * post selection changed events are the preferred choice, otherwise * normal selection changed events are requested. * * @param selectionProvider * the selection provider */ public void install(ISelectionProvider selectionProvider) { if (selectionProvider == null) return; if (selectionProvider instanceof IPostSelectionProvider) { IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider; provider.addPostSelectionChangedListener(this); } else { selectionProvider.addSelectionChangedListener(this); } } /** * Removes this selection changed listener from the given selection * provider. * * @param selectionProvider * the selection provider */ public void uninstall(ISelectionProvider selectionProvider) { if (selectionProvider == null) return; if (selectionProvider instanceof IPostSelectionProvider) { IPostSelectionProvider provider = (IPostSelectionProvider) selectionProvider; provider.removePostSelectionChangedListener(this); } else { selectionProvider.removeSelectionChangedListener(this); } } } /** * Representation of action activation codes. */ static class ActionActivationCode { /** The action id. */ public String fActionId; /** The character. */ public char fCharacter; /** The key code. */ public int fKeyCode = -1; /** The state mask. */ 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 * @return whether this activation code matches <code>event</code> */ public boolean matches(VerifyEvent event) { return (event.character == fCharacter && (fKeyCode == -1 || event.keyCode == fKeyCode) && (fStateMask == SWT.DEFAULT || event.stateMask == fStateMask)); } } /** * 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; /** * Installs this trigger on the editor's text widget. * * @since 2.0 */ public void install() { if (!fIsInstalled) { if (logViewer instanceof ITextViewerExtension) { ITextViewerExtension e = (ITextViewerExtension) logViewer; e.prependVerifyKeyListener(this); } else { StyledText text = logViewer.getTextWidget(); text.addVerifyKeyListener(this); } fKeyBindingService = getEditorSite().getKeyBindingService(); fIsInstalled = true; } } /** * Registers the given action for key activation. * * @param action * the action to be registered * @since 2.0 */ public void registerActionForKeyActivation(IAction action) { if (fIsInstalled && action.getActionDefinitionId() != null) fKeyBindingService.registerAction(action); } /** * Sets the key binding scopes for this editor. * * @param keyBindingScopes * the key binding scopes * @since 2.1 */ public void setScopes(String[] keyBindingScopes) { if (keyBindingScopes != null && keyBindingScopes.length > 0) fKeyBindingService.setScopes(keyBindingScopes); } /** * Uninstalls this trigger from the editor's text widget. * * @since 2.0 */ public void uninstall() { if (fIsInstalled) { if (logViewer instanceof ITextViewerExtension) { ITextViewerExtension e = (ITextViewerExtension) logViewer; e.removeVerifyKeyListener(this); } else if (logViewer != null) { StyledText text = logViewer.getTextWidget(); if (text != null && !text.isDisposed()) text.removeVerifyKeyListener(fActivationCodeTrigger); } fIsInstalled = false; fKeyBindingService = null; } } /** * 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) { if (fIsInstalled && action.getActionDefinitionId() != null) fKeyBindingService.unregisterAction(action); } /* * @see VerifyKeyListener#verifyKey(org.eclipse.swt.events.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; } } } } } } /** * Internal interface for a cursor listener. I.e. aggregation of mouse and * key listener. * * @since 2.0 */ interface ICursorListener extends MouseListener, KeyListener { } /** * Data structure for the position label value. */ private static class PositionLabelValue { public int fValue; public String toString() { return String.valueOf(fValue); } } /** * This selection listener allows the SelectionProvider to implement * {@link ISelectionValidator}. * * @since 3.0 */ private class SelectionListener extends AbstractSelectionChangedListener implements IDocumentListener { private IDocument fDocument; private Object fPostSelection = INVALID_SELECTION; /* * @see * org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged * (org.eclipse.jface.text.DocumentEvent) * * @since 3.0 */ public synchronized void documentAboutToBeChanged(DocumentEvent event) { fPostSelection = INVALID_SELECTION; } /* * @see * org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse * .jface.text.DocumentEvent) * * @since 3.0 */ public void documentChanged(DocumentEvent event) { } /* * @see org.eclipse.ui.texteditor.AbstractTextEditor. * AbstractSelectionChangedListener * #install(org.eclipse.jface.viewers.ISelectionProvider) * * @since 3.0 */ public void install(ISelectionProvider selectionProvider) { super.install(selectionProvider); if (selectionProvider != null) selectionProvider.addSelectionChangedListener(this); } public synchronized boolean isValid(ISelection selection) { return fPostSelection != INVALID_SELECTION && fPostSelection == selection; } /* * @see * org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged * (org.eclipse.jface.viewers.SelectionChangedEvent) */ public synchronized void selectionChanged(SelectionChangedEvent event) { fPostSelection = event.getSelection(); } public void setDocument(IDocument document) { if (fDocument != null) fDocument.removeDocumentListener(this); fDocument = document; if (fDocument != null) fDocument.addDocumentListener(this); } /* * @see org.eclipse.ui.texteditor.AbstractTextEditor. * AbstractSelectionChangedListener * #uninstall(org.eclipse.jface.viewers.ISelectionProvider) * * @since 3.0 */ public void uninstall(ISelectionProvider selectionProvider) { if (selectionProvider != null) selectionProvider.removeSelectionChangedListener(this); if (fDocument != null) { fDocument.removeDocumentListener(this); fDocument = null; } super.uninstall(selectionProvider); } } /** * Editor specific selection provider which wraps the source viewer's * selection provider. * * @since 3.4 protected, was added in 2.1 as private class */ protected class SelectionProvider implements IPostSelectionProvider, ISelectionValidator { /* * @see org.eclipse.jface.text.IPostSelectionProvider# * addPostSelectionChangedListener * (org.eclipse.jface.viewers.ISelectionChangedListener) * * @since 3.0 */ public void addPostSelectionChangedListener(ISelectionChangedListener listener) { if (logViewer != null) { if (logViewer.getSelectionProvider() instanceof IPostSelectionProvider) { IPostSelectionProvider provider = (IPostSelectionProvider) logViewer.getSelectionProvider(); provider.addPostSelectionChangedListener(listener); } } } /* * @see * org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener * (ISelectionChangedListener) */ public void addSelectionChangedListener(ISelectionChangedListener listener) { if (logViewer != null) logViewer.getSelectionProvider().addSelectionChangedListener(listener); } /* * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection() */ public ISelection getSelection() { return doGetSelection(); } /* * @see org.eclipse.jface.text.IPostSelectionValidator#isValid() * * @since 3.0 */ public boolean isValid(ISelection postSelection) { return fSelectionListener != null && fSelectionListener.isValid(postSelection); } /* * @see org.eclipse.jface.text.IPostSelectionProvider# * removePostSelectionChangedListener * (org.eclipse.jface.viewers.ISelectionChangedListener) * * @since 3.0 */ public void removePostSelectionChangedListener(ISelectionChangedListener listener) { if (logViewer != null) { if (logViewer.getSelectionProvider() instanceof IPostSelectionProvider) { IPostSelectionProvider provider = (IPostSelectionProvider) logViewer.getSelectionProvider(); provider.removePostSelectionChangedListener(listener); } } } /* * @see org.eclipse.jface.viewers.ISelectionProvider# * removeSelectionChangedListener(ISelectionChangedListener) */ public void removeSelectionChangedListener(ISelectionChangedListener listener) { if (logViewer != null) logViewer.getSelectionProvider().removeSelectionChangedListener(listener); } /* * @see * org.eclipse.jface.viewers.ISelectionProvider#setSelection(ISelection) */ public void setSelection(ISelection selection) { doSetSelection(selection); } } private static final Object INVALID_SELECTION = new Object(); /** The width of the vertical ruler. */ protected static final int VERTICAL_RULER_WIDTH = 12; /** * Returns the minimal region of the given source viewer's document that * completely comprises everything that is visible in the viewer's widget. * * @param viewer * the viewer go return the coverage for * @return the minimal region of the source viewer's document comprising the * contents of the viewer's widget * @since 2.1 */ protected static final IRegion getCoverage(ISourceViewer viewer) { if (viewer instanceof ITextViewerExtension5) { ITextViewerExtension5 extension = (ITextViewerExtension5) viewer; return extension.getModelCoverage(); } return viewer.getVisibleRegion(); } /** * Tells whether the given region is visible in the given source viewer. * * @param viewer * the source viewer * @param offset * the offset of the region * @param length * the length of the region * @return <code>true</code> if visible * @since 2.1 */ protected static final boolean isVisible(ISourceViewer viewer, int offset, int length) { if (viewer instanceof ITextViewerExtension5) { ITextViewerExtension5 extension = (ITextViewerExtension5) viewer; IRegion overlap = extension.modelRange2WidgetRange(new Region(offset, length)); return overlap != null; } return viewer.overlapsWithVisibleRegion(offset, length); } /** * Returns the offset of the given source viewer's document that corresponds * to the given widget offset or <code>-1</code> if there is no such offset. * * @param viewer * the source viewer * @param widgetOffset * the widget offset * @return the corresponding offset in the source viewer's document or * <code>-1</code> * @since 2.1 */ protected static final int widgetOffset2ModelOffset(ISourceViewer viewer, int widgetOffset) { if (viewer instanceof ITextViewerExtension5) { ITextViewerExtension5 extension = (ITextViewerExtension5) viewer; return extension.widgetOffset2ModelOffset(widgetOffset); } return widgetOffset + viewer.getVisibleRegion().getOffset(); } /** The actions registered with the editor. */ private Map<String, IAction> fActions = new HashMap<String, IAction>(10); private List<ActionActivationCode> fActivationCodes = new ArrayList<ActionActivationCode>(2); /** The verify key listener for activation code triggering. */ private ActivationCodeTrigger fActivationCodeTrigger = new ActivationCodeTrigger(); /** * Helper for accessing annotation from the perspective of this editor. * * <p> * This field should not be referenced by subclasses. It is * <code>protected</code> for API compatibility reasons and will be made * <code>private</code> soon. Use {@link #getAnnotationAccess()} instead. * </p> */ protected IAnnotationAccess fAnnotationAccess; private MarkerAnnotationPreferences fAnnotationPreferences; /** * The editor's background color. * * @since 2.0 */ private Color fBackgroundColor; /** The position label value of the current column. */ private final PositionLabelValue fColumnLabel = new PositionLabelValue(); private SourceViewerConfiguration fConfiguration; /** The actions marked as content dependent. */ private List<String> fContentActions = new ArrayList<String>(5); private ICursorListener fCursorListener; /** The editor's context menu id. */ private String fEditorContextMenuId; /** * The error message shown in the status line in case of failed information * look up. */ protected final String fErrorLabel = IrcUiMessages.Editor_statusline_error_label; /** * The find scope's highlight color. * * @since 2.0 */ private Color fFindScopeHighlightColor; /** The editor's font. */ private Font fFont; private Color fForegroundColor; private final PositionLabelValue fLineLabel = new PositionLabelValue(); /** Context menu listener. */ private IMenuListener fMenuListener; private IOverviewRuler fOverviewRuler; private final String fPositionLabelPattern = IrcUiMessages.Editor_statusline_position_pattern; /** The arguments for the position label pattern. */ private final Object[] fPositionLabelPatternArguments = new Object[] { fLineLabel, fColumnLabel }; /** The editor's preference store. */ private IPreferenceStore fPreferenceStore; /** * The actions marked as property dependent. * * @since 2.0 */ private List<String> fPropertyActions = new ArrayList<String>(5); /** The editor's range indicator. */ private Annotation fRangeIndicator; /** The actions marked as selection dependent. */ private List<String> fSelectionActions = new ArrayList<String>(5); /** * The editor's selection background color. * * @since 3.0 */ private Color fSelectionBackgroundColor; /** Selection changed listener. */ private ISelectionChangedListener fSelectionChangedListener; /** * The editor's selection foreground color. * * @since 3.0 */ private Color fSelectionForegroundColor; /** * The editor's selection listener. * * @since 3.0 */ private SelectionListener fSelectionListener; private SelectionProvider fSelectionProvider = new SelectionProvider(); /** The editor's presentation mode. */ private boolean fShowHighlightRangeOnly; /** * Helper for managing the decoration support of this editor's viewer. * * <p> * This field should not be referenced by subclasses. It is * <code>protected</code> for API compatibility reasons and will be made * <code>private</code> soon. Use * {@link #getSourceViewerDecorationSupport(ISourceViewer)} instead. * </p> */ protected SourceViewerDecorationSupport fSourceViewerDecorationSupport; /** * The actions marked as state dependent. * * @since 2.0 */ private List<String> fStateActions = new ArrayList<String>(5); /** * The map of the editor's status fields. * * @since 2.0 */ private Map<String, IStatusField> fStatusFields; /** The text context menu to be disposed. */ private Menu fTextContextMenu; protected IrcLogViewer logViewer; /** * */ public AbstractIrcEditor() { super(); fAnnotationPreferences = EditorsPlugin.getDefault().getMarkerAnnotationPreferences(); } /** * 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); } } /** * @see org.eclipse.ui.texteditor.ITextEditorExtension#addRulerContextMenuListener(org.eclipse.jface.action.IMenuListener) */ @Override public void addRulerContextMenuListener(IMenuListener listener) { } /** * Adjusts the highlight range so that at least the specified range is * highlighted. * <p> * Subclasses may re-implement this method. * </p> * * @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 (logViewer == null) return; if (logViewer instanceof ITextViewerExtension5) { ITextViewerExtension5 extension = (ITextViewerExtension5) logViewer; extension.exposeModelRange(new Region(offset, length)); } else if (!isVisible(logViewer, offset, length)) { logViewer.resetVisibleRegion(); } } /** * @see org.eclipse.ui.texteditor.ITextEditor#close(boolean) */ @Override public void close(final boolean save) { Display display = getSite().getShell().getDisplay(); display.asyncExec(new Runnable() { public void run() { if (logViewer != null) getSite().getPage().closeEditor(AbstractIrcEditor.this, save); } }); } /** * Configures the decoration support for this editor's source viewer. * Subclasses may override this method, but should call their superclass' * implementation at some point. * * @param support * the decoration support to configure */ protected void configureSourceViewerDecorationSupport(SourceViewerDecorationSupport support) { Iterator<?> e = fAnnotationPreferences.getAnnotationPreferences().iterator(); while (e.hasNext()) support.setAnnotationPreference((AnnotationPreference) e.next()); support.setCursorLinePainterPreferenceKeys( AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE, AbstractDecoratedTextEditorPreferenceConstants.EDITOR_CURRENT_LINE_COLOR); // support.setMarginPainterPreferenceKeys(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN, // AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLOR, // AbstractDecoratedTextEditorPreferenceConstants.EDITOR_PRINT_MARGIN_COLUMN); // support.setSymbolicFontName(getFontPropertyPreferenceKey()); } /** * Creates this editor's standard actions and connects them with the global * workbench actions. * <p> * Subclasses may extend. * </p> */ protected void createActions() { ResourceAction action; setAction(IWorkbenchCommandConstants.EDIT_COPY, null); action = new TextOperationAction(IrcUiMessages.getBundleForConstructedKeys(), "Editor.Copy.", this, //$NON-NLS-1$ ITextOperationTarget.COPY, true); action.setHelpContextId(IAbstractTextEditorHelpContextIds.COPY_ACTION); action.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_COPY); setAction(ITextEditorActionConstants.COPY, action); action = new TextOperationAction(IrcUiMessages.getBundleForConstructedKeys(), "Editor.SelectAll.", this, //$NON-NLS-1$ ITextOperationTarget.SELECT_ALL, true); action.setHelpContextId(IAbstractTextEditorHelpContextIds.SELECT_ALL_ACTION); action.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_SELECT_ALL); setAction(ITextEditorActionConstants.SELECT_ALL, action); action = new TextOperationAction(IrcUiMessages.getBundleForConstructedKeys(), "Editor.Print.", this, //$NON-NLS-1$ ITextOperationTarget.PRINT, true); action.setHelpContextId(IAbstractTextEditorHelpContextIds.PRINT_ACTION); action.setActionDefinitionId(IWorkbenchCommandConstants.FILE_PRINT); setAction(ITextEditorActionConstants.PRINT, action); action = new FindReplaceAction(IrcUiMessages.getBundleForConstructedKeys(), "Editor.FindReplace.", this); //$NON-NLS-1$ action.setHelpContextId(IAbstractTextEditorHelpContextIds.FIND_ACTION); action.setActionDefinitionId(IWorkbenchCommandConstants.EDIT_FIND_AND_REPLACE); setAction(ITextEditorActionConstants.FIND, action); action = new FindNextAction(IrcUiMessages.getBundleForConstructedKeys(), "Editor.FindNext.", this, true); //$NON-NLS-1$ action.setHelpContextId(IAbstractTextEditorHelpContextIds.FIND_NEXT_ACTION); action.setActionDefinitionId(IWorkbenchActionDefinitionIds.FIND_NEXT); setAction(ITextEditorActionConstants.FIND_NEXT, action); action = new FindNextAction(IrcUiMessages.getBundleForConstructedKeys(), "Editor.FindPrevious.", this, //$NON-NLS-1$ false); action.setHelpContextId(IAbstractTextEditorHelpContextIds.FIND_PREVIOUS_ACTION); action.setActionDefinitionId(IWorkbenchActionDefinitionIds.FIND_PREVIOUS); setAction(ITextEditorActionConstants.FIND_PREVIOUS, action); action = new IncrementalFindAction(IrcUiMessages.getBundleForConstructedKeys(), "Editor.FindIncremental.", //$NON-NLS-1$ this, true); action.setHelpContextId(IAbstractTextEditorHelpContextIds.FIND_INCREMENTAL_ACTION); action.setActionDefinitionId(IWorkbenchActionDefinitionIds.FIND_INCREMENTAL); setAction(ITextEditorActionConstants.FIND_INCREMENTAL, action); action = new IncrementalFindAction(IrcUiMessages.getBundleForConstructedKeys(), "Editor.FindIncrementalReverse.", this, false); //$NON-NLS-1$ action.setHelpContextId(IAbstractTextEditorHelpContextIds.FIND_INCREMENTAL_REVERSE_ACTION); action.setActionDefinitionId(IWorkbenchActionDefinitionIds.FIND_INCREMENTAL_REVERSE); setAction(ITextEditorActionConstants.FIND_INCREMENTAL_REVERSE, action); action = new GotoLineAction(IrcUiMessages.getBundleForConstructedKeys(), "Editor.GotoLine.", this); //$NON-NLS-1$ action.setHelpContextId(IAbstractTextEditorHelpContextIds.GOTO_LINE_ACTION); action.setActionDefinitionId(ITextEditorActionDefinitionIds.LINE_GOTO); setAction(ITextEditorActionConstants.GOTO_LINE, action); action = new MoveLinesAction(IrcUiMessages.getBundleForConstructedKeys(), "Editor.MoveLinesUp.", this, //$NON-NLS-1$ getSourceViewer(), true, false); action.setHelpContextId(IAbstractTextEditorHelpContextIds.MOVE_LINES_ACTION); action.setActionDefinitionId(ITextEditorActionDefinitionIds.MOVE_LINES_UP); setAction(ITextEditorActionConstants.MOVE_LINE_UP, action); action = new MoveLinesAction(IrcUiMessages.getBundleForConstructedKeys(), "Editor.MoveLinesDown.", this, //$NON-NLS-1$ getSourceViewer(), false, false); action.setHelpContextId(IAbstractTextEditorHelpContextIds.MOVE_LINES_ACTION); action.setActionDefinitionId(ITextEditorActionDefinitionIds.MOVE_LINES_DOWN); setAction(ITextEditorActionConstants.MOVE_LINE_DOWN, action); action = new MoveLinesAction(IrcUiMessages.getBundleForConstructedKeys(), "Editor.CopyLineUp.", this, //$NON-NLS-1$ getSourceViewer(), true, true); action.setHelpContextId(IAbstractTextEditorHelpContextIds.COPY_LINES_ACTION); action.setActionDefinitionId(ITextEditorActionDefinitionIds.COPY_LINES_UP); setAction(ITextEditorActionConstants.COPY_LINE_UP, action); action = new MoveLinesAction(IrcUiMessages.getBundleForConstructedKeys(), "Editor.CopyLineDown.", this, //$NON-NLS-1$ getSourceViewer(), false, true); action.setHelpContextId(IAbstractTextEditorHelpContextIds.COPY_LINES_ACTION); action.setActionDefinitionId(ITextEditorActionDefinitionIds.COPY_LINES_DOWN); setAction(ITextEditorActionConstants.COPY_LINE_DOWN, action); action = new GotoAnnotationAction(this, true); setAction(ITextEditorActionConstants.NEXT, action); action = new GotoAnnotationAction(this, false); setAction(ITextEditorActionConstants.PREVIOUS, action); action = new RecenterAction(IrcUiMessages.getBundleForConstructedKeys(), "Editor.Recenter.", this); //$NON-NLS-1$ action.setHelpContextId(IAbstractTextEditorHelpContextIds.RECENTER_ACTION); action.setActionDefinitionId(ITextEditorActionDefinitionIds.RECENTER); setAction(ITextEditorActionConstants.RECENTER, action); action = new ShowWhitespaceCharactersAction(IrcUiMessages.getBundleForConstructedKeys(), "Editor.ShowWhitespaceCharacters.", this, getPreferenceStore()); //$NON-NLS-1$ action.setHelpContextId(IAbstractTextEditorHelpContextIds.SHOW_WHITESPACE_CHARACTERS_ACTION); action.setActionDefinitionId(ITextEditorActionDefinitionIds.SHOW_WHITESPACE_CHARACTERS); setAction(ITextEditorActionConstants.SHOW_WHITESPACE_CHARACTERS, action); action = new TextOperationAction(IrcUiMessages.getBundleForConstructedKeys(), "Editor.OpenHyperlink.", this, //$NON-NLS-1$ HyperlinkManager.OPEN_HYPERLINK, true); //; action.setHelpContextId(IAbstractTextEditorHelpContextIds.OPEN_HYPERLINK_ACTION); action.setActionDefinitionId(ITextEditorActionDefinitionIds.OPEN_HYPERLINK); setAction(ITextEditorActionConstants.OPEN_HYPERLINK, action); PropertyDialogAction openProperties = new PropertyDialogAction(new IShellProvider() { public Shell getShell() { return getSite().getShell(); } }, new ISelectionProvider() { public void addSelectionChangedListener(ISelectionChangedListener listener) { } public ISelection getSelection() { return new StructuredSelection(getEditorInput()); } public void removeSelectionChangedListener(ISelectionChangedListener listener) { } public void setSelection(ISelection selection) { } }); openProperties.setActionDefinitionId(IWorkbenchCommandConstants.FILE_PROPERTIES); setAction(ITextEditorActionConstants.PROPERTIES, openProperties); 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_RIGHT_TAB, true); markAsSelectionDependentAction(ITextEditorActionConstants.UPPER_CASE, true); markAsSelectionDependentAction(ITextEditorActionConstants.LOWER_CASE, true); markAsPropertyDependentAction(ITextEditorActionConstants.UNDO, true); markAsPropertyDependentAction(ITextEditorActionConstants.REDO, true); markAsPropertyDependentAction(ITextEditorActionConstants.REVERT_TO_SAVED, true); markAsPropertyDependentAction(ITextEditorActionConstants.SAVE, 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_RIGHT_TAB, 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); markAsStateDependentAction(ITextEditorActionConstants.MOVE_LINE_UP, true); markAsStateDependentAction(ITextEditorActionConstants.MOVE_LINE_DOWN, true); markAsStateDependentAction(ITextEditorActionConstants.CUT_LINE, true); markAsStateDependentAction(ITextEditorActionConstants.CUT_LINE_TO_BEGINNING, true); markAsStateDependentAction(ITextEditorActionConstants.CUT_LINE_TO_END, true); setActionActivationCode(ITextEditorActionConstants.SHIFT_RIGHT_TAB, '\t', -1, SWT.NONE); setActionActivationCode(ITextEditorActionConstants.SHIFT_LEFT, '\t', -1, SWT.SHIFT); } /** * Creates the annotation access for this editor. * * @return the created annotation access */ protected IAnnotationAccess createAnnotationAccess() { return new DefaultMarkerAnnotationAccess(); } /** * 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; } /** * Creates the listener on this editor's context menus. * * @return the created menu listener * @since 3.4 */ protected IMenuListener createContextMenuListener() { return new IMenuListener() { public void menuAboutToShow(IMenuManager menu) { String id = menu.getId(); if (getEditorContextMenuId().equals(id)) { setFocus(); editorContextMenuAboutToShow(menu); } } }; } /** * @see org.eclipse.ui.INavigationLocationProvider#createEmptyNavigationLocation() */ @Override public INavigationLocation createEmptyNavigationLocation() { return new TextSelectionNavigationLocation(this, false); } /** * @see org.eclipse.ui.INavigationLocationProvider#createNavigationLocation() */ @Override public INavigationLocation createNavigationLocation() { return new TextSelectionNavigationLocation(this, true); } protected IOverviewRuler createOverviewRuler(ISharedTextColors sharedColors) { IOverviewRuler ruler = new OverviewRuler(getAnnotationAccess(), VERTICAL_RULER_WIDTH, sharedColors); Iterator<?> e = fAnnotationPreferences.getAnnotationPreferences().iterator(); while (e.hasNext()) { AnnotationPreference preference = (AnnotationPreference) e.next(); if (preference.contributesToHeader()) ruler.addHeaderAnnotationType(preference.getAnnotationType()); } return ruler; } public void createPartControl(Composite parent) { int styles = SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI | SWT.BORDER | SWT.FULL_SELECTION; this.logViewer = createSourceViewer(parent, styles); this.logViewer.configure(fConfiguration); if (fRangeIndicator != null) this.logViewer.setRangeIndicator(fRangeIndicator); getSelectionProvider().addSelectionChangedListener(getSelectionChangedListener()); initializeViewerFont(logViewer); initializeViewerColors(logViewer); initializeFindScopeColor(logViewer); StyledText styledText = logViewer.getTextWidget(); styledText.addMouseListener(getCursorListener()); styledText.addKeyListener(getCursorListener()); // Disable orientation switching until we fully support it. styledText.addListener(SWT.OrientationChange, new Listener() { public void handleEvent(Event event) { event.doit = false; } }); String id = fEditorContextMenuId != null ? fEditorContextMenuId : org.eclipse.ui.texteditor.AbstractTextEditor.DEFAULT_EDITOR_CONTEXT_MENU_ID; MenuManager manager = new MenuManager(id, id); manager.setRemoveAllWhenShown(true); manager.addMenuListener(getContextMenuListener()); fTextContextMenu = manager.createContextMenu(styledText); // comment this line if using gestures, above. styledText.setMenu(fTextContextMenu); if (fEditorContextMenuId != null) getEditorSite().registerContextMenu(fEditorContextMenuId, manager, getSelectionProvider(), isEditorInputIncludedInContextMenu()); getEditorSite().registerContextMenu( org.eclipse.ui.texteditor.AbstractTextEditor.COMMON_EDITOR_CONTEXT_MENU_ID, manager, getSelectionProvider(), false); if (fEditorContextMenuId == null) fEditorContextMenuId = org.eclipse.ui.texteditor.AbstractTextEditor.DEFAULT_EDITOR_CONTEXT_MENU_ID; getSite().setSelectionProvider(getSelectionProvider()); fSelectionListener = new SelectionListener(); fSelectionListener.install(getSelectionProvider()); fSelectionListener.setDocument(logViewer.getDocument()); initializeActivationCodeTrigger(); // createNavigationActions(); createActions(); initializeSourceViewer(getEditorInput()); } protected IrcLogViewer createSourceViewer(Composite parent, int styles) { fAnnotationAccess = getAnnotationAccess(); fOverviewRuler = createOverviewRuler(getSharedColors()); IrcLogViewer result = new IrcLogViewer(parent, null, getOverviewRuler(), isOverviewRulerVisible(), styles); // ensure decoration support has been created and configured. getSourceViewerDecorationSupport(result); return result; } /** * /** Disposes of the non-shared font. * * @since 3.5 */ private void disposeFont() { if (fFont != null) { fFont.dispose(); fFont = null; } } /** * Returns the current selection. * * @return ISelection * @since 2.1 */ protected ISelection doGetSelection() { ISelectionProvider sp = null; if (logViewer != null) sp = logViewer.getSelectionProvider(); return (sp == null ? null : sp.getSelection()); } /** * @see org.eclipse.ui.texteditor.ITextEditor#doRevertToSaved() */ @Override public void doRevertToSaved() { } /** * @see org.eclipse.ui.part.EditorPart#doSave(org.eclipse.core.runtime.IProgressMonitor) */ @Override public void doSave(IProgressMonitor monitor) { } /** * @see org.eclipse.ui.part.EditorPart#doSaveAs() */ @Override public void doSaveAs() { } /** * Sets the given selection. * * @param selection * the selection * @since 2.1 */ protected void doSetSelection(ISelection selection) { if (selection instanceof ITextSelection) { ITextSelection textSelection = (ITextSelection) selection; selectAndReveal(textSelection.getOffset(), textSelection.getLength()); } } /** * 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 GroupMarker(ITextEditorActionConstants.GROUP_SAVE)); 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(IWorkbenchActionConstants.GROUP_ADD)); menu.add(new Separator(ITextEditorActionConstants.GROUP_REST)); menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); addAction(menu, ITextEditorActionConstants.GROUP_COPY, ITextEditorActionConstants.COPY); } /** * 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; } /** * Returns the annotation closest to the given range respecting the given * direction. If an annotation is found, the annotations current position is * copied into the provided annotation position. * * @param offset * the region offset * @param length * the region length * @param forward * <code>true</code> for forwards, <code>false</code> for * backward * @param annotationPosition * the position of the found annotation * @return the found annotation * @since 3.2 */ protected Annotation findAnnotation(final int offset, final int length, boolean forward, Position annotationPosition) { Annotation nextAnnotation = null; Position nextAnnotationPosition = null; Annotation containingAnnotation = null; Position containingAnnotationPosition = null; boolean currentAnnotation = false; IDocument document = getDocumentProvider().getDocument(getEditorInput()); int endOfDocument = document.getLength(); int distance = Integer.MAX_VALUE; IAnnotationModel model = getDocumentProvider().getAnnotationModel(getEditorInput()); Iterator<?> e = model.getAnnotationIterator(); while (e.hasNext()) { Annotation a = (Annotation) e.next(); if (!isNavigationTarget(a)) continue; Position p = model.getPosition(a); if (p == null) continue; if (forward && p.offset == offset || !forward && p.offset + p.getLength() == offset + length) {// || // p.includes(offset)) // { if (containingAnnotation == null || (forward && p.length >= containingAnnotationPosition.length || !forward && p.length >= containingAnnotationPosition.length)) { containingAnnotation = a; containingAnnotationPosition = p; currentAnnotation = p.length == length; } } else { int currentDistance = 0; if (forward) { currentDistance = p.getOffset() - offset; if (currentDistance < 0) currentDistance = endOfDocument + currentDistance; if (currentDistance < distance || currentDistance == distance && p.length < nextAnnotationPosition.length) { distance = currentDistance; nextAnnotation = a; nextAnnotationPosition = p; } } else { currentDistance = offset + length - (p.getOffset() + p.length); if (currentDistance < 0) currentDistance = endOfDocument + currentDistance; if (currentDistance < distance || currentDistance == distance && p.length < nextAnnotationPosition.length) { distance = currentDistance; nextAnnotation = a; nextAnnotationPosition = p; } } } } if (containingAnnotationPosition != null && (!currentAnnotation || nextAnnotation == null)) { annotationPosition.setOffset(containingAnnotationPosition.getOffset()); annotationPosition.setLength(containingAnnotationPosition.getLength()); return containingAnnotation; } if (nextAnnotationPosition != null) { annotationPosition.setOffset(nextAnnotationPosition.getOffset()); annotationPosition.setLength(nextAnnotationPosition.getLength()); } return nextAnnotation; } /** * @see org.eclipse.ui.texteditor.ITextEditor#getAction(java.lang.String) */ @Override 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 annotation access. * * @return the annotation access */ protected IAnnotationAccess getAnnotationAccess() { if (fAnnotationAccess == null) fAnnotationAccess = createAnnotationAccess(); return fAnnotationAccess; } /** * Creates and returns the listener on this editor's context menus. * * @return the menu listener */ protected final IMenuListener getContextMenuListener() { if (fMenuListener == null) fMenuListener = createContextMenuListener(); return fMenuListener; } /** * 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; } /** * Returns a description of the cursor position. * * @return a description of the cursor position * @since 2.0 */ protected String getCursorPosition() { if (logViewer == null) return fErrorLabel; StyledText styledText = logViewer.getTextWidget(); int caret = widgetOffset2ModelOffset(logViewer, styledText.getCaretOffset()); IDocument document = logViewer.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 - (tabWidth == 0 ? 0 : column % tabWidth); else column++; fLineLabel.fValue = line + 1; fColumnLabel.fValue = column + 1; return NLSUtility.format(fPositionLabelPattern, fPositionLabelPatternArguments); } catch (BadLocationException x) { return fErrorLabel; } } /** * @see org.eclipse.ui.texteditor.ITextEditor#getDocumentProvider() */ @Override public IDocumentProvider getDocumentProvider() { return IrcDocumentProvider.getInstance(); } /** * Returns the editor's context menu id. May return <code>null</code> before * the editor's part has been created. * * @return the editor's context menu id which may be <code>null</code> */ protected final String getEditorContextMenuId() { return fEditorContextMenuId; } /* * @see ITextEditor#getHighlightRange() */ public IRegion getHighlightRange() { if (logViewer == null) return null; if (fShowHighlightRangeOnly) return getCoverage(logViewer); return logViewer.getRangeIndication(); } /** * Returns the overview ruler. * * @return the overview ruler */ protected IOverviewRuler getOverviewRuler() { if (fOverviewRuler == null) fOverviewRuler = createOverviewRuler(getSharedColors()); return fOverviewRuler; } /** * Returns this editor's preference store or <code>null</code> if none has * been set. * * @return this editor's preference store which may be <code>null</code> */ protected final IPreferenceStore getPreferenceStore() { return fPreferenceStore; } /** * 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 Display fDisplay; private Runnable fRunnable = new Runnable() { public void run() { // check whether editor has not been disposed yet if (logViewer != null && logViewer.getDocument() != null) { handleCursorPositionChanged(); updateSelectionDependentActions(); } } }; public void selectionChanged(SelectionChangedEvent event) { if (fDisplay == null) fDisplay = getSite().getShell().getDisplay(); if (Display.getCurrent() == fDisplay) fRunnable.run(); else fDisplay.asyncExec(fRunnable); } }; } return fSelectionChangedListener; } /** * @see org.eclipse.ui.texteditor.ITextEditor#getSelectionProvider() */ @Override public ISelectionProvider getSelectionProvider() { return fSelectionProvider; } protected ISharedTextColors getSharedColors() { return EditorsPlugin.getDefault().getSharedTextColors(); } public IrcLogViewer getSourceViewer() { return logViewer; } /** * Returns the source viewer decoration support. * * @param viewer * the viewer for which to return a decoration support * @return the source viewer decoration support */ protected SourceViewerDecorationSupport getSourceViewerDecorationSupport(ISourceViewer viewer) { if (fSourceViewerDecorationSupport == null) { fSourceViewerDecorationSupport = new SourceViewerDecorationSupport(viewer, getOverviewRuler(), getAnnotationAccess(), getSharedColors()); configureSourceViewerDecorationSupport(fSourceViewerDecorationSupport); } return fSourceViewerDecorationSupport; } /** * 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; } /** * Jumps to the next annotation according to the given direction. * * @param forward * <code>true</code> if search direction is forward, * <code>false</code> if backward * @return the selected annotation or <code>null</code> if none * @see #isNavigationTarget(Annotation) * @see #findAnnotation(int, int, boolean, Position) * @since 3.2 */ public Annotation gotoAnnotation(boolean forward) { ITextSelection selection = (ITextSelection) getSelectionProvider().getSelection(); Position position = new Position(0, 0); Annotation annotation = findAnnotation(selection.getOffset(), selection.getLength(), forward, position); setStatusLineErrorMessage(null); setStatusLineMessage(null); if (annotation != null) { selectAndReveal(position.getOffset(), position.getLength()); setStatusLineMessage(annotation.getText()); } return annotation; } /** * Handles a potential change of the cursor position. Subclasses may extend. * * @since 2.0 */ protected void handleCursorPositionChanged() { updateStatusField(ITextEditorActionConstants.STATUS_CATEGORY_INPUT_POSITION); } /** * Initializes the activation code trigger. * * @since 2.1 */ private void initializeActivationCodeTrigger() { // fActivationCodeTrigger.install(); // fActivationCodeTrigger.setScopes(fKeyBindingScopes); } /** * 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, org.eclipse.ui.texteditor.AbstractTextEditor.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) { IDocumentProvider documentProvider = getDocumentProvider(); IAnnotationModel model = documentProvider.getAnnotationModel(input); IDocument rawDocument = documentProvider.getDocument(input); if (rawDocument != null) { logViewer.setRawDocument(rawDocument, model); logViewer.setEditable(false); logViewer.showAnnotations(true); } // if (fElementStateListener instanceof IElementStateListenerExtension) // { // boolean isStateValidated= false; // if (documentProvider instanceof IDocumentProviderExtension) // isStateValidated= // ((IDocumentProviderExtension)documentProvider).isStateValidated(input); // // IElementStateListenerExtension extension= // (IElementStateListenerExtension) fElementStateListener; // extension.elementStateValidationChanged(input, isStateValidated); // } // if (fInitialCaret == null) // fInitialCaret= fSourceViewer.getTextWidget().getCaret(); // if (fIsOverwriting) // fSourceViewer.getTextWidget().invokeAction(ST.TOGGLE_OVERWRITE); // handleInsertModeChanged(); // if (isTabsToSpacesConversionEnabled()) // installTabsToSpacesConverter(); // if (fSourceViewer instanceof ITextViewerExtension8) { // IPreferenceStore store= getPreferenceStore(); // EnrichMode mode= store != null ? // convertEnrichModePreference(store.getInt(PREFERENCE_HOVER_ENRICH_MODE)) // : EnrichMode.AFTER_DELAY; // ((ITextViewerExtension8)fSourceViewer).setHoverEnrichMode(mode); // } } /** * Initializes the fore- and background colors of the given viewer for both * normal and selected text. * * @param viewer * the viewer to be initialized * @since 2.0 */ protected void initializeViewerColors(ISourceViewer viewer) { IPreferenceStore store = getPreferenceStore(); if (store != null) { StyledText styledText = viewer.getTextWidget(); // ----------- foreground color -------------------- Color color = store.getBoolean( org.eclipse.ui.texteditor.AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND_SYSTEM_DEFAULT) ? null : createColor(store, org.eclipse.ui.texteditor.AbstractTextEditor.PREFERENCE_COLOR_FOREGROUND, styledText.getDisplay()); styledText.setForeground(color); if (fForegroundColor != null) fForegroundColor.dispose(); fForegroundColor = color; // ---------- background color ---------------------- color = store.getBoolean( org.eclipse.ui.texteditor.AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND_SYSTEM_DEFAULT) ? null : createColor(store, org.eclipse.ui.texteditor.AbstractTextEditor.PREFERENCE_COLOR_BACKGROUND, styledText.getDisplay()); styledText.setBackground(color); if (fBackgroundColor != null) fBackgroundColor.dispose(); fBackgroundColor = color; // ----------- selection foreground color -------------------- color = store.getBoolean( org.eclipse.ui.texteditor.AbstractTextEditor.PREFERENCE_COLOR_SELECTION_FOREGROUND_SYSTEM_DEFAULT) ? null : createColor(store, org.eclipse.ui.texteditor.AbstractTextEditor.PREFERENCE_COLOR_SELECTION_FOREGROUND, styledText.getDisplay()); styledText.setSelectionForeground(color); if (fSelectionForegroundColor != null) fSelectionForegroundColor.dispose(); fSelectionForegroundColor = color; // ---------- selection background color ---------------------- color = store.getBoolean( org.eclipse.ui.texteditor.AbstractTextEditor.PREFERENCE_COLOR_SELECTION_BACKGROUND_SYSTEM_DEFAULT) ? null : createColor(store, org.eclipse.ui.texteditor.AbstractTextEditor.PREFERENCE_COLOR_SELECTION_BACKGROUND, styledText.getDisplay()); styledText.setSelectionBackground(color); if (fSelectionBackgroundColor != null) fSelectionBackgroundColor.dispose(); fSelectionBackgroundColor = color; } } /** * Initializes the given viewer's font. * * @param viewer * the viewer * @since 2.0 */ private void initializeViewerFont(ISourceViewer viewer) { boolean isSharedFont = true; Font font = null; String symbolicFontName = JFaceResources.DIALOG_FONT; if (symbolicFontName != null) font = JFaceResources.getFont(symbolicFontName); if (font == null) font = JFaceResources.getDialogFont(); if (!font.equals(logViewer.getTextWidget().getFont())) { setFont(viewer, font); disposeFont(); if (!isSharedFont) fFont = font; } else if (!isSharedFont) { font.dispose(); } } /** * @see org.eclipse.ui.part.EditorPart#isDirty() */ @Override public boolean isDirty() { return false; } /** * @see org.eclipse.ui.texteditor.ITextEditor#isEditable() */ @Override public boolean isEditable() { return false; } /** * Tells whether the editor input should be included when adding object * contributions to this editor's context menu. * <p> * This implementation always returns <code>true</code>. * </p> * * @return <code>true</code> if the editor input should be considered * @since 3.2 */ protected boolean isEditorInputIncludedInContextMenu() { return true; } /** * @see org.eclipse.ui.texteditor.ITextEditorExtension#isEditorInputReadOnly() */ @Override public boolean isEditorInputReadOnly() { return true; } protected boolean isLineNumberRulerVisible() { return false; } /** * Returns whether the given annotation is configured as a target for the * "Go to Next/Previous Annotation" actions. * <p> * Per default every annotation is a target. * </p> * * @param annotation * the annotation * @return <code>true</code> if this is a target, <code>false</code> * otherwise * @since 3.2 */ protected boolean isNavigationTarget(Annotation annotation) { return true; } protected boolean isOverviewRulerVisible() { return true; } /** * @see org.eclipse.ui.part.EditorPart#isSaveAsAllowed() */ @Override public boolean isSaveAsAllowed() { return false; } /** * 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 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 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); } /** * Writes a check mark of the given situation into the navigation history. * * @since 2.1 */ protected void markInNavigationHistory() { getSite().getPage().getNavigationHistory().markLocation(this); } /** * @see org.eclipse.ui.texteditor.ITextEditor#removeActionActivationCode(java.lang.String) */ @Override public void removeActionActivationCode(String actionId) { Assert.isNotNull(actionId); ActionActivationCode code = findActionActivationCode(actionId); if (code != null) fActivationCodes.remove(code); } /** * @see org.eclipse.ui.texteditor.ITextEditorExtension#removeRulerContextMenuListener(org.eclipse.jface.action.IMenuListener) */ @Override public void removeRulerContextMenuListener(IMenuListener listener) { } /* * @see ITextEditor#resetHighlightRange */ public void resetHighlightRange() { if (logViewer == null) return; if (fShowHighlightRangeOnly) logViewer.resetVisibleRegion(); else logViewer.removeRangeIndication(); } /** * @see org.eclipse.ui.IPersistableEditor#restoreState(org.eclipse.ui.IMemento) */ @Override public void restoreState(IMemento memento) { } /** * @see org.eclipse.ui.IPersistable#saveState(org.eclipse.ui.IMemento) */ @Override public void saveState(IMemento memento) { } /* * @see ITextEditor#selectAndReveal(int, int) */ public void selectAndReveal(int start, int length) { selectAndReveal(start, length, start, length); } /** * Selects and reveals the specified ranges in this text editor. * * @param selectionStart * the offset of the selection * @param selectionLength * the length of the selection * @param revealStart * the offset of the revealed range * @param revealLength * the length of the revealed range * @since 3.0 */ protected void selectAndReveal(int selectionStart, int selectionLength, int revealStart, int revealLength) { if (logViewer == null) return; ISelection selection = getSelectionProvider().getSelection(); if (selection instanceof ITextSelection) { ITextSelection textSelection = (ITextSelection) selection; if (textSelection.getOffset() != 0 || textSelection.getLength() != 0) markInNavigationHistory(); } StyledText widget = logViewer.getTextWidget(); widget.setRedraw(false); { adjustHighlightRange(revealStart, revealLength); logViewer.revealRange(revealStart, revealLength); logViewer.setSelectedRange(selectionStart, selectionLength); markInNavigationHistory(); } widget.setRedraw(true); } /** * @see org.eclipse.ui.texteditor.ITextEditor#setAction(java.lang.String, * org.eclipse.jface.action.IAction) */ @Override 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 { if (action.getId() == null) action.setId(actionID); // make sure the action ID has been set 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; } /** * @see org.eclipse.ui.part.WorkbenchPart#setFocus() */ @Override public void setFocus() { logViewer.setFocus(); } /** * 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) { ISelectionProvider provider = sourceViewer.getSelectionProvider(); ISelection selection = provider.getSelection(); 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); provider.setSelection(selection); 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); } } /* * @see ITextEditor#setHighlightRange(int, int, boolean) */ public void setHighlightRange(int offset, int length, boolean moveCursor) { if (logViewer == null) return; if (fShowHighlightRangeOnly) { if (moveCursor) logViewer.setVisibleRegion(offset, length); } else { IRegion rangeIndication = logViewer.getRangeIndication(); if (rangeIndication == null || offset != rangeIndication.getOffset() || length != rangeIndication.getLength()) logViewer.setRangeIndication(offset, length, moveCursor); } } @Override public void setInput(IEditorInput input) { super.setInput(input); } /** * Sets this editor's preference store. This method must be called before * the editor's control is created. * * @param store * the preference store or <code>null</code> to remove the * preference store */ protected void setPreferenceStore(IPreferenceStore store) { // if (fPreferenceStore != null) { // fPreferenceStore.removePropertyChangeListener(fPropertyChangeListener); // fPreferenceStore.removePropertyChangeListener(fFontPropertyChangeListener); // } fPreferenceStore = store; // if (fPreferenceStore != null) { // fPreferenceStore.addPropertyChangeListener(fPropertyChangeListener); // fPreferenceStore.addPropertyChangeListener(fFontPropertyChangeListener); // } } /** * 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; } /** * @see org.eclipse.ui.texteditor.ITextEditorExtension#setStatusField(org.eclipse.ui.texteditor.IStatusField, * java.lang.String) */ @Override public void setStatusField(IStatusField field, String category) { Assert.isNotNull(category); if (field != null) { if (fStatusFields == null) fStatusFields = new HashMap<String, IStatusField>(3); fStatusFields.put(category, field); updateStatusField(category); } else if (fStatusFields != null) fStatusFields.remove(category); // if (fIncrementalFindTarget != null && // ITextEditorActionConstants.STATUS_CATEGORY_FIND_FIELD.equals(category)) // fIncrementalFindTarget.setStatusField(field); } /** * Sets the given message as error message to this editor's status line. * * @param message * message to be set * @since 3.2 */ protected void setStatusLineErrorMessage(String message) { IEditorStatusLine statusLine = (IEditorStatusLine) getAdapter(IEditorStatusLine.class); if (statusLine != null) statusLine.setMessage(true, message, null); } /** * Sets the given message as message to this editor's status line. * * @param message * message to be set * @since 3.2 */ protected void setStatusLineMessage(String message) { IEditorStatusLine statusLine = (IEditorStatusLine) getAdapter(IEditorStatusLine.class); if (statusLine != null) statusLine.setMessage(false, message, null); } /* * @see ITextEditor#showHighlightRangeOnly(boolean) */ public void showHighlightRangeOnly(boolean showHighlightRangeOnly) { fShowHighlightRangeOnly = showHighlightRangeOnly; } /** * @see org.eclipse.ui.texteditor.ITextEditorExtension4#showRevisionInformation(org.eclipse.jface.text.revisions.RevisionInformation, * java.lang.String) */ @Override public void showRevisionInformation(RevisionInformation info, String quickDiffProviderId) { } /* * @see ITextEditor#showsHighlightRangeOnly() */ public boolean showsHighlightRangeOnly() { return fShowHighlightRangeOnly; } /** * 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(); } } /** * Updates all content dependent actions. */ protected void updateContentDependentActions() { if (fContentActions != null) { Iterator<String> e = fContentActions.iterator(); while (e.hasNext()) updateAction(e.next()); } } /** * Updates all property dependent actions. * * @since 2.0 */ protected void updatePropertyDependentActions() { if (fPropertyActions != null) { Iterator<String> e = fPropertyActions.iterator(); while (e.hasNext()) updateAction(e.next()); } } /** * Updates all selection dependent actions. */ protected void updateSelectionDependentActions() { if (fSelectionActions != null) { Iterator<String> e = fSelectionActions.iterator(); while (e.hasNext()) updateAction(e.next()); } } /** * Updates all state dependent actions. * * @since 2.0 */ protected void updateStateDependentActions() { if (fStateActions != null) { Iterator<String> e = fStateActions.iterator(); while (e.hasNext()) updateAction(e.next()); } } /** * Updates the status fields for the given category. * * @param category * the 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 = IrcUiMessages.Editor_statusline_state_readonly_label; field.setText(text == null ? fErrorLabel : text); } } }