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

📄 linenumberborder.java~1~

📁 具有不同语法高亮的编辑器实例
💻 JAVA~1~
📖 第 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);

⌨️ 快捷键说明

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