textareapainter.java

来自「java写的多功能文件编辑器」· Java 代码 · 共 899 行 · 第 1/2 页

JAVA
899
字号
  /**    * Returns the font metrics used by this component.    */  public FontMetrics getFontMetrics()  {    return fm;  }  /**    * Sets the font for this component. This is overridden to update the    * cached font metrics and to recalculate which lines are visible.    * @param font The font    */  public void setFont(Font font)  {    super.setFont(font);    fm = Toolkit.getDefaultToolkit().getFontMetrics(font);    textArea.recalculateVisibleLines();  }  /**    * Repaints the text.    * @param g The graphics context    */  public void paint(Graphics gfx)  {    ///// TEMP FIX /////    //setAntiAliasing(gfx);    tabSize = fm.charWidth(' ') *              ((Integer) textArea .getDocument().getProperty(PlainDocument.tabSizeAttribute)).intValue();    Rectangle clipRect = gfx.getClipBounds();    gfx.setColor(getBackground());    gfx.fillRect(clipRect.x, clipRect.y, clipRect.width, clipRect.height);    // We don't use yToLine() here because that method doesn't    // return lines past the end of the document    int height = fm.getHeight();    int firstLine = textArea.getFirstLine();    int firstInvalid = firstLine + clipRect.y / height;    // Because the clipRect's height is usually an even multiple    // of the font height, we subtract 1 from it, otherwise one    // too many lines will always be painted.    int lastInvalid = firstLine + (clipRect.y + clipRect.height - 1) / height;    int x = textArea.getHorizontalOffset();    int lineCount = textArea.getLineCount();    try    {      TokenMarker tokenMarker = textArea.getDocument().getTokenMarker();      int maxWidth = textArea.maxHorizontalScrollWidth;      boolean updateMaxHorizontalScrollWidth = false;      for (int line = firstInvalid; line <= lastInvalid; line++)      {        boolean valid = line >= 0 && line < lineCount;        int width = paintLine(gfx, tokenMarker, valid, line, x) - x + 5 /* Yay */;        if (valid)        {          tokenMarker.setLineWidth(line, width);          if (width > maxWidth)            updateMaxHorizontalScrollWidth = true;        }      }      if (tokenMarker.isNextLineRequested())      {        int h = clipRect.y + clipRect.height;        repaint(0, h, getWidth(), getHeight() - h);      }      if (updateMaxHorizontalScrollWidth)        textArea.updateMaxHorizontalScrollWidth();    } catch (Exception e) {      System.err.println("Error repainting line" + " range {" + firstInvalid + "," + lastInvalid + "}:");      e.printStackTrace();    }  }  /**    * Marks a line as needing a repaint.    * @param line The line to invalidate    */  public final void invalidateLine(int line)  {    repaint(0, textArea.lineToY(line) + fm.getMaxDescent() + fm.getLeading(), getWidth(), fm.getHeight());  }  /**    * Marks a range of lines as needing a repaint.    * @param firstLine The first line to invalidate    * @param lastLine The last line to invalidate    */  public final void invalidateLineRange(int firstLine, int lastLine)  {    repaint(0, textArea.lineToY(firstLine) + fm.getMaxDescent() + fm.getLeading(), getWidth(),            (lastLine - firstLine + 1) * fm.getHeight());  }  /**    * Repaints the lines containing the selection.    */  public final void invalidateSelectedLines()  {    invalidateLineRange(textArea.getSelectionStartLine(), textArea.getSelectionEndLine());  }  /**    * Implementation of TabExpander interface. Returns next tab stop after    * a specified point.    * @param x The x co-ordinate    * @param tabOffset Ignored    * @return The next tab stop after <i>x</i>    */  public float nextTabStop(float x, int tabOffset)  {    if (tabSize == 0)    {      tabSize = fm.charWidth(' ') *              ((Integer) textArea.getDocument().getProperty(PlainDocument.tabSizeAttribute)).intValue();    }    int offset = textArea.getHorizontalOffset();    int ntabs = ((int) x - offset) / tabSize;    return (ntabs + 1) * tabSize + offset;  }  /**    * Returns the painter's preferred size.    */  public Dimension getPreferredSize()  {    Dimension dim = new Dimension();    dim.width = fm.charWidth('w') * cols;    dim.height = fm.getHeight() * rows;    return dim;  }  /**    * Returns the painter's minimum size.    */  public Dimension getMinimumSize()  {    return getPreferredSize();  }  // protected members  protected JEditTextArea textArea;  protected SyntaxStyle[] styles;  protected Color caretColor;  protected Color selectionColor;  protected Color lineHighlightColor;  protected Color highlightColor;  protected Color bracketHighlightColor;  protected Color eolMarkerColor;  protected boolean blockCaret;  protected boolean lineHighlight;  protected boolean bracketHighlight;  protected boolean paintInvalid;  protected boolean eolMarkers;  protected int cols;  protected int rows;  protected int tabSize;  protected FontMetrics fm;  protected TextAreaHighlight highlights;  protected TextAreaHighlight firstPriorityHighlights;  protected int paintLine(Graphics gfx, TokenMarker tokenMarker, boolean valid, int line, int x)  {    Font defaultFont = getFont();    Color defaultColor = getForeground();    int y = textArea.lineToY(line);    if (!valid)    {      if (paintInvalid)      {        paintHighlight(gfx, line, y);        styles[Token.INVALID].setGraphicsFlags(gfx, defaultFont);        gfx.drawString("~", 0, y + fm.getHeight());      }    } else {      x = paintSyntaxLine(gfx, tokenMarker, line, defaultFont, defaultColor, x, y);    }    return x;  }  protected int paintSyntaxLine(Graphics gfx, TokenMarker tokenMarker, int line, Font defaultFont,                                Color defaultColor, int x, int y)  {    // priority highlights first    if (firstPriorityHighlights != null)      firstPriorityHighlights.paintHighlight(gfx, line, y);    Segment tempSeg = textArea.lineSegment;    textArea.getLineText(line, textArea.lineSegment);    Token tokens = tokenMarker.markTokens(textArea.lineSegment, line);    Token first = tokens;    int backY = y + fm.getLeading() + fm.getMaxDescent();    int backHeight = fm.getHeight();    int backWidth = fm.charWidth('w');    int offset = x;    int offsetShift = 0;    int charOffset = 0;    String textLine = textArea.lineSegment.toString();    org.jext.JextTextArea jextArea = (org.jext.JextTextArea) textArea;    while (tokens.id != Token.END)    {      offsetShift = backWidth * org.jext.Utilities.getRealLength(textLine.substring(charOffset, charOffset + tokens.length),                                                                 jextArea.getTabSize());      charOffset += tokens.length;      if (tokens.highlightBackground)      {        gfx.setColor(highlightColor);        gfx.fillRect(offset, backY, offsetShift, backHeight);      }      offset += offsetShift;      tokens = tokens.next;    }    textArea.lineSegment = tempSeg;    paintHighlight(gfx, line, y);    textArea.getLineText(line, textArea.lineSegment);    gfx.setFont(defaultFont);    gfx.setColor(defaultColor);    y += fm.getHeight();    x = SyntaxUtilities.paintSyntaxLine(textArea.lineSegment, first,                                        styles, this, gfx, x, y);    if (eolMarkers)    {      gfx.setColor(eolMarkerColor);      gfx.drawString(".", x, y);    }    return x;  }  protected void paintHighlight(Graphics gfx, int line, int y)  {    if (line >= textArea.getSelectionStartLine() && line <= textArea.getSelectionEndLine())      paintLineHighlight(gfx, line, y);    if (linesIntervalHighlight && linesInterval > 0)      paintLinesInterval(gfx, line, y);    if (wrapGuide && wrapGuideOffset > 0)      paintWrapGuide(gfx, line, y);    if (highlights != null)      highlights.paintHighlight(gfx, line, y);    if (bracketHighlight && line == textArea.getBracketLine())      paintBracketHighlight(gfx, line, y);    if (line == textArea.getCaretLine())      paintCaret(gfx, line, y);    if (line == textArea.getShadowCaretLine())      paintShadowCaret(gfx, line, y);  }  protected void paintWrapGuide(Graphics gfx, int line, int y)  {    gfx.setColor(wrapGuideColor);    int _offset = y + (fm.getLeading() + fm.getMaxDescent());    int start = (line > 0) ? _offset : 0;    int end = (line != textArea.getLineCount() - 1) ? _offset + fm.getHeight() : textArea.getHeight();    int charWidth = fm.charWidth('m');    int offset = textArea.getHorizontalOffset();    int width = textArea.getWidth();    int off = wrapGuideOffset * charWidth + offset;    if (off >= 0 && off < width)      gfx.drawLine(off, start, off, end);  }  protected void paintLinesInterval(Graphics gfx, int line, int y)  {    if (((line + 1) % linesInterval) == 0)    {      int height = fm.getHeight();      int _offset = y + fm.getLeading() + fm.getMaxDescent();      int selectionStart = textArea.getSelectionStart();      int selectionEnd = textArea.getSelectionEnd();      gfx.setColor(linesIntervalColor);      gfx.fillRect(0, _offset, getWidth(), height);      gfx.setColor(selectionColor);      int selectionStartLine = textArea.getSelectionStartLine();      int selectionEndLine = textArea.getSelectionEndLine();      int lineStart = textArea.getLineStartOffset(line);      int x1, x2;      if (textArea.isSelectionRectangular())      {        int lineLen = textArea.getLineLength(line);        x1 = textArea.offsetToX(line,                Math.min(lineLen, selectionStart - textArea.getLineStartOffset(selectionStartLine)));        x2 = textArea.offsetToX(line, Math.min(lineLen, selectionEnd - textArea.getLineStartOffset(selectionEndLine)));        if (x1 == x2)          x2++;      } else if (selectionStartLine == selectionEndLine) {        x1 = textArea.offsetToX(line, selectionStart - lineStart);        x2 = textArea.offsetToX(line, selectionEnd - lineStart);      } else if (line == selectionStartLine) {        x1 = textArea.offsetToX(line, selectionStart - lineStart);        x2 = textArea.offsetToX(line, textArea.getLineLength(line));      } else if (line == selectionEndLine) {        x1 = 0;        x2 = textArea.offsetToX(line, selectionEnd - lineStart);      } else {        x1 = 0;        x2 = textArea.offsetToX(line, textArea.getLineLength(line));      }      gfx.fillRect(x1 > x2 ? x2 : x1, _offset, x1 > x2 ? (x1 - x2) : (x2 - x1), height);    }  }  protected void paintLineHighlight(Graphics gfx, int line, int y)  {    int height = fm.getHeight();    y += fm.getLeading() + fm.getMaxDescent();    int selectionStart = textArea.getSelectionStart();    int selectionEnd = textArea.getSelectionEnd();    if (selectionStart == selectionEnd)    {      if (lineHighlight)      {        gfx.setColor(lineHighlightColor);        gfx.fillRect(0, y, getWidth(), height);      }    } else {      gfx.setColor(selectionColor);      int selectionStartLine = textArea.getSelectionStartLine();      int selectionEndLine = textArea.getSelectionEndLine();      int lineStart = textArea.getLineStartOffset(line);      int x1, x2;      if (textArea.isSelectionRectangular())      {        int lineLen = textArea.getLineLength(line);        x1 = textArea.offsetToX(line,                                Math.min(lineLen, selectionStart - textArea.getLineStartOffset(selectionStartLine)));        x2 = textArea.offsetToX(line,                                Math.min(lineLen, selectionEnd - textArea.getLineStartOffset(selectionEndLine)));        if (x1 == x2)          x2++;      } else if (selectionStartLine == selectionEndLine) {        x1 = textArea.offsetToX(line, selectionStart - lineStart);        x2 = textArea.offsetToX(line, selectionEnd - lineStart);      } else if (line == selectionStartLine) {        x1 = textArea.offsetToX(line, selectionStart - lineStart);        //x2 = getWidth();        x2 = textArea.offsetToX(line, textArea.getLineLength(line));      } else if (line == selectionEndLine) {        x1 = 0;        x2 = textArea.offsetToX(line, selectionEnd - lineStart);      } else {        x1 = 0;        //x2 = getWidth();        x2 = textArea.offsetToX(line, textArea.getLineLength(line));      }      int w = x1 > x2 ? (x1 - x2) : (x2 - x1);      if (w == 0) w = 4;      // "inlined" min/max()      gfx.fillRect(x1 > x2 ? x2 : x1, y, w, height);    }  }  protected void paintBracketHighlight(Graphics gfx, int line, int y)  {    int position = textArea.getBracketPosition();    if (position == -1)      return;    y += fm.getLeading() + fm.getMaxDescent();    int x = textArea.offsetToX(line, position);    gfx.setColor(bracketHighlightColor);    // Hack!!! Since there is no fast way to get the character    // from the bracket matching routine, we use ( since all    // brackets probably have the same width anyway    gfx.fillRect(x, y, fm.charWidth('(') - 1, fm.getHeight() - 1);  }  protected void paintCaret(Graphics gfx, int line, int y)  {    if (textArea.isCaretVisible())    {      int offset = textArea.getCaretPosition() - textArea.getLineStartOffset(line);      int caretX = textArea.offsetToX(line, offset);      int caretWidth = ((blockCaret || textArea.isOverwriteEnabled()) ? fm.charWidth('w') : 1);      y += fm.getLeading() + fm.getMaxDescent();      int height = fm.getHeight();      gfx.setColor(caretColor);      if (textArea.isOverwriteEnabled())      {        gfx.fillRect(caretX, y + height - 1, caretWidth, 1);      } else if (caretWidth > 1) {        gfx.drawRect(caretX, y, caretWidth - 1, height - 1);      } else {        gfx.drawLine(caretX, y, caretX, y + height - 1);      }    }  }  protected void paintShadowCaret(Graphics gfx, int line, int y)  {    int offset = textArea.getShadowCaretPosition() - textArea.getLineStartOffset(line);    int caretX = textArea.offsetToX(line, offset);    y += fm.getLeading() + fm.getMaxDescent();    int height = fm.getHeight();    gfx.setColor(caretColor.darker());    for (int i = 0; i < height; i += 3)      gfx.drawLine(caretX, y + i, caretX, y + i + 1);  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?