import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import java.util.Enumeration;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowListener;
import java.awt.event.WindowEvent;
/**
 * Implements a simple tree
 */
public class Tree extends JFrame {
    private DefaultMutableTreeNode root;
    private JTree tree;
    
    /**
     * The constructor creates a tree. 
     */ 
    public Tree(DefaultMutableTreeNode root) {
	super("Info 4 Tree Frame");
	this.root = deepClone(root);
	this.tree = new JTree(this.root);
	//Create the scroll pane and add the tree to it. 
        JScrollPane treescroller = new JScrollPane(tree);
	getContentPane().add(treescroller);
	addWindowListener(new WindowAdapter() {
		public void windowClosing(WindowEvent ev) {
		    System.exit(0);
		}
	    });
    }

    /**
     * Deep Clone for DefaultMutableTreeNode
     */
    public static DefaultMutableTreeNode deepClone(DefaultMutableTreeNode root) {
	DefaultMutableTreeNode nroot = (DefaultMutableTreeNode)root.clone();
	Enumeration children = root.children();
	while (children.hasMoreElements()) {
	    DefaultMutableTreeNode child = (DefaultMutableTreeNode)children.nextElement();
	    DefaultMutableTreeNode nchild = deepClone(child);
	    nroot.add(nchild);
	}
	return nroot;
    }

    /*expand tree completely*/
    public void expandAll() {
	SwingUtilities.invokeLater(new Runnable() {//watch for threading
		public void run() {
		    for (int i=0;i<Tree.this.tree.getRowCount();++i) {
			Tree.this.tree.expandRow(i);
		    }
		}
	    }) ;
    }

    /**
     * Get the Root value.
     * @return the Root value.
     */
    public DefaultMutableTreeNode getRoot() {
	return root;
    }

    /**
     * Set the Root value.
     * @param newRoot The new Root value.
     */
    public void setRoot(DefaultMutableTreeNode newRoot) {
	this.root = newRoot;
    }

    
    /**
     * Get the Tree value.
     * @return the Tree value.
     */
    public JTree getTree() {
	return tree;
    }

    /**
     * Set the Tree value.
     * @param newTree The new Tree value.
     */
    public void setTree(JTree newTree) {
	this.tree = newTree;
    }

}