KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > sourceViewer > NavigableTextPane


1 /*
2  * FindBugs - Find Bugs in Java programs
3  * Copyright (C) 2006, University of Maryland
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307, USA
18  */

19
20 package edu.umd.cs.findbugs.sourceViewer;
21
22 import java.awt.Rectangle JavaDoc;
23 import java.awt.Container JavaDoc;
24 import java.util.Comparator JavaDoc;
25 import java.util.PriorityQueue JavaDoc;
26 import java.util.Collection JavaDoc;
27 import javax.swing.JTextPane JavaDoc;
28 import javax.swing.JViewport JavaDoc;
29 import javax.swing.SwingUtilities JavaDoc;
30 import javax.swing.text.BadLocationException JavaDoc;
31 import javax.swing.text.Document JavaDoc;
32 import javax.swing.text.Element JavaDoc;
33 import javax.swing.text.StyledDocument JavaDoc;
34
35 import edu.umd.cs.findbugs.gui2.MainFrame;
36
37 /**
38  * @author tuc
39  */

40 public class NavigableTextPane extends JTextPane JavaDoc {
41
42     public NavigableTextPane() {
43     }
44
45     public NavigableTextPane(StyledDocument JavaDoc doc) {
46         super(doc);
47     }
48     
49     /** return the height of the parent (which is presumably a JViewport).
50      * If there is no parent, return this.getHeight(). */

51     private int parentHeight() {
52         Container JavaDoc parent = getParent();
53         if (parent != null) return parent.getHeight();
54         return getHeight(); // entire pane height, may be huge
55
}
56     
57     public int getLineOffset(int line) throws BadLocationException JavaDoc {
58         return lineToOffset(line);
59     }
60     
61     private int lineToOffset(int line) throws BadLocationException JavaDoc {
62         Document JavaDoc d = getDocument();
63         try {
64             Element JavaDoc element = d.getDefaultRootElement().getElement(line-1);
65             if (element == null) throw new BadLocationException JavaDoc("line "+line+" does not exist", -line);
66             return element.getStartOffset();
67         }
68         catch (ArrayIndexOutOfBoundsException JavaDoc aioobe) {
69             BadLocationException JavaDoc ble = new BadLocationException JavaDoc("line "+line+" does not exist", -line);
70             ble.initCause(aioobe);
71             throw ble;
72         }
73     }
74
75     private int offsetToY(int offset) throws BadLocationException JavaDoc {
76         Rectangle JavaDoc r = modelToView(offset);
77         return r.y;
78     }
79     
80     private int lineToY(int line) throws BadLocationException JavaDoc {
81         return offsetToY( lineToOffset(line) );
82     }
83     
84     private void scrollYToVisibleImpl(int y, int margin) {
85         final Rectangle JavaDoc r = new Rectangle JavaDoc(0, y-margin, 4, 2*margin);
86             
87         SwingUtilities.invokeLater(
88             new Runnable JavaDoc() {
89                 public void run() {
90                     scrollRectToVisible(r);
91                 }
92             });
93     }
94     
95     private void scrollLineToVisibleImpl(int line, int margin) {
96         try {
97             int y = lineToY(line);
98             scrollYToVisibleImpl(y, margin);
99         } catch (BadLocationException JavaDoc ble) {
100             if (MainFrame.DEBUG) ble.printStackTrace();
101         }
102     }
103     
104     /** scroll the specified line into view, with a margin of 'margin' pixels above and below */
105     public void scrollLineToVisible(int line, int margin) {
106         int maxMargin = (parentHeight() - 20) / 2;
107         if (margin > maxMargin) margin = Math.max(0, maxMargin);
108         scrollLineToVisibleImpl(line, margin);
109     }
110     
111     /** scroll the specified line into the middle third of the view */
112     public void scrollLineToVisible(int line) {
113         int margin = parentHeight() / 3;
114         scrollLineToVisibleImpl(line, margin);
115     }
116     
117     /** scroll the specified primary lines into view, along
118      * with as many of the other lines as is convenient */

119     public void scrollLinesToVisible(int startLine, int endLine, Collection JavaDoc<Integer JavaDoc> otherLines) {
120         int startY, endY;
121         try {
122             startY = lineToY(startLine);
123         } catch (BadLocationException JavaDoc ble) {
124             if (MainFrame.DEBUG) ble.printStackTrace();
125             return; // give up
126
}
127         try {
128             endY = lineToY(endLine);
129         } catch (BadLocationException JavaDoc ble) {
130             endY = startY; // better than nothing
131
}
132         
133         int max = parentHeight() - 0;
134         if (endY-startY > max) {
135             endY = startY+max;
136         }
137         else if (otherLines!=null && otherLines.size() > 0) {
138             int origin = startY + endY / 2;
139             PriorityQueue JavaDoc<Integer JavaDoc> pq = new PriorityQueue JavaDoc<Integer JavaDoc>(otherLines.size(), new DistanceComparator(origin));
140             for (int line : otherLines) {
141                 int otherY;
142                 try {
143                     otherY = lineToY(line);
144                 } catch (BadLocationException JavaDoc ble) {
145                     continue; // give up on this one
146
}
147                 pq.add(otherY);
148             }
149         
150             while ( !pq.isEmpty() ) {
151                 int y = pq.remove();
152                 int lo = Math.min(startY, y);
153                 int hi = Math.max(endY, y);
154                 if (hi-lo > max) break;
155                 else {
156                     startY = lo;
157                     endY = hi;
158                 }
159             }
160         }
161         scrollYToVisibleImpl((startY+endY)/2, max/2);
162     }
163     
164     public static class DistanceComparator implements Comparator JavaDoc<Integer JavaDoc> {
165         private final int origin;
166         public DistanceComparator(int origin) {
167             this.origin = origin;
168         }
169         /* Returns a negative integer, zero, or a positive integer as
170          * the first argument is farther from, equadistant, or closer
171          * to (respectively) the origin.
172          * This sounds backwards, but this way closer values get a
173          * higher priority in the priority queue. */

174         public int compare(Integer JavaDoc a, Integer JavaDoc b) {
175             return Math.abs(b-origin) - Math.abs(a-origin);
176         }
177     }
178     
179 }
180
Popular Tags