📄 acltextareapainter.java
字号:
/**
* Paints any lines that changed since the last paint to the offscreen
* graphics, then repaints the offscreen to the specified graphics context.
*
* @param g The graphics context
*/
public void update(Graphics g) {
tabSize = fm.charWidth('w') * ((Integer)textArea.getDocument().getProperty(
PlainDocument.tabSizeAttribute)).intValue();
// returns true if offscreen was created. When it's created,
// all lines, not just the invalid ones, need to be painted.
if (ensureOffscreenValid()) {
firstInvalid = textArea.getFirstLine();
lastInvalid = firstInvalid + textArea.getVisibleLines();
}
if (firstInvalid != -1 && lastInvalid != -1) {
int lineCount;
try {
if (firstInvalid == lastInvalid) {
lineCount = offscreenRepaintLine(firstInvalid,
textArea.getHorizontalOffset());
}
else {
lineCount = offscreenRepaintLineRange(
firstInvalid, lastInvalid);
}
if (lastInvalid - firstInvalid + 1 != lineCount) {
// XXX stupid hack
Rectangle clip = g.getClipBounds();
if (!clip.equals(getBounds())) {
repaint();
}
}
}
catch (Exception e) {
System.err.println("Error repainting line"
+ " range {" + firstInvalid + ","
+ lastInvalid + "}:");
e.printStackTrace();
}
firstInvalid = lastInvalid = -1;
}
g.drawImage(offImg, 0, 0, null);
}
/**
* Same as <code>update(g)</code>.
*
* @param g Description of Parameter
*/
public void paint(Graphics g) {
update(g);
}
/**
* Marks a line as needing a repaint, but doesn't actually repaint it until
* <code>repaint()</code> is called manually.
*
* @param line The line to invalidate
*/
public void _invalidateLine(int line) {
int firstVisible = textArea.getFirstLine();
int lastVisible = firstVisible + textArea.getVisibleLines();
if (line < firstVisible || line > lastVisible) {
return;
}
if (line >= firstInvalid && line <= lastInvalid) {
return;
}
if (firstInvalid == -1 && lastInvalid == -1) {
firstInvalid = lastInvalid = line;
}
else {
firstInvalid = Math.min(line, firstInvalid);
lastInvalid = Math.max(line, lastInvalid);
}
}
/**
* Marks a range of lines as needing a repaint, but doesn't actually
* repaint them until <code>repaint()</code> is called.
*
* @param firstLine The first line to invalidate
* @param lastLine The last line to invalidate
*/
public void _invalidateLineRange(int firstLine, int lastLine) {
int firstVisible = textArea.getFirstLine();
int lastVisible = firstVisible + textArea.getVisibleLines();
if (firstLine > lastLine) {
int tmp = firstLine;
firstLine = lastLine;
lastLine = tmp;
}
if (lastLine < firstVisible || firstLine > lastVisible) {
return;
}
if (firstInvalid == -1 && lastInvalid == -1) {
firstInvalid = firstLine;
lastInvalid = lastLine;
}
else {
if (firstLine >= firstInvalid && lastLine <= lastInvalid) {
return;
}
firstInvalid = Math.min(firstInvalid, firstLine);
lastInvalid = Math.max(lastInvalid, lastLine);
}
firstInvalid = Math.max(firstInvalid, firstVisible);
lastInvalid = Math.min(lastInvalid, lastVisible);
}
/**
* Simulates scrolling from <code>oldFirstLine</code> to <code>newFirstLine</code>
* by shifting the offscreen graphics and repainting any revealed lines.
* This should not be called directly; use <code>JEditTextArea.setFirstLine()</code>
* instead.
*
* @param oldFirstLine The old first line
* @param newFirstLine The new first line
* @see org.gjt.sp.jedit.textarea.JEditTextArea#setFirstLine(int)
*/
public void scrollRepaint(int oldFirstLine, int newFirstLine) {
if (offGfx == null) {
return;
}
int visibleLines = textArea.getVisibleLines();
// No point doing this crap if the user scrolled by >= visibleLines
if (copyAreaBroken || oldFirstLine + visibleLines <= newFirstLine
|| newFirstLine + visibleLines <= oldFirstLine) {
_invalidateLineRange(newFirstLine, newFirstLine + visibleLines + 1);
}
else {
int y = fm.getHeight() * (oldFirstLine - newFirstLine);
offGfx.copyArea(0, 0, offImg.getWidth(this), offImg.getHeight(this), 0, y);
if (oldFirstLine < newFirstLine) {
_invalidateLineRange(oldFirstLine + visibleLines - 1,
newFirstLine + visibleLines + 1);
}
else {
_invalidateLineRange(newFirstLine, oldFirstLine);
}
}
}
/**
* Implementation of TabExpander interface. Returns next tab stop after a
* specified point.
*
* @param x The x co-ordinate
* @param tabOffset Ignored
* @return The next tab stop after <i>x</i>
*/
public float nextTabStop(float x, int tabOffset) {
int offset = textArea.getHorizontalOffset();
int ntabs = ((int)x - offset) / tabSize;
return (ntabs + 1) * tabSize + offset;
}
protected boolean ensureOffscreenValid() {
if (offImg == null || offGfx == null) {
offImg = textArea.createImage(getWidth(), getHeight());
offGfx = offImg.getGraphics();
return true;
}
else {
return false;
}
}
protected int offscreenRepaintLineRange(int firstLine, int lastLine) {
if (offGfx == null) {
return 0;
}
int x = textArea.getHorizontalOffset();
int line;
for (line = firstLine; line <= lastLine; ) {
line += offscreenRepaintLine(line, x);
}
return line - firstLine;
}
protected int offscreenRepaintLine(int line, int x) {
ACLSLTokenMarker tokenMarker = textArea.getTokenMarker();
Font defaultFont = getFont();
Color defaultColor = getForeground();
int y = textArea.lineToY(line);
if (line < 0 || line >= textArea.getLineCount()) {
paintHighlight(line, y);
styles[ACLToken.INVALID].setGraphicsFlags(offGfx, defaultFont);
offGfx.drawString(".", 0, y + fm.getHeight());
return 1;
}
if (tokenMarker == null) {
currentLineIndex = line;
paintPlainLine(line, defaultFont, defaultColor, x, y);
return 1;
}
else {
int count = 0;
int lastVisibleLine = Math.min(textArea.getLineCount(),
textArea.getFirstLine() + textArea.getVisibleLines());
do {
currentLineIndex = line + count;
paintSyntaxLine(tokenMarker, currentLineIndex,
defaultFont, defaultColor, x, y);
y += fm.getHeight();
count++;
} while (tokenMarker.isNextLineRequested()
&& line + count < lastVisibleLine);
return count;
}
}
protected void paintPlainLine(int line, Font defaultFont,
Color defaultColor, int x, int y) {
paintHighlight(line, y);
textArea.getLineText(line, currentLine);
offGfx.setFont(defaultFont);
offGfx.setColor(defaultColor);
y += fm.getHeight();
x = Utilities.drawTabbedText(currentLine, x, y, offGfx, this, 0);
if (eolMarkers) {
offGfx.setColor(eolMarkerColor);
offGfx.drawString(".", x, y);
}
}
protected void paintSyntaxLine(ACLSLTokenMarker tokenMarker, int line,
Font defaultFont, Color defaultColor, int x, int y) {
textArea.getLineText(currentLineIndex, currentLine);
currentLineTokens = tokenMarker.markTokens(currentLine,
currentLineIndex);
paintHighlight(line, y);
offGfx.setFont(defaultFont);
offGfx.setColor(defaultColor);
styles = ACLSyntaxUtilities.getDefaultSyntaxStyles(this);
y += fm.getHeight();
x = ACLSyntaxUtilities.paintSyntaxLine(currentLine,
currentLineTokens, styles, this, offGfx, x, y);
if (eolMarkers) {
offGfx.setColor(eolMarkerColor);
offGfx.drawString(".", x, y);
}
}
protected void paintHighlight(int line, int y) {
/*
Clear the line's bounding rectangle
*/
int gap = fm.getMaxDescent() + fm.getLeading();
offGfx.setColor(getBackground());
offGfx.fillRect(0, y + gap, offImg.getWidth(this), fm.getHeight());
if (line >= textArea.getSelectionStartLine()
&& line <= textArea.getSelectionEndLine()) {
paintLineHighlight(line, y);
}
if (bracketHighlight && line == textArea.getBracketLine()) {
paintBracketHighlight(line, y);
}
if (line == textArea.getCaretLine()) {
paintCaret(line, y);
}
}
protected void paintLineHighlight(int line, int y) {
int height = fm.getHeight();
y += fm.getLeading() + fm.getMaxDescent();
int selectionStart = textArea.getSelectionStart();
int selectionEnd = textArea.getSelectionEnd();
if (selectionStart == selectionEnd) {
if (lineHighlight) {
offGfx.setColor(lineHighlightColor);
offGfx.fillRect(0, y, offImg.getWidth(this), height);
}
else {
offGfx.setColor(selectionColor);
int selectionStartLine = textArea.getSelectionStartLine();
int selectionEndLine = textArea.getSelectionEndLine();
int lineStart = textArea.getLineStartOffset(line);
int x1;
int x2;
if (selectionStartLine == selectionEndLine) {
x1 = textArea.offsetToX(line,
selectionStart - lineStart);
x2 = textArea.offsetToX(line,
selectionEnd - lineStart);
}
else if (line == selectionStartLine) {
x1 = textArea.offsetToX(line,
selectionStart - lineStart);
x2 = offImg.getWidth(this);
}
else if (line == selectionEndLine) {
x1 = 0;
x2 = textArea.offsetToX(line,
selectionEnd - lineStart);
}
else {
x1 = 0;
x2 = offImg.getWidth(this);
}
offGfx.fillRect(x1, y, x2 - x1, height);
}
}
}
protected void paintBracketHighlight(int line, int y) {
int position = textArea.getBracketPosition();
if (position == -1) {
return;
}
y += fm.getLeading() + fm.getMaxDescent();
int x = textArea.offsetToX(line, position);
offGfx.setColor(bracketHighlightColor);
// Hack!!! Since there is no fast way to get the character
// from the bracket matching routine, we use ( since all
// brackets probably have the same width anyway
offGfx.drawRect(x, y, fm.charWidth('(') - 1,
fm.getHeight() - 1);
}
protected void paintCaret(int line, int y) {
if (textArea.isCaretVisible()) {
int offset = textArea.getCaretPosition()
- textArea.getLineStartOffset(line);
int caretX = textArea.offsetToX(line, offset);
int caretWidth = ((blockCaret ||
textArea.isOverwriteEnabled()) ?
fm.charWidth('w') : 1);
y += fm.getLeading() + fm.getMaxDescent();
int height = fm.getHeight();
offGfx.setColor(caretColor);
if (textArea.isOverwriteEnabled()) {
offGfx.fillRect(caretX, y + height - 1,
caretWidth, 1);
}
else {
offGfx.drawRect(caretX, y, caretWidth - 1, height - 1);
}
}
}
protected static boolean copyAreaBroken;
// protected members
protected ACLTextArea textArea;
protected ACLSytntaxStyle[] styles;
protected Color caretColor;
protected Color selectionColor;
protected Color lineHighlightColor;
protected Color bracketHighlightColor;
protected Color eolMarkerColor;
protected boolean blockCaret;
protected boolean lineHighlight;
protected boolean bracketHighlight;
protected boolean eolMarkers;
protected int cols;
protected int rows;
protected int tabSize;
protected FontMetrics fm;
protected Graphics offGfx;
protected Image offImg;
protected int firstInvalid;
protected int lastInvalid;
// package-private members
int currentLineIndex;
ACLToken currentLineTokens;
Segment currentLine;
}
// ***EOF***
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -