home *** CD-ROM | disk | FTP | other *** search
Java Source | 1996-08-14 | 23.0 KB | 765 lines |
- /*---------------------------------------------------------------------------
-
- @(#)TextBox.java 0.00 28-Dec-95
-
- A prototype of a scrolling, word-wrapping text area.
-
- Authors:
-
- jlee James Lee
-
- Version Ident:
-
- $Header$
-
- History:
-
- 0.00 5-Mar-96 jlee Initial Creation
- 26-Mar-96 jlee Got rid of panel used 3d border, instead used line drawing
- and fixed some scrolling problem.
- 29-Mar-96 jlee Optimized LineTextBox a little bit.
- ---------------------------------------------------------------------------*/
-
- package pj.awt;
-
- import pj.awt.Panel3D;
- import pj.awt.PjFinals;
-
- import java.awt.BorderLayout;
- import java.awt.Color;
- import java.awt.Container;
- import java.awt.Dimension;
- import java.awt.Event;
- import java.awt.Font;
- import java.awt.FontMetrics;
- import java.awt.Graphics;
- import java.awt.Image;
- import java.awt.Panel;
- import java.awt.Scrollbar;
- import java.lang.String;
- import java.lang.Thread;
-
- import java.util.NoSuchElementException;
- import java.util.StringTokenizer;
- import java.util.Vector;
-
- public class TextBox extends Panel3D
- {
-
-
- // --- Instance variables
- private protected Vector m_vTextArray = null; //growable array for the text contents
- private protected Font m_fntTextPlain = null;
- private protected Font m_fntTextBold = null;
- private protected FontMetrics m_fmTextPlain = null;
- private protected FontMetrics m_fmTextBold = null;
-
-
- private Panel m_pnlText = null; //text area panel
- private Scrollbar m_sbText = null;
-
- private int m_nPagesize = 10; //scroll page size
- private int m_sbTextCurValue = 0;
- private int m_sbTextPrevValue = 0;
- private int m_nLineHeight = 0; //text line height
- private int m_nLeftOffset = PjFinals.nTextBoxHorInset;
- private int m_nLastMax = 0;
-
- private Dimension m_dimPanelText = null; //size of m_pnlText
- private Dimension m_dimPanelTextPrevDim = null; //previous size of m_pnltext
-
- private Graphics m_grPanelText = null; //graphics context for the offscreen image
- private Color m_colorBackgroundColor = null;
-
-
- // --- Public constructors
-
- public TextBox()
- {
- init();
- }
-
- public TextBox( int nBorderSize )
- {
- super( nBorderSize );
- init();
- if (nBorderSize == 0)
- m_colorBackgroundColor = Color.lightGray;
- }
-
-
- // --- Public operations
-
- private void init()
- {
- m_pnlText = new Panel();
-
- m_pnlText.setLayout( new BorderLayout() );
- m_sbText = new Scrollbar( Scrollbar.VERTICAL );
-
- m_sbText.resize( PjFinals.nScrollbarWidth, 10 );
- m_sbText.setBackground( Color.lightGray );
-
- m_pnlText.add( "East", m_sbText );
- m_sbText.hide();
-
- m_dimPanelText = m_pnlText.size();
- m_dimPanelTextPrevDim = new Dimension( -1, -1 );
-
- add( m_pnlText );
-
- m_vTextArray = new Vector();
- m_colorBackgroundColor = Color.white;
- }
-
- public void setBackColor( Color c )
- {
- m_colorBackgroundColor = c;
- repaint();
- }
-
- public void paint( Graphics gParent )
- {
- int nSize = 0;
-
- super.paint( gParent );
-
- if ( m_pnlText != null && m_sbText != null )
- {
- // set line height and pagesize
- if ( null == m_grPanelText )
- m_grPanelText = m_pnlText.getGraphics();
-
- FontMetrics fmText = m_grPanelText.getFontMetrics();
- m_nLineHeight = fmText.getHeight() * 82 / 80;
-
- if ( m_nLineHeight > 0 )
- m_nPagesize = m_pnlText.size().height / m_nLineHeight;
-
- nSize = m_vTextArray.size();
-
- // resize the scrollbar
- if ( nSize > m_nPagesize )
- {
- m_sbText.reshape( m_pnlText.size().width - PjFinals.nScrollbarWidth, 0,
- PjFinals.nScrollbarWidth, m_pnlText.size().height );
- m_sbText.show();
- }
- else
- m_sbText.hide();
-
- if ( nSize > 0 )
- drawScrollString( m_sbText.getValue(), 0, nSize );
- }
- else
- return;
- }
-
- private int resolveSbMaxValue( int nSbValue, int min, int max )
- {
- if ( (m_nLastMax != max) && (m_nLastMax != 0) && (max != 0) )
- nSbValue = nSbValue * max / m_nLastMax;
-
- m_nLastMax = max;
-
- if ( nSbValue + m_nPagesize > max )
- {
- int v = 0;
- v = max - m_nPagesize;
- if ( v < min)
- v = min;
- return v;
- }
- return nSbValue;
- }
-
- public boolean handleEvent(Event evt)
- {
- int v, max;
-
- switch (evt.id)
- {
- case Event.SCROLL_LINE_UP:
- break;
- case Event.SCROLL_LINE_DOWN:
- break;
- case Event.SCROLL_PAGE_UP:
- v = m_sbTextCurValue - m_nPagesize;
- if ( v < 0)
- v = 0;
- m_sbText.setValue( v );
- break;
- case Event.SCROLL_PAGE_DOWN:
- max = m_sbText.getMaximum() - m_nPagesize;
- v = m_sbTextCurValue + m_nPagesize;
- if ( v > max )
- v = max;
- m_sbText.setValue( v );
- break;
- case Event.SCROLL_ABSOLUTE:
- break;
- default:
- return false;
- } // switch
-
- repaint();
- return true;
- }// handleEvent
-
- protected void finalize() throws Throwable
- {
- if ( null != m_grPanelText )
- m_grPanelText.finalize();
- }
-
- public synchronized void setFont( Font f )
- {
- if ( f != null )
- {
- m_fntTextPlain = f;
- m_fmTextPlain = getFontMetrics( f );
-
- m_fntTextBold = new Font( f.getName(), Font.BOLD, f.getSize() );
- m_fmTextBold = getFontMetrics( m_fntTextBold );
- repaint();
- }
- }
-
- private void drawScrollString( int val, int min, int max )
- {
- boolean bFontChanged = false;
- String str;
- int nLeftMargin = 0;
-
- val = resolveSbMaxValue(val, min, max);
-
- m_dimPanelText = m_pnlText.size();
- m_grPanelText.setFont( m_fntTextPlain );
- m_sbTextCurValue = val;
-
- // reset the scroll bar
- m_sbText.setValues( val, m_nPagesize, min, max );
- m_sbText.setPageIncrement( m_nPagesize );//dosen't seem to work.
-
- // fill area with Color.white
- m_grPanelText.setColor( m_colorBackgroundColor );
- m_grPanelText.fillRect( 0, 0, m_dimPanelText.width, m_dimPanelText.height );
-
- // setting black color for the font
- m_grPanelText.setColor( Color.black );
-
- // draw the actual string
- for ( int i = val; i < val + m_nPagesize; i++ )
- {
- if ( i >= max )
- break;
-
- str = (String)m_vTextArray.elementAt( i );
-
- if ( str.length() > 0 )
- {
- if ( '\\' == str.charAt(0) )
- {
- switch ( str.charAt(1) )
- {
- case 'b':
- str = str.substring( 2 );
- m_grPanelText.setFont( m_fntTextBold );
- bFontChanged = true;
- break;
- case 'q':
- switch ( str.charAt(2) )
- {
- case 'l':
- case 'r':
- case 'c':
- str = str.substring( 3 ).trim().replace( '-', '*' );
- int nOffset = m_sbText.isVisible() ? PjFinals.nScrollbarWidth: 0;
- nLeftMargin = ( m_dimPanelText.width - nOffset -
- m_fmTextPlain.stringWidth( str )
- ) / 2;
- break;
- case 'j':
- default:
- break;
- }
- break;
- default:
- break;
- }//switch
- }//if
-
- m_grPanelText.drawString( str, m_nLeftOffset + nLeftMargin, (i + 1 - val) * m_nLineHeight );
-
- nLeftMargin = 0;
-
- if ( bFontChanged )
- {
- m_grPanelText.setFont( m_fntTextPlain );
- bFontChanged = false;
- }
- }//if ( str.length() > 0 )
- }//for ( int i = val; i < val + m_nPagesize; i++ )
- }//drawScrollString
- }//TextBox
-
- /*---------------------------------------------------------------------------
-
- @(#)LineTextBox.java 0.00 28-Dec-95
-
- A prototype of a scrolling, word-wrapping text area.
- Originally written by Rick Hall and released into the public domain.
-
- Authors:
-
- rphall Rick Hall
- jlee James Lee
-
- Version Ident:
-
- $Header$
-
- History:
-
- 0.00 28-Dec-95 rphall Initial Creation
- 0.00 01-Mar-95 jlee List's clear() has a bug, replaced it with delItem() and modified
- list width handling.
-
- ---------------------------------------------------------------------------*/
-
- /**
- * A prototype of a scrolling, word-wrapping text area.
- *
- * @see java.awt.List
- * @version 0.00 28-Dec-95
- * @author rphall
- */
- class LineTextBox extends TextBox
- {
-
- // --- Class variables
-
- /**
- * Default set of line-delimiting characters
- */
- public static final char[] NEWLINE = {'\r','\n'};
-
- /**
- * Default set of word-delimiting characters
- */
- public static final char[] WORDBRK = {'\t',' ','-'};
-
- private static final String CR = "\r";
- private static final String LF = "\n";
- private static final String CRLF = CR + LF;
- private static final boolean bReturnTokens = true;
-
- // --- Instance variables
-
- // Pristine, unwrapped input text
- private String strText;
-
- // Input text broken into word-wrapped lines
- private String[] astrLine;
-
- // Flag that indicates whether selection feature of List is enabled
- private boolean bSelectionEnabled;
-
- // Flag that indicates whether astrLine should be recalc'd
- private boolean bWrapped;
-
- // Cached value of LineTextBox width, including scrollbar
- private int cachedWidth;
-
- // Cached value of LineTextBox height.
- private int cachedHeight;
-
- // Right margin compensating scrollbar
- private int nUnuseableSize = PjFinals.nScrollbarWidth + 2 * PjFinals.nTextBoxHorInset;
-
- private String[] astrLineDelim;
- private String[] astrWordDelim;
- private String strDelim;
-
- // --- Public constructors
-
- /**
- * Construct an empty LineTextBox.
- */
- public LineTextBox()
- {
- init("");
- }
-
- /**
- * Construct an empty LineTextBox.
- */
- public LineTextBox( int nBorderSize )
- {
- super( nBorderSize );
- init("");
- }
-
- /**
- * Construct an empty LineTextBox.
- */
- public LineTextBox( String text, int nBorderSize )
- {
- super( nBorderSize );
- init( text );
- }
-
- /**
- * Construct a LineTextBox with some text.
- *
- * @param text The text that is initially displayed.
- */
- public LineTextBox(String text)
- {
- init( text );
- } // LineTextBox(String)
-
-
- // --- Public operations
-
- public void init( String text )
- {
- strText = new String( cleanString(text) );
- astrLine = null;
- bSelectionEnabled = false;
- bWrapped = false;
- cachedWidth = 0;
- } // init
-
- /**
- * Set the text displayed by a LineTextBox.
- *
- * @param text The new text for a LineTextBox.
- */
- public synchronized void setText(String text)
- {
- strText = new String( cleanString(text) );
- breakText();
- }
-
- /**
- * Clear the text displayed by a LineTextBox.
- * Equivalent to:
- * <pre>
- * setText("");
- * </pre>
- * @see setText
- *
- */
- public synchronized void clearText()
- {
- setText("");
- }
-
- /**
- * Return the text displayed by a LineTextBox.
- */
- public synchronized String getText()
- {
- return strText;
- }
-
- /**
- * Set whether selection features of List are enabled.
- *
- * @param bEnable true enables selection feature
- * @see java.awt.List
- */
- public synchronized void setSelectionEnabled(boolean bEnable)
- {
- bSelectionEnabled = bEnable;
- }
-
- /**
- * Return whether selection features of List are enabled.
- *
- * @see java.awt.List
- */
- public synchronized boolean getSelectionEnabled()
- {
- return bSelectionEnabled;
- }
-
- /**
- * Reshape a LineTextBox:
- * Hand off operation to super, then rewrap text if width has changes.
- *
- * @see java.awt.List#reshape
- * @see java.awt.Component#reshape
- */
- public synchronized void reshape(int x, int y, int width, int height)
- {
- super.reshape( x, y, width, height );
-
- cachedHeight = height;
-
- if ( cachedWidth != width || bWrapped == false )
- {
- cachedWidth = width;
- if ( cachedWidth > nUnuseableSize )
- breakText();
- }
- repaint();
- } // reshape
-
- /**
- * Set the font used by a LineTextBox:
- * Signal an internal flag to rewrap, then hand off operation to super.
- *
- * @see java.awt.Component#setFont
- */
- public synchronized void setFont(Font f)
- {
- super.setFont(f);
- breakText();
- }
-
- // --- Private operations
-
- // Break strText into lines of string
- private void breakText()
- {
- bWrapped = false;
- if ( cachedWidth == 0 || strText == null )
- return;
-
- try {
- initDelimiter();
- int width = cachedWidth - nUnuseableSize;
-
- if ( strText.length() != 0 )
- {
- formatToArray( strText, width );
-
- if ( cachedHeight >= m_vTextArray.size() * m_fmTextPlain.getHeight() )
- {
- width += PjFinals.nScrollbarWidth;
- formatToArray( strText, width );
- }
- }
-
- bWrapped=true;
- }
- catch (LineTextBoxError e)
- {
- System.out.println("Error-TextBox-breakText(): error invoking initDelimiter.");
- }
-
- } // breakText
-
-
- public void initDelimiter()
- {
- astrLineDelim = new String[NEWLINE.length];
- for (int i=0; i<NEWLINE.length; i++)
- astrLineDelim[i] = new String(NEWLINE,i,1);
-
- astrWordDelim = new String[WORDBRK.length];
- for (int i=0; i<WORDBRK.length; i++)
- astrWordDelim[i] = new String(WORDBRK,i,1);
-
- strDelim = new String(NEWLINE) + new String(WORDBRK);
- }
-
- /**
- * Throws an LineTextBoxError if predicate is false.
- * The right way to implement assert is to import Assertable
- * and ImplementationError from
- * <b><a href="http://g.oswego.edu/dl/classes/collections/index.html">
- * Collection Classes</a></b>
- *
- * @param predicate Boolean expression to be checked.
- * @see collections.ImplementationError
- * @see collections.Assertable
- */
- public void assert(boolean predicate)
- throws LineTextBoxError
- {
- if (!predicate) throw new LineTextBoxError();
- }
-
- /**
- * Formats unbroken text into lines.
- * Returns a string array.
- * Each string of the returned array is a line.
- * Line delimiters are stripped from the unbroken text.
- * The sequence "\r\n" is treated as a single line delimiter.
- * Throws an implementation error if input text is empty.
- *
- * @param strRawText The input text, length > 0
- * @param linewidth The desired line width
- */
-
- public void formatToArray( String strRawText, int linewidth ) throws LineTextBoxError
- {
- Thread.currentThread().setPriority( Thread.NORM_PRIORITY );
-
- // Precondition
- assert( strRawText.length() != 0 );
-
- // Format into lines
- formatLine( strRawText, linewidth );
- } // formatToStringArray
-
- // --- Private operations
-
- /*
- * Returns a line and prunes the line from the input text.
- * Line delimiters are stripped from the line. This operation will
- * treat the sequence "\r\n" as two line delimiters, rather than one.
- * If this is undesirable, replace all CRLF sequences by single LF
- * sequences before invoking this operation.
- *
- * @return String[0] An extracted line
- * @return String[1] The input text pruned of the extracted line.
- */
- private void formatLine( String text, int desiredWidth ) throws LineTextBoxError
- {
- int currentWidth;
- int checkWidth;
- int numLineChars;
- String line;
- String strToken;
-
- // reset line array
- m_vTextArray.removeAllElements();
-
- while ( text.length() > 0 )
- {
- // reset FontMetrics
- FontMetrics fm = m_fmTextPlain;
-
- if ( ('\\' == text.charAt(0)) && 'b' == text.charAt(1) )
- fm = m_fmTextBold;
-
- StringTokenizer st = new StringTokenizer( text, strDelim, bReturnTokens );
-
- line = new String(""); // The extracted line
- strToken = null; // A new token from text
- currentWidth = 0; // The current width of the extracted line
- checkWidth = 0; // The currentWidth plus a new token width
- numLineChars = 0; // The number of chars in current line
-
- TokenLoop:
- for ( int i = 0;;i++ )
- {
- // Implementation note: countTokens() does not seem to be
- // working correctly. Hence this loop continues until an
- // exception occurs, rather than politely using countTokens
- // to limit iterations.
- try {
- strToken = st.nextToken();
- }
- catch (NoSuchElementException e)
- {
- break TokenLoop;
- }
-
- // Line delimiters reset a line length calc
- for ( int j = 0; j < astrLineDelim.length; j++ )
- if ( strToken.equals( astrLineDelim[j] ) )
- {
- numLineChars += strToken.length();
- break TokenLoop;
- }
-
- // Check desiredWidth with the addition of the new token
- if ( strToken != null )
- checkWidth = currentWidth + fm.stringWidth(strToken);
- else
- break TokenLoop;
-
- // If the checked width is less than a line width,
- // add the new token to the current line and continue.
- if ( checkWidth < desiredWidth )
- {
- line += strToken;
- currentWidth = checkWidth;
- numLineChars += strToken.length();
- continue TokenLoop;
- }
-
- // If the checked width is longer than a line width,
- // check if the new token is a word delimiter. Extra
- // word delimiters are OK at the end of a line.
- for (int j=0; j<astrWordDelim.length; j++)
- if ( strToken.equals(astrWordDelim[j]) )
- {
- line += strToken;
- currentWidth = checkWidth;
- numLineChars += strToken.length();
- continue TokenLoop;
- }
-
- // Avoid pathology by making sure the current line has
- // at least one token.
- if ( currentWidth == 0 )
- {
- line += strToken;
- currentWidth = checkWidth;
- numLineChars += strToken.length();
- continue TokenLoop;
- }
-
- // If the checked width is longer than a line width,
- // and the current line has at least one token, the line
- // is finished. The new token starts the returned text.
-
- break TokenLoop;
-
- } // for TokenLoop
-
- assert( numLineChars > 0 );
- assert( numLineChars <= text.length() );
- assert( line.length() <= text.length() );
-
- text = ( numLineChars == text.length() ) ? "": text.substring( numLineChars );
-
- m_vTextArray.addElement( line );
- }//while ( text.length() > 0 )
- } // formatLine
-
- // Private operations
- private String cleanString( String text )
- {
- // Replace CRLF with LF
- int nextCRLF = text.indexOf( CRLF );
- int nextSubstr = 0;
-
- while ( nextCRLF != -1 )
- {
- nextSubstr = text.length() - CRLF.length();
- if ( nextSubstr == 0 )
- text = text.substring( 0, nextCRLF ) + LF;
- else
- text = text.substring( 0, nextCRLF ) + LF + text.substring( nextCRLF + CRLF.length() );
- nextCRLF = text.indexOf(CRLF);
- } // while CRLF
-
- return text;
- }
- }; // LineTextBox
-
- /**
- * An internal implementation error
- *
- * @version 0.00 29-Dec-95
- * @author rphall
- */
- class LineTextBoxError extends Error
- {
-
- // --- Public operations
-
- public LineTextBoxError()
- {
- super("LineTextBox implementation error");
- }
- }
-
-