package org.jcon.ui;

//import java.awt.*;
import java.awt.Color;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.*;
import java.io.PrintStream;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JFrame;

public class OutputConsole extends PrintStream
    implements ActionListener, WindowListener {

/**
 * Displays System.out and System.err for debugging purposes.
 * Note that use of System.out may be avoided, but
 * System.err is used by Java internally for uncaught
 * exception dumps.
 * <p>
 * This class is useful when an IDE is unavailable or large
 * amounts of output exist. We may later modify it to print
 * to a log file.
 * <p>
 * *** This was working in Java 1.1 betas. It appears that
 * sometime later Java was modified so that System.out and
 * System.in can only be set in the main thread. Therefore
 * this class now only works ONCE, in the main() thread.
 * It's possible this mod was a security precaution to
 * prevent denial of service attacks which could go into
 * an infinite wait whenever System.out, etc was used.
 * JH 9/7/97 *** And of course this may have changed.
 *
 * @author Jack Harich
 */ // java org.jcon.ui.OutputConsole

//---------- Private Fields ------------------------------
private JFrame       frame    = new JFrame();
private JTextArea    textArea = new JTextArea("", 1, 1);
private PrintStream oldOut = System.out;
private PrintStream oldErr = System.err;
private PrintStream printStream = this;

private static final String TITLE = "System.out And System.err";
private static boolean      unitTesting = false;

//---------- Initialization ------------------------------
public OutputConsole() {
    // Init streams
    super(System.out); // Deprecated, same effect with "err"
    redirect();

    // Init frame
    frame.getContentPane().setLayout(new BorderLayout());
    frame.setBackground(Color.lightGray);
    frame.setSize(500, 400);
	JScrollPane scrollPane = new JScrollPane(textArea);

	scrollPane.setVerticalScrollBarPolicy(
		JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);

	scrollPane.setHorizontalScrollBarPolicy(
		JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

    frame.getContentPane().add("Center", scrollPane);

    // Prepare Button Bar
    JPanel buttonBar = new JPanel();
    buttonBar.setLayout(new FlowLayout());
    buttonBar.add(createButton("Redirect", "Redirect"));
    buttonBar.add(createButton("Restore", "Restore"));
    buttonBar.add(createButton("Test", "PrintTest"));
    buttonBar.add(createButton("Clear", "Clear"));
    buttonBar.add(createButton("New Console", "NewConsole"));
    buttonBar.add(createButton("Mark", "Mark"));
    frame.getContentPane().add("South", buttonBar);

    // Add Listeners
    frame.addWindowListener(this);
}
private JButton createButton(String label, String command) {
    JButton button = new JButton(label);
    button.setActionCommand(command);
    button.addActionListener(this);
    return button;
}
/**
 * Runs the unit test.
 */
public static void main(String args[]) {
    // Unit test
    unitTesting = true;
    OutputConsole console = new OutputConsole();
    console.setVisible(true);
    //printText("Current thread: " + Thread.currentThread());
}
//---------- Superclass Overrides ------------------------
// Note - We may need to override more methods
//----- String
public void print(String text) {
    addLine(text);
}
public void println(String text) {
    addLine(text);
}
//----- Object
public void print(Object object) {
    addLine(object.toString());
}
public void println(Object object) {
    addLine(object.toString());
}
//----- char[]
public void print(char[] text) {
    addLine(String.valueOf(text));
}
// To allow Throwable to print, per doc for:
// private native void printStackTrace0(Object s);
public void println(char[] text) {
    addLine(String.valueOf(text));
}
//---------- ActionListener Implementation ---------------
public void actionPerformed(ActionEvent evt) {
    //printText("Current thread: " + Thread.currentThread());
    String command = evt.getActionCommand();

    if (command.equals("Mark")) {
        addLine("-----------------------");

    } else if (command.equals("Clear")) {
        clear();

    } else if (command.equals("PrintTest")) {
        System.out.println("System.out.println() - TEST OUT");
        System.err.println("System.err.println() - TEST ERR");
        int num = 0;
        print("" + (3 / num));

    } else if (command.equals("Redirect")) {
        redirect();

    } else if (command.equals("Restore")) {
        restore();

    } else if (command.equals("NewConsole")) {
        OutputConsole console = new OutputConsole();
        console.setVisible(true);
        console.redirect();

    }
}
//---------- WindowListener Implementatons ---------------
public void windowClosing(WindowEvent e) {
    destroy();
}
public void windowClosed(WindowEvent e) { }
public void windowDeiconified(WindowEvent e) { }
public void windowIconified(WindowEvent e) { }
public void windowOpened(WindowEvent e) { }
public void windowActivated(WindowEvent e) { }
public void windowDeactivated(WindowEvent e) { }

//---------- Public Methods ------------------------------
public void setVisible(boolean isVisible) {
    frame.setVisible(isVisible);
    if (isVisible) frame.requestFocus();
}
public void addLine(String line) {
    textArea.append(line + "\n");
//    textArea.repaint(); // Causes large bug
}
public void clear() {
    textArea.setText("");
}
public void destroy() {
    restore(); // Important
    frame.setVisible(false);
    frame.dispose();
    if (unitTesting) System.exit(0);
}
public void redirect() {
    System.setOut(printStream);
    System.setErr(printStream);
    frame.setTitle(TITLE + " - Redirected");
}
public void restore() {
    System.setOut(oldOut);
    System.setErr(oldErr);
    frame.setTitle(TITLE + " - Not Redirected");
}
//---------- Private Methods -----------------------------
private static void printText(String text) {
    System.out.println(text);
}


} // End class
