📄 jedittextarea.java
字号:
/* * JEditTextArea.java - jEdit's text component * :tabSize=8:indentSize=8:noTabs=false: * :folding=explicit:collapseFolds=1: * * Copyright (C) 1999, 2004 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.lang.reflect.Method;import java.util.Iterator;import java.util.LinkedList;import java.util.List;import java.util.Set;import java.util.TreeSet;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.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.307 2004/03/12 19:27:00 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); listenerList = new EventListenerList(); caretEvent = new MutableCaretEvent(); blink = true; lineSegment = new Segment(); returnValue = new Point(); structureMatchers = new LinkedList(); structureMatchers.add(new StructureMatcher.BracketMatcher()); //}}} //{{{ Initialize the GUI setLayout(new ScrollLayout()); add(CENTER,painter); add(LEFT,gutter); // some plugins add stuff in a "right-hand" gutter verticalBox = new Box(BoxLayout.X_AXIS); verticalBox.add(vertical = new JScrollBar(JScrollBar.VERTICAL)); vertical.setRequestFocusEnabled(false); add(RIGHT,verticalBox); add(BOTTOM,horizontal = new JScrollBar(JScrollBar.HORIZONTAL)); horizontal.setRequestFocusEnabled(false); 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; } //}}} //{{{ dispose() method /** * Plugins and macros should not call this method. * @since jEdit 4.2pre1 */ public void dispose() { DisplayManager.textAreaDisposed(this); } //}}} //{{{ Getters and setters //{{{ getView() method /** * Returns this text area's view. * @since jEdit 4.2pre5 */ public View getView() { return view; } //}}} //{{{ 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; } //}}} //{{{ getDisplayManager() method /** * Returns the display manager used by this text area. * @since jEdit 4.2pre1 */ public DisplayManager getDisplayManager() { return displayManager; } //}}} //{{{ 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; match = null; } this.buffer = buffer; chunkCache.setBuffer(buffer); propertiesChanged(); if(displayManager != null) { DisplayManager.releaseDisplayManager( displayManager); } displayManager = DisplayManager.getDisplayManager( buffer,this); displayManager.init(); if(!buffer.isLoaded()) updateScrollBars(); repaint(); 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; } //}}} //{{{ getDragAndDropCallback() method /** * Drag and drop of text in jEdit is implementing using jEdit 1.4 APIs, * however since jEdit must run with Java 1.3, this class only has the * necessary support to call a hook method via reflection. The method * is provided by the {@link org.gjt.sp.jedit.Java14} class and handles * the drag and drop API calls themselves. * @since jEdit 4.2pre5 */ public Method getDragAndDropCallback() { return dndCallback; } //}}} //{{{ setDragAndDropCallback() method /** * Drag and drop of text in jEdit is implementing using jEdit 1.4 APIs, * however since jEdit must run with Java 1.3, this class only has the * necessary support to call a hook method via reflection. The method * is provided by the {@link org.gjt.sp.jedit.Java14} class and handles * the drag and drop API calls themselves. * @since jEdit 4.2pre5 */ public void setDragAndDropCallback(Method meth) { dndCallback = meth; } //}}} //{{{ isDragInProgress() method /** * Drag and drop of text in jEdit is implementing using jEdit 1.4 APIs, * however since jEdit must run with Java 1.3, this class only has the * necessary support to call a hook method via reflection. This method * is called by the {@link org.gjt.sp.jedit.Java14} class to signal that * a drag is in progress. * @since jEdit 4.2pre5 */ public boolean isDragInProgress() { return dndInProgress; } //}}} //{{{ setDragInProgress() method /** * Drag and drop of text in jEdit is implementing using jEdit 1.4 APIs, * however since jEdit must run with Java 1.3, this class only has the * necessary support to call a hook method via reflection. This method * is called by the {@link org.gjt.sp.jedit.Java14} class to signal that * a drag is in progress. * @since jEdit 4.2pre5 */ public void setDragInProgress(boolean dndInProgress) { this.dndInProgress = dndInProgress; } //}}} //{{{ isDragEnabled() method /** * Returns if drag and drop of text is enabled. * @since jEdit 4.2pre5 */ public boolean isDragEnabled() { return dndEnabled; } //}}} //{{{ setDragEnabled() method /** * Sets if drag and drop of text is enabled. * @since jEdit 4.2pre5 */ public void setDragEnabled(boolean dndEnabled) { this.dndEnabled = dndEnabled; } //}}} //}}} //{{{ Scrolling //{{{ Debugging code /* public void scrollTest(boolean paint) { Image im = painter.createImage(painter.getWidth(),painter.getHeight()); Graphics gfx = im.getGraphics(); gfx.setFont(painter.getFont()); gfx.setColor(painter.getForeground()); gfx.clipRect(0,0,painter.getWidth(),painter.getHeight()); long start = System.currentTimeMillis(); for(int i = 0; i < displayManager.getScrollLineCount(); i++) { setFirstLine(i); if(!paint) chunkCache.getLineInfo(visibleLines - 1); else painter.paintComponent(gfx); } System.err.println(System.currentTimeMillis() - start); } */ //}}} //{{{ getFirstLine() method /** * Returns the vertical scroll bar position. * @since jEdit 4.2pre1 */ public final int getFirstLine() { return displayManager.firstLine.scrollLine + displayManager.firstLine.skew; } //}}} //{{{ setFirstLine() method public Exception trace; /** * Sets the vertical scroll bar position * * @param firstLine The scroll bar position */ public void setFirstLine(int firstLine) { if(Debug.SCROLL_DEBUG) { Log.log(Log.DEBUG,this,"setFirstLine() from " + getFirstLine() + " to " + firstLine); } //{{{ ensure we don't have empty space at the bottom or top, etc int max = displayManager.getScrollLineCount() - visibleLines + (lastLinePartial ? 1 : 0); if(firstLine > max) firstLine = max; if(firstLine < 0) firstLine = 0; //}}} int oldFirstLine = getFirstLine(); if(firstLine == oldFirstLine) return; trace = new Exception(); if(firstLine >= oldFirstLine + visibleLines) { displayManager.firstLine.scrollDown(firstLine - oldFirstLine); chunkCache.invalidateAll(); } else if(firstLine <= oldFirstLine - visibleLines) { displayManager.firstLine.scrollUp(oldFirstLine - firstLine); chunkCache.invalidateAll(); } else if(firstLine > oldFirstLine) { displayManager.firstLine.scrollDown(firstLine - oldFirstLine); chunkCache.scrollDown(firstLine - oldFirstLine); } else if(firstLine < oldFirstLine) { displayManager.firstLine.scrollUp(oldFirstLine - firstLine); chunkCache.scrollUp(oldFirstLine - firstLine); } // we have to be careful displayManager._notifyScreenLineChanges(); //if(buffer.isLoaded()) // recalculateLastPhysicalLine(); repaint(); fireScrollEvent(true); } //}}} //{{{ getFirstPhysicalLine() method /** * Returns the first visible physical line index. * @since jEdit 4.0pre4 */ public final int getFirstPhysicalLine() { return displayManager.firstLine.physicalLine; } //}}} //{{{ setFirstPhysicalLine() method /** * Sets the vertical scroll bar position. * @param physFirstLine The first physical line to display * @param skew A local screen line delta * @since jEdit 4.2pre1 */ public void setFirstPhysicalLine(int physFirstLine) { setFirstPhysicalLine(physFirstLine,0); } //}}} //{{{ setFirstPhysicalLine() method /** * Sets the vertical scroll bar position. * @param physFirstLine The first physical line to display * @param skew A local screen line delta * @since jEdit 4.2pre1 */ public void setFirstPhysicalLine(int physFirstLine, int skew) { if(Debug.SCROLL_DEBUG) { Log.log(Log.DEBUG,this,"setFirstPhysicalLine(" + physFirstLine + "," + skew + ")"); } //{{{ ensure we don't have empty space at the bottom or top, etc /* int screenLineCount = 0; int physicalLine = displayManager.getLastVisibleLine(); int visibleLines = this.visibleLines - (lastLinePartial ? 1 : 0); for(;;) { screenLineCount += displayManager.getScreenLineCount(physicalLine); if(screenLineCount >= visibleLines) break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -