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;
58 private final FontRenderContext
fontRenderContext =
new FontRenderContext(
null,
false,
false);
247 setAutoscrolls(
true);
248 setDoubleBuffered(
true);
251 ToolTipManager.sharedInstance().registerComponent(
this);
253 setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
255 final Font font =
new Font(
"Monospaced", Font.PLAIN, 14);
258 setForeground(Color.black);
259 setBackground(Color.white);
262 styles = defaults.getStyles();
263 cols = defaults.getCols();
264 rows = defaults.getRows();
281 final Font font = getFont();
359 public final void setFont(@NotNull
final Font font) {
370 public void paint(@NotNull
final Graphics g) {
373 final Rectangle clipRectangle = g.getClipBounds();
375 g.setColor(getBackground());
376 g.fillRect(clipRectangle.x, clipRectangle.y, clipRectangle.width, clipRectangle.height);
381 final int firstInvalid =
firstLine + clipRectangle.y / height;
385 final int lastInvalid =
firstLine + (clipRectangle.y + clipRectangle.height - 1) / height;
390 for (
int line = firstInvalid; line <= lastInvalid; line++) {
395 final int h = clipRectangle.y + clipRectangle.height;
396 repaint(0, h, getWidth(), getHeight() - h);
398 }
catch (
final Exception e) {
399 LOG.error(
"Error repainting line range {" + firstInvalid +
", " + lastInvalid +
"}", e);
436 final Dimension dim = super.getPreferredSize();
443 final Dimension dim = super.getMinimumSize();
465 private void paintLine(@NotNull
final Graphics gfx, @Nullable
final TokenMarker tokenMarker,
final int line,
final int x) {
469 final Font font = getFont();
470 final Color foreground = getForeground();
475 gfx.drawString(
"~", 0, y +
fontMetrics.getHeight());
477 }
else if (tokenMarker ==
null) {
493 private void paintPlainLine(@NotNull
final Graphics gfx,
final int line, @NotNull
final Font
defaultFont, @NotNull
final Color defaultColor,
final int x,
final int y) {
498 gfx.setColor(defaultColor);
501 final int xx = Utilities.drawTabbedText(
currentLine, x, yy, gfx,
this, 0);
505 gfx.drawString(
".", xx, yy);
519 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) {
526 gfx.setColor(defaultColor);
533 gfx.drawString(
".", xx, yy);
544 private void paintHighlight(@NotNull
final Graphics gfx,
final int line,
final int y) {
571 if (selectionStart == selectionEnd) {
574 gfx.fillRect(0, yy, getWidth(), height);
589 x2 = x3 + (x1 == x3 ? 1 : 0);
590 }
else if (selectionStartLine == selectionEndLine) {
591 x1 =
offsetToX2(line, selectionStart - lineStart);
592 x2 =
offsetToX2(line, selectionEnd - lineStart);
593 }
else if (line == selectionStartLine) {
594 x1 =
offsetToX2(line, selectionStart - lineStart);
596 }
else if (line == selectionEndLine) {
598 x2 =
offsetToX2(line, selectionEnd - lineStart);
604 gfx.fillRect(Math.min(x1, x2), yy, Math.abs(x1 - x2), height);
617 if (position == -1) {
636 private void paintCaret(@NotNull
final Graphics gfx,
final int line,
final int y) {
647 gfx.fillRect(caretX, yy + height - 1, caretWidth, 1);
649 if (caretWidth <= 1) {
653 gfx.drawLine(caretX, yy, caretX, yy + height - 1);
655 gfx.drawRect(caretX, yy, caretWidth - 1, height - 1);
699 final int height = getHeight();
702 final int lineHeight;
776 if (tokenMarker ==
null) {
778 return x + Utilities.getTabbedTextWidth(
lineSegment, fm, x,
this, 0);
782 final List<Token> tokens;
792 for (
final Token token : tokens) {
793 final byte id = token.getId();
796 final int length = token.getLength();
798 if (offset + segmentOffset <
lineSegment.offset + length) {
800 return x + Utilities.getTabbedTextWidth(
lineSegment, fm, x,
this, 0);
803 x += Utilities.getTabbedTextWidth(
lineSegment, fm, x,
this, 0);
815 public int offsetToX(
final int line,
final int offset) {
827 final int height = fm.getHeight();
850 if (tokenMarker ==
null) {
851 for (
int i = 0; i < segmentCount; i++) {
852 final char c = segmentArray[i + segmentOffset];
857 charWidth = fm.charWidth(c);
861 if (x - charWidth <= width) {
865 if (x - charWidth / 2 <= width) {
875 final List<Token> tokens;
886 for (
final Token token : tokens) {
887 final byte id = token.getId();
890 final int length = token.getLength();
892 for (
int i = 0; i < length; i++) {
893 final char c = segmentArray[segmentOffset + offset + i];
896 charWidth = (int)
nextTabStop(width, offset + i) - width;
898 charWidth = fm.charWidth(c);
902 if (x - charWidth <= width) {
906 if (x - charWidth / 2 <= width) {