package edu.princeton.cs.algs4.growingtree.framework; /* * @(#)TreeJDesktop.java * * Last Modified: 9/15/01 */ import java.io.File; import javax.swing.*; import javax.swing.event.*; import edu.princeton.cs.algs4.growingtree.experiments.IExperimentLogger; import edu.princeton.cs.algs4.growingtree.interfaces.IDeleteOperator; import edu.princeton.cs.algs4.growingtree.interfaces.IInsertOperator; import edu.princeton.cs.algs4.growingtree.interfaces.ISearchOperator; 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(); private LinkedList> bstPanels;// = new LinkedList>(); private LinkedList panelNames = new LinkedList(); private HashMap> framesToPanels = new HashMap>(); /***************************/ /* Trees panels controlled */ /***************************/ /** * BSTTree Panel. */ //private BSTTreeJPanel bstTreeJPanel; /** * 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; /** * 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(); if (bstPanels == null) bstPanels = new LinkedList>(); } public void init() { // Construct the color options Panel. constructColorOptionsJPanel(); // Set Color. setBackground(Color.white); setBorder(BorderFactory.createEmptyBorder()); // Construct all tree panels. //if (bstTreeJPanel == null) instantiateTrees(); // Set all intial Background Colors. for (Iterator> iter = bstPanels.iterator(); iter.hasNext(); ) { BSTTreeJPanel panel = iter.next(); panel.setBackground(Color.white); addOptionListener(panel); panel.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(); } public

void addTree(String name, P p, IInsertOperator

inserter, ISearchOperator

searcher, IDeleteOperator

deleter, boolean allowRotations) { BSTTreeJPanel

panel = new BSTTreeJPanel

(p, inserter, searcher, deleter, allowRotations); bstPanels.add(panel); panelNames.add(name); JInternalFrame frame = new JInternalFrame(name, true, //resizable true, //closable true, //maximizable true);//iconifiable framesToPanels.put(frame, panel); } public

void addTree(String name, P p, IInsertOperator

inserter, ISearchOperator

searcher, IDeleteOperator

deleter) { addTree(name, p, inserter, searcher, deleter, false); } public

void addTree(String name, P p, IInsertOperator

inserter, ISearchOperator

searcher, IDeleteOperator

deleter, IExperimentLogger

logger, boolean allowRotations) { BSTTreeJPanel

panel = new BSTTreeJPanel

(p, inserter, searcher, deleter, logger, allowRotations); bstPanels.add(panel); panelNames.add(name); JInternalFrame frame = new JInternalFrame(name, true, //resizable true, //closable true, //maximizable true);//iconifiable framesToPanels.put(frame, panel); } public

void addTree(String name, P p, IInsertOperator

inserter, ISearchOperator

searcher, IDeleteOperator

deleter, IExperimentLogger

logger) { addTree(name, p, inserter, searcher, deleter, logger, false); } // create all trees. private void instantiateTrees() { if (bstPanels == null) bstPanels = new LinkedList>(); } /** * 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()) { for (Iterator iter = framesToPanels.keySet().iterator(); iter.hasNext(); ) { JInternalFrame f = iter.next(); remove(f); } } else { remove(tabbedPane); } setWindows(true); for (Iterator iter = framesToPanels.keySet().iterator(); iter.hasNext(); ) { JInternalFrame f = iter.next(); BSTTreeJPanel panel = framesToPanels.get(f); panel.setComponentShown(true); f.getContentPane().add(panel); } setLayout(null); setDragMode(JDesktopPane.OUTLINE_DRAG_MODE); Dimension dim = getSize(); int w = dim.width; int h = dim.height; int i = 0; for (Iterator iter = framesToPanels.keySet().iterator(); iter.hasNext(); ) { JInternalFrame f = iter.next(); add(f); f.setVisible(true); f.setSize(w/3, h/2); f.setLocation((i%3)*w/3,(i/3)*w/2); i++; } 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 for (Iterator iter = framesToPanels.keySet().iterator(); iter.hasNext(); ) { JInternalFrame f = iter.next(); remove(f); BSTTreeJPanel panel = framesToPanels.get(f); panel.setComponentShown(true); } tabbedPane = new JTabbedPane(); tabbedPane.setBorder(BorderFactory.createEmptyBorder()); // Add change listener tabbedPane.addChangeListener(this); Iterator nameIter = panelNames.iterator(); for (Iterator> iter = bstPanels.iterator(); iter.hasNext(); ) { BSTTreeJPanel panel = iter.next(); tabbedPane.addTab(nameIter.next(), panel); } tabbedPane.setSelectedIndex(0); 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 == null) { return framesToPanels.values().iterator().next(); } return framesToPanels.get(selectedFrame); } // Tabs else { int selectedIndex = tabbedPane.getSelectedIndex(); return bstPanels.get(selectedIndex); } } /** ****************** * 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) { if (bstPanels == null) instantiateTrees(); for (Iterator> iter = bstPanels.iterator(); iter.hasNext(); ) { iter.next().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) { for (Iterator> iter = bstPanels.iterator(); iter.hasNext(); ) { iter.next().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) { for (Iterator> iter = bstPanels.iterator(); iter.hasNext(); ) { iter.next().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) { for (Iterator> iter = bstPanels.iterator(); iter.hasNext(); ) { iter.next().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()) { Iterator it = framesToPanels.keySet().iterator(); JInternalFrame currentFrame = it.next(); for (Iterator> iter = bstPanels.iterator(); iter.hasNext(); ) { BSTTreeJPanel panel = iter.next(); if (e.getSource() == panel) { for (Iterator iter2 = framesToPanels.keySet().iterator(); iter2.hasNext(); ) { JInternalFrame f = iter2.next(); if (framesToPanels.get(f) == panel) { currentFrame = f; break; } } } } if (!(currentFrame.isClosed() || currentFrame.isIcon())) { JOptionPane.showMessageDialog((JPanel)e.getSource(), (String)e.getMessageObject(), "Error", JOptionPane.ERROR_MESSAGE); } } else { int checkIndex=bstPanels.indexOf(e.getSource()); if (tabbedPane.getSelectedIndex() == checkIndex) { JOptionPane.showMessageDialog(this, (String)e.getMessageObject(), "Error", JOptionPane.ERROR_MESSAGE); } } return; } else if (e.getMessage().equals(TreeMessageEvent.COLOR_CHANGE)) { if (dialog != null) 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 priorLLRBAnimating = false; boolean priorSelected = false; // clear all trees before making random ones for (Iterator> iter = bstPanels.iterator(); iter.hasNext(); ) { iter.next().getTree().clear(); } LinkedList keyList = new LinkedList(); if (isWindows()) { 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 ( keyList.get(j).intValue() == randomKey) { i--; duplicateFound = true; break; } } if (duplicateFound) { continue; } //Integer randomInt = new Integer(randomKey); keyList.add(new KeyType(randomKey)); } 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 ( keyList.get(j).charValue() == randomKey) { i--; duplicateFound = true; break; } } if (duplicateFound) { continue; } //Character randomChar = new Character(randomKey); keyList.add(new KeyType(randomKey)); } 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( keyList.get(j).doubleValue() - randomKey) <=.000000001) { i--; duplicateFound = true; break; } } if (duplicateFound) { continue; } //Double randomDouble = new Double(randomKey); keyList.add(new KeyType(randomKey)); } 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); } if (priorLLRBAnimating) { optionEvent(animationOnEvent, llrbTreeJPanel); }*/ } 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] = "Number 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); } private void loadKeys(String text) { // 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) { return; } String newType = getTypeChange(text); OptionEvent clearEvent = new OptionEvent(this, OptionEvent.DESKTOP_PANEL, OptionEvent.CLEAR_ALL); optionEvent(clearEvent); OptionEvent changeEvent = new OptionEvent(this, OptionEvent.DESKTOP_PANEL, OptionEvent.INPUT_CHANGE_ALL, newType); optionEvent(changeEvent); messageAction(TreeMessageEvent.KEY_TYPE_CHANGE, newType); OptionEvent optionEvent = new OptionEvent(this, OptionEvent.DESKTOP_PANEL, OptionEvent.INSERT, text); optionEvent(optionEvent); } private String getTypeChange(String text) { String key = text.split("\\s")[0]; String type; try { int k = Integer.parseInt(key); return OptionEvent.INTEGER; } catch (NumberFormatException e) { try { double d = Double.parseDouble(key); return OptionEvent.DOUBLE; } catch (NumberFormatException f) { char c = text.charAt(0); return OptionEvent.CHARACTER; } } } /** * 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) { if (e.getActionCommand().startsWith(OptionEvent.LOAD)) { String loadNum = e.getActionCommand().substring(OptionEvent.LOAD.length()); int index = Integer.parseInt(loadNum); String keys = CenterJFrame.loadKeyList[index]; loadKeys(keys); } // 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(); duplicates = false; makeRandomTree(((JTextField)message[2]).getText(), ((JTextField)message[4]).getText(), size, duplicates); } else if (e.getActionCommand().equals(OptionEvent.TREE_INFORMATION)) { JPanel selected = getSelectedPanel(); for (Iterator> iter = bstPanels.iterator(); iter.hasNext(); ) { BSTTreeJPanel panel = iter.next(); if (selected == panel) { JOptionPane.showMessageDialog(this, GrowingTreeHead.TREE_INFORMATION, "BST Information", JOptionPane.INFORMATION_MESSAGE ); } } } else if (e.getActionCommand().equals(OptionEvent.PROGRAM_INFORMATION)) { JOptionPane.showMessageDialog(this, TreeVisualization.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] = TreeVisualization.LICENSE_INFORMATION; aboutMessage[2] = TreeVisualization.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 = ""; for (Iterator> iter = bstPanels.iterator(); iter.hasNext(); ) { BSTTreeJPanel panel = iter.next(); allStatusString += panel.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 //messageAction(TreeMessageEvent.KEY_TYPE_CHANGE, // e.getObjectValue()); 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())); } }