private void paintHighlighterAfterEndOfLine(Graphics2D g, RangeHighlighterEx highlighter) { if (!highlighter.isAfterEndOfLine()) { return; } int startOffset = highlighter.getStartOffset(); int lineEndOffset = myDocument.getLineEndOffset(myDocument.getLineNumber(startOffset)); if (myEditor.getFoldingModel().isOffsetCollapsed(lineEndOffset)) return; Point lineEnd = myView.offsetToXY(lineEndOffset, true, false); int x = lineEnd.x; int y = lineEnd.y; TextAttributes attributes = highlighter.getTextAttributes(); paintBackground(g, attributes, x, y, myView.getPlainSpaceWidth()); if (attributes != null && hasTextEffect(attributes.getEffectColor(), attributes.getEffectType())) { paintTextEffect( g, x, x + myView.getPlainSpaceWidth() - 1, y + myView.getAscent(), attributes.getEffectColor(), attributes.getEffectType()); } }
private void paintBorderEffect( Graphics2D g, ClipDetector clipDetector, int startOffset, int endOffset, TextAttributes attributes) { if (!clipDetector.rangeCanBeVisible(startOffset, endOffset)) return; int startLine = myDocument.getLineNumber(startOffset); int endLine = myDocument.getLineNumber(endOffset); if (startLine + 1 == endLine && startOffset == myDocument.getLineStartOffset(startLine) && endOffset == myDocument.getLineStartOffset(endLine)) { // special case of line highlighters endLine--; endOffset = myDocument.getLineEndOffset(endLine); } boolean rounded = attributes.getEffectType() == EffectType.ROUNDED_BOX; int lineHeight = myView.getLineHeight() - 1; g.setColor(attributes.getEffectColor()); VisualPosition startPosition = myView.offsetToVisualPosition(startOffset, true, false); VisualPosition endPosition = myView.offsetToVisualPosition(endOffset, false, true); if (startPosition.line == endPosition.line) { int y = myView.visualLineToY(startPosition.line); TFloatArrayList ranges = adjustedLogicalRangeToVisualRanges(startOffset, endOffset); for (int i = 0; i < ranges.size() - 1; i += 2) { int startX = (int) ranges.get(i); int endX = (int) ranges.get(i + 1); if (rounded) { UIUtil.drawRectPickedOut(g, startX, y, endX - startX, lineHeight); } else { g.drawRect(startX, y, endX - startX, lineHeight); } } } else { int maxWidth = myView.getMaxWidthInLineRange(startPosition.line, endPosition.line) - 1; TFloatArrayList leadingRanges = adjustedLogicalRangeToVisualRanges( startOffset, myView.visualPositionToOffset( new VisualPosition(startPosition.line, Integer.MAX_VALUE, true))); TFloatArrayList trailingRanges = adjustedLogicalRangeToVisualRanges( myView.visualPositionToOffset(new VisualPosition(endPosition.line, 0)), endOffset); if (!leadingRanges.isEmpty() && !trailingRanges.isEmpty()) { boolean containsInnerLines = endPosition.line > startPosition.line + 1; int leadingTopY = myView.visualLineToY(startPosition.line); int leadingBottomY = leadingTopY + lineHeight; int trailingTopY = myView.visualLineToY(endPosition.line); int trailingBottomY = trailingTopY + lineHeight; float start = 0; float end = 0; float leftGap = leadingRanges.get(0) - (containsInnerLines ? 0 : trailingRanges.get(0)); int adjustY = leftGap == 0 ? 2 : leftGap > 0 ? 1 : 0; // avoiding 1-pixel gap between aligned lines for (int i = 0; i < leadingRanges.size() - 1; i += 2) { start = leadingRanges.get(i); end = leadingRanges.get(i + 1); if (i > 0) { drawLine(g, leadingRanges.get(i - 1), leadingBottomY, start, leadingBottomY, rounded); } drawLine(g, start, leadingBottomY + (i == 0 ? adjustY : 0), start, leadingTopY, rounded); if ((i + 2) < leadingRanges.size()) { drawLine(g, start, leadingTopY, end, leadingTopY, rounded); drawLine(g, end, leadingTopY, end, leadingBottomY, rounded); } } end = Math.max(end, maxWidth); drawLine(g, start, leadingTopY, end, leadingTopY, rounded); drawLine(g, end, leadingTopY, end, trailingTopY - 1, rounded); float targetX = trailingRanges.get(trailingRanges.size() - 1); drawLine(g, end, trailingTopY - 1, targetX, trailingTopY - 1, rounded); adjustY = end == targetX ? -2 : -1; // for lastX == targetX we need to avoid a gap when rounding is used for (int i = trailingRanges.size() - 2; i >= 0; i -= 2) { start = trailingRanges.get(i); end = trailingRanges.get(i + 1); drawLine(g, end, trailingTopY + (i == 0 ? adjustY : 0), end, trailingBottomY, rounded); drawLine(g, end, trailingBottomY, start, trailingBottomY, rounded); drawLine(g, start, trailingBottomY, start, trailingTopY, rounded); if (i > 0) { drawLine(g, start, trailingTopY, trailingRanges.get(i - 1), trailingTopY, rounded); } } float lastX = start; if (containsInnerLines) { if (start > 0) { drawLine(g, start, trailingTopY, start, trailingTopY - 1, rounded); drawLine(g, start, trailingTopY - 1, 0, trailingTopY - 1, rounded); drawLine(g, 0, trailingTopY - 1, 0, leadingBottomY + 1, rounded); } else { drawLine(g, start, trailingTopY, 0, leadingBottomY + 1, rounded); } lastX = 0; } targetX = leadingRanges.get(0); if (lastX < targetX) { drawLine(g, lastX, leadingBottomY + 1, targetX, leadingBottomY + 1, rounded); } else { drawLine(g, lastX, leadingBottomY + 1, lastX, leadingBottomY, rounded); drawLine(g, lastX, leadingBottomY, targetX, leadingBottomY, rounded); } } } }
private static boolean isBorder(TextAttributes attributes) { return attributes != null && (attributes.getEffectType() == EffectType.BOXED || attributes.getEffectType() == EffectType.ROUNDED_BOX) && attributes.getEffectColor() != null; }
private void paintBackground( Graphics2D g, TextAttributes attributes, float x, int y, float width) { if (attributes == null) return; paintBackground(g, attributes.getBackgroundColor(), x, y, width); }
private static TextAttributes mergeAttributes(TextAttributes primary, TextAttributes secondary) { if (primary == null) return secondary; if (secondary == null) return primary; return new TextAttributes( primary.getForegroundColor() == null ? secondary.getForegroundColor() : primary.getForegroundColor(), primary.getBackgroundColor() == null ? secondary.getBackgroundColor() : primary.getBackgroundColor(), primary.getEffectColor() == null ? secondary.getEffectColor() : primary.getEffectColor(), primary.getEffectType() == null ? secondary.getEffectType() : primary.getEffectType(), primary.getFontType() == Font.PLAIN ? secondary.getFontType() : primary.getFontType()); }