/** * Sets the allocation rectangle for a given line's view, but sets the y value to the passed-in * value. This should be used instead of {@link #childAllocation(int, Rectangle)} since it allows * you to account for hidden lines in collapsed fold regions. * * @param line * @param y * @param alloc */ private void childAllocation2(int line, int y, Rectangle alloc) { alloc.x += getOffset(X_AXIS, line); alloc.y += y; alloc.width = getSpan(X_AXIS, line); alloc.height = getSpan(Y_AXIS, line); // FIXME: This is required due to a bug that I can't track down. The // top margin is being added twice somewhere in wrapped views, so we // have to adjust for it here. alloc.y -= host.getMargin().top; }
/** * Paints this token, using special symbols for whitespace characters. * * @param g The graphics context in which to paint. * @param x The x-coordinate at which to paint. * @param y The y-coordinate at which to paint. * @param host The text area this token is in. * @param e How to expand tabs. * @param clipStart The left boundary of the clip rectangle in which we're painting. This * optimizes painting by allowing us to not paint not paint when this token is "to the left" * of the clip rectangle. * @return The x-coordinate representing the end of the painted text. */ public final float paint( Graphics2D g, float x, float y, RSyntaxTextArea host, TabExpander e, float clipStart) { int origX = (int) x; int end = textOffset + textCount; float nextX = x; int flushLen = 0; int flushIndex = textOffset; Color fg = host.getForegroundForToken(this); Color bg = host.getBackgroundForTokenType(type); g.setFont(host.getFontForTokenType(type)); FontMetrics fm = host.getFontMetricsForTokenType(type); int ascent = fm.getAscent(); int height = fm.getHeight(); for (int i = textOffset; i < end; i++) { switch (text[i]) { case '\t': // Fill in background. nextX = x + fm.charsWidth(text, flushIndex, flushLen); float nextNextX = e.nextTabStop(nextX, 0); if (bg != null) { paintBackground(x, y, nextNextX - x, height, g, ascent, host, bg); } g.setColor(fg); // Paint chars cached before the tab. if (flushLen > 0) { g.drawChars(text, flushIndex, flushLen, (int) x, (int) y); flushLen = 0; } flushIndex = i + 1; // Draw an arrow representing the tab. int halfHeight = height / 2; int quarterHeight = halfHeight / 2; int ymid = (int) y - ascent + halfHeight; g.drawLine((int) nextX, ymid, (int) nextNextX, ymid); g.drawLine((int) nextNextX, ymid, (int) nextNextX - 4, ymid - quarterHeight); g.drawLine((int) nextNextX, ymid, (int) nextNextX - 4, ymid + quarterHeight); x = nextNextX; break; case ' ': // NOTE: There is a little bit of a "fudge factor" // here when "smooth text" is enabled, as "width" // below may well not be the width given to the space // by fm.charsWidth() (it depends on how it places the // space with respect to the preceding character). // But, we assume the approximation is close enough for // our drawing a dot for the space. // "flushLen+1" ensures text is aligned correctly (or, // aligned the same as in getWidth()). nextX = x + fm.charsWidth(text, flushIndex, flushLen + 1); int width = fm.charWidth(' '); // Paint background. if (bg != null) { paintBackground(x, y, nextX - x, height, g, ascent, host, bg); } g.setColor(fg); // Paint chars before space. if (flushLen > 0) { g.drawChars(text, flushIndex, flushLen, (int) x, (int) y); flushLen = 0; } // Paint a dot representing the space. dotRect.x = nextX - width / 2.0f; // "2.0f" for FindBugs dotRect.y = y - ascent + height / 2.0f; // Ditto g.fill(dotRect); flushIndex = i + 1; x = nextX; break; case '\f': // ??? // fall-through for now. default: flushLen += 1; break; } } nextX = x + fm.charsWidth(text, flushIndex, flushLen); if (flushLen > 0 && nextX >= clipStart) { if (bg != null) { paintBackground(x, y, nextX - x, height, g, ascent, host, bg); } g.setColor(fg); g.drawChars(text, flushIndex, flushLen, (int) x, (int) y); } if (host.getUnderlineForToken(this)) { g.setColor(fg); int y2 = (int) (y + 1); g.drawLine(origX, y2, (int) nextX, y2); } // Don't check if it's whitespace - some TokenMakers may return types // other than Token.WHITESPACE for spaces (such as Token.IDENTIFIER). // This also allows us to paint tab lines for MLC's. if (host.getPaintTabLines() && origX == host.getMargin().left) { // && isWhitespace()) { paintTabLines(origX, (int) y, (int) nextX, g, e, host); } return nextX; }