/* AlgAnimFrame.java */ import java.awt.*; import java.applet.*; import java.io.*; import java.net.*; /** * The AlgAnimFrame class is a top-level window with a title * and border. The layout used is GridBagLayout. *

* This extended frame class holds a set references to the panel/frame objects * used in the algorithm animation. * @see Frame */ public class AlgAnimFrame extends Frame { AlgAnimApp parentApp; URL sourceURL; String algname; /** * The reference to the AlgThread which contains the details and * execution sequences of the algorithm. * @see AlgThread */ public AlgThread alg = null; int delay = 200; /** * An instance of the drawing panel which is cast to its super class * Panel. This instance is used to set the GridBagConstraint * of the layout manager. * @see DrawingPanel */ public Panel drawingPanel; /** * An instance of the TextFrame used to set the layout * constraints and highlight certain lines of the source code. * @see TextFrame */ public TextFrame tf; /** * A reference to the control panel. */ public ControlPanel control_panel; boolean step = false, stepWait = false; public ComPanel cpanel; /** * Creates and shows the frame consists of a drawing panel, commentary * panel and control panel. The text frame is now displayed on a separate * window. * @param parentApp The applet which results in the creation of this frame * @param sourceURL The URL of the source code to be displayed on the text * frame * @see URL */ public AlgAnimFrame(AlgAnimApp parentApp, URL sourceURL) { this.parentApp = parentApp; this.sourceURL = sourceURL; this.algname = parentApp.getParameter("algname"); setBackground(Color.white); setTitle(algname); move(0, 0); alg = new AlgThread(this); // Arrange panels within frame GridBagLayout gb = new GridBagLayout(); GridBagConstraints gc = new GridBagConstraints(); setLayout( gb ); gc.fill = GridBagConstraints.BOTH; gc.gridwidth = GridBagConstraints.REMAINDER; /* Give any extra space to the animation panel */ gc.weighty = 1.0; gc.weightx = 2.0; gc.gridx = 0; gc.gridy = 0; gb.setConstraints( drawingPanel, gc ); add(drawingPanel); /* Source panel */ tf = new TextFrame( sourceURL ); /* commentary panel */ gc.gridwidth = GridBagConstraints.RELATIVE; gc.gridx = 0; gc.gridy = GridBagConstraints.RELATIVE; gc.weighty = 0.0; gc.gridheight = GridBagConstraints.REMAINDER; cpanel = new ComPanel( algname, 3 ); gb.setConstraints( cpanel, gc ); add( cpanel ); /* Control panel */ control_panel = new ControlPanel(this, algname); gc.gridx = gc.gridy = GridBagConstraints.RELATIVE; gc.gridwidth = GridBagConstraints.REMAINDER; gc.insets = new Insets(0, 2, 2, 2); gb.setConstraints( control_panel, gc ); add( control_panel ); // generate initial data set alg.generateData(); pack(); validate(); show(); if (tf.tp.n_lines > 0) tf.toFront(); } // init() /** * Returns the preferred size of the frame. By default, it is set * to 920x600. It can be modified based on the specific application. * @return the dimension of the frame */ public Dimension preferredSize() { return new Dimension(800,600); } public Dimension minimumSize() { return new Dimension(800,600); } /** * Event handler of the frame. The main purpose of this method is to * perform the cleanup statements upon receival of the WINDOW_DESTROY * event message. */ public boolean handleEvent(Event event) { if (event.id == Event.WINDOW_DESTROY) { if (alg != null) { alg.drawingPanel = null; if (alg.isAlive()) alg.stop(); } parentApp.start_button.enable(); tf.dispose(); dispose(); } return super.handleEvent(event); } public void setText(int n, String s) { cpanel.setText(n, s); } /** * Highlights the specified line of the source code on the text panel. * If the line is beyond the scroll pane, it will be scrolled to the * center of the window. * @param n The line to be highlighted. */ public void Highlight( int n ) { tf.tp.Highlight(n); int numLineVisible = tf.tp.size().height/tf.tp.line_space; if ( (n < (tf.tp.start + 2)) || (n > (tf.tp.start + numLineVisible - 2))) { int max = tf.vScrollbar.getMaximum(); int min = tf.vScrollbar.getMinimum(); int startLine = n - numLineVisible/2; if (startLine > 0) { tf.tp.setStart(startLine); tf.vScrollbar.setValue(startLine * (max - min) / tf.tp.n_lines); } else { tf.tp.setStart(0); tf.vScrollbar.setValue(0); } } try { Thread.sleep(delay/4); } catch (InterruptedException e) {} } /** * Restore the drawing panel at the end of the animation or during * initialization. */ public void restoreDrawingPanelColor() { alg.restoreDrawingPanelColor(); } /** * Start the animation algorithm if the run or step * button is pressed. */ public void startAlg() { if (alg.isAlive() && !stepWait) { alg.stop(); alg = new AlgThread(this); alg.start(); } else if (alg.isAlive() && stepWait) { //alg.resume(); //System.out.println("alive"); step = true; stepWait = false; } else { // alg.isAlive() == false alg = new AlgThread(this); alg.start(); } if (!stepWait) { control_panel.run_button.disable(); control_panel.data_choice.disable(); control_panel.stop_button.enable(); control_panel.step_button.enable(); } } /** * This method is invoked at the end of the animation or when * the stop button is pressed. It restores the buttons * status on the control panel. */ public void finishAlg() { control_panel.stop_button.disable(); control_panel.run_button.enable(); control_panel.data_choice.enable(); control_panel.step_button.enable(); step = false; alg.restoreDrawingPanelColor(); } /** * This method is called when the step execution mode is used. * It is normally added to the line where the execution will wait * for the step button to be pressed. */ public void waitStep() { if (step) { control_panel.setText("Click NEXT STEP..."); control_panel.step_button.enable(); control_panel.repaint(); step = false; stepWait = true; while (!step) { try { Thread.sleep(100); } catch (InterruptedException e) {} } if (!stepWait) step = false; } } /** * Sets the attribute which indicate if the step execution * mode is current. */ public void setStep(boolean step) { //setText(2, "Stepping through the next line(s)..."); this.step = step; control_panel.stop_button.disable(); control_panel.run_button.enable(); control_panel.data_choice.enable(); if (step) { control_panel.step_button.disable(); stepWait = true; } else stepWait = false; } } // class AlgAnimApp