/* * @(#)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())); } }