4
* FoldingAwareIconRowHeader - Icon row header that paints itself correctly
5
* even when code folding is enabled.
7
* This library is distributed under a modified BSD license. See the included
8
* RSyntaxTextArea.License.txt file for details.
10
package org.fife.ui.rsyntaxtextarea;
12
import java.awt.Color;
13
import java.awt.Graphics;
14
import java.awt.Point;
15
import javax.swing.Icon;
16
import javax.swing.text.BadLocationException;
17
import javax.swing.text.Document;
18
import javax.swing.text.Element;
20
import org.fife.ui.rsyntaxtextarea.folding.FoldManager;
21
import org.fife.ui.rtextarea.GutterIconInfo;
22
import org.fife.ui.rtextarea.IconRowHeader;
26
* A row header component that takes code folding into account when painting
29
* @author Robert Futrell
32
public class FoldingAwareIconRowHeader extends IconRowHeader {
38
* @param textArea The parent text area.
40
public FoldingAwareIconRowHeader(RSyntaxTextArea textArea) {
49
protected void paintComponent(Graphics g) {
51
// When line wrap is not enabled, take the faster code path.
55
RSyntaxTextArea rsta = (RSyntaxTextArea)textArea;
56
FoldManager fm = rsta.getFoldManager();
57
if (!fm.isCodeFoldingSupportedAndEnabled()) {
58
super.paintComponent(g);
62
visibleRect = g.getClipBounds(visibleRect);
63
if (visibleRect==null) { // ???
64
visibleRect = getVisibleRect();
66
//System.out.println("IconRowHeader repainting: " + visibleRect);
67
if (visibleRect==null) {
71
g.setColor(getBackground());
72
g.fillRect(0,visibleRect.y, width,visibleRect.height);
74
if (textArea.getLineWrap()) {
75
paintComponentWrapped(g);
79
Document doc = textArea.getDocument();
80
Element root = doc.getDefaultRootElement();
81
textAreaInsets = textArea.getInsets(textAreaInsets);
83
// Get the first line to paint.
84
int cellHeight = textArea.getLineHeight();
85
int topLine = (visibleRect.y-textAreaInsets.top)/cellHeight;
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
90
int y = topLine*cellHeight + textAreaInsets.top;
92
// AFTER calculating visual offset to paint at, account for folding.
93
topLine += fm.getHiddenLineCountAbove(topLine, true);
95
// Paint the active line range.
96
if (activeLineRangeStart>-1 && activeLineRangeEnd>-1) {
97
Color activeLineRangeColor = getActiveLineRangeColor();
98
g.setColor(activeLineRangeColor);
101
int realY1 = rsta.yForLine(activeLineRangeStart);
102
if (realY1>-1) { // Not in a collapsed fold...
104
int y1 = realY1;//Math.max(y, realY1);
106
int y2 = rsta.yForLine(activeLineRangeEnd);
107
if (y2==-1) { // In a collapsed fold
110
y2 += cellHeight - 1;
112
if (y2<visibleRect.y || y1>visibleRect.y+visibleRect.height) {
113
//System.out.println("... nothing to paint, bailing...");
116
y1 = Math.max(y, realY1);
117
y2 = Math.min(y2, visibleRect.y+visibleRect.height);
118
//System.out.println(y1 + "... " + y2 + "; " + realY1 + ", " + visibleRect);
122
int yEnd = Math.min(y2, j+getWidth());
124
g.drawLine(0,j, xEnd,yEnd);
129
while (i<getWidth()) {
130
int yEnd = y1 + getWidth() - i;
131
g.drawLine(i,y1, getWidth(),yEnd);
135
if (realY1>=y && realY1<visibleRect.y+visibleRect.height) {
136
g.drawLine(0,realY1, getWidth(),realY1);
138
if (y2>=y && y2<visibleRect.y+visibleRect.height) {
139
g.drawLine(0,y2, getWidth(),y2);
144
} catch (BadLocationException ble) {
145
ble.printStackTrace(); // Never happens
150
if (trackingIcons!=null) {
151
int lastLine = textArea.getLineCount() - 1;
152
for (int i=trackingIcons.size()-1; i>=0; i--) { // Last to first
153
GutterIconInfo ti = getTrackingIcon(i);
154
int offs = ti.getMarkedOffset();
155
if (offs>=0 && offs<=doc.getLength()) {
156
int line = root.getElementIndex(offs);
157
if (line<=lastLine && line>=topLine) {
159
Icon icon = ti.getIcon();
161
int lineY = rsta.yForLine(line);
162
if (lineY>=y && lineY<=visibleRect.y+visibleRect.height) {
163
int y2 = lineY + (cellHeight-icon.getIconHeight())/2;
164
icon.paintIcon(this, g, 0, y2);
165
lastLine = line-1; // Paint only 1 icon per line
168
} catch (BadLocationException ble) {
169
ble.printStackTrace(); // Never happens
172
else if (line<topLine) {
173
break; // All other lines are above us, so quit now
183
* Paints icons when line wrapping is enabled. Note that this does not
184
* override the parent class's implementation to avoid this version being
185
* called when line wrapping is disabled.
187
private void paintComponentWrapped(Graphics g) {
189
// The variables we use are as follows:
190
// - visibleRect is the "visible" area of the text area; e.g.
191
// [0,100, 300,100+(lineCount*cellHeight)-1].
192
// actualTop.y is the topmost-pixel in the first logical line we
193
// paint. Note that we may well not paint this part of the logical
194
// line, as it may be broken into many physical lines, with the first
195
// few physical lines scrolled past. Note also that this is NOT the
196
// visible rect of this line number list; this line number list has
197
// visible rect == [0,0, insets.left-1,visibleRect.height-1].
199
// We avoid using modelToView/viewToModel where possible, as these
200
// methods trigger a parsing of the line into syntax tokens, which is
201
// costly. It's cheaper to just grab the child views' bounds.
203
RSyntaxTextArea rsta = (RSyntaxTextArea)textArea;
204
// boolean currentLineHighlighted = textArea.getHighlightCurrentLine();
205
Document doc = textArea.getDocument();
206
Element root = doc.getDefaultRootElement();
207
int topPosition = textArea.viewToModel(
208
new Point(visibleRect.x,visibleRect.y));
209
int topLine = root.getElementIndex(topPosition);
211
int topY = visibleRect.y;
212
int bottomY = visibleRect.y + visibleRect.height;
213
int cellHeight = textArea.getLineHeight();
216
if (trackingIcons!=null) {
217
int lastLine = textArea.getLineCount() - 1;
218
for (int i=trackingIcons.size()-1; i>=0; i--) { // Last to first
219
GutterIconInfo ti = getTrackingIcon(i);
220
int offs = ti.getMarkedOffset();
221
if (offs>=0 && offs<=doc.getLength()) {
222
int line = root.getElementIndex(offs);
223
if (line<=lastLine && line>=topLine) {
225
int lineY = rsta.yForLine(line);
226
if (lineY>=topY && lineY<bottomY) {
227
Icon icon = ti.getIcon();
229
int y2 = lineY + (cellHeight-icon.getIconHeight())/2;
230
ti.getIcon().paintIcon(this, g, 0, y2);
231
lastLine = line-1; // Paint only 1 icon per line
234
} catch (BadLocationException ble) {
235
ble.printStackTrace(); // Never happens
238
else if (line<topLine) {
239
break; // All other lines are above us, so quit now
b'\\ No newline at end of file'