import netscape_beta.application.*;
import netscape_beta.util.*;
import java.io.*;

/**
 * A traversal studio external frame window.
 *
 * When run as an Applet, the frame window communicates
 * with the AppletIOView to import and export data.
 *
 * When run as a stand-alone application, the frame 
 * communicates with the host disk.
 *
 * @version        1.0 12 Dec 1996
 * @author         Andrew Miller
 */
public class DemFrame extends ExternalWindow implements Target
{
    static protected String cmdFileOpen = new String("cmdFileOpen");
    static protected String cmdFileSave = new String("cmdFileSave");
    static protected String cmdFileImport = new String("cmdFileImport");
    static protected String cmdFileExport = new String("cmdFileExport");
    static protected String cmdHelpAbout = new String("cmdHelpAbout");
    static protected int m_xSpacing = 10;
    static protected int m_ySpacing = 10;
    static protected int m_widthVisitorView = 200;
    static protected DemScrollClassView m_viewClass = null;
    static protected DemScrollVisitorView m_viewVisitor = null;
    static protected TextField m_labelVisitor = null;
    static protected TextField m_labelClass = null;
    static protected DemTrav m_app = null;

    /**
     * Construct a frame window for the specified application.
     *
     * @param app           Application requiring a frame
     * @param bIsApplet     TRUE if run in an applet.
     */
    public DemFrame(DemTrav app, boolean bIsApplet)
    {
        super();
        setTitle("DemJava Traversal Studio");

        app.setMainRootView(rootView());
        sizeTo(800,600);

        m_app = app;

        // install the appropriate menu
        installMenu(bIsApplet);
    }


    /**
     * Install the frame's menu.  If running in a applet, 
     * the File menu will contain the items IMPORT and
     * EXPORT which read data from the corresponding 
     * AppletIOView windows.  Otherwise, the File menu
     * contains the items OPEN and SAVE which prompt
     * the user for filenames.
     *
     * @param bIsApplet     TRUE if run in an applet.
     */
    protected void installMenu(boolean bIsApplet)
    {
        Menu menu = new Menu(true);
        MenuItem itemFile= menu.addItemWithSubmenu("File");
        MenuItem itemHelp= menu.addItemWithSubmenu("Help");
        itemHelp.submenu().addItem("About...", cmdHelpAbout, this);

        // can we touch the disk?
        if(bIsApplet == true)
        {
            itemFile.submenu().addItem("Import", cmdFileImport, this);
            itemFile.submenu().addItem("Export", cmdFileExport, this);
        }
        else
        {
            itemFile.submenu().addItem("Open...", cmdFileOpen, this);
            itemFile.submenu().addItem("Save...", cmdFileSave, this);
        }

        setMenu(menu);
    }

    /**
     * Create (or redraw) a new, empty frame displaying no data.
     *
     */
    public void newDoc()
    {
        DemDoc doc = new DemDoc(this);
        
        Rect rcBounds = rootView().bounds();

        // tell the app about it's new doc
        m_app.setDoc(doc);
        
        // remove any references to previously existing subviews
        if(m_viewClass != null)
        {
            m_viewClass.removeFromSuperview();
        }

        if(m_viewVisitor != null)
        {
            m_viewVisitor.removeFromSuperview();
        }

        if(m_labelClass != null)
        {
            m_labelClass.removeFromSuperview();
        }

        if(m_labelVisitor != null)
        {
            m_labelVisitor.removeFromSuperview();
        }

        // Change the color of the root view to be the standard
        // application lightGray.
        rootView().setColor(Color.lightGray);

        // Put some objects in the frame
        Rect rcVisitorL = new Rect(m_xSpacing, m_ySpacing, m_widthVisitorView, 20);
		Rect rcVis = new Rect(m_xSpacing, 
					          m_ySpacing + rcVisitorL.y + rcVisitorL.height, 
					          m_widthVisitorView, 
					          rcBounds.height - (m_ySpacing + rcVisitorL.y + rcVisitorL.height));
		Rect rcCls = new Rect(rcVis.x + rcVis.width + m_xSpacing, 
					          m_ySpacing + rcVisitorL.y + rcVisitorL.height, 
					          rcBounds.width - (rcVis.x + rcVis.width + m_xSpacing) - m_xSpacing,
					          rcBounds.height - (m_ySpacing + rcVisitorL.y + rcVisitorL.height));
		Rect rcCDL = new Rect(m_xSpacing + rcVisitorL.x + rcVisitorL.width, m_ySpacing, 
                              rcCls.width, 20);

        // labels
		m_labelVisitor = new TextField(rcVisitorL);
        m_labelVisitor.setStringValue("Visitors");
        m_labelVisitor.setBorder(null);
        m_labelVisitor.setBackgroundColor(Color.lightGray);
        m_labelVisitor.setSelectable(false);
        m_labelVisitor.setEditable(false);
        //m_labelVisitor.setJustification(Graphics.CENTERED);

        m_labelClass  = new TextField(rcCDL);
        m_labelClass.setStringValue("Class Hierarchy");
        m_labelClass.setBorder(null);
        m_labelClass.setBackgroundColor(Color.lightGray);
        m_labelClass.setSelectable(false);
        m_labelClass.setEditable(false);
        //m_labelClass.setJustification(Graphics.CENTERED);

   		// make the Visitor and Class views
        rootView().addSubview(m_labelVisitor); 
		rootView().addSubview(m_labelClass); 


        m_viewVisitor = new DemScrollVisitorView(rcVis, rootView(), doc);
        m_viewClass = new DemScrollClassView(rcCls, rootView() , doc);       
		
		rootView().setDirty(true);
    }

    /**
     * Perform a command generated by the menu.
     * @param string        Command string.
     * @param obj           Object generating command.
     *
     */
    public void performCommand(String string, Object obj)
    {
	    if(string.equals(cmdFileOpen))
	    {
	       fileOpen();
	    }
	    else if (string.equals(cmdFileSave))
	    {
	       fileSave();
	    }
	    else if (string.equals(cmdFileImport))
	    {
	       fileImport();
	    }
	    else if (string.equals(cmdFileExport))
	    {
	       fileExport();
	    }
        else if (string.equals(cmdHelpAbout))
        {
           helpAbout();
        }
    }

    /**
     * Display the about dialog
     *
     */
    protected void helpAbout()
    {
	Rect rcAbout = new Rect(50,50,300,200);
	DemAbout dlgAbout = new DemAbout(rcAbout);
	dlgAbout.showModally();
    }

    /**
     * Import a class dictionary by reading the text from
     * the AppletIOView input field.
     *
     */
    protected void fileImport()
    {
        String strInput = m_app.getIOView().getAppletInput();
        if(strInput.length() > 0)
        {
            openDoc(new StringBufferInputStream(strInput));
        }
        else
        {
              Alert.runAlertInternally(new String("Warning"),
                                       new String("No class dictionary found."),
                                       new String("Groove"),
                                       null, null);
        }
    }

    /**
     * Export a traversal behavior by writing text to
     * the AppletIOView output field.
     *
     */
    protected void fileExport()
    {
        BehaviorGeneratingVisitor bgv = 
                new BehaviorGeneratingVisitor(m_app.doc().get_visitorManager(),
                                              new String());
        m_app.doc().get_program().toParamClass(bgv);

        if(bgv.get_strBehavior().length() > 0)
        {
            m_app.getIOView().setAppletOutput(bgv.get_strBehavior());
        }
        else
        {
              Alert.runAlertInternally(new String("Warning"),
                                       new String("No traversals to save."),
                                       new String("Groove"),
                                       null, null);
        }
    }

    /**
     * Import a class dictionary by reading from a user specified
     * data file.
     *
     */
    protected void fileOpen()
    {
      // get filename
	  FileChooser chooser = new FileChooser(rootView(), 
	  				            new String("Select class dictionary..."), 
					            FileChooser.LOAD_TYPE);
	  chooser.showModally();
  
	  if(chooser.file() == null)
		  return;

      File infile=null;
      try 
      {
          infile = new File(chooser.file());
          //infile = new File(new String("D://java//trav//test.input"));
          openDoc(new FileInputStream(infile));
      }
      catch(Exception e)
      {
          Alert.runAlertExternally(new String("Error"),
                                   new String("Unable to open input file."),
                                   new String("Deal"),
                                   null, null);

      }

    }

    /**
     * Parse a stream containing a class dictionary and 
     * display it.
     *
     * @param inputStream   Stream to parse.
     */
    protected void openDoc(InputStream inputStream)
    {
	   try
	   {
          // refresh display
          newDoc();
		  
          // load the class dictionary and display it
   	      Program p = Program.GenerateClassTree(inputStream, 
                                                m_viewClass.getClassView());

          m_viewClass.setDirty(true);

          // update current program
          m_app.doc().set_program(p); 

          // set some statics needed for visual traversal specificiation
          TreeNode.setDoc(m_app.doc());
          Visitor.setManager(m_app.doc().get_visitorManager());
	    }
	    catch(Exception e)
	    {
		  // huh huh....he said exception
          Alert.runAlertExternally(new String("Error"),
                                   new String("Unable to read class dictionary."),
                                   new String("Deal"),
                                   null, null);
	    }
    }
    
    /**
     * Export a traversal behavior by prompting the user for a
     * filename.
     *
     */
    protected void fileSave()
    {

        // get filename
	    FileChooser chooser = new FileChooser(rootView(), 
					    new String("Save behavior as..."), 
					    FileChooser.SAVE_TYPE);
	    chooser.showModally();

	    // cancel?
	    if(chooser.file() == null)
	      return;

        BehaviorGeneratingVisitor bgv = 
                new BehaviorGeneratingVisitor(m_app.doc().get_visitorManager(),
                                              new String());
        m_app.doc().get_program().toParamClass(bgv);

        if(bgv.get_strBehavior().length() > 0)
        {
          try 
          {
              OutputStream outStream = new FileOutputStream(new String("D://java//trav//test.output"));
              PrintStream outPrintStream = new PrintStream(outStream);
              outPrintStream.println(bgv.get_strBehavior());
              outPrintStream.close();
          }
          catch(Exception e)
          {
              Alert.runAlertExternally(new String("Internal Error"),
                                       new String("Unable to open output file."),
                                       new String("Deal"),
                                       null, null);

          }

        }
        else
        {
              Alert.runAlertInternally(new String("Warning"),
                                       new String("No traversals to save."),
                                       new String("Groove"),
                                       null, null);
        }
    }

    
    /**
     * Provides access to the frame's DemVisitorView.
     *
     * @return The frame's DemVisitorView.
     */
    public DemVisitorView getVisitorView()
    {
        return m_viewVisitor.getVisitorView();
    }

    /**
     * Provides access to the frame's DemClassView.
     *
     * @return The frame's DemClassView.
     */
    public DemClassView getClassView()
    {
        return m_viewClass.getClassView();
    }
}
