// file: TextTree.java
//

// import java libraries
//
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.tree.*;

public class TextTree extends JPanel implements ActionListener {


    // ---------------------------------------------------
    //
    // declare class member data
    //
    // ---------------------------------------------------
      
    // the JTree iteself.  used to select which text to look at
    //
    public JTree tree = null;
    
    // this is the root node for the tree.  this is what all node are added
    // to, but it doesn't show up in the tree as it is made invisible 
    // by a call in the constructor
    //
    public DefaultMutableTreeNode top = null;

    // this is the filler node for the tree so that it will allow adding 
    // dynamically (it must have an object to display)
    //
    public DefaultMutableTreeNode filler = null;
    
    // scroll pane to hold the tree so it can grow without worrying about
    // overrunning the size of the panel it is mounted upon
    //
    private JScrollPane treeView = null;
    
    // this model is used to allow the insertion of new nodes dynamically.  
    // insertion is not that pretty without this
    //
    public DefaultTreeModel treeModel = null;
    
    // tell the system the total number of direct nodes off of the root
    // so that a new node can be added at the last position
    //
    public int total_entries;

    // stores the name of the user
    //
    String userName;
    
     // ---------------------------------------------------
    //
    // declare class constructors
    //
    // ---------------------------------------------------

    // method: TextTree
    //
    // arguments: none
    // returns  : none
    //
    // default class constructor
    //

    public TextTree(String user, Font newFont, Bug bug) {

	total_entries = 0;

	userName = user;
	
	// Creates a root node
	//
	top = new DefaultMutableTreeNode("Root Node");

	// create the treemodel and tree with the root node attached
	//
	treeModel = new DefaultTreeModel(top);

	// add a created node if there is no tree there currently
	//
	if ((bug.getField("Description") == null) ||
	    (bug.getField("Description").equals("")))
	    writeCreated(newFont, filler);
	else
	    // add a created node if there is no tree there currently
	    //
	    rebuildTree(bug.getField("Description"));

	String starSign="", lineSign="";
	for(int j=0; j< 79; j++) {
	    starSign += "*";
	    lineSign += "-";
	}

 	System.out.println();
 	System.out.println(starSign);
 	System.out.println("Bug description starting from here");
 	System.out.println();
 	System.out.println(lineSign);
 	System.out.print("BugNumber:"+bug.getField("BugNumber"));
 	System.out.print("("+bug.getField("Status")+")");
 	System.out.print("    Title: "+bug.getField("Title"));
 	System.out.println();
 	System.out.println(lineSign);
 	System.out.println(bug.getField("Description"));
 	System.out.println();
 	System.out.println("End for this bug");
 	System.out.println(starSign);

	//	JFrame f = new TextAreaFrame(bug.getField("Description"));
	//f.show();
		
	tree = new JTree(treeModel);
	tree.setFont(newFont);

	// make the root node invisible to the user
 	//
	tree.setRootVisible(false);

	// set all icons to null so the tree will be text based
	//
	DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
	renderer.setLeafIcon(null);
	renderer.setOpenIcon(null);
	renderer.setClosedIcon(null);
	tree.setCellRenderer(renderer);
	renderer.setFont(newFont);

	// makes it where there is the + on the left of shows for the 
	// descriptor nodes as they are now at the top level since the root
	// is hidden
	//
	tree.setShowsRootHandles(true);

	// set the selection model to none so the user can only browse the tree
	//
	tree.setSelectionModel(null);
	
	// create a scroll pane and make it the hold the tree and be the size
	// that was passed in from the calling class
	//
	treeView = new JScrollPane(tree);
	treeView.setPreferredSize(new Dimension(620,300));
	treeView.setFont(newFont);

	// create a border around the scroll pane
        //
        treeView.setBorder(BorderFactory.createEtchedBorder());

	// add all of the compnents to the main panel
	//
	this.setPreferredSize(new Dimension(620, 315));
	this.add(treeView);
	this.setFont(newFont);
    }


    // method: actionPerformed
    //
    // arguments:
    //    ActionEvent e: event that was fired
    //
    // return   : none
    //
    // listens for actions taking place on the components
    //
    public void actionPerformed(ActionEvent e) {
    }

    // method: writeCreated()
    //
    // arguments: none
    //   
    // return   : none
    //
    // creates the Created node
    //

    private void writeCreated(Font newFont, DefaultMutableTreeNode filler) {
	
	// creates the nodes necessary for adding the created node
	//
	DefaultMutableTreeNode category = null;
	DefaultMutableTreeNode leaf = null;
	
	// creates the descriptor node
	//
	Date date = new Date();
	
	filler = new DefaultMutableTreeNode(" ");
	
	// adds that node to the tree structure
	//
	top.add(filler);
	
	// increments the total number of entries so new nodes will fall
	// in place after this
	//
	total_entries++;
    }

    public void rebuildTree(String text) {

	top.removeAllChildren();
	total_entries = 0;

	StringTokenizer tokenizer = new StringTokenizer(text, "\n", true);
	String line = null;
	String newTitle = null;
	String nodeText = new String("");
	String lastAddedTitle = null;
        boolean titleFound = false;
	
	// run through the string until the tokenizer runs out of tokens
	//
	while (tokenizer.hasMoreTokens()) {
	    line = tokenizer.nextToken();
	    
	    if ( (line.startsWith("####")) && (titleFound == false) ) {
		newTitle = line;
		titleFound = true;
		line = tokenizer.nextToken();
	    }

	    else if ( (line.startsWith("####")) && (titleFound == true) ) {
		StringTokenizer testForText = 
		    new StringTokenizer(nodeText, "\n");
		
		if(testForText.hasMoreTokens()) 
		    addNode(nodeText, newTitle);
		else
		    addNode("", newTitle);

		lastAddedTitle = newTitle;
		nodeText = new String("");
		newTitle = line;
		line = tokenizer.nextToken();
	    }
	    
	    else {
		nodeText += line;
	    }
	}
	if(!(newTitle.equals(lastAddedTitle))) {
	    addNode(nodeText, newTitle);
	}

	treeModel.reload();
    }
    
    private void addNode(String text, String newTitle) {
	
	// create nodes to be used for the descriptor (category) and for 
	// the full text(leaf).
	//
	DefaultMutableTreeNode category = null;
	DefaultMutableTreeNode leaf = null;
	
	// tokenizes the string using \n as the delimiter, but keeping the
	// newlines so that any blank lines can be detected
	//
	StringTokenizer tokenizer = new StringTokenizer(text, "\n", true);

	// tells the numbers of leafs that have been added
	//
	int count = 0;

	// used to tell if a blank line in necessary if the current line is 
	// a new line character
	//
	boolean blank = false;
	boolean previous = true;

	// make the title the first line of the edit pane
	//
	category = new DefaultMutableTreeNode(newTitle);

	// add the text that is supposed to be added
	//
	treeModel.insertNodeInto(category, top, total_entries);
	
	// increment the total number of entries
	//
	total_entries++;

	// run through the string until the tokenizer runs out of tokens
	//
	while (tokenizer.hasMoreTokens()) {
	   
	    // read the next token and assign it to line
	    //
	    String line = tokenizer.nextToken();
	    
	    // if the lines is a newline character and the previosu lines
	    // was also a new line, allow the \n character to be added
	    // to the tree by setting blank to true
	    //
	    if ( (line.equals("\n")) && 
		 (previous == true)) {
		blank = true;
	    }

	    // otherwise, do not allow a blank line to be added
      	    else {
		blank = false;
	    }

	    // sets a mark so on the next term, the program will now if this
	    // one was a new line
	    //
	    if (line.equals("\n")) {
		previous = true;
	    }
	    else {
		previous = false;
	    }

	    // if the line is not a newline character or if it is, but the 
	    // blank flag has been set to true, then add the line as 
	    // a leaf node
	    //
	    if ( !(line.equals("\n")) || (blank == true)) {
		// creates the node based on the line of text sent in
		//
		leaf = new DefaultMutableTreeNode(line);
				
		// adds the node as a leaf at the point specified by
		// count
		//
		treeModel.insertNodeInto(leaf, category, count);
		
		// increment count so the next line will occur after this one
		//
		count++;
	    }
	}	
    }
}
// end of file





