textareapainter.java
来自「java写的多功能文件编辑器」· Java 代码 · 共 899 行 · 第 1/2 页
JAVA
899 行
/** * Returns the font metrics used by this component. */ public FontMetrics getFontMetrics() { return fm; } /** * Sets the font for this component. This is overridden to update the * cached font metrics and to recalculate which lines are visible. * @param font The font */ public void setFont(Font font) { super.setFont(font); fm = Toolkit.getDefaultToolkit().getFontMetrics(font); textArea.recalculateVisibleLines(); } /** * Repaints the text. * @param g The graphics context */ public void paint(Graphics gfx) { ///// TEMP FIX ///// //setAntiAliasing(gfx); tabSize = fm.charWidth(' ') * ((Integer) textArea .getDocument().getProperty(PlainDocument.tabSizeAttribute)).intValue(); Rectangle clipRect = gfx.getClipBounds(); gfx.setColor(getBackground()); gfx.fillRect(clipRect.x, clipRect.y, clipRect.width, clipRect.height); // We don't use yToLine() here because that method doesn't // return lines past the end of the document int height = fm.getHeight(); int firstLine = textArea.getFirstLine(); int firstInvalid = firstLine + clipRect.y / height; // Because the clipRect's height is usually an even multiple // of the font height, we subtract 1 from it, otherwise one // too many lines will always be painted. int lastInvalid = firstLine + (clipRect.y + clipRect.height - 1) / height; int x = textArea.getHorizontalOffset(); int lineCount = textArea.getLineCount(); try { TokenMarker tokenMarker = textArea.getDocument().getTokenMarker(); int maxWidth = textArea.maxHorizontalScrollWidth; boolean updateMaxHorizontalScrollWidth = false; for (int line = firstInvalid; line <= lastInvalid; line++) { boolean valid = line >= 0 && line < lineCount; int width = paintLine(gfx, tokenMarker, valid, line, x) - x + 5 /* Yay */; if (valid) { tokenMarker.setLineWidth(line, width); if (width > maxWidth) updateMaxHorizontalScrollWidth = true; } } if (tokenMarker.isNextLineRequested()) { int h = clipRect.y + clipRect.height; repaint(0, h, getWidth(), getHeight() - h); } if (updateMaxHorizontalScrollWidth) textArea.updateMaxHorizontalScrollWidth(); } catch (Exception e) { System.err.println("Error repainting line" + " range {" + firstInvalid + "," + lastInvalid + "}:"); e.printStackTrace(); } } /** * Marks a line as needing a repaint. * @param line The line to invalidate */ public final void invalidateLine(int line) { repaint(0, textArea.lineToY(line) + fm.getMaxDescent() + fm.getLeading(), getWidth(), fm.getHeight()); } /** * Marks a range of lines as needing a repaint. * @param firstLine The first line to invalidate * @param lastLine The last line to invalidate */ public final void invalidateLineRange(int firstLine, int lastLine) { repaint(0, textArea.lineToY(firstLine) + fm.getMaxDescent() + fm.getLeading(), getWidth(), (lastLine - firstLine + 1) * fm.getHeight()); } /** * Repaints the lines containing the selection. */ public final void invalidateSelectedLines() { invalidateLineRange(textArea.getSelectionStartLine(), textArea.getSelectionEndLine()); } /** * 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) { if (tabSize == 0) { tabSize = fm.charWidth(' ') * ((Integer) textArea.getDocument().getProperty(PlainDocument.tabSizeAttribute)).intValue(); } int offset = textArea.getHorizontalOffset(); int ntabs = ((int) x - offset) / tabSize; return (ntabs + 1) * tabSize + offset; } /** * Returns the painter's preferred size. */ public Dimension getPreferredSize() { Dimension dim = new Dimension(); dim.width = fm.charWidth('w') * cols; dim.height = fm.getHeight() * rows; return dim; } /** * Returns the painter's minimum size. */ public Dimension getMinimumSize() { return getPreferredSize(); } // protected members protected JEditTextArea textArea; protected SyntaxStyle[] styles; protected Color caretColor; protected Color selectionColor; protected Color lineHighlightColor; protected Color highlightColor; protected Color bracketHighlightColor; protected Color eolMarkerColor; protected boolean blockCaret; protected boolean lineHighlight; protected boolean bracketHighlight; protected boolean paintInvalid; protected boolean eolMarkers; protected int cols; protected int rows; protected int tabSize; protected FontMetrics fm; protected TextAreaHighlight highlights; protected TextAreaHighlight firstPriorityHighlights; protected int paintLine(Graphics gfx, TokenMarker tokenMarker, boolean valid, int line, int x) { Font defaultFont = getFont(); Color defaultColor = getForeground(); int y = textArea.lineToY(line); if (!valid) { if (paintInvalid) { paintHighlight(gfx, line, y); styles[Token.INVALID].setGraphicsFlags(gfx, defaultFont); gfx.drawString("~", 0, y + fm.getHeight()); } } else { x = paintSyntaxLine(gfx, tokenMarker, line, defaultFont, defaultColor, x, y); } return x; } protected int paintSyntaxLine(Graphics gfx, TokenMarker tokenMarker, int line, Font defaultFont, Color defaultColor, int x, int y) { // priority highlights first if (firstPriorityHighlights != null) firstPriorityHighlights.paintHighlight(gfx, line, y); Segment tempSeg = textArea.lineSegment; textArea.getLineText(line, textArea.lineSegment); Token tokens = tokenMarker.markTokens(textArea.lineSegment, line); Token first = tokens; int backY = y + fm.getLeading() + fm.getMaxDescent(); int backHeight = fm.getHeight(); int backWidth = fm.charWidth('w'); int offset = x; int offsetShift = 0; int charOffset = 0; String textLine = textArea.lineSegment.toString(); org.jext.JextTextArea jextArea = (org.jext.JextTextArea) textArea; while (tokens.id != Token.END) { offsetShift = backWidth * org.jext.Utilities.getRealLength(textLine.substring(charOffset, charOffset + tokens.length), jextArea.getTabSize()); charOffset += tokens.length; if (tokens.highlightBackground) { gfx.setColor(highlightColor); gfx.fillRect(offset, backY, offsetShift, backHeight); } offset += offsetShift; tokens = tokens.next; } textArea.lineSegment = tempSeg; paintHighlight(gfx, line, y); textArea.getLineText(line, textArea.lineSegment); gfx.setFont(defaultFont); gfx.setColor(defaultColor); y += fm.getHeight(); x = SyntaxUtilities.paintSyntaxLine(textArea.lineSegment, first, styles, this, gfx, x, y); if (eolMarkers) { gfx.setColor(eolMarkerColor); gfx.drawString(".", x, y); } return x; } protected void paintHighlight(Graphics gfx, int line, int y) { if (line >= textArea.getSelectionStartLine() && line <= textArea.getSelectionEndLine()) paintLineHighlight(gfx, line, y); if (linesIntervalHighlight && linesInterval > 0) paintLinesInterval(gfx, line, y); if (wrapGuide && wrapGuideOffset > 0) paintWrapGuide(gfx, line, y); if (highlights != null) highlights.paintHighlight(gfx, line, y); if (bracketHighlight && line == textArea.getBracketLine()) paintBracketHighlight(gfx, line, y); if (line == textArea.getCaretLine()) paintCaret(gfx, line, y); if (line == textArea.getShadowCaretLine()) paintShadowCaret(gfx, line, y); } protected void paintWrapGuide(Graphics gfx, int line, int y) { gfx.setColor(wrapGuideColor); int _offset = y + (fm.getLeading() + fm.getMaxDescent()); int start = (line > 0) ? _offset : 0; int end = (line != textArea.getLineCount() - 1) ? _offset + fm.getHeight() : textArea.getHeight(); int charWidth = fm.charWidth('m'); int offset = textArea.getHorizontalOffset(); int width = textArea.getWidth(); int off = wrapGuideOffset * charWidth + offset; if (off >= 0 && off < width) gfx.drawLine(off, start, off, end); } protected void paintLinesInterval(Graphics gfx, int line, int y) { if (((line + 1) % linesInterval) == 0) { int height = fm.getHeight(); int _offset = y + fm.getLeading() + fm.getMaxDescent(); int selectionStart = textArea.getSelectionStart(); int selectionEnd = textArea.getSelectionEnd(); gfx.setColor(linesIntervalColor); gfx.fillRect(0, _offset, getWidth(), height); gfx.setColor(selectionColor); int selectionStartLine = textArea.getSelectionStartLine(); int selectionEndLine = textArea.getSelectionEndLine(); int lineStart = textArea.getLineStartOffset(line); int x1, x2; if (textArea.isSelectionRectangular()) { int lineLen = textArea.getLineLength(line); x1 = textArea.offsetToX(line, Math.min(lineLen, selectionStart - textArea.getLineStartOffset(selectionStartLine))); x2 = textArea.offsetToX(line, Math.min(lineLen, selectionEnd - textArea.getLineStartOffset(selectionEndLine))); if (x1 == x2) x2++; } else 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 = textArea.offsetToX(line, textArea.getLineLength(line)); } else if (line == selectionEndLine) { x1 = 0; x2 = textArea.offsetToX(line, selectionEnd - lineStart); } else { x1 = 0; x2 = textArea.offsetToX(line, textArea.getLineLength(line)); } gfx.fillRect(x1 > x2 ? x2 : x1, _offset, x1 > x2 ? (x1 - x2) : (x2 - x1), height); } } protected void paintLineHighlight(Graphics gfx, 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) { gfx.setColor(lineHighlightColor); gfx.fillRect(0, y, getWidth(), height); } } else { gfx.setColor(selectionColor); int selectionStartLine = textArea.getSelectionStartLine(); int selectionEndLine = textArea.getSelectionEndLine(); int lineStart = textArea.getLineStartOffset(line); int x1, x2; if (textArea.isSelectionRectangular()) { int lineLen = textArea.getLineLength(line); x1 = textArea.offsetToX(line, Math.min(lineLen, selectionStart - textArea.getLineStartOffset(selectionStartLine))); x2 = textArea.offsetToX(line, Math.min(lineLen, selectionEnd - textArea.getLineStartOffset(selectionEndLine))); if (x1 == x2) x2++; } else 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 = getWidth(); x2 = textArea.offsetToX(line, textArea.getLineLength(line)); } else if (line == selectionEndLine) { x1 = 0; x2 = textArea.offsetToX(line, selectionEnd - lineStart); } else { x1 = 0; //x2 = getWidth(); x2 = textArea.offsetToX(line, textArea.getLineLength(line)); } int w = x1 > x2 ? (x1 - x2) : (x2 - x1); if (w == 0) w = 4; // "inlined" min/max() gfx.fillRect(x1 > x2 ? x2 : x1, y, w, height); } } protected void paintBracketHighlight(Graphics gfx, int line, int y) { int position = textArea.getBracketPosition(); if (position == -1) return; y += fm.getLeading() + fm.getMaxDescent(); int x = textArea.offsetToX(line, position); gfx.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 gfx.fillRect(x, y, fm.charWidth('(') - 1, fm.getHeight() - 1); } protected void paintCaret(Graphics gfx, 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(); gfx.setColor(caretColor); if (textArea.isOverwriteEnabled()) { gfx.fillRect(caretX, y + height - 1, caretWidth, 1); } else if (caretWidth > 1) { gfx.drawRect(caretX, y, caretWidth - 1, height - 1); } else { gfx.drawLine(caretX, y, caretX, y + height - 1); } } } protected void paintShadowCaret(Graphics gfx, int line, int y) { int offset = textArea.getShadowCaretPosition() - textArea.getLineStartOffset(line); int caretX = textArea.offsetToX(line, offset); y += fm.getLeading() + fm.getMaxDescent(); int height = fm.getHeight(); gfx.setColor(caretColor.darker()); for (int i = 0; i < height; i += 3) gfx.drawLine(caretX, y + i, caretX, y + i + 1); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?