/*---------------------------------------------------------------------------
File:         			TraceWindow.java
Package:                        JFLAP Version 3.0
Author:				Magda & Octavian Procopiuc V1.0 07/15/96
                                
Description of Contents:	Contains class TraceWindow.
				
--------------------------------------------------------------------------*/

/* 
 * Susan H. Rodger, Magda Procopiuc, Octavian Procopiuc, Eric Gramond
 * Computer Science Department
 * Duke University
 * June 1998
 * Supported by National Science Foundation DUE-9596002 and DUE-9555084.
 *
 * Copyright (c) 1998
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the author.  The name of the author may not be used to
 * endorse or promote products derived from this software without
 * specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

package flap;

import java.awt.*;
import java.util.*;
import java.awt.event.*;

/**
 * This is the window which appears when, after a Fast Run, the user 
 * chooses to see the path that lead to acceptance or when the Trace
 * button from the UpperWindow is pushed. Since no dialog has to
 * be opened from this window, it is itself a Dialog (modal). It has at
 * the bottom a panel with three buttons and in the center a configuration
 * is displayed.
 *
 * @author	Magda & Octavian Procopiuc
 * @version	1.0 15 July 1996
 */
public class TraceWindow extends Dialog implements ActionListener{

  private Frame		parent;
  private String	title;
  private Machine	a;
  private Vector	path = new Vector();  
  private Configuration	currentConfiguration;
  private Configuration	selected;
  private int		pathPosition;
  private Button	next = new Button("Next");
  private Button	previous = new Button("Previous");
  private Button	quit = new Button("Quit");
  private int		width;
  private int		height;
  private boolean	disablePrevious = false;
  private boolean	disableNext = false;

/**
 * Creates a window to trace the path from the initial
 * configuration to the selected configuration
 * @param a		Machine which generated the configuration tree
 *        selected  	Configuration to be traced
 *	  parent	Frame parent of this window
 *        title		Window title
 */ 	
  public TraceWindow(Machine a, Configuration selected, Frame parent, String title) {
    super(parent, title, true);

    Configuration	c;

    next.addActionListener(this);
    quit.addActionListener(this);
    previous.addActionListener(this);

    this.a = a;
    this.selected = selected;
    this.parent = parent;
    setBackground(Params._tw_backcolor);
    Panel p = new Panel();
    p.setLayout(new GridLayout(1, 3));
    add("South", p);
    p.add(previous);
    disablePrevious = true;
    p.add(next);
    p.add(quit);
    p.setFont(Params._dg_font);
    width = Params._tw_width;
    height = Params._tw_height;
    setSize(width, height); 
    setFont(Params._tw_font);   

    for (Enumeration e = a.d.theStates.elements(); e.hasMoreElements(); ) {
       ((State) e.nextElement()).ss = State.NORMAL;
    }
    path.insertElementAt(selected, 0);
    if (!selected.isValid)
      path.insertElementAt(selected, 0);
    c = selected;
    c.isSelected = false;
    while (c.father != null) {
      path.insertElementAt(c.father, 0);
      c = c.father;
    } 
    if (path.size() <= 1)
      disableNext = true;
    currentConfiguration = (Configuration) path.elementAt(0); 
    currentConfiguration.theState.ss = State.FOCUSED; 
    pathPosition = 0;
    Configuration.setParams(width - 2*Params._tw_hoffset, 
    			Params._c_height*4/3, Params._s_radius);
    a.d.repaint();
  }

/**
 * Paints the current configuration.
 * Also, enables/disables "Next" and "Previous" buttons
 * (due to a Java bug on Mac, this has to be done here)
 */
  public void paint(Graphics g) {
    int			x = Params._tw_hoffset;
    int			y = Params._tw_voffset;
  
    if (!currentConfiguration.isValid && (pathPosition == path.size() - 2)) {
      currentConfiguration.isValid = true;
      currentConfiguration.paint(g, x, y);
      currentConfiguration.isValid = false;
    } else
      currentConfiguration.paint(g, x, y);
    if (disablePrevious)  // this is needed due to a bug in JDK 1.0.2 for mac.
      previous.setEnabled(false);
    else
      previous.setEnabled(true);
    if (disableNext)
      next.setEnabled(false);
    else
      next.setEnabled(true); 
  }

/**
 * Depending on the button pushed by user,
 * goes back and forth on the traced path.
 */
  public void actionPerformed(ActionEvent e) {
    String arg = ((Button)(e.getSource())).getLabel();
    if ("Quit".equals(arg)) {
      Configuration cc;
      currentConfiguration.theState.ss = State.NORMAL;
      for (Enumeration ec = a.currentConfigs.elements(); ec.hasMoreElements(); )
      {
        cc = (Configuration) ec.nextElement();
        if (cc.isValid)
          cc.theState.ss = State.FOCUSED;
      }
      Configuration.setParams(Params._c_width, Params._c_height, 11);
      selected.isSelected = false; 
      a.d.repaint();
      if (parent instanceof UpperWindow) 
        ((UpperWindow) parent).cc.repaint();
      setVisible(false);
    } else if ("Next".equals(arg)) {
      currentConfiguration.theState.ss = State.NORMAL;
      pathPosition++;
      if (pathPosition == path.size() - 1) 
        disableNext = true;     
      disablePrevious = false;
      currentConfiguration = (Configuration) path.elementAt(pathPosition);
      if (currentConfiguration.isValid || (pathPosition < path.size() - 1)) 
        currentConfiguration.theState.ss = State.FOCUSED;
      a.d.repaint();
      repaint();
    } else if ("Previous".equals(arg)) {
      currentConfiguration.theState.ss = State.NORMAL;
      pathPosition--;
      if (pathPosition == 0)
        disablePrevious = true;
      disableNext = false;
      currentConfiguration = (Configuration) path.elementAt(pathPosition);
      currentConfiguration.theState.ss = State.FOCUSED;
      a.d.repaint();
      repaint();
    }
  }
          
} 	// end of class TraceWindow

