?? jedittextarea.java
字號:
/* * JEditTextArea.java - jEdit's text component * Copyright (C) 1999 Slava Pestov * * You may use and modify this package for any purpose. Redistribution is * permitted, in both source and binary form, provided that this notice * remains intact in all source distributions of this package. */package org.syntax.jedit;import org.syntax.jedit.tokenmarker.*; import javax.swing.event.*;import javax.swing.text.*;import javax.swing.undo.*;import javax.swing.*;import java.awt.datatransfer.*;import java.awt.event.*;import java.awt.*;import java.util.Enumeration;import java.util.Vector;/** * jEdit's text area component. It is more suited for editing program * source code than JEditorPane, because it drops the unnecessary features * (images, variable-width lines, and so on) and adds a whole bunch of * useful goodies such as: * <ul> * <li>More flexible key binding scheme * <li>Supports macro recorders * <li>Rectangular selection * <li>Bracket highlighting * <li>Syntax highlighting * <li>Command repetition * <li>Block caret can be enabled * </ul> * It is also faster and doesn't have as many problems. It can be used * in other applications; the only other part of jEdit it depends on is * the syntax package.<p> * * To use it in your app, treat it like any other component, for example: * <pre>JEditTextArea ta = new JEditTextArea(); * ta.setTokenMarker(new JavaTokenMarker()); * ta.setText("public class Test {\n" * + " public static void main(String[] args) {\n" * + " System.out.println(\"Hello World\");\n" * + " }\n" * + "}");</pre> * * @author Slava Pestov * @version $Id: JEditTextArea.java,v 1.36 1999/12/13 03:40:30 sp Exp $ */public class JEditTextArea extends JComponent{ /** * Adding components with this name to the text area will place * them left of the horizontal scroll bar. In jEdit, the status * bar is added this way. */ public static String LEFT_OF_SCROLLBAR = "los"; /** * Creates a new JEditTextArea with the default settings. */ public JEditTextArea() { this(TextAreaDefaults.getDefaults()); } /** * Creates a new JEditTextArea with the specified settings. * @param defaults The default settings */ public JEditTextArea(TextAreaDefaults defaults) { // Enable the necessary events enableEvents(AWTEvent.KEY_EVENT_MASK); // Initialize some misc. stuff painter = new TextAreaPainter(this,defaults); documentHandler = new DocumentHandler(); listenerList = new EventListenerList(); caretEvent = new MutableCaretEvent(); lineSegment = new Segment(); bracketLine = bracketPosition = -1; blink = true; // Initialize the GUI setLayout(new ScrollLayout()); add(CENTER,painter); add(RIGHT,vertical = new JScrollBar(JScrollBar.VERTICAL)); add(BOTTOM,horizontal = new JScrollBar(JScrollBar.HORIZONTAL)); // Add some event listeners vertical.addAdjustmentListener(new AdjustHandler()); horizontal.addAdjustmentListener(new AdjustHandler()); painter.addComponentListener(new ComponentHandler()); painter.addMouseListener(new MouseHandler()); painter.addMouseMotionListener(new DragHandler()); addFocusListener(new FocusHandler()); // Load the defaults setInputHandler(defaults.inputHandler); setDocument(defaults.document); editable = defaults.editable; caretVisible = defaults.caretVisible; caretBlinks = defaults.caretBlinks; electricScroll = defaults.electricScroll; popup = defaults.popup; // We don't seem to get the initial focus event? focusedComponent = this; } /** * Returns if this component can be traversed by pressing * the Tab key. This returns false. */ public final boolean isManagingFocus() { return true; } /** * Returns the object responsible for painting this text area. */ public final TextAreaPainter getPainter() { return painter; } /** * Returns the input handler. */ public final InputHandler getInputHandler() { return inputHandler; } /** * Sets the input handler. * @param inputHandler The new input handler */ public void setInputHandler(InputHandler inputHandler) { this.inputHandler = inputHandler; } /** * Returns true if the caret is blinking, false otherwise. */ public final boolean isCaretBlinkEnabled() { return caretBlinks; } /** * Toggles caret blinking. * @param caretBlinks True if the caret should blink, false otherwise */ public void setCaretBlinkEnabled(boolean caretBlinks) { this.caretBlinks = caretBlinks; if(!caretBlinks) blink = false; painter.invalidateSelectedLines(); } /** * Returns true if the caret is visible, false otherwise. */ public final boolean isCaretVisible() { return (!caretBlinks || blink) && caretVisible; } /** * Sets if the caret should be visible. * @param caretVisible True if the caret should be visible, false * otherwise */ public void setCaretVisible(boolean caretVisible) { this.caretVisible = caretVisible; blink = true; painter.invalidateSelectedLines(); } /** * Blinks the caret. */ public final void blinkCaret() { if(caretBlinks) { blink = !blink; painter.invalidateSelectedLines(); } else blink = true; } /** * Returns the number of lines from the top and button of the * text area that are always visible. */ public final int getElectricScroll() { return electricScroll; } /** * Sets the number of lines from the top and bottom of the text * area that are always visible * @param electricScroll The number of lines always visible from * the top or bottom */ public final void setElectricScroll(int electricScroll) { this.electricScroll = electricScroll; } /** * Updates the state of the scroll bars. This should be called * if the number of lines in the document changes, or when the * size of the text are changes. */ public void updateScrollBars() { if(vertical != null && visibleLines != 0) { vertical.setValues(firstLine,visibleLines,0,getLineCount()); vertical.setUnitIncrement(2); vertical.setBlockIncrement(visibleLines); } int width = painter.getWidth(); if(horizontal != null && width != 0) { horizontal.setValues(-horizontalOffset,width,0,width * 5); horizontal.setUnitIncrement(painter.getFontMetrics() .charWidth('w')); horizontal.setBlockIncrement(width / 2); } } /** * Returns the line displayed at the text area's origin. */ public final int getFirstLine() { return firstLine; } /** * Sets the line displayed at the text area's origin without * updating the scroll bars. */ public void setFirstLine(int firstLine) { if(firstLine == this.firstLine) return; int oldFirstLine = this.firstLine; this.firstLine = firstLine; if(firstLine != vertical.getValue()) updateScrollBars(); painter.repaint(); } /** * Returns the number of lines visible in this text area. */ public final int getVisibleLines() { return visibleLines; } /** * Recalculates the number of visible lines. This should not * be called directly. */ public final void recalculateVisibleLines() { if(painter == null) return; int height = painter.getHeight(); int lineHeight = painter.getFontMetrics().getHeight(); int oldVisibleLines = visibleLines; visibleLines = height / lineHeight; updateScrollBars(); } /** * Returns the horizontal offset of drawn lines. */ public final int getHorizontalOffset() { return horizontalOffset; } /** * Sets the horizontal offset of drawn lines. This can be used to * implement horizontal scrolling. * @param horizontalOffset offset The new horizontal offset */ public void setHorizontalOffset(int horizontalOffset) { if(horizontalOffset == this.horizontalOffset) return; this.horizontalOffset = horizontalOffset; if(horizontalOffset != horizontal.getValue()) updateScrollBars(); painter.repaint(); } /** * A fast way of changing both the first line and horizontal * offset. * @param firstLine The new first line * @param horizontalOffset The new horizontal offset * @return True if any of the values were changed, false otherwise */ public boolean setOrigin(int firstLine, int horizontalOffset) { boolean changed = false; int oldFirstLine = this.firstLine; if(horizontalOffset != this.horizontalOffset) { this.horizontalOffset = horizontalOffset; changed = true; } if(firstLine != this.firstLine) { this.firstLine = firstLine; changed = true; } if(changed) { updateScrollBars(); painter.repaint(); } return changed; } /** * Ensures that the caret is visible by scrolling the text area if * necessary. * @return True if scrolling was actually performed, false if the * caret was already visible */ public boolean scrollToCaret() { int line = getCaretLine(); int lineStart = getLineStartOffset(line); int offset = Math.max(0,Math.min(getLineLength(line) - 1, getCaretPosition() - lineStart)); return scrollTo(line,offset); } /** * Ensures that the specified line and offset is visible by scrolling * the text area if necessary. * @param line The line to scroll to * @param offset The offset in the line to scroll to * @return True if scrolling was actually performed, false if the * line and offset was already visible */ public boolean scrollTo(int line, int offset) { // visibleLines == 0 before the component is realized // we can't do any proper scrolling then, so we have // this hack... if(visibleLines == 0) { setFirstLine(Math.max(0,line - electricScroll)); return true; } int newFirstLine = firstLine; int newHorizontalOffset = horizontalOffset; if(line < firstLine + electricScroll) { newFirstLine = Math.max(0,line - electricScroll); } else if(line + electricScroll >= firstLine + visibleLines) { newFirstLine = (line - visibleLines) + electricScroll + 1; if(newFirstLine + visibleLines >= getLineCount()) newFirstLine = getLineCount() - visibleLines; if(newFirstLine < 0) newFirstLine = 0; } int x = _offsetToX(line,offset); int width = painter.getFontMetrics().charWidth('w'); if(x < 0) { newHorizontalOffset = Math.min(0,horizontalOffset - x + width + 5); } else if(x + width >= painter.getWidth()) { newHorizontalOffset = horizontalOffset + (painter.getWidth() - x) - width - 5; } return setOrigin(newFirstLine,newHorizontalOffset); } /** * Converts a line index to a y co-ordinate. * @param line The line */ public int lineToY(int line) { FontMetrics fm = painter.getFontMetrics(); return (line - firstLine) * fm.getHeight() - (fm.getLeading() + fm.getMaxDescent()); } /** * Converts a y co-ordinate to a line index. * @param y The y co-ordinate */ public int yToLine(int y) { FontMetrics fm = painter.getFontMetrics(); int height = fm.getHeight(); return Math.max(0,Math.min(getLineCount() - 1, y / height + firstLine)); } /** * Converts an offset in a line into an x co-ordinate. This is a * slow version that can be used any time. * @param line The line * @param offset The offset, from the start of the line */ public final int offsetToX(int line, int offset) { // don't use cached tokens painter.currentLineTokens = null; return _offsetToX(line,offset); } /** * Converts an offset in a line into an x co-ordinate. This is a * fast version that should only be used if no changes were made * to the text since the last repaint. * @param line The line * @param offset The offset, from the start of the line */ public int _offsetToX(int line, int offset) { TokenMarker tokenMarker = getTokenMarker(); /* Use painter's cached info for speed */ FontMetrics fm = painter.getFontMetrics(); getLineText(line,lineSegment); int segmentOffset = lineSegment.offset; int x = horizontalOffset; /* If syntax coloring is disabled, do simple translation */ if(tokenMarker == null) { lineSegment.count = offset; return x + Utilities.getTabbedTextWidth(lineSegment, fm,x,painter,0); } /* If syntax coloring is enabled, we have to do this because * tokens can vary in width */ else { Token tokens; if(painter.currentLineIndex == line && painter.currentLineTokens != null) tokens = painter.currentLineTokens; else { painter.currentLineIndex = line; tokens = painter.currentLineTokens = tokenMarker.markTokens(lineSegment,line); } Toolkit toolkit = painter.getToolkit(); Font defaultFont = painter.getFont(); SyntaxStyle[] styles = painter.getStyles(); for(;;) { byte id = tokens.id; if(id == Token.END) { return x; } if(id == Token.NULL) fm = painter.getFontMetrics(); else fm = styles[id].getFontMetrics(defaultFont); int length = tokens.length; if(offset + segmentOffset < lineSegment.offset + length) { lineSegment.count = offset - (lineSegment.offset - segmentOffset); return x + Utilities.getTabbedTextWidth( lineSegment,fm,x,painter,0); } else { lineSegment.count = length; x += Utilities.getTabbedTextWidth( lineSegment,fm,x,painter,0); lineSegment.offset += length; } tokens = tokens.next; } } }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -