/* * @(#)TreeJDesktop.java * * Last Modified: 9/15/01 */ 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.*; import java.net.*; /** * The JDesktop class intended for a tree structure. Within this class, the panels for the trees * are constructed as are the JPanel panes to hold them and the internal frames and tabbed pane. * *
The desktop listens for OptionEvents specific to a chosen tree, and calls that required command
* for the selected panel (whether it is tabbed pane or a selected window). Also, the desktop listens
* for events affecting all trees. The only events that bypass the desktop are those based upon clicking
* upon the tree.
*
*
* @author Corey Sanders
* @version 1.3 9/01/02
*/
public class TreeJDesktop extends JDesktopPane implements OptionListener, TreeMessageListener, ChangeListener {
/**
* id for the Desktop Panel.
*/
private static int id = OptionEvent.DESKTOP_PANEL;
/**
* Listeners for the tree messages passed.
*/
private LinkedList optionListeners = new LinkedList();
/**
* Listeners for the tree messages passed.
*/
private LinkedList treeListeners = new LinkedList();
/***************************/
/* Trees panels controlled */
/***************************/
/**
* BSTTree Panel.
*/
private BSTTreeJPanel bstTreeJPanel;
/**
* Splay Panel.
*/
private SplayTreeJPanel splayTreeJPanel;
/**
* Balanced Panel.
*/
private BalancedBSTTreeJPanel balancedBSTTreeJPanel;
/**
* RootInsertion Panel.
*/
private RootInsertionBSTTreeJPanel rootInsertionBSTTreeJPanel;
/**
* Red-Black Panel.
*/
private RedBlackTreeJPanel redBlackTreeJPanel;
/**
* Randomized BST Pannel.
*/
//private RandomizedBSTTreeJPanel randomizedBSTTreeJPanel;
/**
* Flag as to weather the desktop is in windows or tabbed panes.
*/
boolean windows = true;
/**
* Tabbed pane for the desktop, if windows are not used.
*/
JTabbedPane tabbedPane;
/**
* BSTTree JInternalFrame (only needed if windows).
*/
JInternalFrame bstInternalFrame;
/**
* Splay JInternalFrame (only needed if windows).
*/
JInternalFrame splayInternalFrame;
/**
* Balanced JInternalFrame (only needed if windows).
*/
JInternalFrame balancedInternalFrame;
/**
* RootInsertion JInternalFrame (only needed if windows).
*/
JInternalFrame rootInsertionInternalFrame;
/**
* Red-Black JInternalFrame (only needed if windows).
*/
JInternalFrame redBlackInternalFrame;
/**
* Randomized JInternalFrame (only needed if windows).
*/
//JInternalFrame randomizedInternalFrame;
/**
* The message for the dialog box. Starts off null, and must be created.
*/
Object[] message = null;
/**
* The radio button for duplication in the make random tree dialog box.
*/
JRadioButton duplicateButton;
ColorPreferencesDialog dialog;
/**
* True when the message for the dialog box to create a tree has been made.
*/
private boolean constructedMessage = false;
/**
* Sole Constructor, which constructs all of the tree panels and sets up all of the listening.
*/
public TreeJDesktop() {
// Super call.
super();
// Construct the color options Panel.
constructColorOptionsJPanel();
// Set Color.
setBackground(Color.white);
setBorder(BorderFactory.createEmptyBorder());
// Construct all tree panels.
bstTreeJPanel = new BSTTreeJPanel();
splayTreeJPanel = new SplayTreeJPanel();
balancedBSTTreeJPanel = new BalancedBSTTreeJPanel();
rootInsertionBSTTreeJPanel = new RootInsertionBSTTreeJPanel();
redBlackTreeJPanel = new RedBlackTreeJPanel();
//randomizedBSTTreeJPanel = new RandomizedBSTTreeJPanel();
// Set all intial Background Colors.
bstTreeJPanel.setBackground(Color.white);
splayTreeJPanel.setBackground(Color.white);
balancedBSTTreeJPanel.setBackground(Color.white);
rootInsertionBSTTreeJPanel.setBackground(Color.white);
redBlackTreeJPanel.setBackground(Color.white);
//randomizedBSTTreeJPanel.setBackground(Color.white);
// Add all trees as option listeners to this desktop.
addOptionListener(bstTreeJPanel);
addOptionListener(splayTreeJPanel);
addOptionListener(balancedBSTTreeJPanel);
addOptionListener(rootInsertionBSTTreeJPanel);
addOptionListener(redBlackTreeJPanel);
//addOptionListener(randomizedBSTTreeJPanel);
// Adds this as a tree message listener to all panels.
bstTreeJPanel.addTreeMessageListener(this);
splayTreeJPanel.addTreeMessageListener(this);
balancedBSTTreeJPanel.addTreeMessageListener(this);
rootInsertionBSTTreeJPanel.addTreeMessageListener(this);
redBlackTreeJPanel.addTreeMessageListener(this);
//randomizedBSTTreeJPanel.addTreeMessageListener(this);
// Default setup.
makeTabbedPane();
}
/**
* Original intialization. This calls methods that are called everytime a selected
* panel is changed, and obviously needs to be called initially.
*/
public void initialize() {
((TreeJPanel)getSelectedPanel()).getInputOptions();
((TreeJPanel)getSelectedPanel()).makeColorSchemeOptions();
((TreeJPanel)getSelectedPanel()).makeColorSettings();
}
/**
* Makes the windows for the Desktop. The method also removes the JInternalFrames to make
* new frames or removes the tabbedPane (whichever is currently active).
*/
public void makeWindows() {
if (isWindows()) {
remove(bstInternalFrame);
remove(splayInternalFrame);
remove(balancedInternalFrame);
remove(rootInsertionInternalFrame);
remove(redBlackInternalFrame);
// remove(randomizedInternalFrame);
}
else {
remove(tabbedPane);
}
setWindows(true);
bstTreeJPanel.setComponentShown(true);
splayTreeJPanel.setComponentShown(true);
balancedBSTTreeJPanel.setComponentShown(true);
rootInsertionBSTTreeJPanel.setComponentShown(true);
redBlackTreeJPanel.setComponentShown(true);
bstInternalFrame = new JInternalFrame("BST",
true, //resizable
true, //closable
true, //maximizable
true);//iconifiable
(bstInternalFrame.getContentPane()).add(bstTreeJPanel);
splayInternalFrame = new JInternalFrame("Splay Tree",
true, //resizable
true, //closable
true, //maximizable
true);//iconifiable
(splayInternalFrame.getContentPane()).add(splayTreeJPanel);
balancedInternalFrame = new JInternalFrame("Balanced Tree",
true, //resizable
true, //closable
true, //maximizable
true);//iconifiable
(balancedInternalFrame.getContentPane()).add(balancedBSTTreeJPanel);
rootInsertionInternalFrame = new JInternalFrame("Root Insertion",
true, //resizable
true, //closable
true, //maximizable
true);//iconifiable
(rootInsertionInternalFrame.getContentPane()).add(rootInsertionBSTTreeJPanel);
redBlackInternalFrame = new JInternalFrame("Red-Black",
true, //resizable
true, //closable
true, //maximizable
true);//iconifiable
(redBlackInternalFrame.getContentPane()).add(redBlackTreeJPanel);
/*randomizedInternalFrame = new JInternalFrame("Randomized",
true, //resizable
true, //closable
true, //maximizable
true);//iconifiable
(randomizedInternalFrame.getContentPane()).add(randomizedBSTTreeJPanel); */
setLayout(null);
setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
Dimension dim = getSize();
int w = dim.width;
int h = dim.height;
add(bstInternalFrame);
bstInternalFrame.setVisible(true);
bstInternalFrame.setSize(w/3, h/2);
bstInternalFrame.setLocation(0,0);
add(splayInternalFrame);
splayInternalFrame.setVisible(true);
splayInternalFrame.setSize(w/3, h/2);
splayInternalFrame.setLocation(w/3, 0);
add(balancedInternalFrame);
balancedInternalFrame.setVisible(true);
balancedInternalFrame.setSize(w/3, h/2);
balancedInternalFrame.setLocation(2*w/3, 0);
add(rootInsertionInternalFrame);
rootInsertionInternalFrame.setVisible(true);
rootInsertionInternalFrame.setSize(w/3, h/2);
rootInsertionInternalFrame.setLocation(0, h/2);
add(redBlackInternalFrame);
redBlackInternalFrame.setVisible(true);
redBlackInternalFrame.setSize(w/3, h/2);
redBlackInternalFrame.setLocation(w/3, h/2);
// add(randomizedInternalFrame);
// randomizedInternalFrame.setVisible(true);
// randomizedInternalFrame.setSize(w/3, h/2);
// randomizedInternalFrame.setLocation(w/3, h/2);
revalidate();
}
/**
* Makes a tabbedPane. It removes the Internal frames first and then constructs the
* internal frames.
*/
public void makeTabbedPane() {
if (!isWindows()) {
return;
}
setWindows(false);
// Original instantiation
if (bstInternalFrame != null) {
remove(bstInternalFrame);
remove(splayInternalFrame);
remove(balancedInternalFrame);
remove(rootInsertionInternalFrame);
remove(redBlackInternalFrame);
// remove(randomizedInternalFrame);
}
bstTreeJPanel.setComponentShown(true);
splayTreeJPanel.setComponentShown(false);
balancedBSTTreeJPanel.setComponentShown(false);
rootInsertionBSTTreeJPanel.setComponentShown(false);
redBlackTreeJPanel.setComponentShown(false);
tabbedPane = new JTabbedPane();
tabbedPane.setBorder(BorderFactory.createEmptyBorder());
// Add change listener
tabbedPane.addChangeListener(this);
tabbedPane.addTab("BST",bstTreeJPanel);
tabbedPane.setSelectedIndex(0);
tabbedPane.addTab("Splay Tree", splayTreeJPanel);
tabbedPane.addTab("Balanced BST", balancedBSTTreeJPanel);
tabbedPane.addTab("Root Inserted BST", rootInsertionBSTTreeJPanel);
tabbedPane.addTab("Red-Black", redBlackTreeJPanel);
//tabbedPane.addTab("Randomized BST", randomizedBSTTreeJPanel);
setLayout(new BorderLayout());
add(tabbedPane, BorderLayout.CENTER);
revalidate();
}
/**
********************
* Accesssor methods*
********************
*/
/**
* Gets if the desktop is set up in windows format or tabbed pabe format. If the desktop
* is as windows, true is returned.
*
* @return true if the desktop is set as windows.
*/
public boolean isWindows() {
return windows;
}
/**
* Gets the currently selected panel, whether it is the panel selected of the windows
* or whether it is the selected tabbed pane.
*
* @return JPanel currently selected whether in the window or Tabbed Pane.
*/
public JPanel getSelectedPanel() {
// Windows
if (isWindows()) {
JInternalFrame selectedFrame = getSelectedFrame();
if (selectedFrame == bstInternalFrame) {
return bstTreeJPanel;
}
if (selectedFrame == splayInternalFrame) {
return splayTreeJPanel;
}
if (selectedFrame == balancedInternalFrame) {
return balancedBSTTreeJPanel;
}
if (selectedFrame == rootInsertionInternalFrame) {
return rootInsertionBSTTreeJPanel;
}
if (selectedFrame == redBlackInternalFrame) {
return redBlackTreeJPanel;
}
//if (selectedFrame == randomizedInternalFrame) {
// return randomizedBSTTreeJPanel;
//}
}
// Tabs
else {
int selectedIndex = tabbedPane.getSelectedIndex();
if (selectedIndex == 0) {
return bstTreeJPanel;
}
if (selectedIndex == 1) {
return splayTreeJPanel;
}
if (selectedIndex == 2) {
return balancedBSTTreeJPanel;
}
if (selectedIndex == 3) {
return rootInsertionBSTTreeJPanel;
}
if (selectedIndex == 4) {
return redBlackTreeJPanel;
}
if (selectedIndex == 5) {
// return randomizedBSTTreeJPanel;
}
}
return bstTreeJPanel;
}
/**
******************
* Mutator methods*
******************
*/
/**
* Sets whether the desktop is set as windows or tabbed pane. This should only be change
* along with actually changing the format or problems will insue.
*
* @param windows boolean true if the format is as windows.
*/
protected void setWindows(boolean windows) {
this.windows = windows;
}
/**
********************
* Listening methods*
********************
*/
/**
* Adds an OptionEventListener according to
* the OptionEventListener interface and the OptionEvent
.
*
* @param l the listener added recieves the OptionEvents occuring.
*/
public void addOptionListener(OptionListener l) {
optionListeners.add(l);
}
/**
* Removes an OptionEventListener according to
* the OptionEventListener interface and the OptionEvent
.
*
* @param l the listener removed from recieving the OptionEvents occuring.
*/
public void removeOptionListener(TreeMessageListener l) {
optionListeners.remove(l);
}
/**
* Sends an optionEvent to all listeners of the current OptionEvents. Simply
* passes the information on.
*
* @param e the option event to be passed on.
*/
protected void optionEvent(OptionEvent e) {
ListIterator list = optionListeners.listIterator(0);
while (list.hasNext()) {
optionEvent(e, (OptionListener)list.next());
}
}
/**
* Sends an optionEvent to all listeners of the current OptionEvents. Simply
* passes the information on.
*
* @param e the option event to be passed on.
* @param l the specific optionListener to recieve the event.
*/
protected void optionEvent(OptionEvent e, OptionListener l) {
l.optionEventPerformed(e);
}
/**
* Adds an TreeMessageListener from the TREE, according to
* the TreeMessageListener interface and the TreeMessageEvent
.
*
* @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 TreeMessageEvent
.
*
* @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.
*/
protected void messageAction(String msg, Object msgObj) {
TreeMessageEvent messageEvent = new TreeMessageEvent(this, TreeMessageEvent.PANEL, msg, msgObj);
ListIterator list = treeListeners.listIterator(0);
while (list.hasNext()) {
((TreeMessageListener)list.next()).treeMessageEventPerformed(messageEvent);
}
}
/************************************************/
/* Overiding Classes */
/************************************************/
/**
* Adds the specified mouse listener to receive mouse events from this component. If l is null, no exception is thrown and no
* action is performed.
*
* @param l the mouse listener.
*/
public void addMouseListener(MouseListener l) {
bstTreeJPanel.addMouseListener(l);
splayTreeJPanel.addMouseListener(l);
balancedBSTTreeJPanel.addMouseListener(l);
rootInsertionBSTTreeJPanel.addMouseListener(l);
redBlackTreeJPanel.addMouseListener(l);
//randomizedBSTTreeJPanel.addMouseListener(l);
}
/**
* Removes the specified mouse listener so that it no longer receives mouse events from this component. This method
* performs no function, nor does it throw an exception, if the listener specified by the argument was not previously added to
* this component. If l is null, no exception is thrown and no action is performed.
*
* @param l the mouse listener.
*/
public void removeMouseListener(MouseListener l) {
bstTreeJPanel.removeMouseListener(l);
splayTreeJPanel.removeMouseListener(l);
balancedBSTTreeJPanel.removeMouseListener(l);
rootInsertionBSTTreeJPanel.removeMouseListener(l);
redBlackTreeJPanel.removeMouseListener(l);
//randomizedBSTTreeJPanel.removeMouseListener(l);
}
/**
* Adds the specified mouse motion listener to receive mouse motion events from this component. If l is null, no exception is
* thrown and no action is performed.
*
* @param l the mouse motion listener.
*/
public void addMouseMotionListener(MouseMotionListener l) {
bstTreeJPanel.addMouseMotionListener(l);
splayTreeJPanel.addMouseMotionListener(l);
balancedBSTTreeJPanel.addMouseMotionListener(l);
rootInsertionBSTTreeJPanel.addMouseMotionListener(l);
redBlackTreeJPanel.addMouseMotionListener(l);
//randomizedBSTTreeJPanel.addMouseMotionListener(l);
}
/**
* Removes the specified mouse motion listener so that it no longer receives mouse motion events from this component. This
* method performs no function, nor does it throw an exception, if the listener specified by the argument was not previously
* added to this component. If l is null, no exception is thrown and no action is performed.
*
* @param l the mouse motion listener.
*/
public void removeMouseMotionListener(MouseMotionListener l) {
bstTreeJPanel.removeMouseMotionListener(l);
splayTreeJPanel.removeMouseMotionListener(l);
balancedBSTTreeJPanel.removeMouseMotionListener(l);
rootInsertionBSTTreeJPanel.removeMouseMotionListener(l);
redBlackTreeJPanel.removeMouseMotionListener(l);
//randomizedBSTTreeJPanel.removeMouseMotionListener(l);
}
/************************************************/
/* Implements TreeMessage Listener */
/************************************************/
/**
* Listens to tree message events.
*
* @param e TreeMessageEvent that contains information about the tree.
*/
public void treeMessageEventPerformed(TreeMessageEvent e) {
if (e.getMessage().equals(TreeMessageEvent.ERROR_MESSAGE)) {
if (isWindows()) {
JInternalFrame currentFrame = bstInternalFrame;
if (e.getSource() == bstTreeJPanel) {
currentFrame = bstInternalFrame;
}
if (e.getSource() == splayTreeJPanel) {
currentFrame = splayInternalFrame;
}
if (e.getSource() == balancedBSTTreeJPanel) {
currentFrame = balancedInternalFrame;
}
if (e.getSource() == rootInsertionBSTTreeJPanel) {
currentFrame = rootInsertionInternalFrame;
}
if (e.getSource() == redBlackTreeJPanel) {
currentFrame = redBlackInternalFrame;
}
//if (e.getSource() == randomizedBSTTreeJPanel) {
//currentFrame = randomizedInternalFrame;
//}
if (!(currentFrame.isClosed() || currentFrame.isIcon())) {
JOptionPane.showMessageDialog((JPanel)e.getSource(), (String)e.getMessageObject(), "Error", JOptionPane.ERROR_MESSAGE);
}
}
else {
/*int tempIndex = tabbedPane.getSelectedIndex();
if (e.getSource() == bstTreeJPanel) {
tabbedPane.setSelectedIndex(0);
}
if (e.getSource() == splayTreeJPanel) {
tabbedPane.setSelectedIndex(1);
}
if (e.getSource() == balancedBSTTreeJPanel) {
tabbedPane.setSelectedIndex(2);
}
if (e.getSource() == rootInsertionBSTTreeJPanel) {
tabbedPane.setSelectedIndex(3);
}
if (e.getSource() == redBlackTreeJPanel) {
tabbedPane.setSelectedIndex(4);
}
//if (e.getSource() == randomizedBSTTreeJPanel) {
//tabbedPane.setSelectedIndex(5);
//}
JOptionPane.showMessageDialog(this, (String)e.getMessageObject(), "Error", JOptionPane.ERROR_MESSAGE);
tabbedPane.setSelectedIndex(tempIndex);
*/
int checkIndex=0;
if (e.getSource() == bstTreeJPanel) {
checkIndex = 0;
}
if (e.getSource() == splayTreeJPanel) {
checkIndex = 1;
}
if (e.getSource() == balancedBSTTreeJPanel) {
checkIndex = 2;
}
if (e.getSource() == rootInsertionBSTTreeJPanel) {
checkIndex = 3;
}
if (e.getSource() == redBlackTreeJPanel) {
checkIndex = 4;
}
if (tabbedPane.getSelectedIndex() == checkIndex) {
JOptionPane.showMessageDialog(this, (String)e.getMessageObject(), "Error", JOptionPane.ERROR_MESSAGE);
}
}
return;
}
else if (e.getMessage().equals(TreeMessageEvent.COLOR_CHANGE)) {
dialog.setApplied(false);
return;
}
messageAction(e.getMessage(), e.getMessageObject());
}
/**
* Constructs a random Tree for every tree currently in the desktop.
*
* @param startKey the starting key for the random tree.
* @param endKey the ending key for the random tree.
* @param size the size of the random tree created.
* @param duplicates true if duplicates are allowed in the list.
*/
public void makeRandomTree(String startKey, String endKey, int size, boolean duplicates) {
boolean priorBSTAnimating = false;
boolean priorSplayAnimating= false;
boolean priorBalancedAnimating = false;
boolean priorRootInsertionAnimating = false;
boolean priorRedBlackAnimating = false;
boolean priorSelected = false;
LinkedList keyList = new LinkedList();
if (isWindows()) {
priorBSTAnimating = (bstTreeJPanel).isAnimating();
priorSplayAnimating = (splayTreeJPanel).isAnimating();
priorBalancedAnimating = (balancedBSTTreeJPanel).isAnimating();
priorRootInsertionAnimating = (rootInsertionBSTTreeJPanel).isAnimating();
priorRedBlackAnimating = (redBlackTreeJPanel).isAnimating();
OptionEvent animationOffEvent = new OptionEvent(this, OptionEvent.DESKTOP_PANEL, OptionEvent.ANIMATION_OFF);
optionEvent(animationOffEvent);
}
else {
priorSelected = ((TreeJPanel)getSelectedPanel()).isAnimating();
OptionEvent animationOffEvent = new OptionEvent(this, OptionEvent.DESKTOP_PANEL, OptionEvent.ANIMATION_OFF);
optionEvent(animationOffEvent, ((TreeJPanel)getSelectedPanel()));
}
String keyType = ((TreeJPanel)getSelectedPanel()).getKeyType();
if (keyType.equals(TreeJPanel.INTEGER)) {
int start, end;
try {
start = (Integer.decode(startKey)).intValue();
end = (Integer.decode(endKey)).intValue();
}
catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "You must enter key limits that\nare the same type as the trees : Integers!", "Type Error", JOptionPane.ERROR_MESSAGE);
return;
}
for(int i = 0; i < size; i++) {
int randomKey = (int)(Math.random() * (end-start)) + start;
if (!duplicates) {
// Impossible to insert more.
if ( (keyList.size() == (end-start)) || (keyList.size() == (start-end)) ) {
JOptionPane.showMessageDialog(this, "Impossible to enter another distinct key!", "Out of Bounds", JOptionPane.ERROR_MESSAGE);
return;
}
boolean duplicateFound = false;
for (int j = 0; j < keyList.size(); j++) {
// Check if a duplicate exists
if ( ((int)((Integer)keyList.get(j)).intValue()) == randomKey) {
i--;
duplicateFound = true;
break;
}
}
if (duplicateFound) {
continue;
}
Integer randomInt = new Integer(randomKey);
keyList.add(randomInt);
}
OptionEvent optionEvent = new OptionEvent(this, OptionEvent.DESKTOP_PANEL, OptionEvent.INSERT, (new Integer(randomKey)).toString());
optionEvent(optionEvent);
}
}
if (keyType.equals(TreeJPanel.CHARACTER)) {
double start, end;
try {
start = (short)(new Character(startKey.charAt(0)).charValue());
end = (short)(new Character(endKey.charAt(0)).charValue());
}
catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "You must enter key limits that\nare the same type as the trees : Characters!", "Type Error", JOptionPane.ERROR_MESSAGE);
return;
}
for(int i = 0; i < size; i++) {
short randomInt = (short)((Math.random() * (end-start)) + start);
char randomKey = (char)randomInt;
if (!duplicates) {
// Impossible to insert more.
if ( (keyList.size() == (end-start)) || (keyList.size() == (start-end)) ) {
JOptionPane.showMessageDialog(this, "Impossible to enter another distinct key!", "Out of Bounds", JOptionPane.ERROR_MESSAGE);
return;
}
boolean duplicateFound = false;
for (int j = 0; j < keyList.size(); j++) {
// Check if a duplicate exists
if ( ((int)((Character)keyList.get(j)).charValue()) == randomKey) {
i--;
duplicateFound = true;
break;
}
}
if (duplicateFound) {
continue;
}
Character randomChar = new Character(randomKey);
keyList.add(randomChar);
}
OptionEvent optionEvent = new OptionEvent(this, OptionEvent.DESKTOP_PANEL, OptionEvent.INSERT, (new Character(randomKey)).toString());
optionEvent(optionEvent);
}
}
if (keyType.equals(TreeJPanel.DOUBLE)) {
double start, end;
try {
start = (double)(new Double(startKey).doubleValue());
end = (double)(new Double(endKey).doubleValue());
}
catch (NumberFormatException e) {
JOptionPane.showMessageDialog(this, "You must enter key limits that\nare the same type as the trees : Doubles!", "Type Error", JOptionPane.ERROR_MESSAGE);
return;
}
for(int i = 0; i < size; i++) {
double randomKey = (double)((Math.random() * (end-start)) + start);
// Impossible to insert more.
/*if ( (keyList.size() == ((end-start))) || (keyList.size() == ((start-end)*100)) ) {
JOptionPane.showMessageDialog(this, "Impossible to enter another distinct key!", "Out of Bounds", JOptionPane.ERROR_MESSAGE);
return;
}*/
if (!duplicates) {
boolean duplicateFound = false;
for (int j = 0; j < keyList.size(); j++) {
// Check if a duplicate exists
if ( Math.abs( (((Double)keyList.get(j)).doubleValue()) - randomKey) <=.000000001) {
i--;
duplicateFound = true;
break;
}
}
if (duplicateFound) {
continue;
}
Double randomDouble = new Double(randomKey);
keyList.add(randomDouble);
}
OptionEvent optionEvent = new OptionEvent(this, OptionEvent.DESKTOP_PANEL, OptionEvent.INSERT, ((new Double(randomKey)).toString()).substring(0, 5) );
optionEvent(optionEvent);
}
}
OptionEvent animationOnEvent = new OptionEvent(this, OptionEvent.DESKTOP_PANEL, OptionEvent.ANIMATION_ON);
if (isWindows()) {
if (priorBSTAnimating) {
optionEvent(animationOnEvent, bstTreeJPanel);
}
if (priorSplayAnimating) {
optionEvent(animationOnEvent, splayTreeJPanel);
}
if (priorBalancedAnimating) {
optionEvent(animationOnEvent, balancedBSTTreeJPanel);
}
if (priorRootInsertionAnimating) {
optionEvent(animationOnEvent, rootInsertionBSTTreeJPanel);
}
if (priorRedBlackAnimating) {
optionEvent(animationOnEvent, redBlackTreeJPanel);
}
}
else {
if(priorSelected) {
optionEvent(animationOnEvent, ((TreeJPanel)getSelectedPanel()));
}
}
}
/**
* Constructs the message for the creating of a tree with random elements. This is used
* so the last number entered appears in the fields unless the input type changes.
*/
protected void constructMessage() {
JTextField start = new JTextField("0");
JTextField end = new JTextField("100");
JTextField count = new JTextField("50");
String keyType = ((TreeJPanel)getSelectedPanel()).getKeyType();
if (keyType.equals(TreeJPanel.INTEGER)) {
start = new JTextField("0");
end = new JTextField("100");
count = new JTextField("50");
}
if (keyType.equals(TreeJPanel.CHARACTER)) {
start = new JTextField("a");
end = new JTextField("z");
count = new JTextField("15");
}
if (keyType.equals(TreeJPanel.DOUBLE)) {
start = new JTextField("0");
end = new JTextField("1");
count = new JTextField("25");
}
message = new Object[8];
message[0] = "Please enter the values for the random tree construction:";
message[1] = "starting element:";
message[2] = start;
message[3] = "ending element:";
message[4] = end;
message[5] = "amount of elements:";
message[6] = count;
duplicateButton = new JRadioButton("Duplicates");
JRadioButton noDuplicateButton = new JRadioButton("No Duplicates");
noDuplicateButton.setSelected(true);
ButtonGroup group = new ButtonGroup();
group.add(duplicateButton);
group.add(noDuplicateButton);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(1, 0));
buttonPanel.add(noDuplicateButton);
buttonPanel.add(duplicateButton);
message[7] = buttonPanel;
constructedMessage = true;
}
/**
* Gets the icon from the resource (JAR file).
*/
public Icon getIcon(String imageName) {
// Get current classloader
URL url = this.getClass().getResource(imageName);
Image img=Toolkit.getDefaultToolkit().getImage(url);
return new ImageIcon(img);
}
/**
* Option event listener. The result of an optionEvent being performed depends upon the event.
* Within the desktop, the events are used or passed on to the trees accordingly. Here the
* separating of the events takes place.
*
* @param e OptionEvent passed with information about the event.
*/
public void optionEventPerformed(OptionEvent e) {
// Make into windows
if (e.getActionCommand().equals(OptionEvent.WINDOWS)) {
makeWindows();
}
// Make into tabbed panes
else if (e.getActionCommand().equals(OptionEvent.TABBED_PANE)) {
makeTabbedPane();
}
// Make a random tree
else if (e.getActionCommand().equals(OptionEvent.RANDOM_TREE)) {
int size;
boolean duplicates;
if (!constructedMessage) {
constructMessage();
}
// Options
String[] options = {"OK","Cancel"};
int confirm = JOptionPane.showOptionDialog(
this,
message,
"Random Tree Generator",
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options,
options[0]
);
if (confirm != 0) {
return;
}
try {
size = (Integer.decode(((JTextField)message[6]).getText())).intValue();
}
catch (NumberFormatException numberFormatException) {
JOptionPane.showMessageDialog(this, "You must enter an integer count as the size!", "Type Error", JOptionPane.ERROR_MESSAGE);
return;
}
duplicates = duplicateButton.isSelected();
makeRandomTree(((JTextField)message[2]).getText(), ((JTextField)message[4]).getText(), size, duplicates);
}
else if (e.getActionCommand().equals(OptionEvent.TREE_INFORMATION)) {
if (getSelectedPanel() == bstTreeJPanel) {
JOptionPane.showMessageDialog(this, BSTTreeHead.TREE_INFORMATION, "BST Information", JOptionPane.INFORMATION_MESSAGE );
}
if (getSelectedPanel() == splayTreeJPanel) {
JOptionPane.showMessageDialog(this, SplayTreeHead.TREE_INFORMATION, "Splay Information", JOptionPane.INFORMATION_MESSAGE );
}
if (getSelectedPanel() == balancedBSTTreeJPanel) {
JOptionPane.showMessageDialog(this, BalancedBSTTreeHead.TREE_INFORMATION, "Balanced BST Information", JOptionPane.INFORMATION_MESSAGE );
}
if (getSelectedPanel() == rootInsertionBSTTreeJPanel) {
JOptionPane.showMessageDialog(this, RootInsertionBSTTreeHead.TREE_INFORMATION, "Root Insertion Information", JOptionPane.INFORMATION_MESSAGE );
}
if (getSelectedPanel() == redBlackTreeJPanel) {
JOptionPane.showMessageDialog(this, RedBlackTreeHead.TREE_INFORMATION, "Red Black Information", JOptionPane.INFORMATION_MESSAGE );
}
}
else if (e.getActionCommand().equals(OptionEvent.PROGRAM_INFORMATION)) {
JOptionPane.showMessageDialog(this, TreeApplication.PROGRAM_INFORMATION, "Program Information", JOptionPane.INFORMATION_MESSAGE, getIcon("GTIcon.jpg"));
}
else if (e.getActionCommand().equals(OptionEvent.ABOUT)) {
Object[] aboutMessage = new Object[3];
aboutMessage[0] = getIcon("growingTreeTitle.jpg");
aboutMessage[1] = TreeApplication.LICENSE_INFORMATION;
aboutMessage[2] = TreeApplication.CREATOR_INFORMATION;
// Options
String[] options = {"Close"};
int confirm = JOptionPane.showOptionDialog(
this,
aboutMessage,
"About Growing Tree...",
JOptionPane.DEFAULT_OPTION,
JOptionPane.PLAIN_MESSAGE,
null,
options,
options[0]
);
}
// Balance all
else if (e.getActionCommand().equals(OptionEvent.BALANCE_ALL)) {
OptionEvent optionEvent = new OptionEvent(this, id, OptionEvent.BALANCE);
// PASS ON BALANCE_ALL
optionEvent(optionEvent);
}
// Get status of all.
else if (e.getActionCommand().equals(OptionEvent.GET_STATUS_ALL)) {
String allStatusString = new String(
bstTreeJPanel.getTreeStatusMessage()+"\n\n"+
splayTreeJPanel.getTreeStatusMessage()+"\n\n"+
balancedBSTTreeJPanel.getTreeStatusMessage()+"\n\n"+
rootInsertionBSTTreeJPanel.getTreeStatusMessage()+"\n\n"+
redBlackTreeJPanel.getTreeStatusMessage()+"\n\n");
JOptionPane.showMessageDialog(this,allStatusString,"Status of all Trees", JOptionPane.INFORMATION_MESSAGE);
}
// Clear All
else if (e.getActionCommand().equals(OptionEvent.CLEAR_ALL)) {
// Confirm
int response = JOptionPane.showConfirmDialog(this, "Are you sure you wish to clear all trees?", "Clear Tree", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (response == JOptionPane.YES_OPTION) {
// Pass on CLEAR_ALL
optionEvent(e);
}
}
// Input Change Type
else if (e.getActionCommand().equals(OptionEvent.INPUT_CHANGE_ALL)) {
// Confirm
int response = JOptionPane.showConfirmDialog(this, "Are you sure you wish to clear all trees?", "Clear Tree", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
if (response == JOptionPane.YES_OPTION) {
// Pass on INPUT_CHANGE
optionEvent(e);
constructedMessage = false;
}
else {
// Reset the key type.
messageAction(TreeMessageEvent.KEY_TYPE_CHANGE, ((TreeJPanel)getSelectedPanel()).getKeyType());
}
}
else if (e.getActionCommand().equals(OptionEvent.COLOR_SETTINGS)) {
optionEvent(e, (OptionListener)getSelectedPanel());
}
else if (e.getActionCommand().equals(OptionEvent.COLOR_SETTINGS_ALL)) {
// Make new optionEvent
OptionEvent optionEvent = new OptionEvent(this, id, OptionEvent.COLOR_SETTINGS, e.getObjectValue());
// Pass on GET_STATUS
optionEvent(optionEvent);
}
// Input Change Type
else if ((e.getActionCommand().equals(OptionEvent.BALANCE))
|| (e.getActionCommand().equals(OptionEvent.SELECT))
|| (e.getActionCommand().equals(OptionEvent.CLEAR))
//|| (e.getActionCommand().equals(OptionEvent.ANIMATION_ON))
//|| (e.getActionCommand().equals(OptionEvent.ANIMATION_OFF))
|| (e.getActionCommand().equals(OptionEvent.ANIMATION_STEP_ON))
|| (e.getActionCommand().equals(OptionEvent.ANIMATION_STEP_OFF))
|| (e.getActionCommand().equals(OptionEvent.GET_INPUT_OPTIONS))
) {
optionEvent(e, (OptionListener)getSelectedPanel());
}
else if (e.getActionCommand().equals(OptionEvent.GET_STATUS)) {
JOptionPane.showMessageDialog(this,((TreeJPanel)getSelectedPanel()).getTreeStatusMessage(),((TreeJPanel)getSelectedPanel()).getTitle()+" Status", JOptionPane.INFORMATION_MESSAGE);
}
else if (e.getActionCommand().equals(OptionEvent.ANIMATION_PLAY)) {
// Pass on play
optionEvent(e);
//messageAction(TreeMessageEvent.ANIMATION_STEP_CHANGE, new Boolean(((TreeJPanel)getSelectedPanel()).isStep()));
}
else if (e.getActionCommand().equals(OptionEvent.ANIMATION_REWIND)) {
// Pass on rewind
optionEvent(e);
//messageAction(TreeMessageEvent.ANIMATION_STEP_CHANGE, new Boolean(((TreeJPanel)getSelectedPanel()).isStep()));
}
else if (e.getActionCommand().equals(OptionEvent.ANIMATION_STEP_REWIND)) {
if (!((TreeJPanel)getSelectedPanel()).isStep()) {
// Make new optionEvent
OptionEvent optionEvent = new OptionEvent(this, id, OptionEvent.ANIMATION_STEP_ON);
// Pass on animation step on
optionEvent(optionEvent);
}
messageAction(TreeMessageEvent.ANIMATION_STEP_CHANGE, new Boolean(((TreeJPanel)getSelectedPanel()).isStep()));
// Pass on rewind
optionEvent(e);
}
else if (e.getActionCommand().equals(OptionEvent.ANIMATION_STEP_FORWARD)) {
if (!((TreeJPanel)getSelectedPanel()).isStep()) {
// Make new optionEvent
OptionEvent optionEvent = new OptionEvent(this, id, OptionEvent.ANIMATION_STEP_ON);
// Pass on animation step on
optionEvent(optionEvent);
}
messageAction(TreeMessageEvent.ANIMATION_STEP_CHANGE, new Boolean(((TreeJPanel)getSelectedPanel()).isStep()));
// Pass on play
optionEvent(e);
}
else if (e.getActionCommand().equals(OptionEvent.COLOR_OPTIONS)) {
dialog = new ColorPreferencesDialog((JFrame)e.getObjectValue(), colorOptions);
dialog.pack();
dialog.setApplied(true);
dialog.setLocationRelativeTo(this);
dialog.setVisible(true);
}
else if (e.getActionCommand().equals(OptionEvent.RESET)) {
optionEvent(e, (OptionListener)getSelectedPanel());
}
else if (e.getActionCommand().equals(OptionEvent.SAVE_TREE)) {
optionEvent(e, (OptionListener)getSelectedPanel());
}
else if (e.getActionCommand().equals(OptionEvent.SAVE_ALL)) {
// Make new optionEvent
OptionEvent currentTreeOptionEvent = new OptionEvent(this, id, OptionEvent.SAVE_TREE);
optionEvent(currentTreeOptionEvent, (OptionListener)getSelectedPanel());
// Make new optionEvent
OptionEvent AllOptionEvent = new OptionEvent(this, id, OptionEvent.SAVE_ALL, getSelectedPanel());
// Pass on animation step on
optionEvent(AllOptionEvent);
}
else {
optionEvent(e);
}
}
ColorOptionsJPanel colorOptions;
private void constructColorOptionsJPanel() {
colorOptions = new ColorOptionsJPanel();
colorOptions.setPreferredSize(new Dimension(425, 350));
colorOptions.addOptionListener(this);
this.addTreeMessageListener(colorOptions);
}
/**
/************************************************/
/* Implements ChangeListener */
/************************************************/
/**
* Implements Change Listener. On a state changed, messages are sent out
* according to the status of the new panel.
*
* @param e ChangeEvent passed when the state changes.
*/
public void stateChanged(ChangeEvent e) {
((TreeJPanel)getSelectedPanel()).makeColorSchemeOptions();
((TreeJPanel)getSelectedPanel()).makeColorSettings();
messageAction(TreeMessageEvent.ANIMATION_CHANGE, new Boolean(((TreeJPanel)getSelectedPanel()).isAnimating()));
messageAction(TreeMessageEvent.ANIMATION_STEP_CHANGE, new Boolean(((TreeJPanel)getSelectedPanel()).isStep()));
}
/**
* Overides the desktop method, to add functionality, by passing information about the changed
* frame by tree message.
*
* @param f JInternalFrame that is selected.
*/
public void setSelectedFrame(JInternalFrame f) {
super.setSelectedFrame(f);
((TreeJPanel)getSelectedPanel()).makeColorSchemeOptions();
((TreeJPanel)getSelectedPanel()).makeColorSettings();
messageAction(TreeMessageEvent.ANIMATION_CHANGE, new Boolean(((TreeJPanel)getSelectedPanel()).isAnimating()));
messageAction(TreeMessageEvent.ANIMATION_STEP_CHANGE, new Boolean(((TreeJPanel)getSelectedPanel()).isStep()));
}
}