1 19 20 package edu.umd.cs.findbugs.sourceViewer; 21 22 import java.awt.Rectangle ; 23 import java.awt.Container ; 24 import java.util.Comparator ; 25 import java.util.PriorityQueue ; 26 import java.util.Collection ; 27 import javax.swing.JTextPane ; 28 import javax.swing.JViewport ; 29 import javax.swing.SwingUtilities ; 30 import javax.swing.text.BadLocationException ; 31 import javax.swing.text.Document ; 32 import javax.swing.text.Element ; 33 import javax.swing.text.StyledDocument ; 34 35 import edu.umd.cs.findbugs.gui2.MainFrame; 36 37 40 public class NavigableTextPane extends JTextPane { 41 42 public NavigableTextPane() { 43 } 44 45 public NavigableTextPane(StyledDocument doc) { 46 super(doc); 47 } 48 49 51 private int parentHeight() { 52 Container parent = getParent(); 53 if (parent != null) return parent.getHeight(); 54 return getHeight(); } 56 57 public int getLineOffset(int line) throws BadLocationException { 58 return lineToOffset(line); 59 } 60 61 private int lineToOffset(int line) throws BadLocationException { 62 Document d = getDocument(); 63 try { 64 Element element = d.getDefaultRootElement().getElement(line-1); 65 if (element == null) throw new BadLocationException ("line "+line+" does not exist", -line); 66 return element.getStartOffset(); 67 } 68 catch (ArrayIndexOutOfBoundsException aioobe) { 69 BadLocationException ble = new BadLocationException ("line "+line+" does not exist", -line); 70 ble.initCause(aioobe); 71 throw ble; 72 } 73 } 74 75 private int offsetToY(int offset) throws BadLocationException { 76 Rectangle r = modelToView(offset); 77 return r.y; 78 } 79 80 private int lineToY(int line) throws BadLocationException { 81 return offsetToY( lineToOffset(line) ); 82 } 83 84 private void scrollYToVisibleImpl(int y, int margin) { 85 final Rectangle r = new Rectangle (0, y-margin, 4, 2*margin); 86 87 SwingUtilities.invokeLater( 88 new Runnable () { 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 ble) { 100 if (MainFrame.DEBUG) ble.printStackTrace(); 101 } 102 } 103 104 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 112 public void scrollLineToVisible(int line) { 113 int margin = parentHeight() / 3; 114 scrollLineToVisibleImpl(line, margin); 115 } 116 117 119 public void scrollLinesToVisible(int startLine, int endLine, Collection <Integer > otherLines) { 120 int startY, endY; 121 try { 122 startY = lineToY(startLine); 123 } catch (BadLocationException ble) { 124 if (MainFrame.DEBUG) ble.printStackTrace(); 125 return; } 127 try { 128 endY = lineToY(endLine); 129 } catch (BadLocationException ble) { 130 endY = startY; } 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 <Integer > pq = new PriorityQueue <Integer >(otherLines.size(), new DistanceComparator(origin)); 140 for (int line : otherLines) { 141 int otherY; 142 try { 143 otherY = lineToY(line); 144 } catch (BadLocationException ble) { 145 continue; } 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 <Integer > { 165 private final int origin; 166 public DistanceComparator(int origin) { 167 this.origin = origin; 168 } 169 174 public int compare(Integer a, Integer b) { 175 return Math.abs(b-origin) - Math.abs(a-origin); 176 } 177 } 178 179 } 180 | Popular Tags |