KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > editor > errorstripe > AnnotationView


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.editor.errorstripe;
21
22 import java.awt.Color JavaDoc;
23 import java.awt.Component JavaDoc;
24 import java.awt.Cursor JavaDoc;
25 import java.awt.Dimension JavaDoc;
26 import java.awt.Graphics JavaDoc;
27 import java.awt.Insets JavaDoc;
28 import java.awt.Point JavaDoc;
29 import java.awt.Rectangle JavaDoc;
30 import java.awt.event.MouseEvent JavaDoc;
31 import java.awt.event.MouseListener JavaDoc;
32 import java.awt.event.MouseMotionListener JavaDoc;
33 import java.beans.PropertyChangeEvent JavaDoc;
34 import java.beans.PropertyChangeListener JavaDoc;
35 import java.text.MessageFormat JavaDoc;
36 import javax.swing.Icon JavaDoc;
37 import javax.swing.ImageIcon JavaDoc;
38 import javax.swing.JComponent JavaDoc;
39 import javax.swing.JScrollPane JavaDoc;
40 import javax.swing.SwingUtilities JavaDoc;
41 import javax.swing.UIManager JavaDoc;
42 import javax.swing.event.DocumentEvent JavaDoc;
43 import javax.swing.event.DocumentListener JavaDoc;
44 import javax.swing.plaf.TextUI JavaDoc;
45 import javax.swing.text.BadLocationException JavaDoc;
46 import javax.swing.text.Document JavaDoc;
47 import javax.swing.text.JTextComponent JavaDoc;
48 import javax.swing.text.StyledDocument JavaDoc;
49 import javax.swing.text.View JavaDoc;
50 import org.netbeans.api.editor.fold.FoldHierarchy;
51 import org.netbeans.api.editor.fold.FoldHierarchyEvent;
52 import org.netbeans.api.editor.fold.FoldHierarchyListener;
53
54 import org.netbeans.editor.BaseDocument;
55 import org.netbeans.editor.BaseTextUI;
56 import org.netbeans.editor.Utilities;
57 import org.netbeans.modules.editor.errorstripe.caret.CaretMark;
58 import org.netbeans.modules.editor.errorstripe.privatespi.Mark;
59 import org.netbeans.spi.editor.errorstripe.UpToDateStatus;
60 import org.openide.ErrorManager;
61 import org.netbeans.modules.editor.errorstripe.privatespi.Status;
62 import org.openide.text.NbDocument;
63 import org.openide.util.NbBundle;
64 import org.openide.util.RequestProcessor;
65
66
67 /**
68  *
69  * @author Jan Lahoda
70  */

71 public class AnnotationView extends JComponent JavaDoc implements FoldHierarchyListener, MouseListener JavaDoc, MouseMotionListener JavaDoc, DocumentListener JavaDoc, PropertyChangeListener JavaDoc {
72     
73     /*package private*/ static final ErrorManager ERR = ErrorManager.getDefault().getInstance("org.netbeans.modules.editor.errorstripe.AnnotationView"); // NOI18N
74

75     /*package private*/ static final ErrorManager TIMING_ERR = ErrorManager.getDefault().getInstance("org.netbeans.modules.editor.errorstripe.AnnotationView.timing"); // NOI18N
76

77     private static final int STATUS_BOX_SIZE = 7;
78     private static final int THICKNESS = STATUS_BOX_SIZE + 6;
79     /*package private*/ static final int PIXELS_FOR_LINE = 3/*height / lines*/;
80     /*package private*/ static final int LINE_SEPARATOR_SIZE = 1/*2*/;
81     /*package private*/ static final int HEIGHT_OFFSET = 20;
82     
83     /*package private*/ static final int UPPER_HANDLE = 4;
84     /*package private*/ static final int LOWER_HANDLE = 4;
85     
86     private BaseDocument doc;
87     private JTextComponent JavaDoc pane;
88     
89     private static final Color JavaDoc STATUS_UP_PART_COLOR = Color.WHITE;
90     private static final Color JavaDoc STATUS_DOWN_PART_COLOR = new Color JavaDoc(0xCDCABB);
91     
92     private static final int QUIET_TIME = 100;
93     
94     private final RequestProcessor.Task repaintTask;
95     private final RepaintTask repaintTaskRunnable;
96     
97     private AnnotationViewData data;
98     
99     private static Icon JavaDoc busyIcon;
100     
101     static {
102         busyIcon = new ImageIcon JavaDoc(AnnotationView.class.getResource("resources/hodiny.gif"));
103     }
104     
105 // public AnnotationView(JTextComponent pane) {
106
// this(pane, null);
107
// }
108

109     /** Creates a new instance of AnnotationViewBorder */
110     public AnnotationView(JTextComponent JavaDoc pane/*, List/ *<MarkProviderCreator>* / creators*/) {
111         this.pane = pane;
112         
113         FoldHierarchy.get(pane).addFoldHierarchyListener(this);
114         
115         pane.addPropertyChangeListener(this);
116         
117         repaintTask = RequestProcessor.getDefault().create(repaintTaskRunnable = new RepaintTask());
118         
119         data = new AnnotationViewDataImpl(this, pane);
120         
121         updateForNewDocument();
122         
123         addMouseListener(this);
124         addMouseMotionListener(this);
125         
126         setOpaque(true);
127         
128         setToolTipText(org.openide.util.NbBundle.getBundle(AnnotationView.class).getString("TP_ErrorStripe"));
129     }
130     
131     /*package private for tests*/AnnotationViewData getData() {
132         return data;
133     }
134     
135     private synchronized void updateForNewDocument() {
136         data.unregister();
137         Document JavaDoc newDocument = pane.getDocument();
138         
139         if (this.doc != null) {
140             this.doc.removeDocumentListener(this);
141             this.doc = null;
142         }
143         
144         if (newDocument instanceof BaseDocument) {
145             this.doc = (BaseDocument) pane.getDocument();
146             this.doc.addDocumentListener(this);
147         }
148         
149         data.register(this.doc);
150     }
151         
152     /*package private for tests*/int[] getLinesSpan(int currentLine) {
153         double position = modelToView(currentLine);
154         
155         if (position == (-1))
156             return new int[] {currentLine, currentLine};
157             
158         int startLine = currentLine;
159         int endLine = currentLine;
160         
161         while (position == modelToView(startLine - 1) && startLine > 0)
162             startLine--;
163         
164         while ((endLine + 1) < Utilities.getRowCount(doc) && position == modelToView(endLine + 1))
165             endLine++;
166         
167         return new int[] {startLine, endLine};
168     }
169     
170     private void drawOneColorGlobalStatus(Graphics JavaDoc g, Color JavaDoc color) {
171         g.setColor(color);
172         
173         int x = (THICKNESS - STATUS_BOX_SIZE) / 2;
174         int y = (topOffset() - STATUS_BOX_SIZE) / 2;
175         
176         g.fillRect(x, y, STATUS_BOX_SIZE, STATUS_BOX_SIZE);
177         
178         g.setColor(STATUS_DOWN_PART_COLOR);
179         
180         g.drawLine(x - 1, y - 1, x + STATUS_BOX_SIZE, y - 1 );
181         g.drawLine(x - 1, y - 1, x - 1, y + STATUS_BOX_SIZE);
182         
183         g.setColor(STATUS_UP_PART_COLOR);
184         
185         g.drawLine(x - 1, y + STATUS_BOX_SIZE, x + STATUS_BOX_SIZE, y + STATUS_BOX_SIZE);
186         g.drawLine(x + STATUS_BOX_SIZE, y - 1, x + STATUS_BOX_SIZE, y + STATUS_BOX_SIZE);
187     }
188     
189     private void drawInProgressGlobalStatus(Graphics JavaDoc g, Color JavaDoc color) {
190         int x = (THICKNESS - STATUS_BOX_SIZE) / 2;
191         int y = (topOffset() - STATUS_BOX_SIZE) / 2;
192     
193         busyIcon.paintIcon(this, g, x, y); // NOI18N
194

195         g.setColor(STATUS_DOWN_PART_COLOR);
196         
197         g.drawLine(x - 1, y - 1, x + STATUS_BOX_SIZE, y - 1 );
198         g.drawLine(x - 1, y - 1, x - 1, y + STATUS_BOX_SIZE);
199         
200         g.setColor(STATUS_UP_PART_COLOR);
201         
202         g.drawLine(x - 1, y + STATUS_BOX_SIZE, x + STATUS_BOX_SIZE, y + STATUS_BOX_SIZE);
203         g.drawLine(x + STATUS_BOX_SIZE, y - 1, x + STATUS_BOX_SIZE, y + STATUS_BOX_SIZE);
204     
205     }
206     
207     private static final Color JavaDoc GLOBAL_RED = new Color JavaDoc(0xFF2A1C);
208     private static final Color JavaDoc GLOBAL_YELLOW = new Color JavaDoc(0xE1AA00);
209     private static final Color JavaDoc GLOBAL_GREEN = new Color JavaDoc(0x65B56B);
210     
211     private Color JavaDoc getColorForGlobalStatus(Status status) {
212         if (Status.STATUS_ERROR == status)
213             return GLOBAL_RED;
214         
215         if (Status.STATUS_WARNING == status)
216             return GLOBAL_YELLOW;
217         
218         return GLOBAL_GREEN;
219     }
220     
221     private void drawGlobalStatus(Graphics JavaDoc g) {
222         UpToDateStatus type = data.computeTotalStatusType();
223         Color JavaDoc resultingColor;
224         
225         if (type == UpToDateStatus.UP_TO_DATE_DIRTY) {
226                 drawOneColorGlobalStatus(g, UIManager.getColor("Panel.background")); // NOI18N
227
} else {
228             if (type == UpToDateStatus.UP_TO_DATE_PROCESSING) {
229 // Status totalStatus = data.computeTotalStatus();
230
//
231
drawInProgressGlobalStatus(g, null/*Status.getDefaultColor(totalStatus)*/);
232             } else {
233                 if (type == UpToDateStatus.UP_TO_DATE_OK) {
234                     Status totalStatus = data.computeTotalStatus();
235                     
236                     drawOneColorGlobalStatus(g, getColorForGlobalStatus(totalStatus));
237                 } else {
238                     throw new IllegalStateException JavaDoc("Unknown up-to-date type: " + type); // NOI18N
239
}
240             }
241         }
242     }
243     
244     private int getCurrentLine() {
245         int offset = pane.getCaretPosition(); //TODO: AWT?
246
Document JavaDoc doc = pane.getDocument();
247         int line = -1;
248         
249         if (doc instanceof StyledDocument JavaDoc) {
250             line = NbDocument.findLineNumber((StyledDocument JavaDoc) doc, offset);
251         }
252         
253         return line;
254     }
255     
256     public void paintComponent(Graphics JavaDoc g) {
257 // Thread.dumpStack();
258
long startTime = System.currentTimeMillis();
259         super.paintComponent(g);
260         
261         Color JavaDoc oldColor = g.getColor();
262         
263         g.setColor(UIManager.getColor("Panel.background")); // NOI18N
264

265         g.fillRect(0, 0, getWidth(), getHeight());
266         
267 // SortedMap marks = getMarkMap();
268
int currentline = getCurrentLine();
269         int annotatedLine = data.findNextUsedLine(-1);
270         
271         while (annotatedLine != Integer.MAX_VALUE) {
272 // System.err.println("annotatedLine = " + annotatedLine );
273
int[] lineSpan = getLinesSpan(annotatedLine);
274             int startLine = lineSpan[0];
275             int endLine = lineSpan[1];
276             
277             Mark m = data.getMainMarkForBlock(startLine, endLine);
278             
279             if (m != null) {
280                 Status s = m.getStatus();
281                 double start = modelToView(annotatedLine);
282                 
283                 if (s != null) {
284 // System.err.println("m = " + m );
285
Color JavaDoc color = m.getEnhancedColor();
286                     
287                     if (color == null)
288                         color = Status.getDefaultColor(s);
289                     
290                     assert color != null;
291                     
292                     g.setColor(color);
293                     
294                     
295                     //g.fillRect(1, (int) start, THICKNESS - 2, PIXELS_FOR_LINE);
296
//* 3D Version
297
if ( m.getType() != Mark.TYPE_CARET ) {
298                         g.fillRect(1, (int) start , THICKNESS - 2, PIXELS_FOR_LINE);
299                         //g.draw3DRect(1, (int) start, THICKNESS - 3, PIXELS_FOR_LINE - 1, true);
300
}
301                     //*/
302
if ((startLine <= currentline && currentline <= endLine) || m.getType() == Mark.TYPE_CARET ) {
303                         drawCurrentLineMark(g, (int)start);
304                     }
305                 }
306             }
307             
308             annotatedLine = data.findNextUsedLine(endLine);
309         }
310         
311         drawGlobalStatus(g);
312         
313         g.setColor(oldColor);
314         
315         long end = System.currentTimeMillis();
316         
317         if (TIMING_ERR.isLoggable(ErrorManager.INFORMATIONAL)) {
318             TIMING_ERR.log("AnnotationView.paintComponent consumed: " + (end - startTime));
319         }
320     }
321
322     private void drawCurrentLineMark(Graphics JavaDoc g, int start) {
323         g.setColor( CaretMark.getCaretMarkColor());
324         g.drawLine(2, start + PIXELS_FOR_LINE / 2, THICKNESS - 3, start + PIXELS_FOR_LINE / 2 );
325         g.fillRect( THICKNESS / 2 - PIXELS_FOR_LINE / 2, start, PIXELS_FOR_LINE, PIXELS_FOR_LINE );
326         g.draw3DRect( THICKNESS / 2 - PIXELS_FOR_LINE / 2, start, PIXELS_FOR_LINE - 1, PIXELS_FOR_LINE - 1, true );
327         
328     }
329     
330     /*private*/ void fullRepaint() {
331         fullRepaint(false);
332     }
333     
334     /*private*/ void fullRepaint(final boolean clearMarksCache) {
335         fullRepaint(clearMarksCache, false);
336     }
337     
338     /*private*/ void fullRepaint(final boolean clearMarksCache, final boolean clearModelToViewCache) {
339         synchronized (repaintTaskRunnable) {
340             repaintTaskRunnable.setClearMarksCache(clearMarksCache);
341             repaintTaskRunnable.setClearModelToViewCache(clearModelToViewCache);
342             repaintTask.schedule(QUIET_TIME);
343         }
344     }
345     
346     private class RepaintTask implements Runnable JavaDoc {
347         private boolean clearMarksCache;
348         private boolean clearModelToViewCache;
349
350         public void setClearMarksCache(boolean clearMarksCache) {
351             this.clearMarksCache |= clearMarksCache;
352         }
353         
354         public void setClearModelToViewCache(boolean clearModelToViewCache) {
355             this.clearModelToViewCache |= clearModelToViewCache;
356         }
357         
358         private synchronized boolean readAndDestroyClearMarksCache() {
359             boolean result = clearMarksCache;
360             
361             clearMarksCache = false;
362             
363             return result;
364         }
365
366         private synchronized boolean readAndDestroyClearModelToViewCache() {
367             boolean result = clearModelToViewCache;
368             
369             clearModelToViewCache = false;
370             
371             return result;
372         }
373         
374         public void run() {
375             final boolean clearMarksCache = readAndDestroyClearMarksCache();
376             final boolean clearModelToViewCache= readAndDestroyClearModelToViewCache();
377             
378             //Fix for #54193:
379
SwingUtilities.invokeLater(new Runnable JavaDoc() {
380                 public void run() {
381                     synchronized (AnnotationView.this) {
382                         if (clearMarksCache) {
383                             data.clear();
384                         }
385                         if (clearModelToViewCache) {
386                             modelToViewCache = null;
387                         }
388                     }
389                     
390                     invalidate();
391                     repaint();
392                 }
393             });
394         }
395     }
396     
397     private void documentChange() {
398         fullRepaint(lines != Utilities.getRowCount(doc));
399     }
400     
401     private double getComponentHeight() {
402         return pane.getUI().getRootView(pane).getPreferredSpan(View.Y_AXIS);
403     }
404     
405     double getUsableHeight() {
406         //fix for issue #54080:
407
//find the scrollpane which contains the pane:
408
Component JavaDoc scrollPaneCandidade = pane.getParent();
409         
410         if (scrollPaneCandidade != null && !(scrollPaneCandidade instanceof JScrollPane JavaDoc)) {
411             scrollPaneCandidade = scrollPaneCandidade.getParent();
412         }
413         
414         Insets JavaDoc scrollBar = UIManager.getInsets("Nb.Editor.ErrorStripe.ScrollBar.Insets"); // NOI18N
415

416         if (scrollPaneCandidade == null || !(scrollPaneCandidade instanceof JScrollPane JavaDoc) || scrollBar == null) {
417             //no help for #54080:
418
return getHeight() - HEIGHT_OFFSET;
419         }
420         
421         JScrollPane JavaDoc scrollPane = (JScrollPane JavaDoc) scrollPaneCandidade;
422         int visibleHeight = scrollPane.getViewport().getExtentSize().height;
423         
424         int topButton = topOffset();
425         int bottomButton = scrollBar.bottom;
426         
427         return visibleHeight - topButton - bottomButton;
428     }
429     
430     int topOffset() {
431         Insets JavaDoc scrollBar = UIManager.getInsets("Nb.Editor.ErrorStripe.ScrollBar.Insets"); // NOI18N
432

433         if (scrollBar == null) {
434             //no help for #54080:
435
return HEIGHT_OFFSET;
436         }
437         
438         return (HEIGHT_OFFSET > scrollBar.top ? HEIGHT_OFFSET : scrollBar.top) + PIXELS_FOR_LINE;
439     }
440     
441     private int[] modelToViewCache = null;
442     private int lines = -1;
443     private int height = -1;
444     
445     private int getYFromPos(int offset) throws BadLocationException JavaDoc {
446         TextUI JavaDoc ui = pane.getUI();
447         int result;
448         
449         if (ui instanceof BaseTextUI) {
450             result = ((BaseTextUI) ui).getYFromPos(offset);
451         } else {
452             Rectangle JavaDoc r = pane.modelToView(offset);
453             
454             result = r != null ? r.y : 0;
455         }
456         
457         if (result == 0) {
458             return -1;
459         } else {
460             return result;
461         }
462     }
463     
464     private synchronized int getModelToViewImpl(int line) throws BadLocationException JavaDoc {
465         int docLines = Utilities.getRowCount(doc);
466         
467         if (modelToViewCache == null || height != pane.getHeight() || lines != docLines) {
468             modelToViewCache = new int[Utilities.getRowCount(doc) + 2];
469             lines = Utilities.getRowCount(doc);
470             height = pane.getHeight();
471         }
472         
473         if (line >= docLines)
474             return -1;
475         
476         int result = modelToViewCache[line + 1];
477         
478         if (result == 0) {
479             int lineOffset = Utilities.getRowStartFromLineOffset((BaseDocument) pane.getDocument(), line);
480             
481             modelToViewCache[line + 1] = result = getYFromPos(lineOffset);
482         }
483         
484         if (result == (-1))
485             result = 0;
486         
487         return result;
488     }
489     
490     /*package private*/ double modelToView(int line) {
491         try {
492             int r = getModelToViewImpl(line);
493             
494             if (r == (-1))
495                 return -1.0;
496             
497             if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) {
498                 ERR.log(ErrorManager.INFORMATIONAL, "AnnotationView.modelToView: line=" + line); // NOI18N
499
// ERR.log(ErrorManager.INFORMATIONAL, "AnnotationView.modelToView: lineOffset=" + lineOffset); // NOI18N
500
ERR.log(ErrorManager.INFORMATIONAL, "AnnotationView.modelToView: r=" + r); // NOI18N
501
ERR.log(ErrorManager.INFORMATIONAL, "AnnotationView.modelToView: getComponentHeight()=" + getComponentHeight()); // NOI18N
502
ERR.log(ErrorManager.INFORMATIONAL, "AnnotationView.modelToView: getUsableHeight()=" + getUsableHeight()); // NOI18N
503
}
504             
505             if (getComponentHeight() <= getUsableHeight()) {
506                 //1:1 mapping:
507
return r + topOffset();
508             } else {
509                 double position = r / getComponentHeight();
510                 int blocksCount = (int) (getUsableHeight() / (PIXELS_FOR_LINE + LINE_SEPARATOR_SIZE));
511                 int block = (int) (position * blocksCount);
512                 
513                 return block * (PIXELS_FOR_LINE + LINE_SEPARATOR_SIZE) + topOffset();
514             }
515         } catch (BadLocationException JavaDoc e) {
516             ErrorManager.getDefault().notify(e);
517             return -1.0;
518         }
519     }
520     
521     private static final int VIEW_TO_MODEL_IMPORTANCE = ErrorManager.INFORMATIONAL;
522     
523     /*package private*/ int[] viewToModel(double offset) {
524         try {
525             if (getComponentHeight() <= getUsableHeight()) {
526                 //1:1 mapping:
527
int positionOffset = pane.viewToModel(new Point JavaDoc(1, (int) (offset - topOffset())));
528                 int line = Utilities.getLineOffset(doc, positionOffset);
529                 
530                 if (ERR.isLoggable(VIEW_TO_MODEL_IMPORTANCE)) {
531                     ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.viewToModel: line=" + line); // NOI18N
532
}
533                 
534                 double position = modelToView(line);
535                 
536                 if (offset < position || offset >= (position + PIXELS_FOR_LINE))
537                     return null;
538                 
539                 return getLinesSpan(line);
540             } else {
541                 int blocksCount = (int) (getUsableHeight() / (PIXELS_FOR_LINE + LINE_SEPARATOR_SIZE));
542                 int block = (int) ((offset - topOffset()) / (PIXELS_FOR_LINE + LINE_SEPARATOR_SIZE));
543                 double yPos = (getComponentHeight() * block) / blocksCount;
544                 
545                 if (yPos == (int) yPos)
546                     yPos -= 1;
547                 
548                 int positionOffset = pane.viewToModel(new Point JavaDoc(0, (int) yPos));
549                 int line = Utilities.getLineOffset(doc, positionOffset) + 1;
550                 int[] span = getLinesSpan(line);
551                 double normalizedOffset = modelToView(span[0]);
552                 
553                 if (ERR.isLoggable(VIEW_TO_MODEL_IMPORTANCE)) {
554                     ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.viewToModel: offset=" + offset); // NOI18N
555
ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.viewToModel: block=" + block); // NOI18N
556
ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.viewToModel: blocksCount=" + blocksCount); // NOI18N
557
ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.viewToModel: pane.getHeight()=" + pane.getHeight()); // NOI18N
558
ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.viewToModel: yPos=" + yPos); // NOI18N
559
ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.viewToModel: positionOffset=" + positionOffset); // NOI18N
560
ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.viewToModel: line=" + line); // NOI18N
561
ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.viewToModel: normalizedOffset=" + normalizedOffset); // NOI18N
562
}
563                 
564                 if (offset < normalizedOffset || offset >= (normalizedOffset + PIXELS_FOR_LINE)) {
565                     return null;
566                 }
567                 
568                 if (block < 0)
569                     return null;
570                 
571                 return span;
572             }
573         } catch (BadLocationException JavaDoc e) {
574             ErrorManager.getDefault().notify(e);
575             return null;
576         }
577     }
578     
579     private Mark getMarkForPointImpl(double point) {
580         int[] lineSpan = viewToModel(point);
581         
582         if (lineSpan == null)
583             return null;
584         
585         int startLine = lineSpan[0];
586         int endLine = lineSpan[1];
587         
588         if (startLine != (-1)) {
589             return data.getMainMarkForBlock(startLine, endLine);
590         }
591         
592         return null;
593     }
594
595     /*package private*/ Mark getMarkForPoint(double point) {
596         //Normalize the point:
597
point = ((int) (point / (PIXELS_FOR_LINE + LINE_SEPARATOR_SIZE))) * (PIXELS_FOR_LINE + LINE_SEPARATOR_SIZE);
598         
599         Mark a = getMarkForPointImpl(point);
600         
601         if (ERR.isLoggable(VIEW_TO_MODEL_IMPORTANCE)) {
602             ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.getAnnotationForPoint: point=" + point); // NOI18N
603
ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.getAnnotationForPoint: a=" + a); // NOI18N
604
}
605         
606         int relativeMax = Math.max(UPPER_HANDLE + 1, LOWER_HANDLE + 1);
607         
608         for (short relative = 1; relative < relativeMax && a == null; relative++) {
609             if (relative <= UPPER_HANDLE) {
610                 a = getMarkForPointImpl(point + relative);
611                 
612                 if (ERR.isLoggable(VIEW_TO_MODEL_IMPORTANCE)) {
613                     ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.getAnnotationForPoint: a=" + a); // NOI18N
614
ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.getAnnotationForPoint: relative=" + relative); // NOI18N
615
}
616             }
617             
618             if (relative <= LOWER_HANDLE && a == null) {
619                 a = getMarkForPointImpl(point - relative);
620                 
621                 if (ERR.isLoggable(VIEW_TO_MODEL_IMPORTANCE)) {
622                     ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.getAnnotationForPoint: a=" + a); // NOI18N
623
ERR.log(VIEW_TO_MODEL_IMPORTANCE, "AnnotationView.getAnnotationForPoint: relative=-" + relative); // NOI18N
624
}
625             }
626         }
627         
628         return a;
629     }
630     
631     public Dimension JavaDoc getMaximumSize() {
632         return new Dimension JavaDoc(THICKNESS, Integer.MAX_VALUE);
633     }
634
635     public Dimension JavaDoc getMinimumSize() {
636         return new Dimension JavaDoc(THICKNESS, Integer.MIN_VALUE);
637     }
638
639     public Dimension JavaDoc getPreferredSize() {
640         return new Dimension JavaDoc(THICKNESS, Integer.MAX_VALUE);
641     }
642
643     public void mouseReleased(MouseEvent JavaDoc e) {
644         //NOTHING:
645
resetCursor();
646     }
647
648     public void mousePressed(MouseEvent JavaDoc e) {
649         resetCursor();
650     }
651
652     public void mouseMoved(MouseEvent JavaDoc e) {
653         checkCursor(e);
654     }
655
656     public void mouseExited(MouseEvent JavaDoc e) {
657         resetCursor();
658     }
659
660     public void mouseEntered(MouseEvent JavaDoc e) {
661         checkCursor(e);
662     }
663
664     public void mouseDragged(MouseEvent JavaDoc e) {
665     }
666
667     public void mouseClicked(MouseEvent JavaDoc e) {
668         resetCursor();
669         
670         Mark mark = getMarkForPoint(e.getPoint().getY());
671         
672         if (mark!= null) {
673             pane.setCaretPosition(Utilities.getRowStartFromLineOffset(doc, mark.getAssignedLines()[0]));
674         }
675     }
676     
677     private void resetCursor() {
678         setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
679     }
680     
681     private void checkCursor(MouseEvent JavaDoc e) {
682         Mark mark = getMarkForPoint(e.getPoint().getY());
683         
684         if (mark == null) {
685             resetCursor();
686             return ;
687         }
688         
689         setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
690     }
691
692     public String JavaDoc getToolTipText(MouseEvent JavaDoc event) {
693         if (ERR.isLoggable(ErrorManager.INFORMATIONAL)) {
694             ERR.log(ErrorManager.INFORMATIONAL, "getToolTipText: event=" + event); // NOI18N
695
}
696         int y = event.getY();
697         
698         if (y <= topOffset()) {
699             int[] errWar = data.computeErrorsAndWarnings();
700             int errors = errWar[0];
701             int warnings = errWar[1];
702             
703             if (errors == 0 && warnings == 0) {
704                 return NbBundle.getBundle(AnnotationView.class).getString("TP_NoErrors"); // NOI18N
705
}
706             
707             if (errors == 0 && warnings != 0) {
708                 return MessageFormat.format(NbBundle.getBundle(AnnotationView.class).getString("TP_X_warning(s)"), new Object JavaDoc[] {new Integer JavaDoc(warnings)}); // NOI18N
709
}
710             
711             if (errors != 0 && warnings == 0) {
712                 return MessageFormat.format(NbBundle.getBundle(AnnotationView.class).getString("TP_X_error(s)"), new Object JavaDoc[] {new Integer JavaDoc(errors)}); // NOI18N
713
}
714             
715             return MessageFormat.format(NbBundle.getBundle(AnnotationView.class).getString("TP_X_error(s)_Y_warning(s)"), new Object JavaDoc[] {new Integer JavaDoc(errors), new Integer JavaDoc(warnings)}); // NOI18N
716
}
717         
718         Mark mark = getMarkForPoint(y);
719         
720         if (mark != null) {
721             String JavaDoc description = mark.getShortDescription();
722             
723             if (description != null) {
724                 return "<html><body>" + translate(description); // NOI18N
725
}
726         }
727         
728         return null;
729     }
730     
731     private static String JavaDoc[] c = new String JavaDoc[] {"&", "<", ">", "\n", "\""}; // NOI18N
732
private static String JavaDoc[] tags = new String JavaDoc[] {"&amp;", "&lt;", "&gt;", "<br>", "&quot;"}; // NOI18N
733

734     private String JavaDoc translate(String JavaDoc input) {
735         for (int cntr = 0; cntr < c.length; cntr++) {
736             input = input.replaceAll(c[cntr], tags[cntr]);
737         }
738         
739         return input;
740     }
741
742     public void foldHierarchyChanged(FoldHierarchyEvent evt) {
743         //fix for #63402: clear the modelToViewCache after folds changed:
744
//#64498: do not take monitor on this here:
745
fullRepaint(false, true);
746     }
747
748     public void removeUpdate(DocumentEvent JavaDoc e) {
749         documentChange();
750     }
751     
752     public void insertUpdate(DocumentEvent JavaDoc e) {
753         documentChange();
754     }
755     
756     public void changedUpdate(DocumentEvent JavaDoc e) {
757         //ignored...
758
}
759
760     public void propertyChange(PropertyChangeEvent JavaDoc evt) {
761         if (evt.getSource() == this.pane && "document".equals(evt.getPropertyName())) {
762             updateForNewDocument();
763             return ;
764         }
765         
766         fullRepaint();
767     }
768     
769 }
770
Popular Tags