11 package net.sf.gridarta.textedit.textarea;
13 import java.awt.Color;
14 import java.awt.Cursor;
15 import java.awt.Dimension;
17 import java.awt.FontMetrics;
18 import java.awt.Graphics;
19 import java.awt.Rectangle;
20 import java.awt.font.FontRenderContext;
21 import java.awt.font.TextLayout;
22 import java.util.Collections;
23 import java.util.LinkedList;
24 import java.util.List;
25 import javax.swing.JComponent;
26 import javax.swing.ToolTipManager;
27 import javax.swing.text.Segment;
28 import javax.swing.text.TabExpander;
29 import javax.swing.text.Utilities;
31 import org.apache.log4j.Category;
32 import org.apache.log4j.Logger;
33 import org.jetbrains.annotations.NotNull;
34 import org.jetbrains.annotations.Nullable;
57 private final FontRenderContext
fontRenderContext =
new FontRenderContext(null,
false,
false);
240 setAutoscrolls(
true);
241 setDoubleBuffered(
true);
244 ToolTipManager.sharedInstance().registerComponent(
this);
246 setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
248 final Font font =
new Font(
"Monospaced", Font.PLAIN, 14);
251 setForeground(Color.black);
252 setBackground(Color.white);
254 blockCaret = defaults.getBlockCaret();
255 styles = defaults.getStyles();
256 cols = defaults.getCols();
257 rows = defaults.getRows();
258 caretColor = defaults.getCaretColor();
259 selectionColor = defaults.getSelectionColor();
260 lineHighlightColor = defaults.getLineHighlightColor();
261 lineHighlight = defaults.getLineHighlight();
262 bracketHighlightColor = defaults.getBracketHighlightColor();
263 bracketHighlight = defaults.getBracketHighlight();
265 eolMarkerColor = defaults.getEolMarkerColor();
266 eolMarkers = defaults.getEolMarkers();
274 final Font font = getFont();
275 if (defaultFont != null && defaultFont.equals(font)) {
279 defaultCharWidth = (int) Math.round((
double)
new TextLayout(
"WgGhdJj", font, fontRenderContext).getAdvance() / 7.0);
280 defaultLineHeight = Math.round(font.getLineMetrics(
"WgGhdJj", fontRenderContext).getHeight());
352 public final void setFont(@NotNull
final Font font) {
363 public void paint(@NotNull
final Graphics g) {
364 tabSize = fontMetrics.charWidth(
' ') * 4;
366 final Rectangle clipRectangle = g.getClipBounds();
368 g.setColor(getBackground());
369 g.fillRect(clipRectangle.x, clipRectangle.y, clipRectangle.width, clipRectangle.height);
373 final int height = fontMetrics.getHeight();
374 final int firstInvalid = firstLine + clipRectangle.y / height;
378 final int lastInvalid = firstLine + (clipRectangle.y + clipRectangle.height - 1) / height;
383 for (
int line = firstInvalid; line <= lastInvalid; line++) {
384 paintLine(g, tokenMarker, line, horizontalOffset);
388 final int h = clipRectangle.y + clipRectangle.height;
389 repaint(0, h, getWidth(), getHeight() - h);
391 }
catch (
final Exception e) {
392 LOG.error(
"Error repainting line range {" + firstInvalid +
", " + lastInvalid +
"}", e);
401 repaint(0,
lineToY(line) + fontMetrics.getMaxDescent() + fontMetrics.getLeading(), getWidth(), fontMetrics.getHeight());
410 repaint(0,
lineToY(firstLine) + fontMetrics.getMaxDescent() + fontMetrics.getLeading(), getWidth(), (lastLine - firstLine + 1) * fontMetrics.getHeight());
422 final int nTabs = ((int) x - horizontalOffset) /
tabSize;
423 return (
float) ((nTabs + 1) * tabSize + horizontalOffset);
429 final Dimension dim = super.getPreferredSize();
436 final Dimension dim = super.getMinimumSize();
448 return new Dimension(columns * fontMetrics.charWidth(
'w'), rows * fontMetrics.getHeight());
458 private void paintLine(@NotNull
final Graphics gfx, @Nullable
final TokenMarker tokenMarker,
final int line,
final int x) {
459 final Font font = getFont();
460 final Color foreground = getForeground();
462 currentLineIndex = line;
469 gfx.drawString(
"~", 0, y + fontMetrics.getHeight());
471 }
else if (tokenMarker == null) {
487 private void paintPlainLine(@NotNull
final Graphics gfx,
final int line, @NotNull
final Font defaultFont, @NotNull
final Color defaultColor,
final int x,
final int y) {
491 gfx.setFont(defaultFont);
492 gfx.setColor(defaultColor);
494 final int yy = y + fontMetrics.getHeight();
495 final int xx = Utilities.drawTabbedText(currentLine, x, yy, gfx,
this, 0);
498 gfx.setColor(eolMarkerColor);
499 gfx.drawString(
".", xx, yy);
513 private void paintSyntaxLine(@NotNull
final Graphics gfx, @NotNull
final TokenMarker tokenMarker,
final int line, @NotNull
final Font defaultFont, @NotNull
final Color defaultColor,
final int x,
final int y) {
514 selection.
getLineText(currentLineIndex, currentLine);
515 currentLineTokens = tokenMarker.markTokens(currentLine, currentLineIndex);
519 gfx.setFont(defaultFont);
520 gfx.setColor(defaultColor);
521 final int yy = y + fontMetrics.getHeight();
526 gfx.setColor(eolMarkerColor);
527 gfx.drawString(
".", xx, yy);
538 private void paintHighlight(@NotNull
final Graphics gfx,
final int line,
final int y) {
559 final int height = fontMetrics.getHeight();
560 final int yy = y + fontMetrics.getLeading() + fontMetrics.getMaxDescent();
565 if (selectionStart == selectionEnd) {
567 gfx.setColor(lineHighlightColor);
568 gfx.fillRect(0, yy, getWidth(), height);
571 gfx.setColor(selectionColor);
583 x2 = x3 + (x1 == x3 ? 1 : 0);
584 }
else if (selectionStartLine == selectionEndLine) {
585 x1 =
offsetToX2(line, selectionStart - lineStart);
586 x2 =
offsetToX2(line, selectionEnd - lineStart);
587 }
else if (line == selectionStartLine) {
588 x1 =
offsetToX2(line, selectionStart - lineStart);
590 }
else if (line == selectionEndLine) {
592 x2 =
offsetToX2(line, selectionEnd - lineStart);
598 gfx.fillRect(Math.min(x1, x2), yy, Math.abs(x1 - x2), height);
611 if (position == -1) {
615 final int yy = y + fontMetrics.getLeading() + fontMetrics.getMaxDescent();
617 gfx.setColor(bracketHighlightColor);
621 gfx.drawRect(xx, yy, fontMetrics.charWidth(
'(') - 1, fontMetrics.getHeight() - 1);
630 private void paintCaret(@NotNull
final Graphics gfx,
final int line,
final int y) {
634 final int caretWidth = blockCaret || config.
isOverwrite() ? fontMetrics.charWidth(
'w') : 1;
635 final int yy = y + fontMetrics.getLeading() + fontMetrics.getMaxDescent();
636 final int height = fontMetrics.getHeight();
638 gfx.setColor(caretColor);
641 gfx.fillRect(caretX, yy + height - 1, caretWidth, 1);
643 if (caretWidth <= 1) {
647 gfx.drawLine(caretX, yy, caretX, yy + height - 1);
649 gfx.drawRect(caretX, yy, caretWidth - 1, height - 1);
668 currentLineIndex = lineIndex;
677 return currentLineTokens == null ? null : Collections.unmodifiableList(currentLineTokens);
685 currentLineTokens = tokens == null ? null :
new LinkedList<>(tokens);
693 final int height = getHeight();
696 final int lineHeight;
697 if (fontMetrics == null) {
700 lineHeight = fontMetrics.getHeight();
703 visibleLines = height / lineHeight;
719 if (firstLine == this.firstLine) {
732 return (line - firstLine) * fontMetrics.getHeight() - (fontMetrics.getLeading() + fontMetrics.getMaxDescent());
743 if (this.horizontalOffset == horizontalOffset) {
766 final int segmentOffset = lineSegment.offset;
770 if (tokenMarker == null) {
771 lineSegment.count = offset;
772 return x + Utilities.getTabbedTextWidth(lineSegment, fm, x,
this, 0);
776 final List<Token> tokens;
780 currentLineIndex = line;
781 tokens = tokenMarker.
markTokens(lineSegment, line);
785 final Font defaultFont = getFont();
786 for (
final Token token : tokens) {
787 final byte
id = token.getId();
794 final int length = token.getLength();
796 if (offset + segmentOffset < lineSegment.offset + length) {
797 lineSegment.count = offset - (lineSegment.offset - segmentOffset);
798 return x + Utilities.getTabbedTextWidth(lineSegment, fm, x,
this, 0);
800 lineSegment.count = length;
801 x += Utilities.getTabbedTextWidth(lineSegment, fm, x,
this, 0);
802 lineSegment.offset += length;
814 public int offsetToX(
final int line,
final int offset) {
826 final int height = fm.getHeight();
843 final char[] segmentArray = lineSegment.array;
844 final int segmentOffset = lineSegment.offset;
845 final int segmentCount = lineSegment.count;
849 if (tokenMarker == null) {
850 for (
int i = 0; i < segmentCount; i++) {
851 final char c = segmentArray[i + segmentOffset];
854 charWidth = (int)
nextTabStop((
float) width, i) - width;
856 charWidth = fm.charWidth(c);
860 if (x - charWidth <= width) {
864 if (x - charWidth / 2 <= width) {
874 final List<Token> tokens;
878 currentLineIndex = line;
879 tokens = tokenMarker.
markTokens(lineSegment, line);
884 final Font defaultFont = getFont();
885 for (
final Token token : tokens) {
886 final byte
id = token.getId();
893 final int length = token.getLength();
895 for (
int i = 0; i < length; i++) {
896 final char c = segmentArray[segmentOffset + offset + i];
899 charWidth = (int)
nextTabStop((
float) width, offset + i) - width;
901 charWidth = fm.charWidth(c);
905 if (x - charWidth <= width) {
909 if (x - charWidth / 2 <= width) {
void invalidateSelectedLines()
Repaints the lines containing the selection.
final boolean eolMarkers
Whether end of line markers should be painted.
int getCaretLine()
Returns the caret line.
int defaultLineHeight
The line height of defaultFont.
int getFirstLine()
Returns the line displayed at the text area's origin.
final Color caretColor
The caret color.
final void setFont(@NotNull final Font font)
FontMetrics fontMetrics
The font metrics for this instance.
int getSelectionEnd()
Returns the selection end offset.
void paintBracketHighlight(@NotNull final Graphics gfx, final int line, final int y)
Paints the bracket highlight.
boolean isOverwrite()
Returns whether overwrite mode is active.
final Color lineHighlightColor
The color for line highlighting.
void setCurrentLineTokens(@Nullable final List< Token > tokens)
Sets the tokens of the currently painted line.
int getBracketPosition()
Returns the position of the highlighted bracket (the bracket matching the one before the caret)...
void paintPlainLine(@NotNull final Graphics gfx, final int line, @NotNull final Font defaultFont, @NotNull final Color defaultColor, final int x, final int y)
Paint a line without token highlighting.
int getCaretPosition()
Returns the caret position.
final TextAreaSelection selection
void setStyles(@NotNull final SyntaxStyles styles)
Sets the syntax styles used to paint colorized text.
boolean isCaretVisible()
Returns true if the caret is visible, false otherwise.
int getSelectionStart()
Returns the selection start offset.
void paint(@NotNull final Graphics g)
Repaints the text.
SyntaxStyles styles
The syntax styles used to paint colorized text.
A set of SyntaxStyle instances for painting colorized text.
FontMetrics getFontMetrics()
Returns the font metrics used by this component.
The text area repaint manager.
void recalculateVisibleLines()
Recalculates the number of visible lines.
void updateScrollBars()
Updates the state of the scroll bars.
float nextTabStop(final float x, final int tabOffset)
final Color eolMarkerColor
The color for painting eol markers.
void paintLine(@NotNull final Graphics gfx, @Nullable final TokenMarker tokenMarker, final int line, final int x)
Paints one line.
int getLineCount()
Returns the number of lines in the document.
void paintCaret(@NotNull final Graphics gfx, final int line, final int y)
Paints the caret highlight.
int getLineLength(final int line)
Returns the length of the specified line.
int getHorizontalOffset()
Returns the horizontal offset of drawn lines.
final TextAreaConfig config
The TextAreaConfig options to use.
boolean isBracketHighlightEnabled()
Returns whether bracket highlighting is enabled.
TokenMarker getTokenMarker()
Returns the document's token marker.
boolean setHorizontalOffset(final int horizontalOffset)
int xyToOffset(final int x, final int y)
Converts a point to an offset, from the start of the text.
TextAreaPainter(@NotNull final JEditTextArea textArea, @NotNull final TextAreaSelection selection, @NotNull final TextAreaCaret caret, @NotNull final TextAreaDefaults defaults, @NotNull final TextAreaBrackets brackets, @NotNull final TextAreaConfig config, final boolean paintInvalid)
Creates a new repaint manager.
int getDefaultCharWidth()
This works only for fonts with fixed line height.
void setCurrentLineIndex(final int lineIndex)
Sets the currently painted line.
Base package of all Gridarta classes.
TokenMarker getTokenMarker()
Returns the token marker that is to be used to split lines of this document up into tokens...
final Segment lineSegment
CharSequence getLineText(final int lineIndex)
Returns the text on the specified line.
Font defaultFont
The Font from which defaultLineHeight and defaultCharWidth have been calculated.
SyntaxStyle getStyle(final byte id)
Returns a style for a token id.
void paintHighlight(@NotNull final Graphics gfx, final int line, final int y)
Adds highlights for a line: selections, custom highlights from client code, brackets, caret.
SyntaxDocument getDocument()
Returns the document this text area is editing.
static final Category LOG
The Logger for printing log messages.
SyntaxStyles getStyles()
Returns the syntax styles used to paint colorized text.
final JEditTextArea textArea
The associated text area that is painted.
int yToLine(final int y)
Converts a y co-ordinate to a line index.
void paintSyntaxLine(@NotNull final Graphics gfx, @NotNull final TokenMarker tokenMarker, final int line, @NotNull final Font defaultFont, @NotNull final Color defaultColor, final int x, final int y)
Paint a line with token highlighting.
final FontRenderContext fontRenderContext
The font render context for this instance.
int getSelectionStartLine()
Returns the selection start line.
Class with several utility functions used by jEdit's syntax colorizing subsystem. ...
int getDefaultLineHeight()
This works only for fonts with fixed line height.
void invalidateLineRange(final int firstLine, final int lastLine)
Marks a range of lines as needing a repaint.
boolean isBlockCaretEnabled()
Returns whether the caret should be drawn as a block.
Dimension newDimension(final int columns, final int rows)
Returns a Dimension measured in default character sizes.
This package contains the other part of the script editor.
int defaultCharWidth
The character width of defaultFont.
List< Token > markTokens(final Segment line, final int lineIndex)
A wrapper for the lower-level.
int getCurrentLineIndex()
Returns the currently painted line.
final boolean lineHighlight
Whether line highlighting is enabled.
final int rows
The number of rows.
final boolean blockCaret
Whether the caret should be wide even in insert mode.
boolean setFirstLine(final int firstLine)
static final byte NULL
Normal text token id.
int offsetToX(final int line, final int offset)
Converts an offset in a line into an x co-ordinate.
final Color bracketHighlightColor
The color for bracket highlighting.
final boolean paintInvalid
Whether invalid lines should be painted as red tildes.
static int paintSyntaxLine(final Segment line, final Iterable< Token > tokens, final SyntaxStyles styles, final TabExpander expander, final Graphics gfx, final int x, final int y)
Paints the specified line onto the graphics context.
int lineToY(final int line)
Converts a line index to a y co-ordinate.
final TextAreaBrackets brackets
The brackets to paint.
A token marker that splits lines of text into tokens.
Maintains information about the highlighted pairs of brackets.
boolean isSelectionRectangular()
Returns true if the selection is rectangular, false otherwise.
List< Token > getCurrentLineTokens()
Returns the tokens of the currently painted line.
int tabSize
The tab size in pixels.
int xToOffset(final int line, final int x)
Converts an x co-ordinate to an offset within a line.
final TextAreaCaret caret
int getLineStartOffset(final int line)
Returns the start offset of the specified line.
final int cols
The number of columns.
int currentLineIndex
The currently painted line.
Dimension getPreferredSize()
void paintLineHighlight(@NotNull final Graphics gfx, final int line, final int y)
Paints the selection highlight.
jEdit's text area component.
boolean isNextLineRequested()
Returns true if the next line should be repainted.
static final long serialVersionUID
The serial version UID.
static final byte INVALID
Invalid token id.
void updateLineInfo()
Make sure defaultCharWidth and defaultLineHeight are up-to-date.
final Color selectionColor
The selection color.
Miscellaneous configuration settings for JEditTextArea.
FontMetrics getFontMetrics(final Font font, final Graphics g)
Returns the font metrics for the styled font.
int getBracketLine()
Returns the line of the highlighted bracket (the bracket matching the one before the caret)...
int getSelectionEndLine()
Returns the selection end line.
final Segment currentLine
Holds the currently painted line.
final boolean bracketHighlight
Whether bracket highlighting is enabled.
List< Token > currentLineTokens
The tokens of the currently painted line.
int offsetToX2(final int line, final int offset)
Converts an offset in a line into an x co-ordinate.
Encapsulates default settings for a text area.
Dimension getMinimumSize()
void invalidateLine(final int line)
Marks a line as needing a repaint.
void setGraphicsFlags(final Graphics gfx, final Font font)
Sets the text color and font of the specified graphics context to that specified in this style...