source: other-projects/rsyntax-textarea/src/java/org/fife/ui/rsyntaxtextarea/FoldingAwareIconRowHeader.java@ 25584

Last change on this file since 25584 was 25584, checked in by davidb, 12 years ago

Initial cut an a text edit area for GLI that supports color syntax highlighting

File size: 6.8 KB
Line 
1/*
2 * 03/07/2012
3 *
4 * FoldingAwareIconRowHeader - Icon row header that paints itself correctly
5 * even when code folding is enabled.
6 *
7 * This library is distributed under a modified BSD license. See the included
8 * RSyntaxTextArea.License.txt file for details.
9 */
10package org.fife.ui.rsyntaxtextarea;
11
12import java.awt.Color;
13import java.awt.Graphics;
14import java.awt.Point;
15import javax.swing.Icon;
16import javax.swing.text.BadLocationException;
17import javax.swing.text.Document;
18import javax.swing.text.Element;
19
20import org.fife.ui.rsyntaxtextarea.folding.FoldManager;
21import org.fife.ui.rtextarea.GutterIconInfo;
22import org.fife.ui.rtextarea.IconRowHeader;
23
24
25/**
26 * A row header component that takes code folding into account when painting
27 * itself.
28 *
29 * @author Robert Futrell
30 * @version 1.0
31 */
32public class FoldingAwareIconRowHeader extends IconRowHeader {
33
34
35 /**
36 * Constructor.
37 *
38 * @param textArea The parent text area.
39 */
40 public FoldingAwareIconRowHeader(RSyntaxTextArea textArea) {
41 super(textArea);
42 }
43
44
45 /**
46 * {@inheritDoc}
47 */
48 protected void paintComponent(Graphics g) {
49
50 // When line wrap is not enabled, take the faster code path.
51 if (textArea==null) {
52 return;
53 }
54 RSyntaxTextArea rsta = (RSyntaxTextArea)textArea;
55 FoldManager fm = rsta.getFoldManager();
56 if (!fm.isCodeFoldingSupportedAndEnabled()) {
57 super.paintComponent(g);
58 return;
59 }
60
61 visibleRect = g.getClipBounds(visibleRect);
62 if (visibleRect==null) { // ???
63 visibleRect = getVisibleRect();
64 }
65 //System.out.println("IconRowHeader repainting: " + visibleRect);
66 if (visibleRect==null) {
67 return;
68 }
69
70 g.setColor(getBackground());
71 g.fillRect(0,visibleRect.y, width,visibleRect.height);
72
73 if (textArea.getLineWrap()) {
74 paintComponentWrapped(g);
75 return;
76 }
77
78 Document doc = textArea.getDocument();
79 Element root = doc.getDefaultRootElement();
80 textAreaInsets = textArea.getInsets(textAreaInsets);
81
82 // Get the first line to paint.
83 int cellHeight = textArea.getLineHeight();
84 int topLine = (visibleRect.y-textAreaInsets.top)/cellHeight;
85 topLine += fm.getHiddenLineCountAbove(topLine, true);
86
87 // Get where to start painting (top of the row).
88 // We need to be "scrolled up" up just enough for the missing part of
89 // the first line.
90 int y = topLine*cellHeight + textAreaInsets.top;
91
92 // Paint the active line range.
93 if (activeLineRangeStart>-1 && activeLineRangeEnd>-1) {
94 Color activeLineRangeColor = getActiveLineRangeColor();
95 g.setColor(activeLineRangeColor);
96 try {
97
98 int y1 = rsta.yForLine(activeLineRangeStart);
99 if (y1>-1) { // Not in a collapsed fold...
100
101 int y2 = rsta.yForLine(activeLineRangeEnd);
102 if (y2==-1) { // In a collapsed fold
103 y2 = y1;
104 }
105 y2 += cellHeight - 1;
106
107 int j = y1;
108 while (j<=y2) {
109 int yEnd = Math.min(y2, j+getWidth());
110 int xEnd = yEnd-j;
111 g.drawLine(0,j, xEnd,yEnd);
112 j += 2;
113 }
114
115 int i = 2;
116 while (i<getWidth()) {
117 int yEnd = y1 + getWidth() - i;
118 g.drawLine(i,y1, getWidth(),yEnd);
119 i += 2;
120 }
121
122 if (y1>=y && y1<y+visibleRect.height) {
123 g.drawLine(0,y1, getWidth(),y1);
124 }
125 if (y2>=y && y2<y+visibleRect.height) {
126 g.drawLine(0,y2, getWidth(),y2);
127 }
128
129 }
130
131 } catch (BadLocationException ble) {
132 ble.printStackTrace(); // Never happens
133 }
134 }
135
136 // Paint icons
137 if (trackingIcons!=null) {
138 int lastLine = textArea.getLineCount() - 1;
139 for (int i=trackingIcons.size()-1; i>=0; i--) { // Last to first
140 GutterIconInfo ti = getTrackingIcon(i);
141 int offs = ti.getMarkedOffset();
142 if (offs>=0 && offs<=doc.getLength()) {
143 int line = root.getElementIndex(offs);
144 if (line<=lastLine && line>=topLine) {
145 try {
146 int lineY = rsta.yForLine(line);
147 if (lineY>=y && lineY<y+visibleRect.height) {
148 Icon icon = ti.getIcon();
149 if (icon!=null) {
150 int y2 = lineY + (cellHeight-icon.getIconHeight())/2;
151 ti.getIcon().paintIcon(this, g, 0, y2);
152 lastLine = line-1; // Paint only 1 icon per line
153 }
154 }
155 } catch (BadLocationException ble) {
156 ble.printStackTrace(); // Never happens
157 }
158 }
159 else if (line<topLine) {
160 break; // All other lines are above us, so quit now
161 }
162 }
163 }
164 }
165
166 }
167
168
169 /**
170 * Paints icons when line wrapping is enabled. Note that this does not
171 * override the parent class's implementation to avoid this version being
172 * called when line wrapping is disabled.
173 */
174 private void paintComponentWrapped(Graphics g) {
175
176 // The variables we use are as follows:
177 // - visibleRect is the "visible" area of the text area; e.g.
178 // [0,100, 300,100+(lineCount*cellHeight)-1].
179 // actualTop.y is the topmost-pixel in the first logical line we
180 // paint. Note that we may well not paint this part of the logical
181 // line, as it may be broken into many physical lines, with the first
182 // few physical lines scrolled past. Note also that this is NOT the
183 // visible rect of this line number list; this line number list has
184 // visible rect == [0,0, insets.left-1,visibleRect.height-1].
185
186 // We avoid using modelToView/viewToModel where possible, as these
187 // methods trigger a parsing of the line into syntax tokens, which is
188 // costly. It's cheaper to just grab the child views' bounds.
189
190 RSyntaxTextArea rsta = (RSyntaxTextArea)textArea;
191// boolean currentLineHighlighted = textArea.getHighlightCurrentLine();
192 Document doc = textArea.getDocument();
193 Element root = doc.getDefaultRootElement();
194 int topPosition = textArea.viewToModel(
195 new Point(visibleRect.x,visibleRect.y));
196 int topLine = root.getElementIndex(topPosition);
197
198 int topY = visibleRect.y;
199 int bottomY = visibleRect.y + visibleRect.height;
200 int cellHeight = textArea.getLineHeight();
201
202 // Paint icons
203 if (trackingIcons!=null) {
204 int lastLine = textArea.getLineCount() - 1;
205 for (int i=trackingIcons.size()-1; i>=0; i--) { // Last to first
206 GutterIconInfo ti = getTrackingIcon(i);
207 int offs = ti.getMarkedOffset();
208 if (offs>=0 && offs<=doc.getLength()) {
209 int line = root.getElementIndex(offs);
210 if (line<=lastLine && line>=topLine) {
211 try {
212 int lineY = rsta.yForLine(line);
213 if (lineY>=topY && lineY<bottomY) {
214 Icon icon = ti.getIcon();
215 if (icon!=null) {
216 int y2 = lineY + (cellHeight-icon.getIconHeight())/2;
217 ti.getIcon().paintIcon(this, g, 0, y2);
218 lastLine = line-1; // Paint only 1 icon per line
219 }
220 }
221 } catch (BadLocationException ble) {
222 ble.printStackTrace(); // Never happens
223 }
224 }
225 else if (line<topLine) {
226 break; // All other lines are above us, so quit now
227 }
228 }
229 }
230 }
231
232 }
233
234
235}
Note: See TracBrowser for help on using the repository browser.