⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linenumberlist.java

📁 具有不同语法高亮的编辑器实例
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * 11/14/2003
 *
 * LineNumberList.java - Line numbers for a text area contained
 *                        in an RTextScrollPane.
 */
package org.fife.ui.rtextarea;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;

/**
 * Used by <code>RTextScrollPane</code> to display line numbers for a text
 * area.  This component is capable of displaying line numbers for any
 * <code>RTextArea</code>, with line wrap enabled or disabled.  You can also
 * choose the line number font, color, and choose whether or not to "highlight"
 * the current line number.<p>
 *
 * NOTE:  To speed things up a little, this component does not "scroll."  It
 * needs to be added to an <code>RTextScrollPane</code> inside a special
 * viewport, like so:<p>
 *
 * <pre>
 *	JViewport viewport = new JViewport() {
 *			public void setViewPosition(java.awt.Point p) {
 *				Component c = getView();
 *				if (c!=null)
 *					c.repaint();
 *			}
 *		};
 *	viewport.setView(lineNumberList);
 *	setRowHeader(viewport);
 * </pre>
 *
 * This needs to be done because this component figures out how to paint itself
     * from the current scroll-state of the text area, so there is no need to scroll
 * this guy himself.<p>
 *
 * This class is probably going to be replaced by
 * {@link org.fife.ui.LineNumberBorder}, as not only does that class not need
 * to be scrolled, but he is also not a <code>JComponent</code> (less memory)
 * and he doesn't require the additional overhead of a <code>JViewport</code>
 * (slower).
 *
 * @author Robert Futrell
 * @version 0.5
 */
class LineNumberList
    extends JComponent
    implements CaretListener,
    DocumentListener, PropertyChangeListener {

  /**
   *
   */
  private static final long serialVersionUID = -7969233269296717504L;

  private static final int MIN_CELL_WIDTH = 24;
  private static final int RHS_BORDER_WIDTH = 8;

  private RTextArea textArea; // The text component for which we're displaying the line numbers.

  private int currentLine; // The last line the caret was on.
  private int lastY = -1; // Used to check if caret is on a new line when line wrap is enabled.

  private int cellHeight; // The height of a "cell" for a line number when word wrap is off.
  private int cellWidth; // The width used for all line number cells.
  private int ascent; // The ascent to use when painting line numbers.

  private int currentNumLines;

      /*****************************************************************************/

  /**
   * Constructs a new <code>LineNumberList</code> using default values for
   * line number color (gray) and highlighting the current line.
   *
   * @param textArea The text component for which line numbers will be
   *                 displayed.
   */
  public LineNumberList(RTextArea textArea) {
    this(textArea, new Color(128, 128, 128));
  }

      /*****************************************************************************/

  /**
   * Constructs a new <code>LineNumberList</code>.
   *
   * @param textArea The text component for which line numbers will be
   *                 displayed.
   * @param numberColor The color to use for the line numbers.
   */
  public LineNumberList(RTextArea textArea, Color numberColor) {

    // Remember what text component we're keeping line numbers for.
    this.textArea = textArea;

    if (numberColor != null) {
      setForeground(numberColor);
    }
    else {
      setForeground(new Color(128, 128, 128));
    }
    Color bg = textArea.getBackground();
    setBackground(bg == null ? Color.WHITE : bg);

    textArea.addCaretListener(this);
    textArea.addPropertyChangeListener(this);
    textArea.getDocument().addDocumentListener(this);

    // Initialize currentLine; otherwise, the current line won't start
    // off as highlighted.
    currentLine = 1;

    // Have the line number space be just enough space for '1' through '9'.
    updateCellHeights();
    updateCellWidths();

  }

      /*****************************************************************************/

  /**
   * Called whenever the caret changes position; highlight the correct line
   * number.
   */
  public void caretUpdate(CaretEvent e) {

    int caretPosition = textArea.getCaretPosition();

    // We separate the line wrap/no line wrap cases because word wrap can
    // make a single line from the model (document) be on multiple lines
    // on the screen (in the view); thus, we have to enhance the logic for
    // that case a bit - we check the actual y-coordinate of the caret
    // when line wrap is enabled.  For the no-line-wrap case, getting the
    // line number of the caret suffices.  This increases efficiency in
    // the no-line-wrap case.

    if (textArea.getLineWrap() == false) {
      int line = textArea.getDocument().getDefaultRootElement().
          getElementIndex(caretPosition) + 1;
      if (currentLine != line) {
        currentLine = line;
        repaint();
      }
    }
    else { // lineWrap is enabled; must check actual y-coord. of caret.
      try {
        int y = textArea.modelToView(caretPosition).y;
        if (y != lastY) {
          lastY = y;
          currentLine = textArea.getDocument().
              getDefaultRootElement().
              getElementIndex(caretPosition) + 1;
          repaint();
        }
      }
      catch (BadLocationException ble) {
        ble.printStackTrace();
      }
    }

  }

      /*****************************************************************************/

  public void changedUpdate(DocumentEvent e) {}

      /*****************************************************************************/

  /**
   * Returns the color to use to paint line numbers.
   *
   * @return The color used when painting line numbers.
   * @see #setLineNumberColor
   */
  public Color getLineNumberColor() {
    return getForeground();
  }

      /*****************************************************************************/

  public Dimension getPreferredSize() {
    return new Dimension(cellWidth, textArea.getHeight());
  }

      /*****************************************************************************/

  /**
   * Returns the length of a string if it is drawn with the specified
   * graphics context.  This method assumes that there are NO tabs in
   * the string.<br><br>
   *
   * NOTE:  This is basically ripped off from
   * <code>javax.swing.text.Utilities</code>, but slightly optimized for our
   * situation.
   *
   * @param text The text to be painted.
   * @param metrics The metrics with which to do the calculating.
   * @return The width of the string when painted.
   */
  public static final int getTextWidth(String text, FontMetrics metrics) {
    int width = 0;
    int end = text.length();
    for (int i = 0; i < end; i++) {
      width += metrics.charWidth(text.charAt(i));
    }
    return width;
  }

      /*****************************************************************************/

  /**
   * Called whenever a character is input (key is typed) in the text document
   * we're line-numbering.
   */
  public void insertUpdate(DocumentEvent e) {

    int newNumLines = textArea.getDocument().getDefaultRootElement().
        getElementCount();
    if (newNumLines > currentNumLines) {
      // Adjust the amount of space the line numbers take up,
      // if necessary.
      if (newNumLines / 10 > currentNumLines / 10) {
        updateCellWidths();
      }
      currentNumLines = newNumLines;
    }

  }

      /*****************************************************************************/

  // Returns the Component used as the JList cell.
  public void paint(Graphics g) {

    Element root = textArea.getDocument().getDefaultRootElement();
    Rectangle visibleRect = textArea.getVisibleRect();

    if (visibleRect == null) {
      return;
    }

    // Fill in the background the same color as the text component.
    g.setColor(getBackground());
    g.fillRect(0, 0, cellWidth, visibleRect.height);

    if (textArea.getLineWrap() == true) {
      paintWrappedLineNumbers(g, root, visibleRect);
      return;
    }

    // Get the first and last lines to paint.
    int topLine = visibleRect.y / cellHeight + 1;
    int bottomLine = Math.min(topLine + visibleRect.height / cellHeight,
                              root.getElementCount()) + 1;

    // Get where to start painting (top of the row), and where to paint
    // the line number (drawString expects y==baseline).
    // We need to be "scrolled up" up just enough for the missing part of
    // the first line.
    int actualTopY = - (visibleRect.y % cellHeight);
    Insets textAreaInsets = textArea.getInsets();

⌨️ 快捷键说明

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