package edu.princeton.cs.algs4.growingtree.framework; /* * @(#)OptionControlsJPanel.java * * Last Modified: 9/01/02 */ import javax.swing.JPanel; import javax.swing.*; import javax.swing.event.*; import javax.swing.border.*; import java.awt.*; import java.awt.image.*; import java.awt.event.*; import java.awt.geom.*; import java.util.*; import java.net.*; /** * OptionControlsJPanel for use with the the OptionJPanel. Within this JPanel, the options and toolbars are, * made and pictured simply for the controls. * * *

* @author Corey Sanders * @version 1.8 9/01/02 * @see TreeJApplet * @see TreeJPanel */ public class OptionControlsJPanel extends OptionJPanel implements ActionListener, KeyListener, ChangeListener, TreeMessageListener { /** * Used to keep track of the messages to be recieved. */ private int messageMode = 2; /** * Message mode set for messages off. */ public static final int MESSAGE_OFF = 0; /** * Message mode set for onyl final messages. */ public static final int MESSAGE_FINAL_ONLY = 1; /** * Message mode set for messages on. */ public static final int MESSAGE_ON = 2; /** * Id for the control panel. */ protected static int id = OptionEvent.CONTROL_OPTION_PANEL; /** * Textfield used for the key insertion. */ private JTextField insertTextField; /** * Textfield used for the key deletion. */ private JTextField deleteTextField; /** * Textfield used for the key selection. */ private JTextField selectTextField; /** * Textfield used for the key searching. */ private JTextField searchTextField; /** * JButton used for the key insertion. */ private JButton insertButton; /** * JButton used for the key deletion. */ private JButton deleteButton; /** * JButton used for the key selection. */ private JButton selectButton; /** * JButton used for the key searching. */ private JButton searchButton; /** * Panel used to display the node and the border giving the location of the node. */ private JPanel displayPanel; /** * Title around the displayPanel. Changes with a change of node. */ private TitledBorder displayTitleBorder; /** * NodeDrawingJPanel used as the panel for the displaying node. */ private NodeDrawingJPanel nodeDrawingPanel; /** * Panel used to display the messages . */ private JPanel messagePanel; /** * Panel used to display the messages . */ private JScrollPane messageScrollPane; /** * Text Area that keeps the status information. */ private JTextArea messageTextArea; /** * Keeps the previous message passed to the status field, so messages are not repeated. */ private String previousMessage; /** * Slider for the speed of the animation. */ private JSlider speedSlider; /** * Tool bar for the animation buttons. */ private JToolBar animationToolBar; /** * Tool bar for the animation buttons. */ private JToolBar textToolBar; /** * Animation buttons for the tool bar. */ private JButton play, stop, pause, rewind, stepBack, stepForward, treeInformation, programInformation, fastForward, fastRewind, clear, treeStatus; /** * GridBagConstraints of the gridbaglayout. */ private GridBagConstraints c; /** * GridBagLayout of the gridbaglayout. */ private GridBagLayout gridbag; /** * True if the displayPanel should be shown. */ private boolean displayPanelShow = true; /** * True if the message Panel should be shown. */ private boolean messagePanelShow = true; /** * True if the animation Panel should be shown. */ private boolean animationPanelShow = true; /** * This constructor makes the OptionControlsJPanel for usage with OptionMainJPanel. It presents the * options available for manipulation of the actual tree. * * @param codebase the URL of the applet, to allow graphics to be loaded. * */ public OptionControlsJPanel() { super(); setBackground(Color.white); setBorder(new EtchedBorder(EtchedBorder.RAISED)); setDisplayPanelShow(true); setMessagePanelShow(true); setAnimationPanelShow(true); createModificationButtons(); createDisplayPanel(); createMessagePanel(); createToolBar(); createSpeedBar(); createControlPanel(); } /** * Redraws the control panel. */ public void redrawControlPanel() { this.invalidate(); this.removeAll(); createControlPanel(); this.revalidate(); } /** * Creates the control panel. */ protected void createControlPanel() { gridbag = new GridBagLayout(); c = new GridBagConstraints(); int gridX = 0; this.setLayout(gridbag); c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.CENTER; c.insets = new Insets(0,5,0,0); c.ipady = 0; c.weighty = 1; c.gridwidth = 1; if (getMessagePanelShow()) { c.weightx = 1; c.gridx = gridX; c.gridy = 0; c.gridheight = 2; c.insets = new Insets(1,10,1,0); gridbag.setConstraints(messageScrollPane, c); this.add(messageScrollPane); gridX++; } if (getAnimationPanelShow()) { c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; c.weightx = .2; c.gridx = gridX; c.gridy = 0; c.gridheight = 1; c.insets = new Insets(0,5,0,0); gridbag.setConstraints(animationToolBar, c); this.add(animationToolBar); c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.CENTER; c.gridx = gridX; c.gridy = 1; c.insets = new Insets(5,5,0,15); gridbag.setConstraints(speedSlider, c); this.add(speedSlider); gridX++; } c.gridheight = 1; c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.CENTER; c.weightx = .25; c.gridx = gridX; c.gridy = 0; c.insets = new Insets(2,5,5,0); gridbag.setConstraints(searchTextField, c); this.add(searchTextField); gridX++; c.weightx = 0; c.gridx = gridX; c.gridy = 0; c.insets = new Insets(2,2,5,0); gridbag.setConstraints(searchButton, c); this.add(searchButton); gridX++; c.weightx = .25; c.gridx = gridX; c.gridy = 0; c.insets = new Insets(2,5,5,0); gridbag.setConstraints(insertTextField, c); this.add(insertTextField); gridX++; c.weightx = 0; c.gridx = gridX; c.gridy = 0; c.insets = new Insets(2,2,5,0); gridbag.setConstraints(insertButton, c); this.add(insertButton); gridX -= 3; c.weightx = .25; c.gridx = gridX; c.gridy = 1; c.insets = new Insets(2,5,2,0); gridbag.setConstraints(selectTextField, c); this.add(selectTextField); gridX++; c.weightx = 0; c.gridx = gridX; c.gridy = 1; c.insets = new Insets(2,2,2,0); gridbag.setConstraints(selectButton, c); this.add(selectButton); gridX++; c.weightx = .25; c.gridx = gridX; c.gridy = 1; c.insets = new Insets(2,5,2,0); gridbag.setConstraints(deleteTextField, c); this.add(deleteTextField); gridX++; c.weightx = 0; c.gridx = gridX; c.gridy = 1; c.insets = new Insets(2,2,2,0); gridbag.setConstraints(deleteButton, c); this.add(deleteButton); gridX++; if (getDisplayPanelShow()) { c.fill = GridBagConstraints.VERTICAL; c.anchor = GridBagConstraints.EAST; c.weightx = .3; c.gridx = gridX; c.gridy = 0; c.gridheight = 2; c.insets = new Insets(0,10,0,0); gridbag.setConstraints(displayPanel, c); this.add(displayPanel); } } /** * Sets the display of the display Panel in this control bar. */ public void setDisplayPanelShow(boolean displayPanelShow) { this.displayPanelShow = displayPanelShow; } /** * Gets the display of the display Panel in this control bar. */ public boolean getDisplayPanelShow() { return displayPanelShow; } /** * Sets the display of the display Panel in this control bar. */ public void setMessagePanelShow(boolean messagePanelShow) { this.messagePanelShow = messagePanelShow; } /** * Gets the display of the display Panel in this control bar. */ public boolean getMessagePanelShow() { return messagePanelShow; } /** * Sets the display of the animation Panel in this control bar. */ public void setAnimationPanelShow(boolean animationPanelShow) { this.animationPanelShow = animationPanelShow; } /** * Gets the display of the animation Panel in this control bar. */ public boolean getAnimationPanelShow() { return animationPanelShow; } /** * Creates the modification buttons. */ protected void createModificationButtons() { Icon deleteIcon = null, insertIcon = null, selectIcon = null, searchIcon = null; insertIcon = getIcon("insert.gif"); deleteIcon = getIcon("delete.gif"); selectIcon = getIcon("select.gif"); searchIcon = getIcon("search.gif"); if (insertIcon != null) { insertButton = new JButton(insertIcon); } else { insertButton = new JButton("Insert"); } if (deleteIcon != null) { deleteButton = new JButton(deleteIcon); } else { deleteButton = new JButton("Delete"); } if (selectIcon != null) { selectButton = new JButton(selectIcon); } else { selectButton = new JButton("Select"); } if (searchIcon != null) { searchButton = new JButton(searchIcon); } else { searchButton = new JButton("Search"); } insertTextField = new JTextField("", 15); insertTextField.setHorizontalAlignment(JTextField.LEFT); insertTextField.addKeyListener(this); insertButton.setToolTipText("Insert Key"); insertButton.addActionListener(this); insertButton.setActionCommand(OptionEvent.INSERT); insertButton.setBackground(Color.white); insertButton.setPreferredSize(new Dimension(30, 30)); insertButton.setMaximumSize(new Dimension(30, 30)); insertButton.setMinimumSize(new Dimension(30, 30)); deleteTextField = new JTextField("", 15); deleteTextField.setHorizontalAlignment(JTextField.LEFT); deleteTextField.addKeyListener(this); deleteButton.setToolTipText("Delete Key"); deleteButton.addActionListener(this); deleteButton.setActionCommand(OptionEvent.DELETE); deleteButton.setBackground(Color.white); deleteButton.setPreferredSize(new Dimension(30, 30)); deleteButton.setMaximumSize(new Dimension(30, 30)); deleteButton.setMinimumSize(new Dimension(30, 30)); selectTextField = new JTextField("", 15); selectTextField.setHorizontalAlignment(JTextField.LEFT); selectTextField.addKeyListener(this); selectButton.setToolTipText("Select Element"); selectButton.addActionListener(this); selectButton.setActionCommand(OptionEvent.SELECT); selectButton.setBackground(Color.white); selectButton.setPreferredSize(new Dimension(30, 30)); selectButton.setMaximumSize(new Dimension(30, 30)); selectButton.setMinimumSize(new Dimension(30, 30)); searchTextField = new JTextField("", 15); searchTextField.setHorizontalAlignment(JTextField.LEFT); searchTextField.addKeyListener(this); searchButton.setToolTipText("Search for Key"); searchButton.addActionListener(this); searchButton.setActionCommand(OptionEvent.SEARCH); searchButton.setBackground(Color.white); searchButton.setPreferredSize(new Dimension(30, 30)); searchButton.setMaximumSize(new Dimension(30, 30)); searchButton.setMinimumSize(new Dimension(30, 30)); } /** * Creates the speed bar. */ protected void createSpeedBar() { speedSlider = new JSlider(JSlider.HORIZONTAL, 0, 100, 50); speedSlider.addChangeListener(this); speedSlider.setBorder(BorderFactory.createEmptyBorder(0,0,10,0)); speedSlider.setBackground(Color.white); speedSlider.setForeground(Color.black); speedSlider.setToolTipText("Animation Speed"); } /** * Creates the display panel. */ protected void createDisplayPanel() { // Create display panel. displayPanel = new JPanel(); displayPanel.setLayout(new BorderLayout()); displayPanel.setMaximumSize(new Dimension(80, 80)); displayPanel.setPreferredSize(new Dimension(80, 80)); displayPanel.setMinimumSize(new Dimension(80, 80)); displayPanel.setBackground(Color.white); // Create Node Draw Panel. nodeDrawingPanel = new NodeDrawingJPanel(); // Create Border around display panel. displayTitleBorder = new TitledBorder(BorderFactory.createLineBorder(Color.black, 1)); displayTitleBorder.setTitlePosition(TitledBorder.TOP); displayTitleBorder.setTitleJustification(TitledBorder.CENTER); displayTitleBorder.setTitle("No Node"); displayPanel.setBorder(displayTitleBorder); displayPanel.add(nodeDrawingPanel, BorderLayout.CENTER); } /** * Creates the message panel. */ protected void createMessagePanel() { //Create an editor pane. messageTextArea = new JTextArea(1000, 10); messageTextArea.setPreferredSize(new Dimension(10, 10)); messageTextArea.setEditable(true); messagePanel = new JPanel(); messagePanel.setLayout(new BorderLayout()); messagePanel.setBackground(Color.white); messagePanel.add(messageTextArea, BorderLayout.CENTER); // Create a scroll pane messageScrollPane = new JScrollPane(); messageScrollPane.setPreferredSize(new Dimension(300, 50)); messageScrollPane.setViewportView(messagePanel); messageScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); messageScrollPane.getVerticalScrollBar().setUnitIncrement(15); } /** * Gets the icon from the resource (JAR file). */ public Icon getIcon(String imageName) { Image img; // Get current classloader URL url = this.getClass().getResource(imageName); img = Toolkit.getDefaultToolkit().getImage(url); return new ImageIcon(img); } /** * Creates the tool bar. */ protected void createToolBar() { Icon playIcon = null, stopIcon = null, pauseIcon = null, rewindIcon= null, stepBackIcon = null, stepForwardIcon = null, fastRewindIcon = null, fastForwardIcon = null; Icon informationIcon = null, clearIcon = null, treeStatusIcon = null; playIcon = getIcon("play.gif"); stopIcon = getIcon("stop.gif"); pauseIcon = getIcon("pause.gif"); rewindIcon = getIcon("rewind.gif"); stepBackIcon = getIcon("stepback.gif"); stepForwardIcon = getIcon("stepforward.gif"); fastRewindIcon = getIcon("fastrewind.gif"); fastForwardIcon = getIcon("fastforward.gif"); informationIcon = getIcon("information.gif"); clearIcon = getIcon("clear.gif"); treeStatusIcon = getIcon("treestatus.gif"); if (playIcon != null) { play = new JButton(playIcon); } else { play = new JButton(">"); } if (stopIcon != null) { stop = new JButton(stopIcon); } else { stop = new JButton("!!"); } if (pauseIcon != null) { pause = new JButton(pauseIcon); } else { pause = new JButton("::"); } if (rewindIcon != null) { rewind = new JButton(rewindIcon); } else { rewind = new JButton("<"); } if (stepBackIcon != null) { stepBack = new JButton(stepBackIcon); } else { stepBack = new JButton("<|"); } if (stepForwardIcon != null) { stepForward = new JButton(stepForwardIcon); } else { stepForward = new JButton("|>"); } if (fastRewindIcon != null) { fastRewind = new JButton(fastRewindIcon); } else { fastRewind = new JButton("<<"); } if (fastForwardIcon != null) { fastForward = new JButton(fastForwardIcon); } else { fastForward = new JButton(">>"); } if (clearIcon != null) { clear = new JButton(clearIcon); } else { clear = new JButton("X"); } if (treeStatusIcon != null) { treeStatus = new JButton(treeStatusIcon); } else { treeStatus = new JButton("?"); } if (informationIcon != null) { treeInformation = new JButton("Tree Info", informationIcon); programInformation = new JButton("Program Info", informationIcon); } else { treeInformation = new JButton("Tree Info"); programInformation = new JButton("Program Info"); } play.setBackground(Color.white); stop.setBackground(Color.white); pause.setBackground(Color.white); rewind.setBackground(Color.white); stepBack.setBackground(Color.white); stepForward.setBackground(Color.white); fastRewind.setBackground(Color.white); fastForward.setBackground(Color.white); clear.setBackground(Color.white); treeStatus.setBackground(Color.white); treeInformation.setBackground(Color.white); programInformation.setBackground(Color.white); fastRewind.setActionCommand(OptionEvent.ANIMATION_FAST_REWIND); fastRewind.setToolTipText("Skipping Step Rewind"); fastRewind.addActionListener(this); stepBack.setActionCommand(OptionEvent.ANIMATION_STEP_REWIND); stepBack.setToolTipText("Stopping Step Rewind"); stepBack.addActionListener(this); rewind.setActionCommand(OptionEvent.ANIMATION_REWIND); rewind.setToolTipText("Animate Backwards"); rewind.addActionListener(this); stop.setActionCommand(OptionEvent.ANIMATION_STOP); stop.setToolTipText("Stop"); stop.addActionListener(this); pause.setActionCommand(OptionEvent.ANIMATION_PAUSE); pause.setToolTipText("Pause"); pause.addActionListener(this); play.setActionCommand(OptionEvent.ANIMATION_PLAY); play.setToolTipText("Animate Forward"); play.addActionListener(this); stepForward.setActionCommand(OptionEvent.ANIMATION_STEP_FORWARD); stepForward.setToolTipText("Stopping Step Forward"); stepForward.addActionListener(this); fastForward.setActionCommand(OptionEvent.ANIMATION_FAST_FORWARD); fastForward.setToolTipText("Skipping Step Forward"); fastForward.addActionListener(this); clear.setActionCommand(OptionEvent.CLEAR); clear.setToolTipText("Clear Tree"); clear.addActionListener(this); treeStatus.setActionCommand(OptionEvent.GET_STATUS); treeStatus.setToolTipText("Tree Status"); treeStatus.addActionListener(this); treeInformation.setActionCommand(OptionEvent.TREE_INFORMATION); treeInformation.setToolTipText("Tree Information"); treeInformation.addActionListener(this); programInformation.setActionCommand(OptionEvent.PROGRAM_INFORMATION); programInformation.setToolTipText("Program Information"); programInformation.addActionListener(this); resetToolBar(false); } public void resetToolBar(boolean displayPlay) { animationToolBar = new JToolBar("Animation Tools", SwingConstants.CENTER); animationToolBar.setFloatable(false); animationToolBar.setBackground(Color.white); animationToolBar.add(fastRewind); animationToolBar.add(stepBack); animationToolBar.add(rewind); animationToolBar.add(stop); if (displayPlay) animationToolBar.add(play); else animationToolBar.add(pause); animationToolBar.add(stepForward); animationToolBar.add(fastForward); animationToolBar.add(clear); animationToolBar.add(treeStatus); } public void displayPlayButton() { resetToolBar(true); redrawControlPanel(); } public void displayPauseButton() { resetToolBar(false); redrawControlPanel(); } /** * Sets the diplay panel background color. * * @param background color for the display panel background. */ public void setDisplayPanelBackground(Color background) { nodeDrawingPanel.setBackground(background); displayPanel.revalidate(); displayPanel.repaint(); } /** * Sets the diplay panel border. * * @param borderText String text for the border of the panel. */ public void setDisplayPanelBorder(String borderText) { displayTitleBorder.setTitle(borderText); displayPanel.revalidate(); displayPanel.repaint(); } /** * Sets the drawingTree node for the display panel. * * @param node DrawingTree node for the display panel. */ public void setDiplayPanelDrawNode(DrawingTree node) { nodeDrawingPanel.setNode(node); displayPanel.revalidate(); displayPanel.repaint(); } /** * Sets the message mode for the panel. * * @param messageMode int value for the message mode of the panel. */ public void setMessageMode(int messageMode) { this.messageMode = messageMode; } /** * Gets the message mode for the panel. * * @return int value for the message mode of the panel. */ public int getMessageMode() { return messageMode; } /**********************/ /* Effects all trees */ /**********************/ /** * Insert command. * * @param text the String to be inserted. */ protected void insertCommand(String text) { optionAction(OptionEvent.INSERT, text); } /** * Search command. * * @param text the String to be searched for. */ protected void searchCommand(String text) { optionAction(OptionEvent.SEARCH, text); } /** * Select command. * * @param text the String to be selected from. */ protected void selectCommand(String text) { optionAction(OptionEvent.SELECT, text); } /** * Delete command. * * @param text the String to be deleted. */ protected void deleteCommand(String text) { optionAction(OptionEvent.DELETE, text); } /** * Tree Information command. */ protected void treeInformationCommand() { optionAction(OptionEvent.TREE_INFORMATION); } /** * Program Information command. */ protected void programInformationCommand() { optionAction(OptionEvent.PROGRAM_INFORMATION); } /** * Animation command. * * @param cmd String cmd for the animation command. */ protected void animationCommand(String cmd) { optionAction(cmd); } /** * If an action is performed through one of the buttons. * * @param e ActionEvent that contains information about the action performed. */ public void actionPerformed(ActionEvent e) { // Command of action String command = e.getActionCommand(); /**********************/ /* Effects all trees */ /**********************/ if (command.equals(OptionEvent.ANIMATION_PAUSE)) { displayPlayButton(); } if (command.equals(OptionEvent.ANIMATION_PLAY)) { displayPauseButton(); } if (command.equals(OptionEvent.INSERT)) { String text = insertTextField.getText(); if (!(text.equals(""))) { insertCommand(text); insertTextField.setText(""); } } else if (command.equals(OptionEvent.DELETE)) { String text = deleteTextField.getText(); if (!(text.equals(""))) { deleteCommand(text); deleteTextField.setText(""); } } else if (command.equals(OptionEvent.SEARCH)) { String text = searchTextField.getText(); if (!(text.equals(""))) { searchCommand(text); searchTextField.setText(""); } } else if (command.equals(OptionEvent.SELECT)) { String text = selectTextField.getText(); if (!(text.equals(""))) { selectCommand(text); selectTextField.setText(""); } } /************************/ /* Animation Commands */ /************************/ else if (command.startsWith(OptionEvent.ANIMATION)) { animationCommand(command); } else { optionAction(command); } } /** * keyTyped command. No action. */ public void keyTyped (KeyEvent e) {} /** * keyPressed command. No action. */ public void keyPressed(KeyEvent e) {} /** * keyReleased command. * * @param e the KeyEvent for the release of the key. */ public void keyReleased(KeyEvent e) { Object source = e.getSource(); if (source == insertTextField) { if(e.getKeyCode() == KeyEvent.VK_ENTER) { String text = insertTextField.getText(); if (!(text.equals(""))) { insertCommand(text); insertTextField.setText(""); } } } if (source == deleteTextField) { if(e.getKeyCode() == KeyEvent.VK_ENTER) { String text = deleteTextField.getText(); if (!(text.equals(""))) { deleteCommand(text); deleteTextField.setText(""); } } } if (source == searchTextField) { if(e.getKeyCode() == KeyEvent.VK_ENTER) { String text = searchTextField.getText(); if (!(text.equals(""))) { searchCommand(text); searchTextField.setText(""); } } } if (source == selectTextField) { if(e.getKeyCode() == KeyEvent.VK_ENTER) { String text = selectTextField.getText(); if (!(text.equals(""))) { selectCommand(text); selectTextField.setText(""); } } } } /** * Tree Message Event performed. * * @param e TreeMessageEvent. */ public void treeMessageEventPerformed(TreeMessageEvent e) { String msg = e.getMessage(); if ((msg.equals(Animation.PAUSE)) || (msg.equals(TreeMessageEvent.KEY_TYPE_CHANGE)) || (msg.equals(TreeMessageEvent.ANIMATION_CHANGE)) || (msg.equals(TreeMessageEvent.ANIMATION_STEP_CHANGE)) || (msg.equals(TreeMessageEvent.SET_INPUT_OPTIONS)) ) { return; } if (msg.equals(previousMessage) ) { return; } if (msg.equals(Animation.PLAY) || msg.equals(Animation.STOP) || msg.equals(Animation.REWIND) || msg.equals(Animation.FINISH) || msg.equals(TreeMessageEvent.STATUS_MESSAGE)) { previousMessage = msg; if (msg.equals(TreeMessageEvent.STATUS_MESSAGE) || msg.equals(Animation.FINISH) ) { return; } } if (msg.equals(TreeMessageEvent.COLOR_PANEL) || msg.equals(TreeMessageEvent.SET_PRESET_COLOR_OPTIONS)) { return; } if (messageMode == MESSAGE_ON) { messageTextArea.append("\n"+e.getMessage()); messagePanel.repaint(); } else if (messageMode == MESSAGE_FINAL_ONLY) { if (previousMessage != null) { if ( (previousMessage.equals(Animation.FINISH)) || (previousMessage.equals(TreeMessageEvent.STATUS_MESSAGE)) ) { messageTextArea.append("\n"+e.getMessage()); messagePanel.repaint(); previousMessage = msg; } } } else if (messageMode == MESSAGE_OFF) { } } /** * The method called for slider changes occuring. * * @param e The changeEvent for slider events. */ public void stateChanged(ChangeEvent e) { if (e.getSource() == speedSlider) { optionAction(OptionEvent.ANIMATION_SPEED, new Integer(speedSlider.getValue())); } } }