📄 textarea.java
字号:
package java.awt;import java.awt.event.FocusEvent;import java.awt.event.InputEvent;import java.awt.event.KeyEvent;import java.awt.event.KeyListener;import java.awt.event.MouseEvent;import java.awt.event.MouseListener;import java.awt.event.MouseMotionListener;import java.util.Vector;/** * * Copyright (c) 1998 * Transvirtual Technologies, Inc. All rights reserved. * * See the file "license.terms" for information on usage and redistribution * of this file. * * @author J.Mehlitz */public class TextArea extends TextComponent{ final private static long serialVersionUID = 3692302836626095722L; final public static int SCROLLBARS_BOTH = 0; final public static int SCROLLBARS_VERTICAL_ONLY = 1; final public static int SCROLLBARS_HORIZONTAL_ONLY = 2; final public static int SCROLLBARS_NONE = 3; int tabWidth; int crows; int ccols; TextPane tp = new TextPane();class TextPane extends RowCanvas implements KeyListener, MouseListener, MouseMotionListener{ TextCursor tCursor = new TextCursor(); Point sSel = new Point(); Point eSel = new Point();public TextPane () { xOffsInit = 4; xOffs = 4; this.setCursor( Cursor.getPredefinedCursor( Cursor.TEXT_CURSOR)); tCursor.setPos( xOffs, rowHeight + BORDER_WIDTH); insertLine( "", 0); this.addKeyListener( this); this.addMouseListener( this); this.addMouseMotionListener( this); this.addFocusListener( this);}synchronized void append ( String s ) { int i, nOld, nNew; TextBuffer tb; String[] lines; blankCursor(); lines = breakLines( s); nOld = rows.size() - 1; tb = (TextBuffer)rows.elementAt( nOld); tb.append( lines[0]); for ( i=1; i<lines.length; i++ ){ tb = new TextBuffer( lines[i]); tb.setMetrics( fm, tabWidth); rows.addElement( tb); } nNew = rows.size() - 1; makeVisible( nNew); updateScrolls(); repaintRows( nOld, nNew - nOld); setCursorPos( tb.len, nNew, true, true);}void backspace() { TextBuffer tb = getCursorLine(); if ( tCursor.index >= 1 ) { tb.remove( tCursor.index-1, 1); setCursorPos( tCursor.index-1, tCursor.yindex, false, true); repaintLine( tCursor.yindex, tCursor.index, tb); } else if ( cursorLeft(1, false) ){ TextBuffer tb1 = getCursorLine(); tb1.append( tb); rows.removeElement( tb); this.repaint(); updateScrolls(); }}void blankCursor() { TextBuffer tb; if ( rgr != null ) { rgr.setColor( this.bgClr ); tCursor.blank( rgr, xOffs, getRowYPos( tCursor.yindex) ); rgr.setColor( this.fgClr ); tb = (TextBuffer)rows.elementAt( tCursor.yindex ); tb.paint( rgr, xOffs, tCursor.y, rowHeight, tCursor.index, 1); }}String[] breakLines( String str) { int i, i0 = 0, n = str.length(); char c; Vector v; String[] sbuf; char[] cbuf; if ( (str == null) || (n == 0) ) return new String[1]; v = new Vector( n / 20); cbuf = str.toCharArray(); // sometimes I wonder how long we will suffer from old DOS habits: some // editors still use obscure '\r\r\n' or '\r' "weak" linefeeds to mark // automatically wrapped lines for ( i=0; i<n; i++ ) { if ( (c=cbuf[i]) == '\n' ) { v.addElement( new String( cbuf, i0, i-i0)); i0 = i+1; } else if ( c == '\r' ) { v.addElement( new String( cbuf, i0, i-i0)); // skip all subsequent '\r' for ( i++; (i < n) && (cbuf[i] == '\r'); i++ ); i0 = (cbuf[i] == '\n') ? i+1 : i; } } if ( i0 <= n ){ v.addElement( new String( cbuf, i0, i-i0)); } sbuf = new String[v.size()]; v.copyInto( sbuf); return sbuf;}void cursorDown( int steps, boolean extend) { int newY = Math.min( tCursor.yindex + steps, rows.size() -1); if ( newY != tCursor.yindex) { if ( extend ) updateSel( tCursor.index, newY, true); else setCursorPos( tCursor.index, newY, true, true); }}void cursorEnd( boolean extend) { TextBuffer tb = getCursorLine(); if ( extend) updateSel( tb.len, tCursor.yindex, true); else setCursorPos( tb.len, tCursor.yindex, true, true);}void cursorHome( boolean extend) { if ( extend) updateSel( 0, tCursor.yindex, true); else setCursorPos( 0, tCursor.yindex, true, true);}boolean cursorLeft( int steps, boolean extend) { int nx = -1, ny = -1; if ( tCursor.index >= steps) { nx = tCursor.index - steps; ny = tCursor.yindex; } else if ( tCursor.yindex > 0 ) { nx = ((TextBuffer)rows.elementAt( tCursor.yindex-1)).len; ny = tCursor.yindex-1; } if ( ny > -1 ) { if ( extend ) updateSel( nx, ny, true); else setCursorPos( nx, ny, true, true); return true; } return false;}void cursorRight( int steps, boolean extend) { int nx = -1, ny = -1; TextBuffer tb = (TextBuffer)rows.elementAt( tCursor.yindex); if ( tb.len >= tCursor.index + steps) { nx = tCursor.index + steps; ny = tCursor.yindex; } else if ( tCursor.yindex < rows.size() - 1 ) { nx = 0; ny = tCursor.yindex+1; } if ( ny > -1 ) { if ( extend) updateSel( nx, ny, true); else setCursorPos( nx, ny, true, true); }}void cursorTextEnd( boolean extend) { int yIdx = rows.size() - 1; TextBuffer tb = (TextBuffer)rows.elementAt( yIdx); if ( extend) updateSel( tb.len, yIdx, true); else setCursorPos( tb.len, yIdx, true, true);}void cursorTextHome( boolean extend) { if ( extend) updateSel( 0, 0, true); else setCursorPos( 0, 0, true, true);}void cursorUp( int steps, boolean extend) { int newY = Math.max( tCursor.yindex - steps, 0); if ( newY != tCursor.yindex) { if ( extend ) updateSel( tCursor.index, newY, true); else setCursorPos( tCursor.index, newY, true, true); }}void del() { TextBuffer tb = getCursorLine(); if ( tb.len > tCursor.index ) { tb.remove( tCursor.index, 1); repaintLine( tCursor.yindex, tCursor.index, tb); } else if ( tCursor.yindex < rows.size() - 1 ){ TextBuffer tb1 = (TextBuffer)rows.elementAt( tCursor.yindex+1); tb.append( tb1); rows.removeElement( tb1); updateScrolls(); this.repaint(); }}void deleteSel() { Point ps = getSelStart(); Point pe = getSelEnd(); TextBuffer tb = (TextBuffer)rows.elementAt( ps.y); int af = 1; if ( (ps.x == pe.x) && (ps.y == pe.y) ) return; if ( ps.y == pe.y ) { tb.remove( ps.x, pe.x - ps.x); setCursorPos( ps.x, ps.y, true, true); if ( updateHScroll() ) rearrange(); return; } if ( ps.x > 0 ) tb.remove( ps.x, tb.len - ps.x); else af = 0; tb = (TextBuffer)rows.elementAt( pe.y); tb.remove( 0, pe.x); for ( int i = ps.y + af; i < pe.y; i++) rows.removeElementAt( ps.y + af); setCursorPos( ps.x, ps.y, false, true); updateScrolls(); this.repaint();}public void focusGained( FocusEvent e) { repaintCursor(); super.focusGained( e);}public void focusLost( FocusEvent e) { paintInactiveCursor(); //would confuse replacement with clipboard contents via popup // if ( hasSel() ) // copyToClipboard(); super.focusLost( e);}int get1D( Point p) { int xt = 0; for ( int i=0; i<p.y; i++) { TextBuffer tb = (TextBuffer)rows.elementAt( i); xt += tb.len; xt ++; // hjb 01-27-1999: count the virtual newline } xt += p.x; return xt;}Point get2D( int pos) { int rs = rows.size(); int xt = 0; TextBuffer tb = null; if ( rs == 0 ) return new Point( -1, -1); for ( int i=0; i<rs; i++) { tb = (TextBuffer)rows.elementAt( i); xt += tb.len; if (xt >= pos) return new Point( tb.len - xt + pos, i); pos --; // hjb 01-27-1999: substract 1 for the virtual newline } return new Point( tb.len, rs-1);}int getCol( int row, int x) { TextBuffer tb = (TextBuffer) rows.elementAt( row); return tb.getIdx( x - xOffs);}TextBuffer getCursorLine() { return (TextBuffer)rows.elementAt( tCursor.yindex);}Point getSelEnd() { if ( sSel.y > eSel.y ) return sSel; if ( sSel.y == eSel.y ) { if ( sSel.x > eSel.x ) return sSel; return eSel; } return eSel;}Point getSelStart() { if ( sSel.y < eSel.y ) return sSel; if ( sSel.y == eSel.y ) { if ( sSel.x < eSel.x ) return sSel; return eSel; } return eSel;}boolean hasSel() { return ( (sSel.x != eSel.x) || (sSel.y != eSel.y) );}boolean hasSel( int row) { if ( hasSel() ) return ( (sSel.y <= row) || (eSel.y >= row) ); return false;}void insert( String s, boolean keepCursor) { if ( (s == null) || (s.length() == 0) ) return; String[] lns = breakLines( s); int lnsi = 0; TextBuffer tb = (TextBuffer)rows.elementAt( tCursor.yindex); if ( lns.length == 0 ) return; if ( lns.length == 1 ) { int ncp = keepCursor ? tCursor.index : tCursor.index + lns[0].length(); tb.insert( tCursor.index, lns[0] ); setCursorPos( ncp, tCursor.yindex, false, false); repaintLine( tCursor.yindex, 0, tb); return; } String le = tb.getString( tCursor.index, tb.len - tCursor.index); tb.remove( tCursor.index, tb.len - tCursor.index); tb.append( lns[lnsi++] ); while ( lnsi < lns.length) tb = insertLine( lns[lnsi++], tCursor.yindex + lnsi - 1 ); if ( ! keepCursor) setCursorPos( tb.len, tCursor.yindex + lns.length - 1, false, false); tb.append( le); updateScrolls(); this.repaint();}void insert( String s, int pos) { insertText(s, pos);}void insertChar( char c) { boolean app; TextBuffer tb = (TextBuffer)rows.elementAt( tCursor.yindex); app = ( tCursor.index == tb.len); tb.insert( tCursor.index, c); if ( !app){ //leading problem ( repaint left cursor char also) int sIdx = (tCursor.index > 0 ) ? tCursor.index-1 : tCursor.index; repaintLine( tCursor.yindex, sIdx, tb); } cursorRight( 1, false);}TextBuffer insertLine( String str, int lIdx) { TextBuffer tb = new TextBuffer( str); tb.setMetrics( fm, tabWidth); rows.insertElementAt( tb, lIdx); return tb;}/** * @deprecated */void insertText(String s, int pos) { Point p = get2D( pos); setCursorPos( p.x, p.y, true, true); insert( s, false);}public void keyPressed( KeyEvent e) { if ( this.parent.keyListener != null ){ // give our parent a chance to intercept keystrokes // check for keyListeners first, it's a rare case redirectKeyEvent( e); } int code = e.getKeyCode(); int mods = e.getModifiers(); boolean sh = e.isShiftDown(); //do not consume unused key for ShortcutHandler if ( (mods != 0) && (mods != KeyEvent.SHIFT_MASK) ) return; switch( code) { case KeyEvent.VK_LEFT: cursorLeft( 1, sh); break; case KeyEvent.VK_RIGHT: cursorRight( 1, sh); break; case KeyEvent.VK_UP: cursorUp( 1, sh); break; case KeyEvent.VK_DOWN: cursorDown( 1, sh); break; case KeyEvent.VK_TAB: if (sh) { return; //do not consume event for HotKeyHandler } if (!isEditable) { // hjb 01-27-1999: do nothing for break; // TAB, ENTER, DEL and BS if not editable } insertChar( '\t' ); break; case KeyEvent.VK_ENTER: if ( ! isEditable) break; newline(); break; case KeyEvent.VK_BACK_SPACE: if ( ! isEditable) break; if ( hasSel() ) replaceSelectionWith(""); else backspace(); break; case KeyEvent.VK_DELETE: if ( ! isEditable) break; if ( hasSel() ) replaceSelectionWith(""); else del(); break; case KeyEvent.VK_HOME: cursorHome( sh); break; case KeyEvent.VK_END: cursorEnd( sh); break; case KeyEvent.VK_PAGE_UP: pageUp( sh); break; case KeyEvent.VK_PAGE_DOWN: pageDown( sh); break; case KeyEvent.VK_ESCAPE: resetSel( true); break; default: return; } e.consumed = true;}public void keyReleased( KeyEvent e) { redirectKeyEvent( e); e.consumed = true;}public void keyTyped( KeyEvent e) { if ( ! isEditable || ! isPrintableTyped( e) ) return; char c = e.getKeyChar(); if ( hasSel() ) { Character cc = new Character( c); replaceSelectionWith( cc.toString() ); } else insertChar( c ); if ( this.parent.keyListener != null ) { // check for keyListeners first, it's a rare case redirectKeyEvent( e); } if ( (textListener != null) || (this.eventMask & AWTEvent.TEXT_EVENT_MASK) != 0 ) { Toolkit.eventQueue.postEvent( TextEvt.getEvent( TextArea.this, TextEvt.TEXT_VALUE_CHANGED)); } e.consumed = true;}int maxRowWidth() { int rs = rows.size(); int iw, mw = 0; for ( int i=0; i<rs; i++ ) { iw = ((TextBuffer)rows.elementAt( i)).getWidth(); if ( iw > mw ) mw = iw; } return mw;}public void mouseClicked( MouseEvent e) { if ( this.parent.mouseListener != null ){ // no need to retarget, already done by mousePressed this.parent.process( e); }}public void mouseDragged( MouseEvent e) { int y = getRowIdx( e.getY() ); int x = getCol( y, e.getX() ); updateSel( x, y, true); if ( this.parent.motionListener != null ){ // unlikely, check motionListener first redirectMotionEvent( e); }}public void mouseEntered( MouseEvent e) { redirectMouseEvent( e);}public void mouseExited( MouseEvent e) { redirectMouseEvent( e);}public void mouseMoved( MouseEvent e) { if ( this.parent.motionListener != null ){ // unlikely, check listener first redirectMotionEvent( e); }}public void mousePressed( MouseEvent e) { int mods = e.getModifiers(); if ( e.isPopupTrigger() ){ if ( (this.triggerPopup( e.getX(), e.getY())) != null ) return; } switch ( mods) { case InputEvent.BUTTON1_MASK: tp.requestFocus(); resetSel( true); int y = getRowIdx( e.getY() ); int x = getCol( y, e.getX() ); setCursorPos( x, y, true, true); break; case InputEvent.BUTTON2_MASK: pasteFromClipboard(); break; } redirectMouseEvent( e);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -