📄 jedittextarea.java
字号:
/* * JEditTextArea.java - jEdit's text component * :tabSize=8:indentSize=8:noTabs=false: * :folding=explicit:collapseFolds=1: * * Copyright (C) 1999, 2003 Slava Pestov * Portions copyright (C) 2000 Ollie Rutherfurd * * 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.gjt.sp.jedit.textarea;//{{{ Importsimport java.awt.*;import java.awt.event.*;import java.util.ArrayList;import java.util.Arrays;import java.util.Enumeration;import java.util.Hashtable;import java.util.Vector;import javax.swing.*;import javax.swing.border.*;import javax.swing.event.*;import javax.swing.plaf.metal.MetalLookAndFeel;import javax.swing.text.Position;import javax.swing.text.Segment;import org.gjt.sp.jedit.*;import org.gjt.sp.jedit.buffer.*;import org.gjt.sp.jedit.gui.*;import org.gjt.sp.jedit.syntax.*;import org.gjt.sp.util.Log;//}}}/** * jEdit's text component.<p> * * Unlike most other text editors, the selection API permits selection and * concurrent manipulation of multiple, non-contiguous regions of text. * Methods in this class that deal with selecting text rely upon classes derived * the {@link Selection} class. * * @author Slava Pestov * @author John Gellene (API documentation) * @version $Id: JEditTextArea.java,v 1.188 2003/02/23 04:05:22 spestov Exp $ */public class JEditTextArea extends JComponent{ //{{{ JEditTextArea constructor /** * Creates a new JEditTextArea. */ public JEditTextArea(View view) { enableEvents(AWTEvent.FOCUS_EVENT_MASK | AWTEvent.KEY_EVENT_MASK); this.view = view; //{{{ Initialize some misc. stuff selection = new Vector(); chunkCache = new ChunkCache(this); painter = new TextAreaPainter(this); gutter = new Gutter(view,this); bufferHandler = new BufferChangeHandler(); listenerList = new EventListenerList(); caretEvent = new MutableCaretEvent(); bracketLine = bracketPosition = -1; blink = true; lineSegment = new Segment(); returnValue = new Point(); runnables = new ArrayList(); //}}} //{{{ Initialize the GUI setLayout(new ScrollLayout()); add(LEFT,gutter); add(CENTER,painter); add(RIGHT,vertical = new JScrollBar(JScrollBar.VERTICAL)); add(BOTTOM,horizontal = new JScrollBar(JScrollBar.HORIZONTAL)); horizontal.setValues(0,0,0,0); //}}} //{{{ this ensures that the text area's look is slightly // more consistent with the rest of the metal l&f. // while it depends on not-so-well-documented portions // of Swing, it only affects appearance, so future // breakage shouldn't matter if(UIManager.getLookAndFeel() instanceof MetalLookAndFeel) { setBorder(new TextAreaBorder()); vertical.putClientProperty("JScrollBar.isFreeStanding", Boolean.FALSE); horizontal.putClientProperty("JScrollBar.isFreeStanding", Boolean.FALSE); //horizontal.setBorder(null); } //}}} //{{{ Add some event listeners vertical.addAdjustmentListener(new AdjustHandler()); horizontal.addAdjustmentListener(new AdjustHandler()); mouseHandler = new MouseHandler(); painter.addMouseListener(mouseHandler); painter.addMouseMotionListener(mouseHandler); addFocusListener(new FocusHandler()); //}}} // This doesn't seem very correct, but it fixes a problem // when setting the initial caret position for a buffer // (eg, from the recent file list) focusedComponent = this; } //}}} //{{{ Getters and setters //{{{ getPainter() method /** * Returns the object responsible for painting this text area. */ public final TextAreaPainter getPainter() { return painter; } //}}} //{{{ getGutter() method /** * Returns the gutter to the left of the text area or null if the gutter * is disabled */ public final Gutter getGutter() { return gutter; } //}}} //{{{ getFoldVisibilityManager() method /** * Returns the fold visibility manager used by this text area. * @since jEdit 4.0pre1 */ public FoldVisibilityManager getFoldVisibilityManager() { return foldVisibilityManager; } //}}} //{{{ isCaretBlinkEnabled() method /** * Returns true if the caret is blinking, false otherwise. */ public final boolean isCaretBlinkEnabled() { return caretBlinks; } //}}} //{{{ setCaretBlinkEnabled() method /** * 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; if(buffer != null) invalidateLine(caretLine); } //}}} //{{{ getElectricScroll() method /** * Returns the number of lines from the top and button of the * text area that are always visible. */ public final int getElectricScroll() { return electricScroll; } //}}} //{{{ setElectricScroll() method /** * 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; } //}}} //{{{ isQuickCopyEnabled() method /** * Returns if clicking the middle mouse button pastes the most * recent selection (% register), and if Control-dragging inserts * the selection at the caret. */ public final boolean isQuickCopyEnabled() { return quickCopy; } //}}} //{{{ setQuickCopyEnabled() method /** * Sets if clicking the middle mouse button pastes the most * recent selection (% register), and if Control-dragging inserts * the selection at the caret. * @param quickCopy A boolean flag */ public final void setQuickCopyEnabled(boolean quickCopy) { this.quickCopy = quickCopy; } //}}} //{{{ getBuffer() method /** * Returns the buffer this text area is editing. */ public final Buffer getBuffer() { return buffer; } //}}} //{{{ setBuffer() method /** * Sets the buffer this text area is editing. Do not call this method - * use {@link org.gjt.sp.jedit.EditPane#setBuffer(Buffer)} instead. * @param buffer The buffer */ public void setBuffer(Buffer buffer) { if(this.buffer == buffer) return; try { bufferChanging = true; if(this.buffer != null) { // dubious? //setFirstLine(0); selectNone(); caretLine = caret = caretScreenLine = 0; bracketLine = bracketPosition = -1; this.buffer._releaseFoldVisibilityManager(foldVisibilityManager); this.buffer.removeBufferChangeListener(bufferHandler); } this.buffer = buffer; foldVisibilityManager = buffer._getFoldVisibilityManager(this); buffer.addBufferChangeListener(bufferHandler); bufferHandlerInstalled = true; firstLine = 0; maxHorizontalScrollWidth = 0; physFirstLine = foldVisibilityManager.getFirstVisibleLine(); chunkCache.setFirstLine(0,physFirstLine,true); propertiesChanged(); recalculateLastPhysicalLine(); painter.repaint(); gutter.repaint(); updateScrollBars(); fireScrollEvent(true); } finally { bufferChanging = false; } } //}}} //{{{ isEditable() method /** * Returns true if this text area is editable, false otherwise. */ public final boolean isEditable() { return buffer.isEditable(); } //}}} //{{{ getRightClickPopup() method /** * Returns the right click popup menu. */ public final JPopupMenu getRightClickPopup() { return popup; } //}}} //{{{ setRightClickPopup() method /** * Sets the right click popup menu. * @param popup The popup */ public final void setRightClickPopup(JPopupMenu popup) { this.popup = popup; } //}}} //}}} //{{{ Scrolling //{{{ getFirstLine() method /** * Returns the line displayed at the text area's origin. This is * a virtual, not a physical, line number. See * {@link FoldVisibilityManager#virtualToPhysical(int)}. */ public final int getFirstLine() { return firstLine; } //}}} //{{{ setFirstLine() method /** * Sets the line displayed at the text area's origin. * * @param firstLine A virtual, not a physical, line number. See * {@link FoldVisibilityManager#physicalToVirtual(int)}. */ public void setFirstLine(int firstLine) { if(firstLine == this.firstLine) return; _setFirstLine(firstLine); view.synchroScrollVertical(this,firstLine); } //}}} //{{{ _setFirstLine() method public void _setFirstLine(int firstLine) { firstLine = Math.max(0,Math.min(getVirtualLineCount() - 1,firstLine)); this.firstLine = firstLine; physFirstLine = virtualToPhysical(firstLine); maxHorizontalScrollWidth = 0; chunkCache.setFirstLine(firstLine,physFirstLine,false); recalculateLastPhysicalLine(); painter.repaint(); gutter.repaint(); if(this.firstLine != vertical.getValue()) updateScrollBars(); fireScrollEvent(true); } //}}} //{{{ getVisibleLines() method /** * Returns the number of lines visible in this text area. */ public final int getVisibleLines() { return visibleLines; } //}}} //{{{ getFirstPhysicalLine() method /** * Returns the first visible physical line index. * @since jEdit 4.0pre4 */ public final int getFirstPhysicalLine() { return physFirstLine; } //}}} //{{{ getLastPhysicalLine() method /** * Returns the last visible physical line index. * @since jEdit 4.0pre4 */ public final int getLastPhysicalLine() { return physLastLine; } //}}} //{{{ getHorizontalOffset() method /** * Returns the horizontal offset of drawn lines. */ public final int getHorizontalOffset() { return horizontalOffset; } //}}} //{{{ setHorizontalOffset() method /** * 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; _setHorizontalOffset(horizontalOffset); view.synchroScrollHorizontal(this,horizontalOffset); } //}}} //{{{ _setHorizontalOffset() method public void _setHorizontalOffset(int horizontalOffset) { this.horizontalOffset = horizontalOffset; if(horizontalOffset != horizontal.getValue()) updateScrollBars(); painter.repaint(); fireScrollEvent(false); } //}}} //{{{ updateScrollBars() method /** * Updates the state of the scroll bars. This should be called * if the number of lines in the buffer changes, or when the * size of the text are changes. */ public void updateScrollBars() { if(vertical != null && visibleLines != 0) { // don't display stuff past the end of the buffer if // we can help it int lineCount = getVirtualLineCount(); // very stupid but proper fix will go in later if(softWrap) lineCount += visibleLines - 1; if(lineCount < firstLine + visibleLines) { // this will call updateScrollBars(), so // just return... int newFirstLine = Math.max(0,lineCount - visibleLines); if(newFirstLine != firstLine) { setFirstLine(newFirstLine); return; } } vertical.setValues(firstLine,visibleLines,0,lineCount); vertical.setUnitIncrement(2); vertical.setBlockIncrement(visibleLines); } int width = painter.getWidth(); if(horizontal != null && width != 0) { maxHorizontalScrollWidth = 0; painter.repaint(); horizontal.setUnitIncrement(painter.getFontMetrics() .charWidth('w')); horizontal.setBlockIncrement(width / 2); } } //}}} //{{{ scrollUpLine() method /** * Scrolls up by one line. * @since jEdit 2.7pre2 */ public void scrollUpLine() { if(firstLine > 0) setFirstLine(firstLine - 1); //else // getToolkit().beep(); } //}}} //{{{ scrollUpPage() method /** * Scrolls up by one page. * @since jEdit 2.7pre2 */ public void scrollUpPage() { if(firstLine > 0) { int newFirstLine; if(softWrap) { newFirstLine = firstLine; int screenLineCount = 0; while(--newFirstLine >= 0) { int lines = chunkCache .getLineInfosForPhysicalLine( newFirstLine).length; if(screenLineCount + lines >= visibleLines) break; else screenLineCount += lines; } } else { newFirstLine = firstLine - visibleLines; } setFirstLine(newFirstLine); } /* else { getToolkit().beep(); } */ } //}}} //{{{ scrollDownLine() method /** * Scrolls down by one line. * @since jEdit 2.7pre2 */ public void scrollDownLine() { int numLines = getVirtualLineCount(); if((softWrap && firstLine + 1 < numLines) || (firstLine + visibleLines < numLines)) setFirstLine(firstLine + 1); //else // getToolkit().beep(); } //}}} //{{{ scrollDownPage() method /** * Scrolls down by one page. * @since jEdit 2.7pre2 */ public void scrollDownPage() { int numLines = getVirtualLineCount(); if((softWrap && firstLine + 1 < numLines) || (firstLine + visibleLines < numLines)) { setFirstLine(physicalToVirtual(physLastLine)); } //else // getToolkit().beep(); } //}}} //{{{ scrollToCaret() method /** * Ensures that the caret is visible by scrolling the text area if * necessary.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -