// file: $ISIP_IFC/util/demo/isip_demo_selector/DebugWindow.java
// version: $Id: DebugWindow.java 10233 2005-09-13 14:46:42Z stanley $ 
//

// import necessary java libraries
//
import java.net.*;
import java.io.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
import javax.swing.border.*;

public class DebugWindow implements ActionListener {
    
    //------------------------------------------------------------------------
    //
    // protected data
    //
    //-----------------------------------------------------------------------
    
    // default height and width
    //
    static protected int DEFAULT_DIALOG_HEIGHT = 450;
    static protected int DEFAULT_DIALOG_WIDTH = 900;
    
    // default rows and columns
    //
    static protected int DEFAULT_TEXTAREA_ROWS = 20;
    static protected int DEFAULT_TEXTAREA_COLS = 50;
    
    // default size and default increments
    //
    static protected int DEFAULT_VECTOR_INITIAL_SIZE = 10;
    static protected int DEFAULT_VECTOR_ADD_AT_OVERFLOW = 5;
    
    // text for the user interface
    //
    static protected String clear_button_text = "Clear";
    static protected String close_button_text = "Close Window";
    
    // the vector that stores all the strings that are the logs
    //
    protected Vector<String> logs_d = null;
    
    // used in created of the dialog
    //
    protected JFrame parent_frame_d = null;

    // variable to hold the dialog box when it is visible
    //
    JDialog dialog_box_d = null;

    // text area that shows the text
    //
    JTextArea text_area_d = null;

    // window is not initially visible
    //
    protected boolean visible = false;

    //-------------------------------------------------------------------------
    //
    // public methods
    //
    //-------------------------------------------------------------------------

    /**
     * Constructor for this class.
     *
     * @param parent_frame_a frame reference to parent frame
     * @param show_immediately_a boolean to show or not immediately
     */
    public DebugWindow(JFrame parent_frame_a, boolean show_immediately_a) {

	// error check
	if (parent_frame_a == null)
	    return;

	// store parent
	//
	parent_frame_d = parent_frame_a;

	// create the vector to hold the logs
	//
	logs_d = new Vector<String> (DEFAULT_VECTOR_INITIAL_SIZE,
			    DEFAULT_VECTOR_ADD_AT_OVERFLOW);

	if (show_immediately_a) {
	    showDialog();
	}
    }

    /**
     * Constructor for this class. Is a wrapper with default 
     * show_immediate = false.
     *
     * @param parent_frame_a frame reference to parent frame
     */
    public DebugWindow(JFrame parent_frame_a) {
	this (parent_frame_a, false);
    }

    /**
     * Appends a line into the textbox to be displayed
     *
     * @param str_a a string to add to the window
     * @param add_newline_a boolean, true = add new line, false = add as-is
     *
     */
     public void addLogEntry(String str_a, boolean add_newline_a) {
	 if (str_a == null) {
	    return;
	 }
	 
	 if (add_newline_a == true && str_a.endsWith("\n") == false) {
	     str_a = str_a.concat("\n");
	 }
	 
	 logs_d.add(str_a);
	 logUpdated();
     }
    
    /**
     * Appends a line into the textbox to be displayed with add newline equal
     * to false. String added as-is.
     *
     * @param str_a a string to add to the window
     *
     */
     public void addLogEntry(String str_a) {
	addLogEntry(str_a, true);
    }

    /**
     * Clears the vector storing all the text. Also clears the window if it
     * is visible currently.
     *
     */
     public void clearLog() {
	 if (logs_d == null) {
	     return;
	 }
	 logs_d.clear();
	 logUpdated();
     }
    
    /**
     * If the dialog is currently visible, will destroy it safely. All added
     * text is saved though for next viewing.
     *
     */
    public void destroyDialog() {
	if (visible && dialog_box_d != null) {
	    visible = false;
	    dialog_box_d.setVisible(false);
	    dialog_box_d.dispose();
	    dialog_box_d = null;
	}
    }	
    
    /**
     * If the dialog is not currently visible, will create it and put all
     * text in the string vector into it. 
     *
     */
    public void showDialog() {
	if (visible || dialog_box_d != null || logs_d == null)
	    return;
	System.out.println("Entered showDialog\n");
	dialog_box_d = new JDialog(this.parent_frame_d,
				   "Debug Window",
				   false,
				   null);
	
	JPanel logPanel = new JPanel(new BorderLayout());
	logPanel.setBorder(new TitledBorder(new EtchedBorder(), 
					    "Debug Log"));
	
	JPanel buttonPanel = new JPanel();
	JButton clear_button = new JButton(clear_button_text);
	JButton close_button = new JButton(close_button_text);
	clear_button.addActionListener(this);
	close_button.addActionListener(this);
	
	buttonPanel.add(clear_button);
	buttonPanel.add(close_button);
	
	text_area_d = new JTextArea(DEFAULT_TEXTAREA_ROWS,
				    DEFAULT_TEXTAREA_COLS);
	
	for (int i = 0; i < logs_d.size(); i++) {
	    // To force it to string
	    //
	    text_area_d.append( logs_d.elementAt(i) + "");
	}

	logPanel.add(new JScrollPane(text_area_d), BorderLayout.NORTH);
	
	JPanel contentPane = new JPanel(new BorderLayout());
	contentPane.add(logPanel, BorderLayout.NORTH);
	contentPane.add(buttonPanel, BorderLayout.SOUTH);
	
	// Set the content pane
	//
	dialog_box_d.setContentPane(contentPane);
	
	// Display the dialog box
	//
	dialog_box_d.setSize(new Dimension(DEFAULT_DIALOG_WIDTH, 
					   DEFAULT_DIALOG_HEIGHT));
	dialog_box_d.setLocationRelativeTo(parent_frame_d);
	dialog_box_d.setVisible(true);
	visible = true;
	
	// Don't let the dialog box close itself. Add a window listener
	// which then executes the actionlistener with the same message
	// the close button has on it.
	//
	dialog_box_d.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
	dialog_box_d.addWindowListener(new WindowAdapter() {
		public void windowClosing(WindowEvent e) {
		    actionPerformed(new 
		    		    ActionEvent(this, 0, close_button_text));
		}
	    });
    }

    /**
     * This performs the respective actions whenever a menu item
     * or button is pressed.
     *
     * @param evt event the represents the chosen button or menu item.
     *
     */
    public void actionPerformed(ActionEvent evt) {
	String arg = evt.getActionCommand();
	
	if (arg == null) {
	    return;
	}
	
	if (arg.equals(clear_button_text)) {
	    clearLog();
	}
	
	if (arg.equals(close_button_text)) {
	    destroyDialog();
	}
    } 
    

    //-----------------------------------------------------------------------
    //
    // protected methods
    //
    //-----------------------------------------------------------------------

    /**
     * Local function that is called whenever an event occurs that changes
     * the text in the buffer.
     *
     */
    protected void logUpdated() {
	
	if (logs_d == null || text_area_d == null) {
	    return;
	}
	
	if (visible) {
	    // if cleared
	    //
	    if (logs_d.size() == 0) {
		text_area_d.setText("");
	    }

	    // if updated, then it is the most previous line so merely add it
	    //
	    else {
		text_area_d.append(logs_d.lastElement().toString());
	    }
	}
    }
}

    
