/* Copyright (c) 2012,
 * Mathias Kuhring, KuhringM@rki.de, Robert Koch-Institut, Germany, 
 * All rights reserved. For details, please note the license.txt.
 */

package de.rki.ng4.ipig.gui;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

/**
 * <p>A extension of a JTextArea which is able to redirect (catch and print) the system output stream and system error stream.</p>
 * 
 * <p>Source of main idea: <a href="http://unserializableone.blogspot.com/2009/01/redirecting-systemout-and-systemerr-to.html">
 * http://unserializableone.blogspot.com/2009/01/redirecting-systemout-and-systemerr-to.html</a></p>
 * 
 * @author Mathias Kuhring
 *
 */
public class OutputJTextArea extends JTextArea {

	private static final long serialVersionUID = 1L;
	
	private OutputStream newout;
	private PrintStream stdout = System.out;
	private PrintStream stderr = System.err;
	
	/**
	 * Simple constructor which prepares the redirection.
	 */
	public OutputJTextArea(){
		super();
		init();
	}

	/**
	 * This constructor prepares the redirection and initiates the text area with a passed String.
	 * 
	 * @param text text to be printed in the text area
	 */
	public OutputJTextArea(String text){
		super(text);
		init();
	}
	
	/**
	 * This constructor prepares the redirection and creates the text area in a given size (rows and columns).
	 * 
	 * @param rows number of rows
	 * @param cols number of columns
	 */
	public OutputJTextArea(int rows, int cols){
		super(rows, cols);
		init();
	}
	
	// initiates and adapts an output stream
	private void init(){
		newout = new OutputStream() {
			@Override
			public void write(int b) throws IOException {
				updateTextArea(String.valueOf((char) b));
			}

			@Override
			public void write(byte[] b, int off, int len) throws IOException {
				updateTextArea(new String(b, off, len));
			}

			@Override
			public void write(byte[] b) throws IOException {
				write(b, 0, b.length);
			}
		};
	}

	// used by the output stream to write into the text area
	private void updateTextArea(final String text) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				append(text);
			}
		});
	}

	/**
	 * <p>Controls the redirection of the output stream and error stream.</p>
	 *  
	 * @param out set true for redirection into the text area, false to use the standard output stream
	 * @param err set true for redirection into the text area, false to use the standard error stream
	 */
	public void redirectSystemStreams(boolean out, boolean err) {
		if (out){
			System.setOut(new PrintStream(newout, true));
		}
		else{
			System.setOut(stdout);
		}
		
		if (err){
			System.setErr(new PrintStream(newout, true));
		}
		else{
			System.setErr(stderr);
		}
	}
}
