/** * Paints the word-wrapped text. * * @param g The graphics context in which to paint. * @param a The shape (usually a rectangle) in which to paint. */ public void paint(Graphics g, Shape a) { Rectangle alloc = (a instanceof Rectangle) ? (Rectangle) a : a.getBounds(); tabBase = alloc.x; Graphics2D g2d = (Graphics2D) g; host = (RSyntaxTextArea) getContainer(); int ascent = host.getMaxAscent(); int fontHeight = host.getLineHeight(); FoldManager fm = host.getFoldManager(); TokenPainter painter = host.getTokenPainter(); Element root = getElement(); // Whether token styles should always be painted, even in selections int selStart = host.getSelectionStart(); int selEnd = host.getSelectionEnd(); boolean useSelectedTextColor = host.getUseSelectedTextColor(); int n = getViewCount(); // Number of lines. int x = alloc.x + getLeftInset(); tempRect.y = alloc.y + getTopInset(); Rectangle clip = g.getClipBounds(); for (int i = 0; i < n; i++) { tempRect.x = x + getOffset(X_AXIS, i); // tempRect.y = y + getOffset(Y_AXIS, i); tempRect.width = getSpan(X_AXIS, i); tempRect.height = getSpan(Y_AXIS, i); // System.err.println("For line " + i + ": tempRect==" + tempRect); if (tempRect.intersects(clip)) { Element lineElement = root.getElement(i); int startOffset = lineElement.getStartOffset(); int endOffset = lineElement.getEndOffset() - 1; // Why always "-1"? View view = getView(i); if (!useSelectedTextColor || selStart == selEnd || (startOffset >= selEnd || endOffset < selStart)) { drawView(painter, g2d, alloc, view, fontHeight, tempRect.y + ascent); } else { // System.out.println("Drawing line with selection: " + i); drawViewWithSelection( painter, g2d, alloc, view, fontHeight, tempRect.y + ascent, selStart, selEnd); } } tempRect.y += tempRect.height; Fold possibleFold = fm.getFoldForLine(i); if (possibleFold != null && possibleFold.isCollapsed()) { i += possibleFold.getCollapsedLineCount(); // Visible indicator of collapsed lines Color c = RSyntaxUtilities.getFoldedLineBottomColor(host); if (c != null) { g.setColor(c); g.drawLine(x, tempRect.y - 1, alloc.width, tempRect.y - 1); } } } }
/** * Draws the passed-in text using syntax highlighting for the current language. Tokens are checked * for being in a selected region, and are rendered appropriately if they are. * * @param painter The painter to render the tokens. * @param token The list of tokens to draw. * @param g The graphics context in which to draw. * @param x The x-coordinate at which to draw. * @param y The y-coordinate at which to draw. * @param selStart The start of the selection. * @param selEnd The end of the selection. * @return The x-coordinate representing the end of the painted text. */ private float drawLineWithSelection( TokenPainter painter, Token token, Graphics2D g, float x, float y, int selStart, int selEnd) { float nextX = x; // The x-value at the end of our text. boolean useSTC = host.getUseSelectedTextColor(); while (token != null && token.isPaintable() && nextX < clipEnd) { // Selection starts in this token if (token.containsPosition(selStart)) { if (selStart > token.getOffset()) { tempToken.copyFrom(token); tempToken.textCount = selStart - tempToken.getOffset(); nextX = painter.paint(tempToken, g, nextX, y, host, this, clipStart); tempToken.textCount = token.length(); tempToken.makeStartAt(selStart); // Clone required since token and tempToken must be // different tokens for else statement below token = new TokenImpl(tempToken); } int tokenLen = token.length(); int selCount = Math.min(tokenLen, selEnd - token.getOffset()); if (selCount == tokenLen) { nextX = painter.paintSelected(token, g, nextX, y, host, this, clipStart, useSTC); } else { tempToken.copyFrom(token); tempToken.textCount = selCount; nextX = painter.paintSelected(tempToken, g, nextX, y, host, this, clipStart, useSTC); tempToken.textCount = token.length(); tempToken.makeStartAt(token.getOffset() + selCount); token = tempToken; nextX = painter.paint(token, g, nextX, y, host, this, clipStart); } } // Selection ends in this token else if (token.containsPosition(selEnd)) { tempToken.copyFrom(token); tempToken.textCount = selEnd - tempToken.getOffset(); nextX = painter.paintSelected(tempToken, g, nextX, y, host, this, clipStart, useSTC); tempToken.textCount = token.length(); tempToken.makeStartAt(selEnd); token = tempToken; nextX = painter.paint(token, g, nextX, y, host, this, clipStart); } // This token is entirely selected else if (token.getOffset() >= selStart && token.getEndOffset() <= selEnd) { nextX = painter.paintSelected(token, g, nextX, y, host, this, clipStart, useSTC); } // This token is entirely unselected else { nextX = painter.paint(token, g, nextX, y, host, this, clipStart); } token = token.getNextToken(); } // NOTE: We should re-use code from Token (paintBackground()) here, // but don't because I'm just too lazy. if (host.getEOLMarkersVisible()) { g.setColor(host.getForegroundForTokenType(Token.WHITESPACE)); g.setFont(host.getFontForTokenType(Token.WHITESPACE)); g.drawString("\u00B6", nextX, y); } // Return the x-coordinate at the end of the painted text. return nextX; }