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

📄 linenumberborder.java~2~

📁 具有不同语法高亮的编辑器实例
💻 JAVA~2~
📖 第 1 页 / 共 2 页
字号:
/*
 * 11/18/2004
 *
 * LineNumberBorder.java - Line numbers for a text area contained
 *                         in an RTextScrollPane.
 * Copyright (C) 2004 Robert Futrell
 * email@address.com
 * www.website.com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package org.fife.ui.rtextarea;

import java.awt.Color;
import java.awt.Component;
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.awt.Shape;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JScrollPane;
import javax.swing.border.*;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.View;

import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;

/**
 * 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.
 *
 * @author Robert Futrell
 * @version 0.5
 */
class LineNumberBorder
    implements Border, CaretListener, DocumentListener,
    PropertyChangeListener, ChangeListener {

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

  private static final Color DEFAULT_FOREGROUND = new Color(128, 128, 128);

  private RTextArea textArea;
  private JScrollPane scrollPane;

  private Font font;
  private Color foreground;
  private Color background;

  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's enabled.

  private Insets insets;
  private int cellHeight; // The height of a "cell" for a line number when word wrap is off.
  private int ascent; // The ascent to use when painting line numbers.

  private int currentNumLines;

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

  /**
   * Constructs a new <code>LineNumberBorder</code> using default values for
   * line number color (gray) and highlighting the current line.
   *
   * @param scrollPane The scroll pane using this border as the viewport
   *                   border.
   * @param textArea The text component for which line numbers will be
   *                 displayed.
   */
  public LineNumberBorder(JScrollPane scrollPane, RTextArea textArea) {
    this(scrollPane, textArea, DEFAULT_FOREGROUND);
  }

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

  /**
   * Constructs a new <code>LineNumberBorder</code>.
   *
   * @param scrollPane The scroll pane using this border as the viewport
   *                   border.
   * @param textArea The text component for which line numbers will be
   *                 displayed.
   * @param numberColor The color to use for the line numbers.  If
   *                    <code>null</code>, a default is used.
   */
  public LineNumberBorder(JScrollPane scrollPane, RTextArea textArea,
                          Color numberColor) {

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

    setForeground(numberColor != null ? numberColor : DEFAULT_FOREGROUND);
    Color bg = textArea.getBackground();
    setBackground(bg == null ? Color.WHITE : bg);

    textArea.addCaretListener(this);
    textArea.addPropertyChangeListener(this);
    scrollPane.getViewport().addChangeListener(this);
    textArea.getDocument().addDocumentListener(this);

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

    setFont(null); // Default font.
    insets = new Insets(0, 0, 0, 0);

    updateCellHeights();
    updateCellWidths();
    insertUpdate(null); // Will call updateCellWidths().

  }

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

  /**
   * Called whenever the caret changes position; highlight the correct line
   * number.
   *
   * @param e The caret event.
   */
  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;
        scrollPane.repaint();
      }
    }
    else { // lineWrap is enabled; must check actual y-coord. of caret.
      try {
        Rectangle r = textArea.modelToView(caretPosition);
        if (r != null && r.y != lastY) {
          lastY = r.y;
          currentLine = textArea.getDocument().
              getDefaultRootElement().
              getElementIndex(caretPosition) + 1;
          scrollPane.repaint();
        }
      }
      catch (BadLocationException ble) {
        ble.printStackTrace();
      }
    }

  }

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

  public void changedUpdate(DocumentEvent e) {}

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

  /**
   * Returns the background color of the line number list.
   *
   * @return The background color.
   * @see #setBackground
   */
  public Color getBackground() {
    return background;
  }

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

  /**
   * Returns the insets of this border.
   *
   * @param c This parameter is ignored.
   * @return The insets of this border.
   */
  public Insets getBorderInsets(Component c) {
    return insets;
  }

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

  /**
   * Returns the bounds of a child view as a rectangle, since
   * <code>View</code>s tend to use <code>Shape</code>.
   *
   * @param parent The parent view of the child whose bounds we're getting.
   * @param line The index of the child view.
   * @param editorRect Returned from the text area's
   *        <code>getVisibleEditorRect</code> method.
   * @return The child view's bounds.
   */
  private static final Rectangle getChildViewBounds(View parent, int line,
      Rectangle editorRect) {
    Shape alloc = parent.getChildAllocation(line, editorRect);
    return alloc instanceof Rectangle ? (Rectangle) alloc :
        alloc.getBounds();
  }

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

  /**
   * Returns the font used for the line numbers.
   *
   * @return The font.
   * @see #setFont
   */
  public Font getFont() {
    return font;
  }

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

  /**
   * Returns the foreground color of the line number list.
   *
   * @return The foreground color.
   * @see #setForeground
   */
  public Color getForeground() {
    return foreground;
  }

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

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

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

  /**
   * Called whenever a character is input (key is typed) in the text
   * document we're line-numbering.
   *
   * @param e The document event.
   */
  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 whether this border is opaque.
   *
   * @return Whether this border is opaque.
   */
  public boolean isBorderOpaque() {
    return true;
  }

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

  /**
   * Paints the line numbers.  If word wrap is enabled, the gruntwork is
   * passed on to another method.
   *
   * @param c The text area.
   * @param g The graphics context.
   * @param x The x-coordinate of the border.
   * @param y The y-coordinate of the border.
   * @param width The width of the border.
   * @param height The height of the border.
   * @see #paintWrappedLineNumbers
   */
  public void paintBorder(Component c, Graphics g, int x, int y, int width,
                          int height) {

    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(x, y, insets.left, height);
    g.setFont(font);

    if (textArea.getLineWrap() == true) {
      paintWrappedLineNumbers(g, root, x, y, visibleRect);

⌨️ 快捷键说明

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