blob: b16c24648540d51329902f69c6c2fd2647f1c8ad [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2017 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.texteditor;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.text.CursorLinePainter;
import org.eclipse.jface.text.IPainter;
import org.eclipse.jface.text.ITextViewerExtension2;
import org.eclipse.jface.text.ITextViewerExtension4;
import org.eclipse.jface.text.MarginPainter;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.AnnotationPainter;
import org.eclipse.jface.text.source.AnnotationPainter.IDrawingStrategy;
import org.eclipse.jface.text.source.AnnotationPainter.ITextStyleStrategy;
import org.eclipse.jface.text.source.IAnnotationAccess;
import org.eclipse.jface.text.source.ICharacterPairMatcher;
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.MatchingCharacterPainter;
/**
* Support class used by text editors to draw and update decorations on the
* source viewer and its rulers. An instance of this class is independent of a
* certain editor and must be configured with the needed preference keys and
* helper objects before it can be used.
* <p>
* Once configured, an instance may be installed (see
* {@link #install(IPreferenceStore) install}) on a preference store, from then
* on monitoring the configured preference settings and changing the respective
* decorations. Calling {@link #uninstall() uninstall} will unregister the
* listeners with the preferences store and must be called before changing the
* preference store by another call to <code>install</code>.<br>
* {@link #dispose() dispose} will uninstall the support and remove any
* decorations from the viewer. It is okay to reuse a
* <code>SourceViewerDecorationSupport</code> instance after disposing it.
* </p>
* <p>
* <code>SourceViewerDecorationSupport</code> can draw the following
* decorations:
* <ul>
* <li>matching character highlighting,</li>
* <li>current line highlighting,</li>
* <li>print margin, and</li>
* <li>annotations.</li>
* </ul>
* Annotations are managed for the overview ruler and also drawn onto the text
* widget by an
* {@link org.eclipse.jface.text.source.AnnotationPainter AnnotationPainter}
* instance.
* </p>
* <p>
* Subclasses may add decorations but should adhere to the lifecyle described
* above.
* </p>
*
* @see org.eclipse.jface.text.source.AnnotationPainter
* @since 2.1
*/
public class SourceViewerDecorationSupport {
/**
* Draws an iBeam at the given offset, the length is ignored.
*
* @since 3.0
*/
private static final class IBeamStrategy implements IDrawingStrategy {
@Override
public void draw(Annotation annotation, GC gc, StyledText textWidget, int offset, int length, Color color) {
if (gc != null) {
Point left= textWidget.getLocationAtOffset(offset);
int x1= left.x;
int y1= left.y;
gc.setForeground(color);
gc.drawLine(x1, y1, x1, left.y + textWidget.getLineHeight(offset) - 1);
} else {
/*
* The length for IBeam's is always 0, which causes no redraw to occur in
* StyledText#redraw(int, int, boolean). We try to normally redraw at length of one,
* and up to the line start of the next line if offset is at the end of line. If at
* the end of the document, we redraw the entire document as the offset is behind
* any content.
*/
final int contentLength= textWidget.getCharCount();
if (offset >= contentLength) {
textWidget.redraw();
return;
}
char ch= textWidget.getTextRange(offset, 1).charAt(0);
if (ch == '\r' || ch == '\n') {
// at the end of a line, redraw up to the next line start
int nextLine= textWidget.getLineAtOffset(offset) + 1;
if (nextLine >= textWidget.getLineCount()) {
/*
* Panic code: should not happen, as offset is not the last offset,
* and there is a delimiter character at offset.
*/
textWidget.redraw();
return;
}
int nextLineOffset= textWidget.getOffsetAtLine(nextLine);
length= nextLineOffset - offset;
} else {
length= 1;
}
textWidget.redrawRange(offset, length, true);
}
}
}
/**
* The box drawing strategy.
* @since 3.0
*/
private static ITextStyleStrategy fgBoxStrategy= new AnnotationPainter.BoxStrategy(SWT.BORDER_SOLID);
/**
* The dashed box drawing strategy.
* @since 3.3
*/
private static ITextStyleStrategy fgDashedBoxStrategy= new AnnotationPainter.BoxStrategy(SWT.BORDER_DASH);
/**
* The null drawing strategy.
* @since 3.0
*/
private static IDrawingStrategy fgNullStrategy= new AnnotationPainter.NullStrategy();
/**
* The underline drawing strategy.
* @since 3.0
*/
private static ITextStyleStrategy fgUnderlineStrategy= new AnnotationPainter.UnderlineStrategy(SWT.UNDERLINE_SINGLE);
/**
* The iBeam drawing strategy.
* @since 3.0
*/
private static IDrawingStrategy fgIBeamStrategy= new IBeamStrategy();
/**
* The squiggles drawing strategy.
* @since 3.0
*/
private static ITextStyleStrategy fgSquigglesStrategy= new AnnotationPainter.UnderlineStrategy(SWT.UNDERLINE_SQUIGGLE);
/**
* The error drawing strategy.
* @since 3.4
*/
private static ITextStyleStrategy fgProblemUnderlineStrategy= new AnnotationPainter.UnderlineStrategy(SWT.UNDERLINE_ERROR);
/** The viewer */
private ISourceViewer fSourceViewer;
/** The viewer's overview ruler */
private IOverviewRuler fOverviewRuler;
/** The annotation access */
private IAnnotationAccess fAnnotationAccess;
/** The shared color manager */
private ISharedTextColors fSharedTextColors;
/** The editor's line painter */
private CursorLinePainter fCursorLinePainter;
/** The editor's margin ruler painter */
private MarginPainter fMarginPainter;
/** The editor's annotation painter */
private AnnotationPainter fAnnotationPainter;
/** The editor's peer character painter */
private MatchingCharacterPainter fMatchingCharacterPainter;
/** The character painter's pair matcher */
private ICharacterPairMatcher fCharacterPairMatcher;
/** Map with annotation type preference per annotation type */
private Map<Object, AnnotationPreference> fAnnotationTypeKeyMap= new LinkedHashMap<>();
/** Preference key for the cursor line highlighting */
private String fCursorLinePainterEnableKey;
/** Preference key for the cursor line background color */
private String fCursorLinePainterColorKey;
/** Preference key for the margin painter */
private String fMarginPainterEnableKey;
/** Preference key for the margin painter color */
private String fMarginPainterColorKey;
/** Preference key for the margin painter column */
private String fMarginPainterColumnKey;
/** Preference key for the matching character painter */
private String fMatchingCharacterPainterEnableKey;
/** Preference key for highlighting character at caret location */
private String fMatchingCharacterPainterHighlightCharacterAtCaretLocationKey;
/** Preference key for enclosing peer characters */
private String fMatchingCharacterPainterEnclosingPeerCharactersKey;
/** Preference key for the matching character painter color */
private String fMatchingCharacterPainterColorKey;
/** The property change listener */
private IPropertyChangeListener fPropertyChangeListener;
/** The preference store */
private IPreferenceStore fPreferenceStore;
/**
* Creates a new decoration support for the given viewer.
*
* @param sourceViewer the source viewer
* @param overviewRuler the viewer's overview ruler
* @param annotationAccess the annotation access
* @param sharedTextColors the shared text color manager
*/
public SourceViewerDecorationSupport(ISourceViewer sourceViewer, IOverviewRuler overviewRuler, IAnnotationAccess annotationAccess, ISharedTextColors sharedTextColors) {
fSourceViewer= sourceViewer;
fOverviewRuler= overviewRuler;
fAnnotationAccess= annotationAccess;
fSharedTextColors= sharedTextColors;
}
/**
* Installs this decoration support on the given preference store. It assumes
* that this support has completely been configured.
*
* @param store the preference store
*/
public void install(IPreferenceStore store) {
fPreferenceStore= store;
if (fPreferenceStore != null) {
fPropertyChangeListener= new IPropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent event) {
handlePreferenceStoreChanged(event);
}
};
fPreferenceStore.addPropertyChangeListener(fPropertyChangeListener);
}
updateTextDecorations();
updateOverviewDecorations();
}
/**
* Updates the text decorations for all configured annotation types.
*/
private void updateTextDecorations() {
StyledText widget= fSourceViewer.getTextWidget();
if (widget == null || widget.isDisposed())
return;
if (areMatchingCharactersShown())
showMatchingCharacters();
else
hideMatchingCharacters();
if (isCursorLineShown())
showCursorLine();
else
hideCursorLine();
if (isMarginShown())
showMargin();
else
hideMargin();
Iterator<Object> e= fAnnotationTypeKeyMap.keySet().iterator();
while (e.hasNext()) {
Object type= e.next();
if (areAnnotationsHighlighted(type) || areAnnotationsShown(type))
showAnnotations(type, false);
else
hideAnnotations(type, false);
}
updateAnnotationPainter();
}
/**
* Returns the annotation decoration style used for the show in text preference for
* a given annotation type.
*
* @param annotationType the annotation type being looked up
* @return the decoration style for <code>type</code> or <code>null</code> if highlighting
* @since 3.0
*/
private Object getAnnotationDecorationType(Object annotationType) {
if (areAnnotationsHighlighted(annotationType))
return null;
if (areAnnotationsShown(annotationType) && fPreferenceStore != null) {
AnnotationPreference info= fAnnotationTypeKeyMap.get(annotationType);
if (info != null) {
String key= info.getTextStylePreferenceKey();
if (key != null)
return fPreferenceStore.getString(key);
// legacy
return AnnotationPreference.STYLE_SQUIGGLES;
}
}
return AnnotationPreference.STYLE_NONE;
}
/**
* Updates the annotation overview for all configured annotation types.
*/
public void updateOverviewDecorations() {
if (fOverviewRuler != null) {
Iterator<Object> e= fAnnotationTypeKeyMap.keySet().iterator();
while (e.hasNext()) {
Object type= e.next();
if (isAnnotationOverviewShown(type))
showAnnotationOverview(type, false);
else
hideAnnotationOverview(type, false);
}
fOverviewRuler.update();
}
}
/**
* Uninstalls this support from the preference store it has previously been
* installed on. If there is no such preference store, this call is without
* effect.
*/
public void uninstall() {
if (fPreferenceStore != null) {
fPreferenceStore.removePropertyChangeListener(fPropertyChangeListener);
fPropertyChangeListener= null;
fPreferenceStore= null;
}
}
/**
* Disposes this decoration support. Internally calls
* <code>uninstall</code>.
*/
public void dispose() {
uninstall();
updateTextDecorations();
updateOverviewDecorations();
fOverviewRuler= null;
// Painters got disposed in updateTextDecorations() or by the PaintManager
fMatchingCharacterPainter= null;
fAnnotationPainter= null;
fCursorLinePainter= null;
fMarginPainter= null;
if (fAnnotationTypeKeyMap != null)
fAnnotationTypeKeyMap.clear();
}
/**
* Sets the character pair matcher for the matching character painter.
*
* @param pairMatcher the character pair matcher
*/
public void setCharacterPairMatcher(ICharacterPairMatcher pairMatcher) {
fCharacterPairMatcher= pairMatcher;
}
/**
* Sets the preference keys for the annotation painter.
*
* @param type the annotation type
* @param colorKey the preference key for the color
* @param editorKey the preference key for the presentation in the text area
* @param overviewRulerKey the preference key for the presentation in the overview ruler
* @param layer the layer
*/
public void setAnnotationPainterPreferenceKeys(Object type, String colorKey, String editorKey, String overviewRulerKey, int layer) {
AnnotationPreference info= new AnnotationPreference(type, colorKey, editorKey, overviewRulerKey, layer);
fAnnotationTypeKeyMap.put(type, info);
}
/**
* Sets the preference info for the annotation painter.
* @param info the preference info to be set
*/
public void setAnnotationPreference(AnnotationPreference info) {
fAnnotationTypeKeyMap.put(info.getAnnotationType(), info);
}
/**
* Sets the preference keys for the cursor line painter.
* @param enableKey the preference key for the cursor line painter
* @param colorKey the preference key for the color used by the cursor line
* painter
*/
public void setCursorLinePainterPreferenceKeys(String enableKey, String colorKey) {
fCursorLinePainterEnableKey= enableKey;
fCursorLinePainterColorKey= colorKey;
}
/**
* Sets the preference keys for the margin painter.
* @param enableKey the preference key for the margin painter
* @param colorKey the preference key for the color used by the margin
* painter
* @param columnKey the preference key for the margin column
*/
public void setMarginPainterPreferenceKeys(String enableKey, String colorKey, String columnKey) {
fMarginPainterEnableKey= enableKey;
fMarginPainterColorKey= colorKey;
fMarginPainterColumnKey= columnKey;
}
/**
* Sets the preference keys for the matching character painter.
*
* <p>
* Use {@link #setMatchingCharacterPainterPreferenceKeys(String, String, String, String)} if
* highlighting of character at caret location or enclosing peer characters is required.
* </p>
*
* @param enableKey the preference key for the matching character painter
* @param colorKey the preference key for the color used by the matching character painter
*/
public void setMatchingCharacterPainterPreferenceKeys(String enableKey, String colorKey) {
setMatchingCharacterPainterPreferenceKeys(enableKey, colorKey, null, null);
}
/**
* Sets the preference keys for the matching character painter.
*
* @param enableKey the preference key for the matching character painter
* @param colorKey the preference key for the color used by the matching character painter
* @param highlightCharacterAtCaretLocationKey the preference key for highlighting character at
* caret location
* @param enclosingPeerCharactersKey the preference key for highlighting enclosing peer
* characters
*
* @since 3.8
*/
public void setMatchingCharacterPainterPreferenceKeys(String enableKey, String colorKey, String highlightCharacterAtCaretLocationKey, String enclosingPeerCharactersKey) {
fMatchingCharacterPainterEnableKey= enableKey;
fMatchingCharacterPainterColorKey= colorKey;
fMatchingCharacterPainterEnclosingPeerCharactersKey= enclosingPeerCharactersKey;
fMatchingCharacterPainterHighlightCharacterAtCaretLocationKey= highlightCharacterAtCaretLocationKey;
}
/**
* Sets the symbolic font name that is used for computing the margin width.
*
* @param symbolicFontName
* the symbolic font name
* @deprecated As of 4.8, this is no longer used
*/
@Deprecated
public void setSymbolicFontName(String symbolicFontName) {
}
/**
* Returns the annotation preference for the given key.
*
* @param preferenceKey the preference key string
* @return the annotation preference
*/
private AnnotationPreference getAnnotationPreferenceInfo(String preferenceKey) {
Iterator<AnnotationPreference> e= fAnnotationTypeKeyMap.values().iterator();
while (e.hasNext()) {
AnnotationPreference info= e.next();
if (info != null && info.isPreferenceKey(preferenceKey))
return info;
}
return null;
}
/*
* @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
*/
protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
String p= event.getProperty();
if (fMatchingCharacterPainterEnableKey != null && fMatchingCharacterPainterEnableKey.equals(p) && fCharacterPairMatcher != null) {
if (areMatchingCharactersShown())
showMatchingCharacters();
else
hideMatchingCharacters();
return;
}
if (fMatchingCharacterPainterHighlightCharacterAtCaretLocationKey != null && fMatchingCharacterPainterHighlightCharacterAtCaretLocationKey.equals(p)) {
if (fMatchingCharacterPainter != null) {
fMatchingCharacterPainter.setHighlightCharacterAtCaretLocation(isCharacterAtCaretLocationShown());
fMatchingCharacterPainter.paint(IPainter.CONFIGURATION);
}
return;
}
if (fMatchingCharacterPainterEnclosingPeerCharactersKey != null && fMatchingCharacterPainterEnclosingPeerCharactersKey.equals(p)) {
if (fMatchingCharacterPainter != null) {
fMatchingCharacterPainter.setHighlightEnclosingPeerCharacters(areEnclosingPeerCharactersShown());
fMatchingCharacterPainter.paint(IPainter.CONFIGURATION);
}
return;
}
if (fMatchingCharacterPainterColorKey != null && fMatchingCharacterPainterColorKey.equals(p)) {
if (fMatchingCharacterPainter != null) {
fMatchingCharacterPainter.setColor(getColor(fMatchingCharacterPainterColorKey));
fMatchingCharacterPainter.paint(IPainter.CONFIGURATION);
}
return;
}
if (fCursorLinePainterEnableKey != null && fCursorLinePainterEnableKey.equals(p)) {
if (isCursorLineShown())
showCursorLine();
else
hideCursorLine();
return;
}
if (fCursorLinePainterColorKey != null && fCursorLinePainterColorKey.equals(p)) {
if (fCursorLinePainter != null) {
hideCursorLine();
showCursorLine();
}
return;
}
if (fMarginPainterEnableKey != null && fMarginPainterEnableKey.equals(p)) {
if (isMarginShown())
showMargin();
else
hideMargin();
return;
}
if (fMarginPainterColorKey != null && fMarginPainterColorKey.equals(p)) {
if (fMarginPainter != null) {
fMarginPainter.setMarginRulerColor(getColor(fMarginPainterColorKey));
fMarginPainter.paint(IPainter.CONFIGURATION);
}
return;
}
if (fMarginPainterColumnKey != null && fMarginPainterColumnKey.equals(p)) {
if (fMarginPainter != null && fPreferenceStore != null) {
fMarginPainter.setMarginRulerColumn(fPreferenceStore.getInt(fMarginPainterColumnKey));
fMarginPainter.paint(IPainter.CONFIGURATION);
}
return;
}
AnnotationPreference info= getAnnotationPreferenceInfo(p);
if (info != null) {
if (info.getColorPreferenceKey().equals(p)) {
Color color= getColor(info.getColorPreferenceKey());
if (fAnnotationPainter != null) {
fAnnotationPainter.setAnnotationTypeColor(info.getAnnotationType(), color);
fAnnotationPainter.paint(IPainter.CONFIGURATION);
}
setAnnotationOverviewColor(info.getAnnotationType(), color);
return;
}
Object type= info.getAnnotationType();
if ((info.getTextPreferenceKey().equals(p) || info.getTextStylePreferenceKey() != null && info.getTextStylePreferenceKey().equals(p)) ||
(info.getHighlightPreferenceKey() != null && info.getHighlightPreferenceKey().equals(p))) {
if (areAnnotationsHighlighted(type) || areAnnotationsShown(type))
showAnnotations(type, true);
else
hideAnnotations(type, true);
return;
}
if (info.getOverviewRulerPreferenceKey().equals(p)) {
if (isAnnotationOverviewShown(info.getAnnotationType()))
showAnnotationOverview(info.getAnnotationType(), true);
else
hideAnnotationOverview(info.getAnnotationType(), true);
return;
}
}
}
/**
* Returns the shared color for the given key.
*
* @param key the color key string
* @return the shared color for the given key
*/
private Color getColor(String key) {
if (fPreferenceStore != null) {
RGB rgb= PreferenceConverter.getColor(fPreferenceStore, key);
return getColor(rgb);
}
return null;
}
/**
* Returns the shared color for the given RGB.
*
* @param rgb the RGB
* @return the shared color for the given RGB
*/
private Color getColor(RGB rgb) {
return fSharedTextColors.getColor(rgb);
}
/**
* Returns the color of the given annotation type.
*
* @param annotationType the annotation type
* @return the color of the annotation type
*/
private Color getAnnotationTypeColor(Object annotationType) {
AnnotationPreference info= fAnnotationTypeKeyMap.get(annotationType);
if (info != null)
return getColor( info.getColorPreferenceKey());
return null;
}
/**
* Returns the layer of the given annotation type.
*
* @param annotationType the annotation type
* @return the layer
*/
private int getAnnotationTypeLayer(Object annotationType) {
AnnotationPreference info= fAnnotationTypeKeyMap.get(annotationType);
if (info != null)
return info.getPresentationLayer();
return 0;
}
/**
* Enables showing of matching characters.
*/
private void showMatchingCharacters() {
if (fMatchingCharacterPainter == null) {
if (fSourceViewer instanceof ITextViewerExtension2) {
fMatchingCharacterPainter= new MatchingCharacterPainter(fSourceViewer, fCharacterPairMatcher);
fMatchingCharacterPainter.setColor(getColor(fMatchingCharacterPainterColorKey));
fMatchingCharacterPainter.setHighlightCharacterAtCaretLocation(isCharacterAtCaretLocationShown());
fMatchingCharacterPainter.setHighlightEnclosingPeerCharacters(areEnclosingPeerCharactersShown());
ITextViewerExtension2 extension= (ITextViewerExtension2) fSourceViewer;
extension.addPainter(fMatchingCharacterPainter);
}
}
}
/**
* Disables showing of matching characters.
*/
private void hideMatchingCharacters() {
if (fMatchingCharacterPainter != null) {
if (fSourceViewer instanceof ITextViewerExtension2) {
ITextViewerExtension2 extension= (ITextViewerExtension2) fSourceViewer;
extension.removePainter(fMatchingCharacterPainter);
fMatchingCharacterPainter.deactivate(true);
fMatchingCharacterPainter.dispose();
fMatchingCharacterPainter= null;
}
}
}
/**
* Tells whether matching characters are shown.
*
* @return <code>true</code> if the matching characters are shown
*/
private boolean areMatchingCharactersShown() {
if (fPreferenceStore != null && fMatchingCharacterPainterEnableKey != null)
return fPreferenceStore.getBoolean(fMatchingCharacterPainterEnableKey);
return false;
}
/**
* Tells whether character at caret location is shown.
*
* @return <code>true</code> if character at caret location is shown
*/
private boolean isCharacterAtCaretLocationShown() {
if (fPreferenceStore != null && fMatchingCharacterPainterHighlightCharacterAtCaretLocationKey != null)
return fPreferenceStore.getBoolean(fMatchingCharacterPainterHighlightCharacterAtCaretLocationKey);
return false;
}
/**
* Tells whether enclosing peer characters are shown.
*
* @return <code>true</code> if the enclosing peer characters are shown
*/
private boolean areEnclosingPeerCharactersShown() {
if (fPreferenceStore != null && fMatchingCharacterPainterEnclosingPeerCharactersKey != null)
return fPreferenceStore.getBoolean(fMatchingCharacterPainterEnclosingPeerCharactersKey);
return false;
}
/**
* Shows the cursor line.
*/
private void showCursorLine() {
if (fCursorLinePainter == null) {
if (fSourceViewer instanceof ITextViewerExtension2) {
fCursorLinePainter= new CursorLinePainter(fSourceViewer);
fCursorLinePainter.setHighlightColor(getColor(fCursorLinePainterColorKey));
ITextViewerExtension2 extension= (ITextViewerExtension2) fSourceViewer;
extension.addPainter(fCursorLinePainter);
}
}
}
/**
* Hides the cursor line.
*/
private void hideCursorLine() {
if (fCursorLinePainter != null) {
if (fSourceViewer instanceof ITextViewerExtension2) {
ITextViewerExtension2 extension= (ITextViewerExtension2) fSourceViewer;
extension.removePainter(fCursorLinePainter);
fCursorLinePainter.deactivate(true);
fCursorLinePainter.dispose();
fCursorLinePainter= null;
}
}
}
/**
* Tells whether the cursor line is shown.
*
* @return <code>true</code> if the cursor line is shown
*/
private boolean isCursorLineShown() {
if (fPreferenceStore != null && fCursorLinePainterEnableKey != null)
return fPreferenceStore.getBoolean(fCursorLinePainterEnableKey);
return false;
}
/**
* Shows the margin.
*/
private void showMargin() {
if (fMarginPainter == null) {
if (fSourceViewer instanceof ITextViewerExtension2) {
fMarginPainter= new MarginPainter(fSourceViewer);
fMarginPainter.setMarginRulerColor(getColor(fMarginPainterColorKey));
if (fPreferenceStore != null)
fMarginPainter.setMarginRulerColumn(fPreferenceStore.getInt(fMarginPainterColumnKey));
ITextViewerExtension2 extension= (ITextViewerExtension2) fSourceViewer;
extension.addPainter(fMarginPainter);
}
}
}
/**
* Hides the margin.
*/
private void hideMargin() {
if (fMarginPainter != null) {
if (fSourceViewer instanceof ITextViewerExtension2) {
ITextViewerExtension2 extension= (ITextViewerExtension2) fSourceViewer;
extension.removePainter(fMarginPainter);
fMarginPainter.deactivate(true);
fMarginPainter.dispose();
fMarginPainter= null;
}
}
}
/**
* Tells whether the margin is shown.
*
* @return <code>true</code> if the margin is shown
*/
private boolean isMarginShown() {
if (fPreferenceStore != null && fMarginPainterEnableKey != null)
return fPreferenceStore.getBoolean(fMarginPainterEnableKey);
return false;
}
/**
* Enables annotations in the source viewer for the given annotation type.
*
* @param annotationType the annotation type
* @param updatePainter if <code>true</code> update the annotation painter
* @since 3.0
*/
private void showAnnotations(Object annotationType, boolean updatePainter) {
if (fSourceViewer instanceof ITextViewerExtension2) {
if (fAnnotationPainter == null) {
fAnnotationPainter= createAnnotationPainter();
if (fSourceViewer instanceof ITextViewerExtension4)
((ITextViewerExtension4)fSourceViewer).addTextPresentationListener(fAnnotationPainter);
ITextViewerExtension2 extension= (ITextViewerExtension2) fSourceViewer;
extension.addPainter(fAnnotationPainter);
}
fAnnotationPainter.setAnnotationTypeColor(annotationType, getAnnotationTypeColor(annotationType));
Object decorationType= getAnnotationDecorationType(annotationType);
if (decorationType != null)
fAnnotationPainter.addAnnotationType(annotationType, decorationType);
else
fAnnotationPainter.addHighlightAnnotationType(annotationType);
if (updatePainter)
updateAnnotationPainter();
}
}
/**
* Creates and configures the annotation painter and configures.
* @return an annotation painter
* @since 3.0
*/
protected AnnotationPainter createAnnotationPainter() {
AnnotationPainter painter= new AnnotationPainter(fSourceViewer, fAnnotationAccess);
/*
* XXX:
* Could provide an extension point for drawing strategies,
* see https://bugs.eclipse.org/bugs/show_bug.cgi?id=51498
*/
painter.addDrawingStrategy(AnnotationPreference.STYLE_NONE, fgNullStrategy);
painter.addDrawingStrategy(AnnotationPreference.STYLE_IBEAM, fgIBeamStrategy);
painter.addTextStyleStrategy(AnnotationPreference.STYLE_SQUIGGLES, fgSquigglesStrategy);
painter.addTextStyleStrategy(AnnotationPreference.STYLE_PROBLEM_UNDERLINE, fgProblemUnderlineStrategy);
painter.addTextStyleStrategy(AnnotationPreference.STYLE_BOX, fgBoxStrategy);
painter.addTextStyleStrategy(AnnotationPreference.STYLE_DASHED_BOX, fgDashedBoxStrategy);
painter.addTextStyleStrategy(AnnotationPreference.STYLE_UNDERLINE, fgUnderlineStrategy);
return painter;
}
/**
* Updates the annotation painter.
* @since 3.0
*/
private void updateAnnotationPainter() {
if (fAnnotationPainter == null)
return;
fAnnotationPainter.paint(IPainter.CONFIGURATION);
if (!fAnnotationPainter.isPaintingAnnotations()) {
if (fSourceViewer instanceof ITextViewerExtension2) {
ITextViewerExtension2 extension= (ITextViewerExtension2) fSourceViewer;
extension.removePainter(fAnnotationPainter);
}
if (fSourceViewer instanceof ITextViewerExtension4)
((ITextViewerExtension4)fSourceViewer).removeTextPresentationListener(fAnnotationPainter);
fAnnotationPainter.deactivate(true);
fAnnotationPainter.dispose();
fAnnotationPainter= null;
}
}
/**
* Hides annotations in the source viewer for the given annotation type.
*
* @param annotationType the annotation type
* @param updatePainter if <code>true</code> update the annotation painter
* @since 3.0
*/
private void hideAnnotations(Object annotationType, boolean updatePainter) {
if (fAnnotationPainter != null) {
fAnnotationPainter.removeAnnotationType(annotationType);
if (updatePainter) {
updateAnnotationPainter();
}
}
}
/**
* Tells whether annotations are shown in the source viewer for the given type.
*
* @param annotationType the annotation type
* @return <code>true</code> if the annotations are shown
*/
private boolean areAnnotationsShown(Object annotationType) {
if (fPreferenceStore != null) {
AnnotationPreference info= fAnnotationTypeKeyMap.get(annotationType);
if (info != null) {
String key= info.getTextPreferenceKey();
return key != null && fPreferenceStore.getBoolean(key);
}
}
return false;
}
/**
* Tells whether annotations are highlighted in the source viewer for the given type.
*
* @param annotationType the annotation type
* @return <code>true</code> if the annotations are highlighted
* @since 3.0
*/
private boolean areAnnotationsHighlighted(Object annotationType) {
if (fPreferenceStore != null) {
AnnotationPreference info= fAnnotationTypeKeyMap.get(annotationType);
if (info != null)
return info.getHighlightPreferenceKey() != null && fPreferenceStore.getBoolean(info.getHighlightPreferenceKey());
}
return false;
}
/**
* Tells whether annotation overview is enabled for the given type.
*
* @param annotationType the annotation type
* @return <code>true</code> if the annotation overview is shown
*/
private boolean isAnnotationOverviewShown(Object annotationType) {
if (fPreferenceStore != null && fOverviewRuler != null) {
AnnotationPreference info= fAnnotationTypeKeyMap.get(annotationType);
if (info != null)
return fPreferenceStore.getBoolean(info.getOverviewRulerPreferenceKey());
}
return false;
}
/**
* Enable annotation overview for the given annotation type.
*
* @param annotationType the annotation type
* @param update <code>true</code> if the overview should be updated
*/
private void showAnnotationOverview(Object annotationType, boolean update) {
if (fOverviewRuler != null) {
fOverviewRuler.setAnnotationTypeColor(annotationType, getAnnotationTypeColor(annotationType));
fOverviewRuler.setAnnotationTypeLayer(annotationType, getAnnotationTypeLayer(annotationType));
fOverviewRuler.addAnnotationType(annotationType);
if (update)
fOverviewRuler.update();
}
}
/**
* Hides the annotation overview for the given type.
* @param annotationType the annotation type
* @param update <code>true</code> if the overview should be updated
*/
private void hideAnnotationOverview(Object annotationType, boolean update) {
if (fOverviewRuler != null) {
fOverviewRuler.removeAnnotationType(annotationType);
if (update)
fOverviewRuler.update();
}
}
/**
* Hides the annotation overview.
*/
public void hideAnnotationOverview() {
if (fOverviewRuler != null) {
Iterator<Object> e= fAnnotationTypeKeyMap.keySet().iterator();
while (e.hasNext())
fOverviewRuler.removeAnnotationType(e.next());
fOverviewRuler.update();
}
}
/**
* Sets the annotation overview color for the given annotation type.
*
* @param annotationType the annotation type
* @param color the color
*/
private void setAnnotationOverviewColor(Object annotationType, Color color) {
if (fOverviewRuler != null) {
fOverviewRuler.setAnnotationTypeColor(annotationType, color);
fOverviewRuler.update();
}
}
}