KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > text > source > AnnotationRulerColumn


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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 package org.eclipse.jface.text.source;
12
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Collections JavaDoc;
16 import java.util.Comparator JavaDoc;
17 import java.util.HashMap JavaDoc;
18 import java.util.HashSet JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.List JavaDoc;
21 import java.util.Map JavaDoc;
22 import java.util.Set JavaDoc;
23
24 import org.eclipse.swt.SWT;
25 import org.eclipse.swt.custom.StyledText;
26 import org.eclipse.swt.events.DisposeEvent;
27 import org.eclipse.swt.events.DisposeListener;
28 import org.eclipse.swt.events.MouseEvent;
29 import org.eclipse.swt.events.MouseListener;
30 import org.eclipse.swt.events.MouseMoveListener;
31 import org.eclipse.swt.events.PaintEvent;
32 import org.eclipse.swt.events.PaintListener;
33 import org.eclipse.swt.graphics.Cursor;
34 import org.eclipse.swt.graphics.Font;
35 import org.eclipse.swt.graphics.GC;
36 import org.eclipse.swt.graphics.Image;
37 import org.eclipse.swt.graphics.Point;
38 import org.eclipse.swt.graphics.Rectangle;
39 import org.eclipse.swt.widgets.Canvas;
40 import org.eclipse.swt.widgets.Composite;
41 import org.eclipse.swt.widgets.Control;
42 import org.eclipse.swt.widgets.Display;
43
44
45 import org.eclipse.jface.text.BadLocationException;
46 import org.eclipse.jface.text.IDocument;
47 import org.eclipse.jface.text.IRegion;
48 import org.eclipse.jface.text.ITextListener;
49 import org.eclipse.jface.text.ITextViewer;
50 import org.eclipse.jface.text.ITextViewerExtension5;
51 import org.eclipse.jface.text.IViewportListener;
52 import org.eclipse.jface.text.JFaceTextUtil;
53 import org.eclipse.jface.text.Position;
54 import org.eclipse.jface.text.TextEvent;
55 import org.eclipse.jface.text.TextViewer;
56
57
58 /**
59  * A vertical ruler column showing graphical representations of annotations.
60  * Will become final.
61  * <p>
62  * Do not subclass.
63  * </p>
64  *
65  * @since 2.0
66  */

67 public class AnnotationRulerColumn implements IVerticalRulerColumn, IVerticalRulerInfo, IVerticalRulerInfoExtension {
68
69     /**
70      * Internal listener class.
71      */

72     class InternalListener implements IViewportListener, IAnnotationModelListener, ITextListener {
73
74         /*
75          * @see IViewportListener#viewportChanged(int)
76          */

77         public void viewportChanged(int verticalPosition) {
78             if (verticalPosition != fScrollPos)
79                 redraw();
80         }
81
82         /*
83          * @see IAnnotationModelListener#modelChanged(IAnnotationModel)
84          */

85         public void modelChanged(IAnnotationModel model) {
86             postRedraw();
87         }
88
89         /*
90          * @see ITextListener#textChanged(TextEvent)
91          */

92         public void textChanged(TextEvent e) {
93             if (e.getViewerRedrawState())
94                 postRedraw();
95         }
96     }
97
98     /**
99      * Implementation of <code>IRegion</code> that can be reused
100      * by setting the offset and the length.
101      */

102     private static class ReusableRegion extends Position implements IRegion {}
103
104     /**
105      * Pair of an annotation and their associated position. Used inside the paint method
106      * for sorting annotations based on the offset of their position.
107      * @since 3.0
108      */

109     private static class Tuple {
110         Annotation annotation;
111         Position position;
112
113         Tuple(Annotation annotation, Position position) {
114             this.annotation= annotation;
115             this.position= position;
116         }
117     }
118
119     /**
120      * Comparator for <code>Tuple</code>s.
121      * @since 3.0
122      */

123     private static class TupleComparator implements Comparator JavaDoc {
124         /*
125          * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
126          */

127         public int compare(Object JavaDoc o1, Object JavaDoc o2) {
128             Position p1= ((Tuple) o1).position;
129             Position p2= ((Tuple) o2).position;
130             return p1.getOffset() - p2.getOffset();
131         }
132     }
133
134     /** This column's parent ruler */
135     private CompositeRuler fParentRuler;
136     /** The cached text viewer */
137     private ITextViewer fCachedTextViewer;
138     /** The cached text widget */
139     private StyledText fCachedTextWidget;
140     /** The ruler's canvas */
141     private Canvas fCanvas;
142     /** The vertical ruler's model */
143     private IAnnotationModel fModel;
144     /** Cache for the actual scroll position in pixels */
145     private int fScrollPos;
146     /** The buffer for double buffering */
147     private Image fBuffer;
148     /** The internal listener */
149     private InternalListener fInternalListener= new InternalListener();
150     /** The width of this vertical ruler */
151     private int fWidth;
152     /** Switch for enabling/disabling the setModel method. */
153     private boolean fAllowSetModel= true;
154     /**
155      * The list of annotation types to be shown in this ruler.
156      * @since 3.0
157      */

158     private Set JavaDoc fConfiguredAnnotationTypes= new HashSet JavaDoc();
159     /**
160      * The list of allowed annotation types to be shown in this ruler.
161      * An allowed annotation type maps to <code>true</code>, a disallowed
162      * to <code>false</code>.
163      * @since 3.0
164      */

165     private Map JavaDoc fAllowedAnnotationTypes= new HashMap JavaDoc();
166     /**
167      * The annotation access extension.
168      * @since 3.0
169      */

170     private IAnnotationAccessExtension fAnnotationAccessExtension;
171     /**
172      * The hover for this column.
173      * @since 3.0
174      */

175     private IAnnotationHover fHover;
176     /**
177      * The cached annotations.
178      * @since 3.0
179      */

180     private List JavaDoc fCachedAnnotations= new ArrayList JavaDoc();
181     /**
182      * The comparator for sorting annotations according to the offset of their position.
183      * @since 3.0
184      */

185     private Comparator JavaDoc fTupleComparator= new TupleComparator();
186     /**
187      * The hit detection cursor.
188      * @since 3.0
189      */

190     private Cursor fHitDetectionCursor;
191     /**
192      * The last cursor.
193      * @since 3.0
194      */

195     private Cursor fLastCursor;
196     /**
197      * This ruler's mouse listener.
198      * @since 3.0
199      */

200     private MouseListener fMouseListener;
201
202     /**
203      * Constructs this column with the given arguments.
204      *
205      * @param model the annotation model to get the annotations from
206      * @param width the width of the vertical ruler
207      * @param annotationAccess the annotation access
208      * @since 3.0
209      */

210     public AnnotationRulerColumn(IAnnotationModel model, int width, IAnnotationAccess annotationAccess) {
211         this(width, annotationAccess);
212         fAllowSetModel= false;
213         fModel= model;
214         fModel.addAnnotationModelListener(fInternalListener);
215     }
216
217     /**
218      * Constructs this column with the given arguments.
219      *
220      * @param width the width of the vertical ruler
221      * @param annotationAccess the annotation access
222      * @since 3.0
223      */

224     public AnnotationRulerColumn(int width, IAnnotationAccess annotationAccess) {
225         fWidth= width;
226         if (annotationAccess instanceof IAnnotationAccessExtension)
227             fAnnotationAccessExtension= (IAnnotationAccessExtension) annotationAccess;
228     }
229
230     /**
231      * Constructs this column with the given arguments.
232      *
233      * @param model the annotation model to get the annotations from
234      * @param width the width of the vertical ruler
235      */

236     public AnnotationRulerColumn(IAnnotationModel model, int width) {
237         fWidth= width;
238         fAllowSetModel= false;
239         fModel= model;
240         fModel.addAnnotationModelListener(fInternalListener);
241     }
242
243     /**
244      * Constructs this column with the given width.
245      *
246      * @param width the width of the vertical ruler
247      */

248     public AnnotationRulerColumn(int width) {
249         fWidth= width;
250     }
251
252     /*
253      * @see IVerticalRulerColumn#getControl()
254      */

255     public Control getControl() {
256         return fCanvas;
257     }
258
259     /*
260      * @see IVerticalRulerColumn#getWidth()
261      */

262     public int getWidth() {
263         return fWidth;
264     }
265
266     /*
267      * @see IVerticalRulerColumn#createControl(CompositeRuler, Composite)
268      */

269     public Control createControl(CompositeRuler parentRuler, Composite parentControl) {
270
271         fParentRuler= parentRuler;
272         fCachedTextViewer= parentRuler.getTextViewer();
273         fCachedTextWidget= fCachedTextViewer.getTextWidget();
274
275         fHitDetectionCursor= new Cursor(parentControl.getDisplay(), SWT.CURSOR_HAND);
276
277         fCanvas= createCanvas(parentControl);
278
279         fCanvas.addPaintListener(new PaintListener() {
280             public void paintControl(PaintEvent event) {
281                 if (fCachedTextViewer != null)
282                     doubleBufferPaint(event.gc);
283             }
284         });
285
286         fCanvas.addDisposeListener(new DisposeListener() {
287             public void widgetDisposed(DisposeEvent e) {
288                 handleDispose();
289                 fCachedTextViewer= null;
290                 fCachedTextWidget= null;
291             }
292         });
293
294         fMouseListener= new MouseListener() {
295             public void mouseUp(MouseEvent event) {
296                 int lineNumber;
297                 if (isPropagatingMouseListener()) {
298                     fParentRuler.setLocationOfLastMouseButtonActivity(event.x, event.y);
299                     lineNumber= fParentRuler.getLineOfLastMouseButtonActivity();
300                 } else
301                     lineNumber= fParentRuler.toDocumentLineNumber(event.y);
302
303                 if (1 == event.button)
304                     mouseClicked(lineNumber);
305             }
306
307             public void mouseDown(MouseEvent event) {
308                 if (isPropagatingMouseListener())
309                     fParentRuler.setLocationOfLastMouseButtonActivity(event.x, event.y);
310             }
311
312             public void mouseDoubleClick(MouseEvent event) {
313                 int lineNumber;
314                 if (isPropagatingMouseListener()) {
315                     fParentRuler.setLocationOfLastMouseButtonActivity(event.x, event.y);
316                     lineNumber= fParentRuler.getLineOfLastMouseButtonActivity();
317                 } else
318                     lineNumber= fParentRuler.toDocumentLineNumber(event.y);
319
320                 if (1 == event.button)
321                     mouseDoubleClicked(lineNumber);
322             }
323         };
324         fCanvas.addMouseListener(fMouseListener);
325
326         fCanvas.addMouseMoveListener(new MouseMoveListener() {
327             /*
328              * @see org.eclipse.swt.events.MouseMoveListener#mouseMove(org.eclipse.swt.events.MouseEvent)
329              * @since 3.0
330              */

331             public void mouseMove(MouseEvent e) {
332                 handleMouseMove(e);
333             }
334         });
335
336         if (fCachedTextViewer != null) {
337             fCachedTextViewer.addViewportListener(fInternalListener);
338             fCachedTextViewer.addTextListener(fInternalListener);
339         }
340
341         return fCanvas;
342     }
343
344     /**
345      * Creates a canvas with the given parent.
346      *
347      * @param parent the parent
348      * @return the created canvas
349      */

350     private Canvas createCanvas(Composite parent) {
351         return new Canvas(parent, SWT.NO_BACKGROUND) {
352             /*
353              * @see org.eclipse.swt.widgets.Control#addMouseListener(org.eclipse.swt.events.MouseListener)
354              * @since 3.0
355              */

356             public void addMouseListener(MouseListener listener) {
357                 if (isPropagatingMouseListener() || listener == fMouseListener)
358                     super.addMouseListener(listener);
359             }
360         };
361     }
362
363     /**
364      * Tells whether this ruler column propagates mouse listener
365      * events to its parent.
366      *
367      * @return <code>true</code> if propagating to parent
368      * @since 3.0
369      */

370     protected boolean isPropagatingMouseListener() {
371         return true;
372     }
373
374     /**
375      * Hook method for a mouse double click event on the given ruler line.
376      *
377      * @param rulerLine the ruler line
378      */

379     protected void mouseDoubleClicked(int rulerLine) {
380     }
381
382     /**
383      * Hook method for a mouse click event on the given ruler line.
384      *
385      * @param rulerLine the ruler line
386      * @since 3.0
387      */

388     protected void mouseClicked(int rulerLine) {
389     }
390
391     /**
392      * Handles mouse moves.
393      *
394      * @param event the mouse move event
395      */

396     private void handleMouseMove(MouseEvent event) {
397         fParentRuler.setLocationOfLastMouseButtonActivity(event.x, event.y);
398         if (fCachedTextViewer != null) {
399             int line= toDocumentLineNumber(event.y);
400             Cursor cursor= (hasAnnotation(line) ? fHitDetectionCursor : null);
401             if (cursor != fLastCursor) {
402                 fCanvas.setCursor(cursor);
403                 fLastCursor= cursor;
404             }
405         }
406     }
407
408     /**
409      * Tells whether the given line contains an annotation.
410      *
411      * @param lineNumber the line number
412      * @return <code>true</code> if the given line contains an annotation
413      */

414     protected boolean hasAnnotation(int lineNumber) {
415
416         IAnnotationModel model= fModel;
417         if (fModel instanceof IAnnotationModelExtension)
418             model= ((IAnnotationModelExtension)fModel).getAnnotationModel(SourceViewer.MODEL_ANNOTATION_MODEL);
419
420         if (model == null)
421             return false;
422
423         IRegion line;
424         try {
425             IDocument d= fCachedTextViewer.getDocument();
426             if (d == null)
427                 return false;
428             
429             line= d.getLineInformation(lineNumber);
430         } catch (BadLocationException ex) {
431             return false;
432         }
433
434         int lineStart= line.getOffset();
435         int lineLength= line.getLength();
436
437         Iterator JavaDoc e= model.getAnnotationIterator();
438         while (e.hasNext()) {
439             Annotation a= (Annotation) e.next();
440
441             if (a.isMarkedDeleted())
442                 continue;
443
444             if (skip(a))
445                 continue;
446
447             Position p= model.getPosition(a);
448             if (p == null || p.isDeleted())
449                 continue;
450
451             if (p.overlapsWith(lineStart, lineLength) || p.length == 0 && p.offset == lineStart + lineLength)
452                 return true;
453         }
454
455         return false;
456     }
457
458     /**
459      * Disposes the ruler's resources.
460      */

461     private void handleDispose() {
462
463         if (fCachedTextViewer != null) {
464             fCachedTextViewer.removeViewportListener(fInternalListener);
465             fCachedTextViewer.removeTextListener(fInternalListener);
466         }
467
468         if (fModel != null)
469             fModel.removeAnnotationModelListener(fInternalListener);
470
471         if (fBuffer != null) {
472             fBuffer.dispose();
473             fBuffer= null;
474         }
475
476         if (fHitDetectionCursor != null) {
477             fHitDetectionCursor.dispose();
478             fHitDetectionCursor= null;
479         }
480
481         fConfiguredAnnotationTypes.clear();
482         fAllowedAnnotationTypes.clear();
483         fAnnotationAccessExtension= null;
484     }
485
486     /**
487      * Double buffer drawing.
488      *
489      * @param dest the GC to draw into
490      */

491     private void doubleBufferPaint(GC dest) {
492
493         Point size= fCanvas.getSize();
494
495         if (size.x <= 0 || size.y <= 0)
496             return;
497
498         if (fBuffer != null) {
499             Rectangle r= fBuffer.getBounds();
500             if (r.width != size.x || r.height != size.y) {
501                 fBuffer.dispose();
502                 fBuffer= null;
503             }
504         }
505         if (fBuffer == null)
506             fBuffer= new Image(fCanvas.getDisplay(), size.x, size.y);
507
508         GC gc= new GC(fBuffer);
509         gc.setFont(fCachedTextWidget.getFont());
510         try {
511             gc.setBackground(fCanvas.getBackground());
512             gc.fillRectangle(0, 0, size.x, size.y);
513
514             if (fCachedTextViewer instanceof ITextViewerExtension5)
515                 doPaint1(gc);
516             else
517                 doPaint(gc);
518         } finally {
519             gc.dispose();
520         }
521
522         dest.drawImage(fBuffer, 0, 0);
523     }
524
525     /**
526      * Returns the document offset of the upper left corner of the source viewer's
527      * view port, possibly including partially visible lines.
528      *
529      * @return document offset of the upper left corner including partially visible lines
530      */

531     protected int getInclusiveTopIndexStartOffset() {
532         if (fCachedTextWidget == null || fCachedTextWidget.isDisposed())
533             return -1;
534         
535         IDocument document= fCachedTextViewer.getDocument();
536         if (document == null)
537             return -1;
538         
539         int top= JFaceTextUtil.getPartialTopIndex(fCachedTextViewer);
540         try {
541             return document.getLineOffset(top);
542         } catch (BadLocationException x) {
543             return -1;
544         }
545     }
546
547     /**
548      * Returns the first invisible document offset of the lower right corner of the source viewer's view port,
549      * possibly including partially visible lines.
550      *
551      * @return the first invisible document offset of the lower right corner of the view port
552      */

553     private int getExclusiveBottomIndexEndOffset() {
554         if (fCachedTextWidget == null || fCachedTextWidget.isDisposed())
555             return -1;
556         
557         IDocument document= fCachedTextViewer.getDocument();
558         if (document == null)
559             return -1;
560         
561         int bottom= JFaceTextUtil.getPartialBottomIndex(fCachedTextViewer);
562         try {
563             if (bottom >= document.getNumberOfLines())
564                 bottom= document.getNumberOfLines() - 1;
565             return document.getLineOffset(bottom) + document.getLineLength(bottom);
566         } catch (BadLocationException x) {
567             return -1;
568         }
569     }
570
571     /**
572      * Draws the vertical ruler w/o drawing the Canvas background.
573      *
574      * @param gc the GC to draw into
575      */

576     protected void doPaint(GC gc) {
577
578         if (fModel == null || fCachedTextViewer == null)
579             return;
580
581         int topLeft= getInclusiveTopIndexStartOffset();
582         int bottomRight;
583
584         IRegion coverage= null;
585         if (fCachedTextViewer instanceof ITextViewerExtension5) {
586             ITextViewerExtension5 extension= (ITextViewerExtension5) fCachedTextViewer;
587             coverage= extension.getModelCoverage();
588         } else if (fCachedTextViewer instanceof TextViewer) {
589             // TODO remove once TextViewer implements ITextViewerExtension5
590
TextViewer extension= (TextViewer) fCachedTextViewer;
591             coverage= extension.getModelCoverage();
592         }
593
594         if (coverage != null)
595             bottomRight= coverage.getOffset() + coverage.getLength();
596         else {
597             // http://dev.eclipse.org/bugs/show_bug.cgi?id=14938
598
// http://dev.eclipse.org/bugs/show_bug.cgi?id=22487
599
// add 1 as getBottomIndexEndOffset returns the inclusive offset, but we want the exclusive offset (right after the last character)
600
bottomRight= fCachedTextViewer.getBottomIndexEndOffset() + 1;
601         }
602         int viewPort= bottomRight - topLeft;
603
604         fScrollPos= fCachedTextWidget.getTopPixel();
605         Point dimension= fCanvas.getSize();
606
607         IDocument doc= fCachedTextViewer.getDocument();
608         if (doc == null)
609             return;
610
611         int topLine= -1, bottomLine= -1;
612         try {
613             IRegion region= fCachedTextViewer.getVisibleRegion();
614             topLine= doc.getLineOfOffset(region.getOffset());
615             bottomLine= doc.getLineOfOffset(region.getOffset() + region.getLength());
616         } catch (BadLocationException x) {
617             return;
618         }
619
620         // draw Annotations
621
Rectangle r= new Rectangle(0, 0, 0, 0);
622         int maxLayer= 1; // loop at least once through layers.
623

624         for (int layer= 0; layer < maxLayer; layer++) {
625             Iterator JavaDoc iter= fModel.getAnnotationIterator();
626             while (iter.hasNext()) {
627                 Annotation annotation= (Annotation) iter.next();
628
629                 int lay= IAnnotationAccessExtension.DEFAULT_LAYER;
630                 if (fAnnotationAccessExtension != null)
631                     lay= fAnnotationAccessExtension.getLayer(annotation);
632                 maxLayer= Math.max(maxLayer, lay+1); // dynamically update layer maximum
633
if (lay != layer) // wrong layer: skip annotation
634
continue;
635
636                 if (skip(annotation))
637                     continue;
638
639                 Position position= fModel.getPosition(annotation);
640                 if (position == null)
641                     continue;
642
643                 // https://bugs.eclipse.org/bugs/show_bug.cgi?id=20284
644
// Position.overlapsWith returns false if the position just starts at the end
645
// of the specified range. If the position has zero length, we want to include it anyhow
646
int viewPortSize= position.getLength() == 0 ? viewPort + 1 : viewPort;
647                 if (!position.overlapsWith(topLeft, viewPortSize))
648                     continue;
649
650                 try {
651
652                     int offset= position.getOffset();
653                     int length= position.getLength();
654
655                     int startLine= doc.getLineOfOffset(offset);
656                     if (startLine < topLine)
657                         startLine= topLine;
658
659                     int endLine= startLine;
660                     if (length > 0)
661                         endLine= doc.getLineOfOffset(offset + length - 1);
662                     if (endLine > bottomLine)
663                         endLine= bottomLine;
664
665                     startLine -= topLine;
666                     endLine -= topLine;
667
668                     r.x= 0;
669                     r.y= JFaceTextUtil.computeLineHeight(fCachedTextWidget, 0, startLine, startLine) - fScrollPos;
670                     
671                     r.width= dimension.x;
672                     int lines= endLine - startLine;
673                     
674                     r.height= JFaceTextUtil.computeLineHeight(fCachedTextWidget, startLine, endLine + 1, lines + 1);
675
676                     if (r.y < dimension.y && fAnnotationAccessExtension != null) // annotation within visible area
677
fAnnotationAccessExtension.paint(annotation, gc, fCanvas, r);
678
679                 } catch (BadLocationException x) {
680                 }
681             }
682         }
683     }
684
685     /**
686      * Draws the vertical ruler w/o drawing the Canvas background. Implementation based
687      * on <code>ITextViewerExtension5</code>. Will replace <code>doPaint(GC)</code>.
688      *
689      * @param gc the GC to draw into
690      */

691     protected void doPaint1(GC gc) {
692
693         if (fModel == null || fCachedTextViewer == null)
694             return;
695
696         ITextViewerExtension5 extension= (ITextViewerExtension5) fCachedTextViewer;
697
698         fScrollPos= fCachedTextWidget.getTopPixel();
699         Point dimension= fCanvas.getSize();
700
701         int vOffset= getInclusiveTopIndexStartOffset();
702         int vLength= getExclusiveBottomIndexEndOffset() - vOffset;
703
704         // draw Annotations
705
Rectangle r= new Rectangle(0, 0, 0, 0);
706         ReusableRegion range= new ReusableRegion();
707
708         int minLayer= Integer.MAX_VALUE, maxLayer= Integer.MIN_VALUE;
709         fCachedAnnotations.clear();
710         Iterator JavaDoc iter= fModel.getAnnotationIterator();
711         while (iter.hasNext()) {
712             Annotation annotation= (Annotation) iter.next();
713
714             if (skip(annotation))
715                 continue;
716
717             Position position= fModel.getPosition(annotation);
718             if (position == null)
719                 continue;
720
721             if (!position.overlapsWith(vOffset, vLength))
722                 continue;
723
724             int lay= IAnnotationAccessExtension.DEFAULT_LAYER;
725             if (fAnnotationAccessExtension != null)
726                 lay= fAnnotationAccessExtension.getLayer(annotation);
727
728             minLayer= Math.min(minLayer, lay);
729             maxLayer= Math.max(maxLayer, lay);
730             fCachedAnnotations.add(new Tuple(annotation, position));
731         }
732         Collections.sort(fCachedAnnotations, fTupleComparator);
733
734         for (int layer= minLayer; layer <= maxLayer; layer++) {
735             for (int i= 0, n= fCachedAnnotations.size(); i < n; i++) {
736                 Tuple tuple= (Tuple) fCachedAnnotations.get(i);
737                 Annotation annotation= tuple.annotation;
738                 Position position= tuple.position;
739
740                 int lay= IAnnotationAccessExtension.DEFAULT_LAYER;
741                 if (fAnnotationAccessExtension != null)
742                     lay= fAnnotationAccessExtension.getLayer(annotation);
743                 if (lay != layer) // wrong layer: skip annotation
744
continue;
745
746                 range.setOffset(position.getOffset());
747                 range.setLength(position.getLength());
748                 IRegion widgetRegion= extension.modelRange2WidgetRange(range);
749                 if (widgetRegion == null)
750                     continue;
751
752                 int startLine= extension.widgetLineOfWidgetOffset(widgetRegion.getOffset());
753                 if (startLine == -1)
754                     continue;
755
756                 int endLine= extension.widgetLineOfWidgetOffset(widgetRegion.getOffset() + Math.max(widgetRegion.getLength() -1, 0));
757                 if (endLine == -1)
758                     continue;
759
760                 r.x= 0;
761                 r.y= JFaceTextUtil.computeLineHeight(fCachedTextWidget, 0, startLine, startLine) - fScrollPos;
762                 
763                 r.width= dimension.x;
764                 int lines= endLine - startLine;
765                 r.height= JFaceTextUtil.computeLineHeight(fCachedTextWidget, startLine, endLine + 1, lines + 1);
766
767                 if (r.y < dimension.y && fAnnotationAccessExtension != null) // annotation within visible area
768
fAnnotationAccessExtension.paint(annotation, gc, fCanvas, r);
769             }
770         }
771
772         fCachedAnnotations.clear();
773     }
774
775
776     /**
777      * Post a redraw request for this column into the UI thread.
778      */

779     private void postRedraw() {
780         if (fCanvas != null && !fCanvas.isDisposed()) {
781             Display d= fCanvas.getDisplay();
782             if (d != null) {
783                 d.asyncExec(new Runnable JavaDoc() {
784                     public void run() {
785                         redraw();
786                     }
787                 });
788             }
789         }
790     }
791
792     /*
793      * @see IVerticalRulerColumn#redraw()
794      */

795     public void redraw() {
796         if (fCanvas != null && !fCanvas.isDisposed()) {
797             GC gc= new GC(fCanvas);
798             doubleBufferPaint(gc);
799             gc.dispose();
800         }
801     }
802
803     /*
804      * @see IVerticalRulerColumn#setModel
805      */

806     public void setModel(IAnnotationModel model) {
807         if (fAllowSetModel && model != fModel) {
808
809             if (fModel != null)
810                 fModel.removeAnnotationModelListener(fInternalListener);
811
812             fModel= model;
813
814             if (fModel != null)
815                 fModel.addAnnotationModelListener(fInternalListener);
816
817             postRedraw();
818         }
819     }
820
821     /*
822      * @see IVerticalRulerColumn#setFont(Font)
823      */

824     public void setFont(Font font) {
825     }
826
827     /**
828      * Returns the cached text viewer.
829      *
830      * @return the cached text viewer
831      */

832     protected ITextViewer getCachedTextViewer() {
833         return fCachedTextViewer;
834     }
835
836     /*
837      * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#getModel()
838      */

839     public IAnnotationModel getModel() {
840         return fModel;
841     }
842
843     /**
844      * Adds the given annotation type to this annotation ruler column. Starting
845      * with this call, annotations of the given type are shown in this annotation
846      * ruler column.
847      *
848      * @param annotationType the annotation type
849      * @since 3.0
850      */

851     public void addAnnotationType(Object JavaDoc annotationType) {
852         fConfiguredAnnotationTypes.add(annotationType);
853         fAllowedAnnotationTypes.clear();
854     }
855
856     /*
857      * @see org.eclipse.jface.text.source.IVerticalRulerInfo#getLineOfLastMouseButtonActivity()
858      * @since 3.0
859      */

860     public int getLineOfLastMouseButtonActivity() {
861         return fParentRuler.getLineOfLastMouseButtonActivity();
862     }
863
864     /*
865      * @see org.eclipse.jface.text.source.IVerticalRulerInfo#toDocumentLineNumber(int)
866      * @since 3.0
867      */

868     public int toDocumentLineNumber(int y_coordinate) {
869         return fParentRuler.toDocumentLineNumber(y_coordinate);
870     }
871     
872     /**
873      * Removes the given annotation type from this annotation ruler column.
874      * Annotations of the given type are no longer shown in this annotation
875      * ruler column.
876      *
877      * @param annotationType the annotation type
878      * @since 3.0
879      */

880     public void removeAnnotationType(Object JavaDoc annotationType) {
881         fConfiguredAnnotationTypes.remove(annotationType);
882         fAllowedAnnotationTypes.clear();
883     }
884
885     /**
886      * Returns whether the given annotation should be skipped by the drawing
887      * routine.
888      *
889      * @param annotation the annotation
890      * @return <code>true</code> if annotation of the given type should be
891      * skipped, <code>false</code> otherwise
892      * @since 3.0
893      */

894     private boolean skip(Annotation annotation) {
895         Object JavaDoc annotationType= annotation.getType();
896         Boolean JavaDoc allowed= (Boolean JavaDoc) fAllowedAnnotationTypes.get(annotationType);
897         if (allowed != null)
898             return !allowed.booleanValue();
899
900         boolean skip= skip(annotationType);
901         fAllowedAnnotationTypes.put(annotationType, !skip ? Boolean.TRUE : Boolean.FALSE);
902         return skip;
903     }
904
905     /**
906      * Computes whether the annotation of the given type should be skipped or
907      * not.
908      *
909      * @param annotationType the annotation type
910      * @return <code>true</code> if annotation should be skipped, <code>false</code>
911      * otherwise
912      * @since 3.0
913      */

914     private boolean skip(Object JavaDoc annotationType) {
915         if (fAnnotationAccessExtension != null) {
916             Iterator JavaDoc e= fConfiguredAnnotationTypes.iterator();
917             while (e.hasNext()) {
918                 if (fAnnotationAccessExtension.isSubtype(annotationType, e.next()))
919                     return false;
920             }
921             return true;
922         }
923         return !fConfiguredAnnotationTypes.contains(annotationType);
924     }
925
926     /*
927      * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#getHover()
928      * @since 3.0
929      */

930     public IAnnotationHover getHover() {
931         return fHover;
932     }
933
934     /**
935      * @param hover The hover to set.
936      * @since 3.0
937      */

938     public void setHover(IAnnotationHover hover) {
939         fHover= hover;
940     }
941
942     /*
943      * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#addVerticalRulerListener(org.eclipse.jface.text.source.IVerticalRulerListener)
944      * @since 3.0
945      */

946     public void addVerticalRulerListener(IVerticalRulerListener listener) {
947         throw new UnsupportedOperationException JavaDoc();
948     }
949
950     /*
951      * @see org.eclipse.jface.text.source.IVerticalRulerInfoExtension#removeVerticalRulerListener(org.eclipse.jface.text.source.IVerticalRulerListener)
952      * @since 3.0
953      */

954     public void removeVerticalRulerListener(IVerticalRulerListener listener) {
955         throw new UnsupportedOperationException JavaDoc();
956     }
957 }
958
Popular Tags