/* * LogTextArea.java * JCollider * * Copyright (c) 2004-2010 Hanns Holger Rutz. All rights reserved. * * This software 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, june 1991 of the License, or (at your option) any later version. * * This software 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 (gpl.txt) along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * For further information, please contact Hanns Holger Rutz at * contact@sciss.de , or visit http://www.sciss.de/jcollider * * * JCollider is closely modelled after SuperCollider Language, * often exhibiting a direct translation from Smalltalk to Java. * SCLang is a software originally developed by James McCartney, * which has become an Open Source project. * See http://www.audiosynth.com/ for details. * * * Changelog: * 30-May-04 created * 31-Jul-04 commented * 26-May-05 moved from de.sciss.meloncillo.gui * 08-Sep-05 some utility functions, empty constructor, clear action * 10-Sep-05 copied from de.sciss.gui package */ package de.sciss.jcollider.gui; import java.awt.event.ActionEvent; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import javax.swing.AbstractAction; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.ScrollPaneConstants; /** * A <code>JTextArea</code> encompassing a <code>PrintWriter</code> that * can be used as an alternative to the standard <code>System.out</code> * or <code>System.err</code> objects. Writing to this <code>PrintWriter</code> * will append the text to the text area. * <p> * This code is based on an idea by Real Gagnon published at:<br> * <A HREF="http://tanksoftware.com/juk/developer/src/com/tanksoftware/util/RedirectedFrame.java"> * tanksoftware.com/juk/developer/src/com/tanksoftware/util/RedirectedFrame.java</A> * * @author Hanns Holger Rutz * @version 0.32, 25-Feb-08 * * @see java.io.PrintStream * @see java.lang.System#setOut( PrintStream ) * @see java.lang.System#setErr( PrintStream ) */ public class LogTextArea extends JTextArea { protected final boolean useLogFile; protected final File logFile; private final PrintStream outStream; protected FileWriter logFileWriter = null; // private final JTextArea textArea = this; private int totalLength = 0; // XXX JCollider // private MenuAction actionClear = null; private AbstractAction actionClear = null; /** * Constructs a new text area for logging messages. * The area is readonly and wraps lines as they exceed * the right margin. Alternatively messages can * be logged in a text file. * * @param rows same as in JTextArea() * @param columns same as in JTextArea() * @param useLogFile <code>true</code> to have a copy of the output logged into a file * @param logFile if <code>useLogFile</code> is <code>true</code>, this is the file * into which the log is written. if <code>useLogFile</code> is * <code>false</code>, you can pass <code>null</code> here. */ public LogTextArea( int rows, int columns, boolean useLogFile, File logFile ) { super( rows, columns ); this.useLogFile = useLogFile; this.logFile = logFile; outStream = new PrintStream( new RedirectedStream() ); setEditable( false ); setLineWrap( true ); } public LogTextArea() { this( 6, 40, false, null ); } /* * Returns the stream used by this * gadget to write data to. * * @return the <code>PrintStream</code>, useful * for redirecting system output to. * * @see java.lang.System#setOut( PrintStream ) * @see java.lang.System#setErr( PrintStream ) * * @warning Theoretically if you use this stream for * <code>System.setErr</code>, you will create * a recursion deadlock if an exception is thrown * within the <code>write</code> method of the * stream. This case has never been experienced however. */ public PrintStream getLogStream() { return outStream; } /** * This method is public because * of the superclass method. Appending * text using this method directly * will not use the internal print * stream and thus not appear in * a log file. */ public void append( String str ) { super.append( str ); totalLength += str.length(); updateCaret(); } private void updateCaret() { try { setCaretPosition( Math.max( 0, totalLength - 1 )); } catch( IllegalArgumentException e1 ) { /* ignored */ } } /** * Replaces the gadget's text. * This is useful for clearing * the gadget. This doesn't * affect the <code>PrintStream</code> * or the log file. * * @param str the new text to replace * the gadgets content or <code>null</code> * to clear the gadget. */ public void setText( String str ) { super.setText( str ); totalLength = str == null ? 0 : str.length(); } // public void laterInvocation( Object o ) // { // append( (String) o ); // } // XXX JCollider // public MenuAction getClearAction() public AbstractAction getClearAction() { if( actionClear == null ) { actionClear = new ActionClear(); } return actionClear; } public JScrollPane placeMeInAPane() { return( new JScrollPane( this, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, // aqua hin aqua her. VERTICAL_SCROLLBAR_ALWAYS ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER )); } public void makeSystemOutput() { System.setOut( getLogStream() ); System.setErr( getLogStream() ); } // ---------------- internal classes ---------------- private class RedirectedStream extends OutputStream { private byte[] cheesy = new byte[1]; // private int totalLength = 0; protected RedirectedStream() { super(); } public void write( byte b[] ) throws IOException { this.write( b, 0, b.length ); } public void write( byte b[], int off, int len ) throws IOException { String str = new String( b, off, len ); append( str ); // lim.queue( str ); if( useLogFile ) { if( logFileWriter == null ) { logFileWriter = new FileWriter( logFile ); } logFileWriter.write( str ); } } public void flush() throws IOException { if( logFileWriter != null ) { logFileWriter.flush(); } super.flush(); } public void close() throws IOException { if( logFileWriter != null ) { logFileWriter.close(); logFileWriter = null; } super.close(); } public void write( int b ) throws IOException { cheesy[0] = (byte) b; this.write( cheesy ); } } private class ActionClear // XXX JCollider // extends MenuAction extends AbstractAction { protected ActionClear() { /* empty */ } public void actionPerformed( ActionEvent e ) { setText( null ); } } }