/*
 * @(#)TreeJPanel.java
 *
 * Last Modified: 9/01/02
 */
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.beans.*;

/** * This class provides the panel for a <code>Tree</code>. It keeps the graphics for drawing
	* the tree and the image for redrawing. It also keeps a timer for the animation and all changes
	* to the tree proceed through the panel. This is a class that is extended for each specific tree.
	*
 	* @author  Corey Sanders
	* @version 3.5 9/15/01
 	*/
public class TreeJPanel extends DrawingJPanel implements OptionListener, ActionListener, TreeMessageListener {

	/**
	 * TreeHead kept for the current Panel.
	 */
	private AnimatingTreeHead tree;

	/**
	 * Timer for the animation.
	 */
	javax.swing.Timer animationTimer;

	/**
	 * The delay rate for the animation, set to DEFAULT_DELAY.
	 */
	private int delayRate;

	/**
	 * Represents the current type of inserting value.
	 */
    private String keyType;

	/**
	 * Flag whether the tree is animating or not.
	 */
	private boolean animating = true;

	/**
	 * Flag whether the tree is stepping or not.
	 */
	private boolean step = false;

	/**
	 * Listeners for the tree messages passed.
	 */
	 private LinkedList treeListeners = new LinkedList();

 	/**
     * command passed for type errors.
     */
	public static final String TYPEERR = "type";

	/**
	 * command passed for no key errors.
	 */
	public static final String NOKEY= "key";

	/**
	 * String representing integer types.
	 */
    public static final String INTEGER = "Integer";

	/**
	 * String representing character types.
	 */
    public static final String CHARACTER = "Character";

	/**
	 * String representing double types.
	 */
    public static final String DOUBLE = "Double";


    /**
     * String representing DRAWING color scheme.
     */
     public static final String DRAWING = "Drawing Schemes";


    /**
     * String representing DRAWING color scheme.
     */
     public static final String BACKGROUND = "Background Color";

  	/**
     * String representing INSERT color scheme.
     */
     public static final String INSERT = "Insert Schemes";

    /**
     * String representing SEARCH color scheme.
     */
     public static final String SEARCH = "Search Schemes";

    /**
     * String representing SELECT color scheme.
     */
     public static final String SELECT = "Select Schemes";

    /**
     * String representing ROTATE color scheme.
     */
     public static final String ROTATE = "Rotate Schemes";

     /**
      * String representing DELETE color scheme.
      */
     public static final String DELETE = "Delete Schemes";
     /**
      * String representing TRAVERSE color scheme.
      */
     public static final String TRAVERSE = "Traversal Schemes";


     /**
      * String representing Node color scheme.
      */
     public static final String NODE = "Node";

     /**
      * String representing Key color scheme.
      */
     public static final String KEY = "Key";

    /**
	 * String representing Paint color scheme.
	 */
     public static final String PAINT = "Paint";

     /**
      * String representing node left color scheme.
      */
     public static final String NODE_LEFT_SETTINGS = "Node Left";

     /**
      * String representing node right color scheme.
      */
     public static final String NODE_RIGHT_SETTINGS = "Node Right";

     /**
      * String representing node animator color scheme.
      */
     public static final String NODE_ANIMATOR_SETTINGS = "Node Animator";

     /**
      * String representing key animator color scheme.
      */
     public static final String KEY_ANIMATOR_SETTINGS = "Key Animator";

     /**
      * String representing key original color scheme.
      */
     public static final String KEY_ORIGINAL_SETTINGS = "Key Original";


     /**
      * String representing node root color scheme.
      */
     public static final String NODE_ROOT_SETTINGS = "Node Root";

     /**
      * String representing node child color scheme.
      */
     public static final String NODE_CHILD_SETTINGS = "Node Child";

     /**
      * String representing node descendant color scheme.
      */
     public static final String NODE_DESCENDANT_SETTINGS = "Node Descendant";

     /**
      * String representing node original color scheme.
      */
     public static final String NODE_ORIGINAL_SETTINGS = "Node Original";

     /**
      * String representing the left paint.
      */
     public static final String LEFT_PAINT = "Paint Left";

     /**
      * String representing the right paint.
      */
     public static final String RIGHT_PAINT = "Paint Right";

	/**
	 * The default delay for animation (90).
	 */
	public static final int DEFAULT_DELAY = 1;

	/**
	 * Sole constructor which sets all of the default values for the Panel. Calls the super
	 * constructor of JPanel. Also, it adds itself to listen to component events.
	 */
    public TreeJPanel() {

		super();

		// Set delay rate
		setDelayRate(DEFAULT_DELAY);

		// Initiates timer
		setAnimationTimer(new javax.swing.Timer(delayRate, this));

		// Sets the default insert type
		setKeyType(INTEGER);
    }


	/****************/
	/* Mutators     */
	/****************/

	/**
     * Sets the head of the tree currently drawn in the Panel.
     *
     * @param tree AnimatingTreeHead head.
     */
	public void setTree(AnimatingTreeHead tree) {
		if (getTree() != null) {
			getTree().removeTreeMessageListener(this);
		}

		this.tree = tree;
		getTree().addTreeMessageListener(this);
	}

	/**
	 * Sets the delay rate for the timer for the animation.
	 *
	 * param t int delay rate.
	 */
    public void setDelayRate(int t) {
		//delayRate = (int)((t*-10) + 1000);
		delayRate = t;
		if (getAnimationTimer() != null) {
			getAnimationTimer().setDelay(delayRate);
		}
	}

	/**
	 * Sets whether the tree is animating or not.
	 *
	 * @param animating boolean flag as to whether the tree is animating.
	 */
	public void setAnimating(boolean animating) {
		this.animating = animating;
		setDrawTree(true);
		repaint();
	}

	/**
	 * Sets whether the tree is stepping or not.
	 *
	 * @param step boolean flag as to whether the tree is stepping.
	 */
	public void setStep(boolean step) {
		this.step = step;
		getTree().setStepPause(step);
	}


	/**
	 * Sets the animation timer for the animation of the panel.
	 *
	 * @param animationTimer javax.swing.Timer defining the steps of animation.
	 */
	protected void setAnimationTimer(javax.swing.Timer animationTimer) {
		this.animationTimer = animationTimer;
	}



	/**
	 * Sets the key type for the tree.
	 *
	 * @param keyType String defining the type of key in the tree.
	 */
	protected void setKeyType(String keyType) {
		this.keyType = keyType;
	}

	/**
	 * Given a String, converts the string into the specific type set currently for the tree.
	 * A <code>NumberFormatException</code> is caught and an error message String is returned instead
	 * of an object.
	 *
	 * @param text String to be converted into an object.
	 *
	 * @return the object after converting to the type of the tree, or a String error message.
	 */

	protected Object stringToType(String text) {

		String errors;
		Object returnObject = null;

		try {

			if (getKeyType().equals(INTEGER)) {
				returnObject =  new Integer(text);
			}
			if (getKeyType().equals(CHARACTER)) {
				returnObject =  new Character(text.charAt(0));
			}
			if (getKeyType().equals(DOUBLE)) {
				returnObject =  new Double(text);
			}
		}
		catch (NumberFormatException e) {

			errors = new String(" - "+text+" - ");

			returnObject =  errors;

		}

		return returnObject;

	}

	/****************/
	/* Accesors     */
	/****************/

	/**
	 * Gets the title for the tree.
	 *
	 * @return String defining the title of the tree.
	 */
	public String getTitle() {
		return "None";
	}

	/**
	 * Get the tree message. The method calls <code>TreeStatusMessage</code> of the tree within the panel.
	 */
	public String getTreeStatusMessage() {
		return getTree().getTreeStatusMessage();
	}


    /**
     * Gets the head of the tree currently drawn in the Panel.
     *
     * @return TreeHead the tree head.
     */
	public AnimatingTreeHead getTree() {
		return tree;
	}

	/**
	 * Gets whether the tree is animating or not.
	 *
	 * @param true if the tree is animating.
	 */
	public boolean isAnimating() {
		return animating;
	}

	/**
	 * Gets whether the tree is stepping or not.
	 *
	 * @param true if the tree is stepping.
	 */
	public boolean isStep() {
		return step;
	}


	/**
	 * Gets the key type for the tree.
	 *
	 * @return String defining the type of key in the tree.
	 */
	public String getKeyType() {
		return keyType;
	}


	/**
	 * Gets the animation timer for the animation of the panel.
	 *
	 * @return javax.swing.Timer defining the steps of animation.
	 */
	protected javax.swing.Timer getAnimationTimer() {
		return animationTimer;
	}

	/**
	 * Gets the input options for the current tree.
	 *
	 * @return String array of the options for the current tree.
	 */
	public void getInputOptions() {
		String[] options = {INTEGER, CHARACTER, DOUBLE};

		TreeMessageEvent messageEvent = new TreeMessageEvent(this, TreeMessageEvent.PANEL, TreeMessageEvent.SET_INPUT_OPTIONS, options);
			ListIterator list = treeListeners.listIterator(0);
			while (list.hasNext()) {
				((TreeMessageListener)list.next()).treeMessageEventPerformed(messageEvent);
		}

	}


	/**
	 * Gets a List of objects made from the String text. The method first gets a List of
	 * Strings using <code>getStringList</code>. Then the method uses <code>stringToType</code>
	 * repeatedly, constructing a LinkedList of objects. Any incorrect strings, the error message
	 * is automatically made and sent in the form of a Dialog.
	 *
	 * @param text String to be made into an Object list.
	 *
	 * @return LinkedList List of objects.
	 */
	protected LinkedList getObjectList(String text) {
		StringBuffer errors = null;

		LinkedList objectList = new LinkedList();

		LinkedList stringList = getStringList(text);

		int stringListSize  = stringList.size();

		for (int i=0; i<stringListSize; i++) {
			String currentString = (String)stringList.get(i);

			Object key = stringToType(currentString);

			if (key instanceof String) {
				if (errors == null) {
					errors = new StringBuffer();
				}

				errors.append(key);

			}
			else {
				objectList.add(key);
			}
		}

		if (errors != null) {
			makeTypeErrorMessage(errors.toString());
		}

		return objectList;

	}


	/**
	 * Processes a given text String into a LinkedList of Strings. This allows for multiple inserts
	 * deletes and so forth.
	 *
	 * @param text the String to be parsed into Strings.
	 *
	 * @return LinkedList of Strings, parsed from the text passed.
	 */
	protected LinkedList getStringList(String text) {
		int previousLocation = -1;

		LinkedList stringList = new LinkedList();

		// Remove leading and following whitespace.
		String workingText = text.trim();

		// Length of string
		int stringLength = workingText.length();

		// Go through entire string and put words followed by spaces into linked list.
		for (int i=0; i<stringLength; i++) {
			// Space
			if (workingText.charAt(i) == ' ') {
				// Multiple spaces are skipped
				if (previousLocation == (i-1)) {
					previousLocation = i;
				}
				else {
					// Add to list and reset previousLocation
					stringList.add(workingText.substring(previousLocation+1, i));
					previousLocation = i;
				}
			}
		}

		// Add the final word
		stringList.add(workingText.substring(previousLocation+1));

		return stringList;
 	}


	/**
 	 *******************
	 * Drawing methods *
	 *******************
	 */

	/**
	 * Method actually called to complete the drawing of the panel. The node is drawn to fill the
	 * entire graphics given within the panel.
	 */
	protected void draw() {
		if(!tree.isTreeEmpty()) {
			getTree().MakeTree(getDrawTreeGraphics());
			getTree().DrawTree(getDrawTreeGraphics());
		}
	}

	/**
	 * Overides paintComponenet and is called whenever the Panel needs to be painted. The
	 * painting includes painting the image and then painting the animation (if any).
	 *
	 * @param g Graphics to which the component is drawn.
	 */
	public void paintComponent(Graphics g) {

		Graphics2D g2 = (Graphics2D)g;

		super.paintComponent(g);

		// Rendering hints.
		(g2).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

		// Animate the tree (if animation exists)
		getTree().AnimateTree(g2);

		// Tree has an animation occuring.
		if (getTree().isTreeAnimating()) {
			// Turn on timer
			if (!(getAnimationTimer().isRunning()))
				getAnimationTimer().start();

		}
		else {
			// Turn off timer (Animations complete
			if (getAnimationTimer().isRunning()) {
				getAnimationTimer().stop();
				// Draw tree
				setDrawTree(true);
				repaint();
			}
		}


	}


	/******************/
	/* Errors Msgs    */
	/******************/

 	/**
 	 * Constructs a error type message based upon the current type and the String passed in.
 	 *
 	 * @param String attached to end of error message.
 	 */
 	 protected void makeTypeErrorMessage(String error) {
		 String errorMsg = new String("The following types\nare not "+getKeyType()+" : "+error);

 		 messageAction(TreeMessageEvent.ERROR_MESSAGE, errorMsg.toString());

 	 }

 	/**
 	 * Constructs a error type message based upon the current type and the String passed in.
 	 *
 	 * @param String attached to end of error message.
 	 */
 	 protected void makeTypeIntegerErrorMessage(String error) {
		 String errorMsg = new String("You must enter\nintegers for"+error);

 		 messageAction(TreeMessageEvent.ERROR_MESSAGE, errorMsg.toString());
 	 }

 	/**
 	 * Constructs a error missing message based upon the current type and the String passed in.
 	 *
 	 * @param String attached to end of error message.
 	 */
 	 protected void makeMissingErrorMessage(String error) {
		 String errorMsg = new String("The following keys are\nnot in the tree :"+error);

 		 messageAction(TreeMessageEvent.ERROR_MESSAGE, errorMsg.toString());

 	 }




	/******************/
	/* Field Commands */
	/******************/

	/**
	 * Inserts the given text as keys into the tree. The method uses the protected method
	 * <code>getObjectList</code> to produce objects. Then, those objects are inserted with
	 * a newly made DrawingKey.
	 *
	 * @param text String to be inserted into the tree.
	 */
	protected void insertKeys(String text) {

		// Set initial status.
		playCommand();

		// Object list constructed
		LinkedList insertObjects = getObjectList(text);

		int objectListSize = insertObjects.size();
		// Proceed through list

		for (int i=0; i< objectListSize; i++) {
			Comparable key = (Comparable)insertObjects.get(i);

			if (getTree().isTreeEmpty()) {
				getTree().insert(key, new DrawingKey(insertObjects.get(i)));
				drawTree();
			}
			else {
				// Insert the object and a new drawing key
				getTree().insert(key, new DrawingKey(insertObjects.get(i)));
			}


			// Draw the tree



		}

		setDrawTree(true);
		repaint();


	}

	/**
	 * Searches the given text for keys in the tree. The method uses the protected method
	 * <code>getObjectList</code> to produce objects. Then, those objects are searched for.
	 *
	 * @param text String to be searched into the tree.
	 */
	protected void searchKeys(String text) {
		// Set initial status.
		playCommand();

		// Object list constructed
		LinkedList insertObjects = getObjectList(text);

		int objectListSize = insertObjects.size();
		// Proceed through list
		for (int i=0; i< objectListSize; i++) {
			Comparable key = (Comparable)insertObjects.get(i);
			// Search
			getTree().search(key);
		}

		setDrawTree(true);
		repaint();
	}


	/**
	 * Selects the given text for keys in the tree. The method uses the protected method
	 * <code>getObjectList</code> to produce objects. Then, those objects are selected.
	 *
	 * @param text String to be selected into the tree.
	 */
	protected void selectKeys(String text) {

		// Set initial status.
		playCommand();

		// Object list constructed
		LinkedList stringList = getStringList(text);

		int stringListSize = stringList.size();
		// Proceed through list
		for (int i=0; i< stringListSize; i++) {
			try {

				int key = (Integer.decode((String)stringList.get(i))).intValue();

				Tree returnTree = getTree().select(getTree().getChild(), key);

				if (returnTree == null) {
					messageAction(TreeMessageEvent.ERROR_MESSAGE, "You must enter an integer less\nthan the size of that node's subtree!");
				}
			}
			catch (NumberFormatException e) {
				makeTypeIntegerErrorMessage(" selection.");
				break;
			}
		}

		setDrawTree(true);
		repaint();
	}


	/**
	 * Deletes the given text from the tree. The method uses the protected method
	 * <code>getObjectList</code> to produce objects. Then, those objects are deleted.
	 *
	 * @param text String to be deleted into the tree.
	 */
	protected void deleteKeys(String text) {
		// Set initial status.
		playCommand();


		StringBuffer errors = null;

		// Object list constructed
		LinkedList insertObjects = getObjectList(text);

		int objectListSize = insertObjects.size();
		// Proceed through list
		for (int i=0; i< objectListSize; i++) {

			Comparable key = (Comparable)insertObjects.get(i);
			// Delete
			if(!getTree().remove(key)) {
				if (errors == null) {
					errors = new StringBuffer();
				}

				errors.append(" - "+key+" - ");
			}

		}

		if (errors != null) {
			makeMissingErrorMessage(errors.toString());
		}

		setDrawTree(true);
		repaint();

	}

	/*******************/
	/* Click Commands  */
	/*******************/

	/**
	 * Deletes the given node from the tree.
	 *
	 * @param node the Tree node to be deleted from the tree.
	 */
	protected void deleteNode(Tree node) {
		// Set initial status.
		playCommand();


		getTree().remove(node);

		setDrawTree(true);
		repaint();
	}

	/**
	 * Partitions the given node. A JOptionPane appears requesting the entering of the kth element
	 * with which to partition.
	 *
	 * @param node the node to partition.
	 */
	protected void partitionNode(Tree node) {
		// Set initial status.
		playCommand();


		if (node == null)
			return;

		// Get the kth element.
		String response = JOptionPane.showInputDialog(this, "Please enter the kth\nelement to partition:", "Partition Element", JOptionPane.QUESTION_MESSAGE);


		try {
			int key = (Integer.decode(response)).intValue();

			Tree returnTree = getTree().partition(node, key);

			if (returnTree == null) {
				JOptionPane.showMessageDialog(this, "You must enter an integer less than the size of that node's subtree!", "Type Error", JOptionPane.ERROR_MESSAGE);
			}


		}
		catch (NumberFormatException e) {
			JOptionPane.showMessageDialog(this, "You must enter an integer count for a partition!", "Type Error", JOptionPane.ERROR_MESSAGE);
		}

		setDrawTree(true);
		repaint();
	}

	/**
	 * Selects the given node. A JOptionPane appears requesting the entering of the kth element
	 * with which to select.
	 *
	 * @param node the node to select from.
	 */
	protected void selectNode(Tree node) {
		// Set initial status.
		playCommand();


		if (node == null)
			return;

		// Get the kth element.
		String response = JOptionPane.showInputDialog(this, "Please enter the kth\nelement to select:", "Select Element", JOptionPane.QUESTION_MESSAGE);


		try {
			int key = (Integer.decode(response)).intValue();

			Tree returnTree = getTree().select(node, key);

			if (returnTree == null) {
				JOptionPane.showMessageDialog(this, "You must enter an integer less than the size of that node's subtree!", "Type Error", JOptionPane.ERROR_MESSAGE);
			}


		}
		catch (NumberFormatException e) {
			JOptionPane.showMessageDialog(this, "You must enter an integer count for a partition!", "Type Error", JOptionPane.ERROR_MESSAGE);
		}

		setDrawTree(true);
		repaint();
	}


	/**
	 * Changes the input according to the text string. The tree is cleared if it is not empty.
	 * Also a key type change message is sent to all listeners.
	 *
	 * @param text the String representing the input change.
	 */
	protected void inputChange(String text) {

		// Already set
		if (getKeyType().equals(text))
			return;

		// Clear tree
		clear();
		setKeyType(text);

	}


	/**
	 * Clears the tree. Initiates a JOptionPane to confirm clearing.
	 */
	protected int clearTree() {
		// Set initial status.
		playCommand();



		// Confirm
		int response = JOptionPane.showConfirmDialog(this, "Are ou sure you wish to clear the tree?", "Clear Tree", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);

		if (response == JOptionPane.YES_OPTION) {

			// Clears tree
			clear();
			// Cleared tree
			return 1;
		}
		// Didn't clear
		return 0;
	}

	/**
	 * Clears the tree. Does not initiate a JOptionPane to confirm clearing. Just clears.
	 */
	protected void clear() {
		// Clears tree
		getTree().clear();

		setDrawTree(true);
		repaint();
	}


	/************************************************/
	/* Commands that are called after OptionEvents. */
	/************************************************/


	/**
	 * Insert command. Simply calls insertKeys with the text. Overide if necessary.
	 *
	 * @param text String to insert.
	 */
	public void insertCommand(String text) {
		insertKeys(text);
	}

	/**
	 * Search command. Simply calls searchKeys with the text. Overide if necessary.
	 *
	 * @param text String to search.
	 */
	public void searchCommand(String text) {
		searchKeys(text);
	}

	/**
	 * Delete command. Simply calls deleteKeys with the text. Overide if necessary.
	 *
	 * @param text String to delete.
	 */
	public void deleteCommand(String text) {
		deleteKeys(text);
	}

	/**
	 * Insert command. Simply calls insertKeys with the text. Overide if necessary.
	 *
	 * @param node Tree to delete.
	 */
	public void deleteCommand(Tree node) {
		deleteNode(node);
	}

	/**
	 * Select command. Simply calls selectKeys with the text. Overide if necessary.
	 *
	 * @param text String to select.
	 */
	public void selectCommand(String text) {
		selectKeys(text);
	}

	/**
	 * Select command. Simply calls selectKeys with the text. Overide if necessary.
	 *
	 * @param text String to select.
	 */
	public void selectCommand(Tree node) {
		selectNode(node);
	}

	/**
	 * Clear command. Simply calls clearTree. Overide if necessary.
	 */
	public void clearCommand() {
		clearTree();
	}


	/**
	 * Clear all command. Simply calls clear. Overide if necessary.
	 */
	public void clearAllCommand() {
		clear();
	}

	/**
	 * Partition command. Simply calls partitionNode. Overide if necessary.
	 *
	 * @param node Tree to partition.
	 */
	public void partitionCommand(Tree node) {
		partitionNode(node);
	}


	/**
	 * RotateUp command. Does Nothing (not all trees have rotations). Overide if necessary.
	 *
	 * @param node Tree to rotateUp.
	 */
	public void rotateUpCommand(Tree node) {

	}

	/**
	 * RotateToTop command. Does Nothing (not all trees have rotations). Overide if necessary.
	 *
	 * @param node Tree to rotateToTop.
	 */
	public void rotateToTopCommand(Tree node) {

	}

	/**
	 * RotateUpDouble command. Does Nothing (not all trees have rotations). Overide if necessary.
	 *
	 * @param node Tree to rotateUpDouble.
	 */
	public void rotateUpDoubleCommand(Tree node) {

	}

	/**
	 * Splay command. Does Nothing (not all trees have rotations). Overide if necessary.
	 *
	 * @param node Tree to splay.
	 */
	public void splayCommand(Tree node) {

	}

	/**
	 * Balance command. Does Nothing. Overide if necessary.
	 *
	 * @param node Tree to balance.
	 */
	public void balanceCommand(Tree node) {

	}

	/**
	 * Traverse command. Does Nothing. Overide if necessary.
	 *
	 * @param traverseType int that defines the traverseType.
	 */
	 public void traverseCommand(int traverseType) {

	 }

	/**
	 * Play command.
	 */
	public void playCommand() {
		getTree().setJumpStep(false);
		getTree().setStepPause(false);
		getTree().play();
	}

	/**
	 * Play command.
	 */
	public void playStepCommand() {
		getTree().setJumpStep(false);
		getTree().setStepPause(true);
		getTree().play();
	}

	/**
	 * Play command.
	 */
	public void playFastCommand() {
		getTree().setJumpStep(true);
		getTree().setStepPause(true);
		getTree().play();
	}

	/**
	 * Play command.
	 */
	public void rewindCommand() {
		getTree().setJumpStep(false);
		getTree().setStepPause(false);
		getTree().rewind();
	}

	/**
	 * Play command.
	 */
	public void rewindStepCommand() {
		getTree().setJumpStep(false);
		getTree().setStepPause(true);
		getTree().rewind();
	}

	/**
	 * Play command.
	 */
	public void rewindFastCommand() {
		getTree().setJumpStep(true);
		getTree().setStepPause(true);
		getTree().rewind();
	}


	/**
	 * Pause command.
	 */
	public void pauseCommand() {
		getTree().pause();
	}


	/**
	 * Stop command.
	 */
	public void stopCommand() {
		getTree().stop();
	}


	/**
	 * Animation command.
	 *
	 * @param step boolean turning animation on or off.
	 */
	public void animatingCommand(boolean animatingCommand) {
		setAnimating(animatingCommand);
	}

	/**
	 * Animation quality command.
	 *
	 * @param quality int setting the quality of the animation.
	 */
	public void animationQualityCommand(int quality) {
		setDelayRate(quality);
	}

	/**
	 * Animation speed command.
	 *
	 * @param speed int setting the speed of the animation.
	 */
	public void animationSpeedCommand(int speed) {
		getTree().setTreeAnimationsStepSize(speed);
	}

	/**
	 * Input Change Command.
	 *
	 * @param input string setting the new input type.
	 */
	public void inputChangeCommand(String input) {
		inputChange(input);
	}


	public void saveTreeCommand(TreeJPanel panel) {
		if (panel != this) {
			panel.setSettings(this);
		}
	}


	/**
	 * Constructs a popupmenu, using the actionlistener passed. The popupMenu
	 * contains all of the options available through the current tree. For this
	 * class, no items are added, making it necessary to overide the method.
	 *
	 * @param actionListener the listener add to the actions of all the items made in the menu.
	 *
	 * @return JPopupMenu which is the menu constructed within the panel.
	 */
	public JPopupMenu makeJPopupMenu(ActionListener actionListener) {
		JPopupMenu popupMenu = new JPopupMenu();

		return popupMenu;
	}

	/**
	 * Passes a message to make the color scheme options for the current Panel. Generally called
	 * if this panel becomes selected. A tree message is sent with <code>TreeMessageEvent.COLOR_PANEL</code> with
	 * this as the object.
	 */
	public void makeColorSchemeOptions() {
		messageAction(TreeMessageEvent.COLOR_PANEL, this);
	}

	/**
	 * Passes a message to make the color settings options for the current Panel. Generally called
	 * if this panel becomes selected. A tree message is sent with <code>TreeMessageEvent.SET_PRESET_COLOR_OPTIONS</code> with
	 * this as the object.
	 */
	public void makeColorSettings() {
		messageAction(TreeMessageEvent.SET_PRESET_COLOR_OPTIONS, this);
	}

	/**
	 * Constructs the color settings for this tree, using the given parameter.
	 *
	 * @param allTreeToolsPanel Panel to construct the color settings.
	 */
	public void constructColorOptions(ColorOptionsJPanel allTreeToolsPanel) {
	}

	/**
	 * Constructs the color settings combo box and sets the box for the given colorOptionsPanel.
	 *
	 * @param colorOptionsPanel the colorOptionsPanel for which the JComboBox is set.
	 */
	public void constructPresetColorOptions(ColorOptionsJPanel colorOptionsPanel) {
	}

	/************************/
	/* Tree Message Methods */
	/************************/

	/**
	 * Adds an TreeMessageListener from the TREE, according to
	 * the TreeMessageListener interface and the <code>TreeMessageEvent</code>.
	 *
	 * @param l the listener added recieves the TreeMessageEvents occuring.
	 */
	public void addTreeMessageListener(TreeMessageListener l) {
		treeListeners.add(l);
	}

	/**
	 * Removes an TreeMessageListener from the TREE, according to
	 * the TreeMessageListener interface and the <code>TreeMessageEvent</code>.
	 *
	 * @param l the listener removed from recieving the TreeMessageEvents occuring.
	 */
	public void removeTreeMessageListener(TreeMessageListener l) {
		treeListeners.remove(l);
	}

	/**
	 * Calls all of the treeListeners of the Tree and passes the tree message information information regarding the
	 * status of the Tree.
	 *
	 * @param msg String message for the action of the message.
	 * @param msgObj the accompanying object for the message.
	 */
	protected void messageAction(String msg, Object msgObj) {

		 // Returns if the panel is not shown, and the message is not an error or tree status (msgObj = tree).
		 if (!isComponentShown() && !(msg.equals(TreeMessageEvent.ERROR_MESSAGE)) && !(msg.equals(TreeMessageEvent.COLOR_PANEL)) && !(msgObj == getTree()) && !(msg.equals(TreeMessageEvent.SET_PRESET_COLOR_OPTIONS))) {

			 return;
		 }

		if (msgObj == getTree()) {
			TreeMessageEvent messageEvent = new TreeMessageEvent(this, TreeMessageEvent.PANEL, TreeMessageEvent.STATUS_MESSAGE);
			ListIterator list = treeListeners.listIterator(0);
			while (list.hasNext()) {
				((TreeMessageListener)list.next()).treeMessageEventPerformed(messageEvent);
			}
		}

		TreeMessageEvent messageEvent = new TreeMessageEvent(this, TreeMessageEvent.PANEL, msg, msgObj);
		ListIterator list = treeListeners.listIterator(0);
		while (list.hasNext()) {
			((TreeMessageListener)list.next()).treeMessageEventPerformed(messageEvent);
		}
	}





	/******************************/
	/* Implements OptionListener. */
	/******************************/

	/**
	 * Sets the settings for the panel param.
	 *
	 * @param panel the panel for the settings to be set.
	 */
	public void setSettings(TreeJPanel panel) {

	}

	/**
	 * Recieved an event from an OptionJPanel with one of the given commands. The Panel
	 * responds accordingly. The Methods it calls (for example: insertCommand, rotateCommand...)
	 * should be overiden in extending classes to functionable.
	 *
	 * @param e OptionEvent recieved from the event performed.
	 */
	public void optionEventPerformed(OptionEvent e) {

		if (e.getActionCommand().equals(OptionEvent.INSERT)) {
			insertCommand((String)e.getObjectValue());
		}

		if (e.getActionCommand().equals(OptionEvent.CLEAR)) {
			clearCommand();
		}
		if (e.getActionCommand().equals(OptionEvent.CLEAR_ALL)) {
			clearAllCommand();
		}

		if (e.getActionCommand().equals(OptionEvent.ROTATE_CLICK)) {
			rotateUpCommand((Tree)e.getObjectValue());
		}

		if (e.getActionCommand().equals(OptionEvent.ROTATE_TOP_CLICK)) {
			rotateToTopCommand((Tree)e.getObjectValue());
		}

		if (e.getActionCommand().equals(OptionEvent.ROTATE_DOUBLE_CLICK)) {
			rotateUpDoubleCommand((Tree)e.getObjectValue());
		}

		if (e.getActionCommand().equals(OptionEvent.SPLAY_CLICK)) {
			splayCommand((Tree)e.getObjectValue());
		}

		if (e.getActionCommand().equals(OptionEvent.PARTITION_CLICK)) {
			partitionCommand((Tree)e.getObjectValue());
		}

		if (e.getActionCommand().equals(OptionEvent.DELETE)) {
			deleteCommand((String)e.getObjectValue());
		}
		if (e.getActionCommand().equals(OptionEvent.DELETE_CLICK)) {
			deleteCommand((Tree)e.getObjectValue());
		}

		if (e.getActionCommand().equals(OptionEvent.INPUT_CHANGE_ALL)) {
			inputChangeCommand((String)e.getObjectValue());
		}

		if (e.getActionCommand().equals(OptionEvent.SEARCH)) {
			searchCommand((String)e.getObjectValue());
		}


		if (e.getActionCommand().equals(OptionEvent.SELECT)) {
			selectCommand((String)e.getObjectValue());
		}
		if (e.getActionCommand().equals(OptionEvent.SELECT_CLICK)) {
			selectCommand((Tree)e.getObjectValue());
		}

		if (e.getActionCommand().equals(OptionEvent.BALANCE)) {
			balanceCommand(null);
		}
		if (e.getActionCommand().equals(OptionEvent.BALANCE_CLICK)) {
			balanceCommand((AnimatingTree)e.getObjectValue());
		}

		if (e.getActionCommand().equals(OptionEvent.PREORDER_TRAVERSAL)) {
			traverseCommand(TreeHead.PREORDER_TRAVERSAL);
		}
		if (e.getActionCommand().equals(OptionEvent.POSTORDER_TRAVERSAL)) {
			traverseCommand(TreeHead.POSTORDER_TRAVERSAL);
		}
		if (e.getActionCommand().equals(OptionEvent.INORDER_TRAVERSAL)) {
			traverseCommand(TreeHead.INORDER_TRAVERSAL);
		}
		if (e.getActionCommand().equals(OptionEvent.LEVELORDER_TRAVERSAL)) {
			traverseCommand(TreeHead.LEVELORDER_TRAVERSAL);
		}

		if (e.getActionCommand().equals(OptionEvent.ANIMATION_PAUSE)) {
			pauseCommand();
		}
		if (e.getActionCommand().equals(OptionEvent.ANIMATION_STOP)) {
			stopCommand();
		}
		if (e.getActionCommand().equals(OptionEvent.ANIMATION_PLAY)) {
			playCommand();
		}
		if (e.getActionCommand().equals(OptionEvent.ANIMATION_REWIND)) {
			rewindCommand();
		}
		if (e.getActionCommand().equals(OptionEvent.ANIMATION_STEP_REWIND)) {
			rewindStepCommand();

		}
		if (e.getActionCommand().equals(OptionEvent.ANIMATION_STEP_FORWARD)) {
			playStepCommand();
		}
		if (e.getActionCommand().equals(OptionEvent.ANIMATION_FAST_REWIND)) {
			rewindFastCommand();

		}
		if (e.getActionCommand().equals(OptionEvent.ANIMATION_FAST_FORWARD)) {
			playFastCommand();
		}

		if (e.getActionCommand().equals(OptionEvent.ANIMATION_ON)) {
			animatingCommand(true);
		}

		if (e.getActionCommand().equals(OptionEvent.ANIMATION_OFF)) {
			animatingCommand(false);
		}

		if (e.getActionCommand().equals(OptionEvent.ANIMATION_QUALITY)) {
			animationQualityCommand(((Integer)e.getObjectValue()).intValue());
		}

		if (e.getActionCommand().equals(OptionEvent.ANIMATION_SPEED)) {
			animationSpeedCommand(((Integer)e.getObjectValue()).intValue());
		}

		if (e.getActionCommand().equals(OptionEvent.GET_INPUT_OPTIONS)) {
			getInputOptions();
		}
		if (e.getActionCommand().equals(OptionEvent.SAVE_ALL)) {
			saveTreeCommand((TreeJPanel)e.getObjectValue());
		}

	}




	/************************************************/
	/* Implements TreeMessage Listener              */
	/************************************************/

	/**
	 * Listens to tree message events.
	 *
	 * @param e TreeMessageEvent that contains information about the tree.
	 */
	public void treeMessageEventPerformed(TreeMessageEvent e) {

		// FINISH message or REDRAW message
		if ((e.getMessage().equals(Animation.FINISH)) || (e.getMessage().equals(Animation.REDRAW))) {
			setDrawTree(true);
			repaint();
		}
		// Else send the message out further to those listenning to this object
		if (!(e.getMessage().equals(Animation.REDRAW))) {
			messageAction(e.getMessage(), e.getMessageObject());
		}

	}

	/************************************************/
	/* Implements Action Listener              */
	/************************************************/

	/**
	 * Listens to action events.
	 *
	 * @param e ActionEvent that contains information about the tree.
	 */
	public void actionPerformed(ActionEvent e) {
		repaint();
	}


}