// MyDrawPanel.java
//
// Panel for the drawing area
//
// this one handles the mouse events
//
// Student Name: Aleman Meza, Boanerges
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
/**
* Class DrawPanel for Binary Tree
*/
public class DrawPanel extends JPanel
{
protected Node root;
boolean firstTime;
private int maxx;
private int maxy;
/**
* DrawPanel default constructor
*/
public DrawPanel()
{
setBackground(Color.white);
root = null;
firstTime = true;
maxx = 600;
maxy = 400;
repaint();
}
/**
* Gets the component preferred size
* @return a Dimension with the size
*/
public Dimension getPreferredSize()
{
return new Dimension(maxx, maxy);
}
/**
* Paints the tree graphic visualization
* @param g the Graphics context
*/
public void paint(Graphics g)
{
super.paint(g);
int xleft = 0;
int xright = 0;
int ydown = 0;
boolean changesize = false;
if(firstTime && root != null)
{
FontMetrics fm = g.getFontMetrics();
root.setMetrics(fm.getHeight(), fm.getMaxAdvance(), fm.getAscent());
firstTime = false;
}
if(root != null)
{
xleft = Math.abs(root.getMinx(0));
xright = Math.abs(root.getMaxx(0)) + 60;
ydown = root.getMaxy(0) + root.getHeight() * 3;
}
if(maxx < (xright + xleft))
{
maxx = (xright + xleft);
changesize = true;
}
if(maxy < ydown)
{
maxy = ydown;
changesize = true;
}
if(changesize == true)
{
setSize(maxx, maxy);
}
if(root != null)
root.inorder(g, xleft + 20, 16);
else
{
int y = 16;
xleft = 30;
g.drawString("root", xleft - 12, y);
g.drawLine(xleft, y + 2, xleft, y + 16);
g.drawLine(xleft, y + 16, xleft - 4, y + 16 - 4);
g.drawLine(xleft, y + 16, xleft + 4, y + 16 - 4);
g.drawString("null", xleft - 12, y + 28);
}
}
/**
* Adds an element
* @param elem the element
* @return true if the element is added successfully
*/
public boolean addElement(String s)
{
boolean retValue;
if(root == null)
root = new Node(s);
retValue = root.add(s);
repaint();
return retValue;
}
/**
* Gets the Pre-Order traversal
* @return a String representation of the pre-order traversal
*/
public String getPreOrder()
{
String temp;
if(root == null)
return "";
temp = root.txtPreorder();
return temp.substring(1, temp.length());
}
/**
* Gets the In-Order traversal
* @return a String representation of the in-order traversal
*/
public String getInOrder()
{
String temp;
if(root == null)
return "";
temp = root.txtInorder();
return temp.substring(1, temp.length());
}
/**
* Gets the Post-Order traversal
* @return a String representation of the post-order traversal
*/
public String getPostOrder()
{
String temp;
if(root == null)
return "";
temp = root.txtPostorder();
return temp.substring(1, temp.length());
}
/**
* Clears the tree
*/
public void clear()
{
root = null;
firstTime = true;
repaint();
}
/**
* Finds an element
* @param elem the element
* @return true if the element was found
*/
public boolean findElement(String elem)
{
if(root == null)
return false;
return root.findElement(elem);
}
/**
* Deletes an element
* @param elem the element
* @return true if the element was deleted successfully
*/
public boolean deleteElement(String elem)
{
if(root == null)
return false;
Node current = root;
Node parent = root;
boolean isLeftChild = true;
while(! current.data.equals(elem))
{
parent = current;
if(current.data.compareTo(elem) > 0)
{
isLeftChild = true;
current = current.left;
}
else
{
isLeftChild = false;
current = current.right;
}
if(current == null)
return false;
}
if(current.left == null && current.right == null)
{
if(current == root)
root = null;
else
if(isLeftChild)
{
parent.left = null;
parent.numLeftChilds = 0;
}
else
{
parent.right = null;
parent.numRightChilds = 0;
}
}
else if(current.right == null)
if(current == root)
root = current.left;
else if(isLeftChild)
parent.left = current.left;
else
parent.right = current.left;
else if(current.left == null)
if(current == root)
root = current.right;
else if(isLeftChild)
parent.left = current.right;
else
parent.right = current.right;
else
{
Node successor = getSuccessor(current);
if(current == root)
root = successor;
else if(isLeftChild)
parent.left = successor;
else
parent.right = successor;
successor.left = current.left;
}
if(root != null)
{
root.setNumChildsNull();
root.adjustNumChilds();
}
repaint();
return true;
}
/**
* Gets the node successor
* @parma delNode the node
* @return a Node reference to the successor
*/
private Node getSuccessor(Node delNode)
{
Node successorParent = delNode;
Node successor = delNode;
Node current = delNode.right;
while(current != null)
{
successorParent = successor;
successor = current;
current = current.left;
}
if(successor != delNode.right)
{
successorParent.left = successor.right;
successor.right = delNode.right;
}
return successor;
}
/**
* Does the tree has elements
* @return true if the tree has elements
*/
public boolean hasElements()
{
return root != null;
}
}
/**
* Class Node
* implements a tree node
*/
class Node
{
protected String data;
protected int numLeftChilds;
protected int numRightChilds;
protected Node left;
protected Node right;
private int width;
private int height;
private int strHeight;
private int strWidth;
private int strAscent;
private int arrow;
private int margin;
private final int rounded = 4;
private final int ptrline = 8;
private final int maxLetters = 2;
/**
* Class Node constructor
* @param d the data
*/
public Node(String d)
{
data = d;
left = null;
right = null;
numLeftChilds = 0;
numRightChilds = 0;
}
/**
* Class Node constructor
* @param d the data
* @param h the height
* @param w the width
* @param a the ascent
*/
public Node(String d, int h, int w, int a)
{
data = d;
left = null;
right = null;
setMetrics(h, w, a);
}
/**
* Sets the metrix for the node
* @param h the height
* @param w the width
* @param a the ascent
*/
public void setMetrics(int h, int w, int a)
{
width = h * maxLetters;
height = 12 + h;
strHeight = h;
strWidth = w;
strAscent = a;
arrow = ptrline;
margin = 2;
}
/**
* Adds a
* @param d the data
* @param h the height
* @param w the width
* @param a the ascent
*/
public boolean add(String o)
{
boolean retValue = true;
if(data.equals(o))
{
retValue = false;
}
else
{
if(data.compareTo(o) > 0)
{
if(left == null)
{
left = new Node(o, strHeight, strWidth, strAscent);
numLeftChilds++;
}
else
{
retValue = left.add(o);
if(retValue)
numLeftChilds++;
}
}
else
{
if(right == null)
{
right = new Node(o, strHeight, strWidth, strAscent);
numRightChilds++;
}
else
{
retValue = right.add(o);
if(retValue)
numRightChilds++;
}
}
}
return retValue;
}
public boolean findElement(String o)
{
boolean retValue = false;
if(data.equals(o))
return true;
if(data.compareTo(o) > 0)
{
if(left != null)
retValue = left.findElement(o);
}
else
{
if(right != null)
retValue = right.findElement(o);
}
return retValue;
}
public String txtInorder()
{
String retValue = "";
if(left != null)
retValue += left.txtInorder();
if(data != null)
retValue += "," + data;
if(right != null)
retValue += right.txtInorder();
return retValue;
}
public String txtPreorder()
{
String retValue = "";
if(data != null)
retValue += "," + data;
if(left != null)
retValue += left.txtPreorder();
if(right != null)
retValue += right.txtPreorder();
return retValue;
}
public String txtPostorder()
{
String retValue = "";
if(left != null)
retValue += left.txtPostorder();
if(right != null)
retValue += right.txtPostorder();
if(data != null)
retValue += "," + data;
return retValue;
}
public void setNumChildsNull()
{
numLeftChilds = -1;
numRightChilds = -1;
if(left != null)
left.setNumChildsNull();
if(right != null)
right.setNumChildsNull();
}
public void adjustNumChilds()
{
if(numLeftChilds == -1)
{
if(left == null)
numLeftChilds = 0;
else
{
left.adjustNumChilds();
numLeftChilds = left.numLeftChilds + left.numRightChilds + 1;
}
}
if(numRightChilds == -1)
{
if(right == null)
numRightChilds = 0;
else
{
right.adjustNumChilds();
numRightChilds = right.numLeftChilds + right.numRightChilds + 1;
}
}
}
public void inorder(Graphics g, int x, int y)
{
g.drawString("root", x - 12, y);
g.drawLine(x, y + 2, x, y + 16);
g.drawLine(x, y + 16, x - 4, y + 16 - 4);
g.drawLine(x, y + 16, x + 4, y + 16 - 4);
inorder(g, x, y + 16, false);
}
public void inorder(Graphics g, int x, int y, boolean t)
{
int strWidth, xn, yn;
String tmpStr = data.substring(0, (data.length() < maxLetters ? data.length() : maxLetters));
g.drawRoundRect(x - width / 2, y, width, height, rounded, rounded);
g.drawLine(x - width / 2, y + height - ptrline, x + width / 2, y + height - ptrline);
g.drawLine(x, y + height - ptrline, x, y + height);
FontMetrics fm = g.getFontMetrics();
strWidth = fm.stringWidth(tmpStr);
g.drawString(tmpStr, x - strWidth / 2, y + height - ptrline - strAscent / 2);
if(left == null)
{
g.drawLine(x - width / 2, y + height - ptrline, x, y + height);
g.drawLine(x, y + height - ptrline, x - width / 2 + 1, y + height - 1);
}
else
{
xn = x - width * (left.numRightChilds + 1) - arrow;
yn = y + height + ptrline;
g.drawLine(x - width / 4, y + height - ptrline / 2, xn, yn);
left.inorder(g, xn, yn, false);
}
if(right == null)
{
g.drawLine(x + width / 2, y + height - ptrline, x, y + height);
g.drawLine(x, y + height - ptrline, x + width / 2 - 1, y + height - 1);
}
else
{
xn = x + width * (right.numLeftChilds + 1) + arrow;
yn = y + height + ptrline;
g.drawLine(x + width / 4, y + height - ptrline / 2, xn, yn);
right.inorder(g, xn, yn, false);
}
}
public int getMinx(int x)
{
int xn;
if(left != null)
xn = x - width * (numLeftChilds + 1) - arrow;
else
xn = x - width;
return Math.min(x, xn);
}
public int getMaxx(int x)
{
int xn;
if(right != null)
xn = x + width * (numRightChilds + 1) + arrow;
else
xn = x + width;
return Math.max(x, xn);
}
public int getMaxy(int y)
{
int yleft = y, yright = y, yn;
if(left != null)
{
yn = y + height + ptrline;
yleft = left.getMaxy(yn);
}
if(right != null)
{
yn = y + height + ptrline;
yright = right.getMaxy(yn);
}
return Math.max(Math.max(yright, yleft), y);
}
public int getHeight()
{
return height;
}
}