KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > texteditor > SourceViewerDecorationSupport


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.ui.texteditor;
13
14 import java.util.HashMap JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.Map JavaDoc;
17
18 import org.eclipse.swt.SWT;
19 import org.eclipse.swt.custom.StyledText;
20 import org.eclipse.swt.graphics.Color;
21 import org.eclipse.swt.graphics.GC;
22 import org.eclipse.swt.graphics.Point;
23 import org.eclipse.swt.graphics.RGB;
24 import org.eclipse.swt.graphics.Rectangle;
25
26 import org.eclipse.jface.preference.IPreferenceStore;
27 import org.eclipse.jface.preference.PreferenceConverter;
28 import org.eclipse.jface.resource.JFaceResources;
29 import org.eclipse.jface.text.CursorLinePainter;
30 import org.eclipse.jface.text.IPainter;
31 import org.eclipse.jface.text.ITextViewerExtension2;
32 import org.eclipse.jface.text.ITextViewerExtension4;
33 import org.eclipse.jface.text.MarginPainter;
34 import org.eclipse.jface.text.source.Annotation;
35 import org.eclipse.jface.text.source.AnnotationPainter;
36 import org.eclipse.jface.text.source.IAnnotationAccess;
37 import org.eclipse.jface.text.source.ICharacterPairMatcher;
38 import org.eclipse.jface.text.source.IOverviewRuler;
39 import org.eclipse.jface.text.source.ISharedTextColors;
40 import org.eclipse.jface.text.source.ISourceViewer;
41 import org.eclipse.jface.text.source.MatchingCharacterPainter;
42 import org.eclipse.jface.text.source.AnnotationPainter.IDrawingStrategy;
43 import org.eclipse.jface.util.IPropertyChangeListener;
44 import org.eclipse.jface.util.PropertyChangeEvent;
45
46 /**
47  * Support class used by text editors to draw and update decorations on the
48  * source viewer and its rulers. An instance of this class is independent of a
49  * certain editor and must be configured with the needed preference keys and
50  * helper objects before it can be used.
51  * <p>
52  * Once configured, an instance may be installed (see
53  * {@link #install(IPreferenceStore) install}) on a preference store, from then
54  * on monitoring the configured preference settings and changing the respective
55  * decorations. Calling {@link #uninstall() uninstall} will unregister the
56  * listeners with the preferences store and must be called before changing the
57  * preference store by another call to <code>install</code>.<br>
58  * {@link #dispose() dispose} will uninstall the support and remove any
59  * decorations from the viewer. It is okay to reuse a
60  * <code>SourceViewerDecorationSupport</code> instance after disposing it.
61  * </p>
62  * <p>
63  * <code>SourceViewerDecorationSupport</code> can draw the following
64  * decorations:
65  * <ul>
66  * <li>matching character highlighting,</li>
67  * <li>current line highlighting,</li>
68  * <li>print margin, and</li>
69  * <li>annotations.</li>
70  * </ul>
71  * Annotations are managed for the overview ruler and also drawn onto the text
72  * widget by an
73  * {@link org.eclipse.jface.text.source.AnnotationPainter AnnotationPainter}
74  * instance.
75  * </p>
76  * <p>
77  * Subclasses may add decorations but should adhere to the lifecyle described
78  * above.
79  * </p>
80  *
81  * @see org.eclipse.jface.text.source.AnnotationPainter
82  * @since 2.1
83  */

84 public class SourceViewerDecorationSupport {
85
86
87     /**
88      * Underline drawing strategy.
89      *
90      * @since 3.0
91      */

92     private static final class UnderlineDrawingStrategy implements IDrawingStrategy {
93
94         /*
95          * @see org.eclipse.jface.text.source.AnnotationPainter.IDrawingStrategy#draw(org.eclipse.jface.text.source.Annotation, org.eclipse.swt.graphics.GC, org.eclipse.swt.custom.StyledText, int, int, org.eclipse.swt.graphics.Color)
96          */

97         public void draw(Annotation annotation, GC gc, StyledText textWidget, int offset, int length, Color color) {
98             if (gc != null) {
99
100                 Rectangle bounds;
101                 if (length > 0)
102                     bounds= textWidget.getTextBounds(offset, offset + length - 1);
103                 else {
104                     Point loc= textWidget.getLocationAtOffset(offset);
105                     bounds= new Rectangle(loc.x, loc.y, 1, textWidget.getLineHeight(offset));
106                 }
107
108                 int y= bounds.y + bounds.height - 1;
109
110                 gc.setForeground(color);
111                 gc.drawLine(bounds.x, y, bounds.x + bounds.width, y);
112
113             } else {
114                 textWidget.redrawRange(offset, length, true);
115             }
116         }
117     }
118
119     /**
120      * Draws a box around a given range.
121      *
122      * @since 3.0
123      */

124     private static class BoxDrawingStrategy implements IDrawingStrategy {
125         /*
126          * @see org.eclipse.jface.text.source.AnnotationPainter.IDrawingStrategy#draw(org.eclipse.jface.text.source.Annotation, org.eclipse.swt.graphics.GC, org.eclipse.swt.custom.StyledText, int, int, org.eclipse.swt.graphics.Color)
127          */

128         public void draw(Annotation annotation, GC gc, StyledText textWidget, int offset, int length, Color color) {
129
130             if (length == 0) {
131                 fgIBeamStrategy.draw(annotation, gc, textWidget, offset, length, color);
132                 return;
133             }
134
135             if (gc != null) {
136
137                 Rectangle bounds;
138                 if (length > 0)
139                     bounds= textWidget.getTextBounds(offset, offset + length - 1);
140                 else {
141                     Point loc= textWidget.getLocationAtOffset(offset);
142                     bounds= new Rectangle(loc.x, loc.y, 1, textWidget.getLineHeight(offset));
143                 }
144
145                 drawBox(gc, textWidget, color, bounds);
146
147             } else {
148                 textWidget.redrawRange(offset, length, true);
149             }
150         }
151
152         protected void drawBox(GC gc, StyledText textWidget, Color color, Rectangle bounds) {
153             gc.setForeground(color);
154             gc.drawRectangle(bounds.x, bounds.y, bounds.width - 1, bounds.height - 1);
155         }
156     }
157     
158     /**
159      * Dashed box drawing strategy.
160      *
161      * @since 3.3
162      */

163     private static final class DashedBoxDrawingStrategy extends BoxDrawingStrategy {
164         /*
165          * @see org.eclipse.ui.texteditor.SourceViewerDecorationSupport.BoxDrawingStrategy#drawBox(org.eclipse.swt.graphics.GC, org.eclipse.swt.graphics.Color, org.eclipse.swt.graphics.Rectangle)
166          */

167         protected void drawBox(GC gc, StyledText textWidget, Color color, Rectangle bounds) {
168             //clean bg:
169
gc.setForeground(textWidget.getBackground());
170             gc.setLineStyle(SWT.LINE_SOLID);
171             int x= bounds.x;
172             int y= bounds.y;
173             int w= bounds.width - 1;
174             int h= bounds.height - 1;
175             gc.drawRectangle(x, y, w, h);
176             
177             gc.setForeground(color);
178             gc.setLineDash(new int[] { 3 });
179             
180             // gc.drawRectangle(x, y, w, h) is platform-dependent and can look "animated"
181
gc.drawLine(x, y, x + w, y);
182             gc.drawLine(x, y + h, x + w, y + h);
183             gc.drawLine(x, y, x, y + h);
184             gc.drawLine(x + w, y, x + w, y + h);
185
186             //RESET (same GC is passed around!):
187
gc.setLineStyle(SWT.LINE_SOLID);
188         }
189     }
190     
191     /**
192      * Draws an iBeam at the given offset, the length is ignored.
193      *
194      * @since 3.0
195      */

196     private static final class IBeamStrategy implements IDrawingStrategy {
197
198         /*
199          * @see org.eclipse.jface.text.source.AnnotationPainter.IDrawingStrategy#draw(org.eclipse.jface.text.source.Annotation, org.eclipse.swt.graphics.GC, org.eclipse.swt.custom.StyledText, int, int, org.eclipse.swt.graphics.Color)
200          */

201         public void draw(Annotation annotation, GC gc, StyledText textWidget, int offset, int length, Color color) {
202             if (gc != null) {
203
204                 Point left= textWidget.getLocationAtOffset(offset);
205                 int x1= left.x;
206                 int y1= left.y;
207
208                 gc.setForeground(color);
209                 gc.drawLine(x1, y1, x1, left.y + textWidget.getLineHeight(offset) - 1);
210
211             } else {
212                 /*
213                  * The length for IBeam's is always 0, which causes no redraw to occur in
214                  * StyledText#redraw(int, int, boolean). We try to normally redraw at length of one,
215                  * and up to the line start of the next line if offset is at the end of line. If at
216                  * the end of the document, we redraw the entire document as the offset is behind
217                  * any content.
218                  */

219                 final int contentLength= textWidget.getCharCount();
220                 if (offset >= contentLength) {
221                     textWidget.redraw();
222                     return;
223                 }
224                 
225                 char ch= textWidget.getTextRange(offset, 1).charAt(0);
226                 if (ch == '\r' || ch == '\n') {
227                     // at the end of a line, redraw up to the next line start
228
int nextLine= textWidget.getLineAtOffset(offset) + 1;
229                     if (nextLine >= textWidget.getLineCount()) {
230                         /*
231                          * Panic code: should not happen, as offset is not the last offset,
232                          * and there is a delimiter character at offset.
233                          */

234                         textWidget.redraw();
235                         return;
236                     }
237                     
238                     int nextLineOffset= textWidget.getOffsetAtLine(nextLine);
239                     length= nextLineOffset - offset;
240                 } else {
241                     length= 1;
242                 }
243                 
244                 textWidget.redrawRange(offset, length, true);
245             }
246         }
247     }
248
249     /**
250      * The box drawing strategy.
251      * @since 3.0
252      */

253     private static IDrawingStrategy fgBoxStrategy= new BoxDrawingStrategy();
254     
255     /**
256      * The dashed box drawing strategy.
257      * @since 3.3
258      */

259     private static IDrawingStrategy fgDashedBoxStrategy= new DashedBoxDrawingStrategy();
260
261     /**
262      * The null drawing strategy.
263      * @since 3.0
264      */

265     private static IDrawingStrategy fgNullStrategy= new AnnotationPainter.NullStrategy();
266
267     /**
268      * The underline drawing strategy.
269      * @since 3.0
270      */

271     private static IDrawingStrategy fgUnderlineStrategy= new UnderlineDrawingStrategy();
272
273     /**
274      * The iBeam drawing strategy.
275      * @since 3.0
276      */

277     private static IDrawingStrategy fgIBeamStrategy= new IBeamStrategy();
278
279     /**
280      * The squiggles drawing strategy.
281      * @since 3.0
282      */

283     private static IDrawingStrategy fgSquigglesStrategy= new AnnotationPainter.SquigglesStrategy();
284
285     /*
286      * @see IPropertyChangeListener
287      */

288     private class FontPropertyChangeListener implements IPropertyChangeListener {
289         /*
290          * @see IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
291          */

292         public void propertyChange(PropertyChangeEvent event) {
293             if (fMarginPainter != null && fSymbolicFontName != null && fSymbolicFontName.equals(event.getProperty()))
294                 fMarginPainter.initialize();
295         }
296     }
297
298
299     /** The viewer */
300     private ISourceViewer fSourceViewer;
301     /** The viewer's overview ruler */
302     private IOverviewRuler fOverviewRuler;
303     /** The annotation access */
304     private IAnnotationAccess fAnnotationAccess;
305     /** The shared color manager */
306     private ISharedTextColors fSharedTextColors;
307
308     /** The editor's line painter */
309     private CursorLinePainter fCursorLinePainter;
310     /** The editor's margin ruler painter */
311     private MarginPainter fMarginPainter;
312     /** The editor's annotation painter */
313     private AnnotationPainter fAnnotationPainter;
314     /** The editor's peer character painter */
315     private MatchingCharacterPainter fMatchingCharacterPainter;
316     /** The character painter's pair matcher */
317     private ICharacterPairMatcher fCharacterPairMatcher;
318
319     /** Map with annotation type preference per annotation type */
320     private Map JavaDoc fAnnotationTypeKeyMap= new HashMap JavaDoc();
321     /** Preference key for the cursor line highlighting */
322     private String JavaDoc fCursorLinePainterEnableKey;
323     /** Preference key for the cursor line background color */
324     private String JavaDoc fCursorLinePainterColorKey;
325     /** Preference key for the margin painter */
326     private String JavaDoc fMarginPainterEnableKey;
327     /** Preference key for the margin painter color */
328     private String JavaDoc fMarginPainterColorKey;
329     /** Preference key for the margin painter column */
330     private String JavaDoc fMarginPainterColumnKey;
331     /** Preference key for the matching character painter */
332     private String JavaDoc fMatchingCharacterPainterEnableKey;
333     /** Preference key for the matching character painter color */
334     private String JavaDoc fMatchingCharacterPainterColorKey;
335     /** The property change listener */
336     private IPropertyChangeListener fPropertyChangeListener;
337     /** The preference store */
338     private IPreferenceStore fPreferenceStore;
339     /** The symbolic font name */
340     private String JavaDoc fSymbolicFontName;
341     /** The font change listener */
342     private FontPropertyChangeListener fFontPropertyChangeListener;
343
344
345     /**
346      * Creates a new decoration support for the given viewer.
347      *
348      * @param sourceViewer the source viewer
349      * @param overviewRuler the viewer's overview ruler
350      * @param annotationAccess the annotation access
351      * @param sharedTextColors the shared text color manager
352      */

353     public SourceViewerDecorationSupport(ISourceViewer sourceViewer, IOverviewRuler overviewRuler, IAnnotationAccess annotationAccess, ISharedTextColors sharedTextColors) {
354         fSourceViewer= sourceViewer;
355         fOverviewRuler= overviewRuler;
356         fAnnotationAccess= annotationAccess;
357         fSharedTextColors= sharedTextColors;
358     }
359
360     /**
361      * Installs this decoration support on the given preference store. It assumes
362      * that this support has completely been configured.
363      *
364      * @param store the preference store
365      */

366     public void install(IPreferenceStore store) {
367
368         fPreferenceStore= store;
369         if (fPreferenceStore != null) {
370             fPropertyChangeListener= new IPropertyChangeListener() {
371                 public void propertyChange(PropertyChangeEvent event) {
372                     handlePreferenceStoreChanged(event);
373                 }
374             };
375             fPreferenceStore.addPropertyChangeListener(fPropertyChangeListener);
376         }
377
378         updateTextDecorations();
379         updateOverviewDecorations();
380     }
381
382     /**
383      * Updates the text decorations for all configured annotation types.
384      */

385     private void updateTextDecorations() {
386
387         StyledText widget= fSourceViewer.getTextWidget();
388         if (widget == null || widget.isDisposed())
389             return;
390
391         if (areMatchingCharactersShown())
392             showMatchingCharacters();
393         else
394             hideMatchingCharacters();
395
396         if (isCursorLineShown())
397             showCursorLine();
398         else
399             hideCursorLine();
400
401         if (isMarginShown())
402             showMargin();
403         else
404             hideMargin();
405
406         Iterator JavaDoc e= fAnnotationTypeKeyMap.keySet().iterator();
407         while (e.hasNext()) {
408             Object JavaDoc type= e.next();
409             Object JavaDoc style= getAnnotationDecorationType(type);
410             if (style != AnnotationPreference.STYLE_NONE)
411                 showAnnotations(type, false, false);
412             else
413                 hideAnnotations(type, false, false);
414             if (areAnnotationsHighlighted(type))
415                 showAnnotations(type, true, false);
416             else
417                 hideAnnotations(type, true, false);
418
419         }
420         updateAnnotationPainter();
421     }
422
423     /**
424      * Returns the annotation decoration style used for the show in text preference for
425      * a given annotation type.
426      *
427      * @param annotationType the annotation type being looked up
428      * @return the decoration style for <code>type</code>
429      * @since 3.0
430      */

431     private Object JavaDoc getAnnotationDecorationType(Object JavaDoc annotationType) {
432         if (areAnnotationsShown(annotationType) && fPreferenceStore != null) {
433             AnnotationPreference info= (AnnotationPreference) fAnnotationTypeKeyMap.get(annotationType);
434             if (info != null) {
435                 String JavaDoc key= info.getTextStylePreferenceKey();
436                 if (key != null)
437                     return fPreferenceStore.getString(key);
438                 // legacy
439
return AnnotationPreference.STYLE_SQUIGGLES;
440             }
441         }
442         return AnnotationPreference.STYLE_NONE;
443     }
444
445     /**
446      * Updates the annotation overview for all configured annotation types.
447      */

448     public void updateOverviewDecorations() {
449         if (fOverviewRuler != null) {
450             Iterator JavaDoc e= fAnnotationTypeKeyMap.keySet().iterator();
451             while (e.hasNext()) {
452                 Object JavaDoc type= e.next();
453                 if (isAnnotationOverviewShown(type))
454                     showAnnotationOverview(type, false);
455                 else
456                     hideAnnotationOverview(type, false);
457             }
458             fOverviewRuler.update();
459         }
460     }
461
462     /**
463      * Uninstalls this support from the preference store it has previously been
464      * installed on. If there is no such preference store, this call is without
465      * effect.
466      */

467     public void uninstall() {
468
469         if (fPreferenceStore != null) {
470             fPreferenceStore.removePropertyChangeListener(fPropertyChangeListener);
471             fPropertyChangeListener= null;
472             fPreferenceStore= null;
473         }
474     }
475
476     /**
477      * Disposes this decoration support. Internally calls
478      * <code>uninstall</code>.
479      */

480     public void dispose() {
481         uninstall();
482         updateTextDecorations();
483         updateOverviewDecorations();
484
485         if (fFontPropertyChangeListener != null) {
486             JFaceResources.getFontRegistry().removeListener(fFontPropertyChangeListener);
487             fFontPropertyChangeListener= null;
488         }
489
490         fOverviewRuler= null;
491
492         // Painters got disposed in updateTextDecorations() or by the PaintManager
493
fMatchingCharacterPainter= null;
494         fCursorLinePainter= null;
495         fAnnotationPainter= null;
496         fCursorLinePainter= null;
497         fMarginPainter= null;
498
499         if (fAnnotationTypeKeyMap != null) {
500             fAnnotationTypeKeyMap.clear();
501             fAnnotationTypeKeyMap= null;
502         }
503     }
504
505     /**
506      * Sets the character pair matcher for the matching character painter.
507      *
508      * @param pairMatcher
509      */

510     public void setCharacterPairMatcher(ICharacterPairMatcher pairMatcher) {
511         fCharacterPairMatcher= pairMatcher;
512     }
513
514     /**
515      * Sets the preference keys for the annotation painter.
516      *
517      * @param type the annotation type
518      * @param colorKey the preference key for the color
519      * @param editorKey the preference key for the presentation in the text area
520      * @param overviewRulerKey the preference key for the presentation in the overview ruler
521      * @param layer the layer
522      */

523     public void setAnnotationPainterPreferenceKeys(Object JavaDoc type, String JavaDoc colorKey, String JavaDoc editorKey, String JavaDoc overviewRulerKey, int layer) {
524         AnnotationPreference info= new AnnotationPreference(type, colorKey, editorKey, overviewRulerKey, layer);
525         fAnnotationTypeKeyMap.put(type, info);
526     }
527
528     /**
529      * Sets the preference info for the annotation painter.
530      * @param info the preference info to be set
531      */

532     public void setAnnotationPreference(AnnotationPreference info) {
533         fAnnotationTypeKeyMap.put(info.getAnnotationType(), info);
534     }
535
536     /**
537      * Sets the preference keys for the cursor line painter.
538      * @param enableKey the preference key for the cursor line painter
539      * @param colorKey the preference key for the color used by the cursor line
540      * painter
541      */

542     public void setCursorLinePainterPreferenceKeys(String JavaDoc enableKey, String JavaDoc colorKey) {
543         fCursorLinePainterEnableKey= enableKey;
544         fCursorLinePainterColorKey= colorKey;
545     }
546
547     /**
548      * Sets the preference keys for the margin painter.
549      * @param enableKey the preference key for the margin painter
550      * @param colorKey the preference key for the color used by the margin
551      * painter
552      * @param columnKey the preference key for the margin column
553      */

554     public void setMarginPainterPreferenceKeys(String JavaDoc enableKey, String JavaDoc colorKey, String JavaDoc columnKey) {
555         fMarginPainterEnableKey= enableKey;
556         fMarginPainterColorKey= colorKey;
557         fMarginPainterColumnKey= columnKey;
558     }
559
560     /**
561      * Sets the preference keys for the matching character painter.
562      * @param enableKey the preference key for the matching character painter
563      * @param colorKey the preference key for the color used by the matching
564      * character painter
565      */

566     public void setMatchingCharacterPainterPreferenceKeys(String JavaDoc enableKey, String JavaDoc colorKey) {
567         fMatchingCharacterPainterEnableKey= enableKey;
568         fMatchingCharacterPainterColorKey= colorKey;
569     }
570
571     /**
572      * Sets the symbolic font name that is used for computing the margin width.
573      * @param symbolicFontName
574      */

575     public void setSymbolicFontName(String JavaDoc symbolicFontName) {
576         fSymbolicFontName= symbolicFontName;
577     }
578
579     /**
580      * Returns the annotation preference for the given key.
581      *
582      * @param preferenceKey the preference key string
583      * @return the annotation preference
584      */

585     private AnnotationPreference getAnnotationPreferenceInfo(String JavaDoc preferenceKey) {
586         Iterator JavaDoc e= fAnnotationTypeKeyMap.values().iterator();
587         while (e.hasNext()) {
588             AnnotationPreference info= (AnnotationPreference) e.next();
589             if (info != null && info.isPreferenceKey(preferenceKey))
590                 return info;
591         }
592         return null;
593     }
594
595
596     /*
597      * @see AbstractTextEditor#handlePreferenceStoreChanged(PropertyChangeEvent)
598      */

599     protected void handlePreferenceStoreChanged(PropertyChangeEvent event) {
600
601         String JavaDoc p= event.getProperty();
602
603         if (fMatchingCharacterPainterEnableKey != null && fMatchingCharacterPainterEnableKey.equals(p) && fCharacterPairMatcher != null) {
604             if (areMatchingCharactersShown())
605                 showMatchingCharacters();
606             else
607                 hideMatchingCharacters();
608             return;
609         }
610
611         if (fMatchingCharacterPainterColorKey != null && fMatchingCharacterPainterColorKey.equals(p)) {
612             if (fMatchingCharacterPainter != null) {
613                 fMatchingCharacterPainter.setColor(getColor(fMatchingCharacterPainterColorKey));
614                 fMatchingCharacterPainter.paint(IPainter.CONFIGURATION);
615             }
616             return;
617         }
618
619         if (fCursorLinePainterEnableKey != null && fCursorLinePainterEnableKey.equals(p)) {
620             if (isCursorLineShown())
621                 showCursorLine();
622             else
623                 hideCursorLine();
624             return;
625         }
626
627         if (fCursorLinePainterColorKey != null && fCursorLinePainterColorKey.equals(p)) {
628             if (fCursorLinePainter != null) {
629                 hideCursorLine();
630                 showCursorLine();
631             }
632             return;
633         }
634
635         if (fMarginPainterEnableKey != null && fMarginPainterEnableKey.equals(p)) {
636             if (isMarginShown())
637                 showMargin();
638             else
639                 hideMargin();
640             return;
641         }
642
643         if (fMarginPainterColorKey != null && fMarginPainterColorKey.equals(p)) {
644             if (fMarginPainter != null) {
645                 fMarginPainter.setMarginRulerColor(getColor(fMarginPainterColorKey));
646                 fMarginPainter.paint(IPainter.CONFIGURATION);
647             }
648             return;
649         }
650
651         if (fMarginPainterColumnKey != null && fMarginPainterColumnKey.equals(p)) {
652             if (fMarginPainter != null && fPreferenceStore != null) {
653                 fMarginPainter.setMarginRulerColumn(fPreferenceStore.getInt(fMarginPainterColumnKey));
654                 fMarginPainter.paint(IPainter.CONFIGURATION);
655             }
656             return;
657         }
658
659         AnnotationPreference info= getAnnotationPreferenceInfo(p);
660         if (info != null) {
661
662             if (info.getColorPreferenceKey().equals(p)) {
663                 Color color= getColor(info.getColorPreferenceKey());
664                 if (fAnnotationPainter != null) {
665                     fAnnotationPainter.setAnnotationTypeColor(info.getAnnotationType(), color);
666                     fAnnotationPainter.paint(IPainter.CONFIGURATION);
667                 }
668                 setAnnotationOverviewColor(info.getAnnotationType(), color);
669                 return;
670             }
671
672             if (info.getTextPreferenceKey().equals(p) || info.getTextStylePreferenceKey() != null && info.getTextStylePreferenceKey().equals(p)) {
673                 Object JavaDoc style= getAnnotationDecorationType(info.getAnnotationType());
674                 if (AnnotationPreference.STYLE_NONE != style)
675                     showAnnotations(info.getAnnotationType(), false, true);
676                 else
677                     hideAnnotations(info.getAnnotationType(), false, true);
678                 return;
679             }
680
681             if (info.getHighlightPreferenceKey() != null && info.getHighlightPreferenceKey().equals(p)) {
682                 if (areAnnotationsHighlighted(info.getAnnotationType()))
683                     showAnnotations(info.getAnnotationType(), true, true);
684                 else
685                     hideAnnotations(info.getAnnotationType(), true, true);
686                 return;
687             }
688
689             Object JavaDoc style= getAnnotationDecorationType(info.getAnnotationType());
690             if (style != AnnotationPreference.STYLE_NONE)
691                 showAnnotations(info.getAnnotationType(), false, false);
692             else
693                 hideAnnotations(info.getAnnotationType(), false, false);
694
695             if (info.getOverviewRulerPreferenceKey().equals(p)) {
696                 if (isAnnotationOverviewShown(info.getAnnotationType()))
697                     showAnnotationOverview(info.getAnnotationType(), true);
698                 else
699                     hideAnnotationOverview(info.getAnnotationType(), true);
700                 return;
701             }
702         }
703
704     }
705
706     /**
707      * Returns the shared color for the given key.
708      *
709      * @param key the color key string
710      * @return the shared color for the given key
711      */

712     private Color getColor(String JavaDoc key) {
713         if (fPreferenceStore != null) {
714             RGB rgb= PreferenceConverter.getColor(fPreferenceStore, key);
715             return getColor(rgb);
716         }
717         return null;
718     }
719
720     /**
721      * Returns the shared color for the given RGB.
722      *
723      * @param rgb the RGB
724      * @return the shared color for the given RGB
725      */

726     private Color getColor(RGB rgb) {
727         return fSharedTextColors.getColor(rgb);
728     }
729
730     /**
731      * Returns the color of the given annotation type.
732      *
733      * @param annotationType the annotation type
734      * @return the color of the annotation type
735      */

736     private Color getAnnotationTypeColor(Object JavaDoc annotationType) {
737         AnnotationPreference info= (AnnotationPreference) fAnnotationTypeKeyMap.get(annotationType);
738         if (info != null)
739             return getColor( info.getColorPreferenceKey());
740         return null;
741     }
742
743
744
745     /**
746      * Returns the layer of the given annotation type.
747      *
748      * @param annotationType the annotation type
749      * @return the layer
750      */

751     private int getAnnotationTypeLayer(Object JavaDoc annotationType) {
752         AnnotationPreference info= (AnnotationPreference) fAnnotationTypeKeyMap.get(annotationType);
753         if (info != null)
754             return info.getPresentationLayer();
755         return 0;
756     }
757
758     /**
759      * Enables showing of matching characters.
760      */

761     private void showMatchingCharacters() {
762         if (fMatchingCharacterPainter == null) {
763             if (fSourceViewer instanceof ITextViewerExtension2) {
764                 fMatchingCharacterPainter= new MatchingCharacterPainter(fSourceViewer, fCharacterPairMatcher);
765                 fMatchingCharacterPainter.setColor(getColor(fMatchingCharacterPainterColorKey));
766                 ITextViewerExtension2 extension= (ITextViewerExtension2) fSourceViewer;
767                 extension.addPainter(fMatchingCharacterPainter);
768             }
769         }
770     }
771
772     /**
773      * Disables showing of matching characters.
774      */

775     private void hideMatchingCharacters() {
776         if (fMatchingCharacterPainter != null) {
777             if (fSourceViewer instanceof ITextViewerExtension2) {
778                 ITextViewerExtension2 extension= (ITextViewerExtension2) fSourceViewer;
779                 extension.removePainter(fMatchingCharacterPainter);
780                 fMatchingCharacterPainter.deactivate(true);
781                 fMatchingCharacterPainter.dispose();
782                 fMatchingCharacterPainter= null;
783             }
784         }
785     }
786
787     /**
788      * Tells whether matching characters are shown.
789      *
790      * @return <code>true</code> if the matching characters are shown
791      */

792     private boolean areMatchingCharactersShown() {
793         if (fPreferenceStore != null && fMatchingCharacterPainterEnableKey != null)
794             return fPreferenceStore.getBoolean(fMatchingCharacterPainterEnableKey);
795         return false;
796     }
797
798     /**
799      * Shows the cursor line.
800      */

801     private void showCursorLine() {
802         if (fCursorLinePainter == null) {
803             if (fSourceViewer instanceof ITextViewerExtension2) {
804                 fCursorLinePainter= new CursorLinePainter(fSourceViewer);
805                 fCursorLinePainter.setHighlightColor(getColor(fCursorLinePainterColorKey));
806                 ITextViewerExtension2 extension= (ITextViewerExtension2) fSourceViewer;
807                 extension.addPainter(fCursorLinePainter);
808             }
809         }
810     }
811
812     /**
813      * Hides the cursor line.
814      */

815     private void hideCursorLine() {
816         if (fCursorLinePainter != null) {
817             if (fSourceViewer instanceof ITextViewerExtension2) {
818                 ITextViewerExtension2 extension= (ITextViewerExtension2) fSourceViewer;
819                 extension.removePainter(fCursorLinePainter);
820                 fCursorLinePainter.deactivate(true);
821                 fCursorLinePainter.dispose();
822                 fCursorLinePainter= null;
823             }
824         }
825     }
826
827     /**
828      * Tells whether the cursor line is shown.
829      *
830      * @return <code>true</code> if the cursor line is shown
831      */

832     private boolean isCursorLineShown() {
833         if (fPreferenceStore != null && fCursorLinePainterEnableKey != null)
834             return fPreferenceStore.getBoolean(fCursorLinePainterEnableKey);
835         return false;
836     }
837
838     /**
839      * Shows the margin.
840      */

841     private void showMargin() {
842         if (fMarginPainter == null) {
843             if (fSourceViewer instanceof ITextViewerExtension2) {
844                 fMarginPainter= new MarginPainter(fSourceViewer);
845                 fMarginPainter.setMarginRulerColor(getColor(fMarginPainterColorKey));
846                 if (fPreferenceStore != null)
847                     fMarginPainter.setMarginRulerColumn(fPreferenceStore.getInt(fMarginPainterColumnKey));
848                 ITextViewerExtension2 extension= (ITextViewerExtension2) fSourceViewer;
849                 extension.addPainter(fMarginPainter);
850
851                 fFontPropertyChangeListener= new FontPropertyChangeListener();
852                 JFaceResources.getFontRegistry().addListener(fFontPropertyChangeListener);
853             }
854         }
855     }
856
857     /**
858      * Hides the margin.
859      */

860     private void hideMargin() {
861         if (fMarginPainter != null) {
862             if (fSourceViewer instanceof ITextViewerExtension2) {
863                 JFaceResources.getFontRegistry().removeListener(fFontPropertyChangeListener);
864                 fFontPropertyChangeListener= null;
865
866                 ITextViewerExtension2 extension= (ITextViewerExtension2) fSourceViewer;
867                 extension.removePainter(fMarginPainter);
868                 fMarginPainter.deactivate(true);
869                 fMarginPainter.dispose();
870                 fMarginPainter= null;
871             }
872         }
873     }
874
875     /**
876      * Tells whether the margin is shown.
877      *
878      * @return <code>true</code> if the margin is shown
879      */

880     private boolean isMarginShown() {
881         if (fPreferenceStore != null && fMarginPainterEnableKey != null)
882             return fPreferenceStore.getBoolean(fMarginPainterEnableKey);
883         return false;
884     }
885
886     /**
887      * Enables annotations in the source viewer for the given annotation type.
888      *
889      * @param annotationType the annotation type
890      * @param highlighting <code>true</code> if highlighting <code>false</code> if painting squiggles
891      * @param updatePainter if <code>true</code> update the annotation painter
892      * @since 3.0
893      */

894     private void showAnnotations(Object JavaDoc annotationType, boolean highlighting, boolean updatePainter) {
895         if (fSourceViewer instanceof ITextViewerExtension2) {
896             if (fAnnotationPainter == null) {
897                 fAnnotationPainter= createAnnotationPainter();
898                 if (fSourceViewer instanceof ITextViewerExtension4)
899                     ((ITextViewerExtension4)fSourceViewer).addTextPresentationListener(fAnnotationPainter);
900                 ITextViewerExtension2 extension= (ITextViewerExtension2) fSourceViewer;
901                 extension.addPainter(fAnnotationPainter);
902             }
903             fAnnotationPainter.setAnnotationTypeColor(annotationType, getAnnotationTypeColor(annotationType));
904             if (highlighting)
905                 fAnnotationPainter.addHighlightAnnotationType(annotationType);
906             else
907                 fAnnotationPainter.addAnnotationType(annotationType, getAnnotationDecorationType(annotationType));
908
909             if (updatePainter)
910                 updateAnnotationPainter();
911         }
912     }
913
914     /**
915      * Creates and configures the annotation painter and configures.
916      * @return an annotation painter
917      * @since 3.0
918      */

919     protected AnnotationPainter createAnnotationPainter() {
920         AnnotationPainter painter= new AnnotationPainter(fSourceViewer, fAnnotationAccess);
921
922         /*
923          * XXX:
924          * Could provide an extension point for drawing strategies,
925          * see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=51498
926          */

927         painter.addDrawingStrategy(AnnotationPreference.STYLE_BOX, fgBoxStrategy);
928         painter.addDrawingStrategy(AnnotationPreference.STYLE_DASHED_BOX, fgDashedBoxStrategy);
929         painter.addDrawingStrategy(AnnotationPreference.STYLE_NONE, fgNullStrategy);
930         painter.addDrawingStrategy(AnnotationPreference.STYLE_SQUIGGLES, fgSquigglesStrategy);
931         painter.addDrawingStrategy(AnnotationPreference.STYLE_UNDERLINE, fgUnderlineStrategy);
932         painter.addDrawingStrategy(AnnotationPreference.STYLE_IBEAM, fgIBeamStrategy);
933
934         return painter;
935     }
936
937     /**
938      * Updates the annotation painter.
939      * @since 3.0
940      */

941     private void updateAnnotationPainter() {
942         if (fAnnotationPainter == null)
943             return;
944
945         fAnnotationPainter.paint(IPainter.CONFIGURATION);
946         if (!fAnnotationPainter.isPaintingAnnotations()) {
947             if (fSourceViewer instanceof ITextViewerExtension2) {
948                 ITextViewerExtension2 extension= (ITextViewerExtension2) fSourceViewer;
949                 extension.removePainter(fAnnotationPainter);
950             }
951             if (fSourceViewer instanceof ITextViewerExtension4)
952                 ((ITextViewerExtension4)fSourceViewer).removeTextPresentationListener(fAnnotationPainter);
953
954             fAnnotationPainter.deactivate(true);
955             fAnnotationPainter.dispose();
956             fAnnotationPainter= null;
957         }
958     }
959
960     /**
961      * Hides annotations in the source viewer for the given annotation type.
962      *
963      * @param annotationType the annotation type
964      * @param highlighting <code>true</code> if highlighting <code>false</code> if painting squiggles
965      * @param updatePainter if <code>true</code> update the annotation painter
966      * @since 3.0
967      */

968     private void hideAnnotations(Object JavaDoc annotationType, boolean highlighting, boolean updatePainter) {
969         if (fAnnotationPainter != null) {
970             if (highlighting)
971                 fAnnotationPainter.removeHighlightAnnotationType(annotationType);
972             else
973                 fAnnotationPainter.removeAnnotationType(annotationType);
974
975             if (updatePainter) {
976                 updateAnnotationPainter();
977             }
978         }
979     }
980
981     /**
982      * Tells whether annotations are shown in the source viewer for the given type.
983      *
984      * @param annotationType the annotation type
985      * @return <code>true</code> if the annotations are shown
986      */

987     private boolean areAnnotationsShown(Object JavaDoc annotationType) {
988         if (fPreferenceStore != null) {
989             AnnotationPreference info= (AnnotationPreference) fAnnotationTypeKeyMap.get(annotationType);
990             if (info != null) {
991                 String JavaDoc key= info.getTextPreferenceKey();
992                 return key != null && fPreferenceStore.getBoolean(key);
993             }
994         }
995         return false;
996     }
997
998     /**
999      * Tells whether annotations are highlighted in the source viewer for the given type.
1000     *
1001     * @param annotationType the annotation type
1002     * @return <code>true</code> if the annotations are highlighted
1003     * @since 3.0
1004     */

1005    private boolean areAnnotationsHighlighted(Object JavaDoc annotationType) {
1006        if (fPreferenceStore != null) {
1007            AnnotationPreference info= (AnnotationPreference)fAnnotationTypeKeyMap.get(annotationType);
1008            if (info != null)
1009                return info.getHighlightPreferenceKey() != null && fPreferenceStore.getBoolean(info.getHighlightPreferenceKey());
1010        }
1011        return false;
1012    }
1013
1014    /**
1015     * Tells whether annotation overview is enabled for the given type.
1016     *
1017     * @param annotationType the annotation type
1018     * @return <code>true</code> if the annotation overview is shown
1019     */

1020    private boolean isAnnotationOverviewShown(Object JavaDoc annotationType) {
1021        if (fPreferenceStore != null && fOverviewRuler != null) {
1022            AnnotationPreference info= (AnnotationPreference) fAnnotationTypeKeyMap.get(annotationType);
1023            if (info != null)
1024                return fPreferenceStore.getBoolean(info.getOverviewRulerPreferenceKey());
1025        }
1026        return false;
1027    }
1028
1029    /**
1030     * Enable annotation overview for the given annotation type.
1031     *
1032     * @param annotationType the annotation type
1033     * @param update <code>true</code> if the overview should be updated
1034     */

1035    private void showAnnotationOverview(Object JavaDoc annotationType, boolean update) {
1036        if (fOverviewRuler != null) {
1037            fOverviewRuler.setAnnotationTypeColor(annotationType, getAnnotationTypeColor(annotationType));
1038            fOverviewRuler.setAnnotationTypeLayer(annotationType, getAnnotationTypeLayer(annotationType));
1039            fOverviewRuler.addAnnotationType(annotationType);
1040            if (update)
1041                fOverviewRuler.update();
1042        }
1043    }
1044
1045    /**
1046     * Hides the annotation overview for the given type.
1047     * @param annotationType the annotation type
1048     * @param update <code>true</code> if the overview should be updated
1049     */

1050    private void hideAnnotationOverview(Object JavaDoc annotationType, boolean update) {
1051        if (fOverviewRuler != null) {
1052            fOverviewRuler.removeAnnotationType(annotationType);
1053            if (update)
1054                fOverviewRuler.update();
1055        }
1056    }
1057
1058    /**
1059     * Hides the annotation overview.
1060     */

1061    public void hideAnnotationOverview() {
1062        if (fOverviewRuler != null) {
1063            Iterator JavaDoc e= fAnnotationTypeKeyMap.keySet().iterator();
1064            while (e.hasNext())
1065                fOverviewRuler.removeAnnotationType(e.next());
1066            fOverviewRuler.update();
1067        }
1068    }
1069
1070    /**
1071     * Sets the annotation overview color for the given annotation type.
1072     *
1073     * @param annotationType the annotation type
1074     * @param color the color
1075     */

1076    private void setAnnotationOverviewColor(Object JavaDoc annotationType, Color color) {
1077        if (fOverviewRuler != null) {
1078            fOverviewRuler.setAnnotationTypeColor(annotationType, color);
1079            fOverviewRuler.update();
1080        }
1081    }
1082}
1083
Popular Tags