/*---------------------------------------------------------------------------
File:         			RegExpInputWindow.java
Package:                        JFLAP Version 3.1
Author:			        Ted Hung
                                
Description of Contents:	Contains class RegExpInputWindow.
				
--------------------------------------------------------------------------*/

/* 
 * Susan H. Rodger, Magda Procopiuc, Octavian Procopiuc, Eric Gramond, Ted Hung
 * Computer Science Department
 * Duke University
 * August 1999
 * Supported by National Science Foundation DUE-9596002, DUE-9555084,
 *  and DUE-9752583
 *
 * Copyright (c) 1999
 * 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.awt.event.*;
import java.util.*;
import flap.operators.*;
import java.io.*;

//
//
// RegExpInputWindow
//
//
public class RegExpInputWindow extends SourceWindow implements ActionListener
{
   //user interface controls
   private Button createbutton;
   private TextField regexpfield;
   private Menu myFileMenu;

   public RegExpInputWindow(MainMenu mainmenu)
   {

      super(mainmenu, mainmenu.isApplet);
      setLayout(new GridLayout(3, 1));
      setTitle("Regular Expression Input Window");
      
      add(new Label("Input Regular Expression: "));
      Panel p1 = new Panel(new FlowLayout());
      p1.add(regexpfield = new TextField("", 40));
      add(p1);
      
      Panel p2 = new Panel(new FlowLayout());
      p2.add(createbutton = new Button("Create FSA"));
      add(p2);
     

      createbutton.addActionListener(this);
      
      this.addWindowListener(
	 new WindowAdapter()
	 {
	    public void windowClosing(WindowEvent e)
	    {
	       RegExpInputWindow.this.startThread("quit");
	    }
	 }
      );
      
      addMenuBar();
      this.pack();
      this.setResizable(false);
      this.setVisible(true);
   }

   protected void addMenuBar()
   {
    MenuBar  mb = new MenuBar();
    Menu	 m;
    MenuItem item;
    
    mb.setFont(Params._m_font);
    
    myFileMenu = new Menu("File");

    myFileMenu.add(item = new MenuItem("Open...", new MenuShortcut('o')));
    if (isApplet) item.setEnabled(false);
    item.addActionListener(this);
    myFileMenu.add(item = new MenuItem("Save", new MenuShortcut('s')));
    if (isApplet) item.setEnabled(false);
    item.addActionListener(this);
    myFileMenu.add(item = new MenuItem("Save as...", new MenuShortcut('S',true)));
    if (isApplet) item.setEnabled(false);
    item.addActionListener(this);
    myFileMenu.addSeparator();

    myFileMenu.add(item = new MenuItem(SourceWindow.STR_CLOSE,new MenuShortcut('c')));
    item.addActionListener(this);
    myFileMenu.add(item = new MenuItem(SourceWindow.STR_QUIT, new MenuShortcut('q')));
    if (isApplet) item.setEnabled(false);
    item.addActionListener(mainmenu);
    mb.add(myFileMenu);
    
    m = new Menu("Help");
    m.add(item = new MenuItem("About", new MenuShortcut('A')));
    item.addActionListener(this);
    m.add(item = new MenuItem("Help HTML", new MenuShortcut('h')));
    item.addActionListener(this);
    m.add(item = new MenuItem("Help Text", new MenuShortcut('t')));
    item.addActionListener(this);
    mb.setHelpMenu(m);
    
    setMenuBar(mb);	
  }

   /**
    * sets the regular expression that is shown in the
    * regular expression input box
    */
   public void setRegExp(String regexp)
      throws BadInputException
   {
      regexpfield.setText(regexp);
   }

   public void actionPerformed(ActionEvent h)
   {
      if(h.getActionCommand().equals(SourceWindow.STR_CLOSE)) 
	 startThread("quit");
      else if (h.getActionCommand().equals("Open..."))
	 startThread("load");
      else if (h.getActionCommand().equals("Save"))
	 save();
      else if (h.getActionCommand().equals("Save as..."))
	 saveAs();
      else if(h.getActionCommand().equals("Help HTML"))
      {
	 helpHTML();
	 mainmenu.myHelpWindow.setCurrentTopic("Regular Expression Input Window");
      }
      else if(h.getActionCommand().equals("Help Text"))
      {
	 helpText();
	 mainmenu.myHelpWindow.setCurrentTopic("Regular Expression Input Window");
      }
      else if(h.getActionCommand().equals("About"))
	 about();
      else if(h.getSource() == createbutton)
      {
	  String temp = regexpfield.getText();
	  int parenthcount = 0;
	  for(int x = 0; x < temp.length(); ++x)
	  {
	     if(temp.charAt(x) == '(')
	     {
	       ++parenthcount;
	     }
	     else if(temp.charAt(x) == ')')
	     {
	       --parenthcount;
	     }
	  }

	  if(parenthcount != 0)
	  {
	     OKDialog dg;
	     if(parenthcount < 0)
	     {
	       dg = new OKDialog("Missing beginning parenthesis.", this, "Regular Expression Error");
	     }
	     else
	     {
	       dg = new OKDialog("Missing end parenthesis.", this, "Regular Expression Error");
	     }
	     dg.show();
	     return;
	  }

	  setEnabled(false);
    
	  Environment env = new Environment(Machine.FSA, Environment.NO_FILE_NAME, mainmenu, isApplet);
	  env.pack();
	  try
	  {
	    env.setRegExpToFSA(regexpfield.getText(), 
	       new RegExptoFSAParser(env, regexpfield.getText()));
	  }
	  catch(Exception e)
	  {
	     OKDialog dg;
	     dg = new OKDialog("Invalid Regular Expression", this, "Regular Expression Error");
	     dg.show();
	     setEnabled(true);
	     return;
	  }
	  env.setAutoRelabel();
	  env.setVisible(true);
	  
	  setEnabled(true);
	  return;
      }
   }

       /**
     * save the grammar in a file
     */

  public boolean save() {
    if (NO_FILE_NAME.equals(fileName))
      return saveAs();
    else
      return save(fileName);
  }

    /**
     * input a file name. save grammar in it
     */
  public boolean saveAs() {

    FileDialog fd = new FileDialog(this, "Save Regular Expression", FileDialog.SAVE);
    if (currentDir != null)
      fd.setDirectory(currentDir);
    fd.setBackground(Params._dg_backcolor);
    fd.show();
    String strFile = fd.getFile();
    String strDir = fd.getDirectory();
    if (strDir == null || strFile == null)
      return false;
    if (strFile.endsWith(".*.*"))  // ugly bug in JDK 1.0.2 for win32.
      strFile = strFile.substring(0, strFile.length() - 4);
    if (!strDir.endsWith(MainMenu.fileSeparator))
      strDir += MainMenu.fileSeparator;
    currentDir = strDir;
    String aName = strDir + strFile;
    return save(aName);
  }

    /**
     * save grammar in the given file name
     */
  public boolean save(String name) {
    boolean answer = false;
    
    try {
      if (name.trim().endsWith(MainMenu.fileSeparator))
        throw (new Exception("Not a valid file name.\n"));
      if (!name.endsWith(".REX")) 
        name += ".REX";
      String text = regexpfield.getText();
      PrintWriter ps = new PrintWriter((new FileWriter(name)), true);
      ps.println("# Regular Expression created by JFLAP 3.1");
      ps.println(text);
      fileName = name;
      answer = true;
    }
    catch (IOException e) {
      OKDialog dg = new OKDialog("I/O Error.\nFile not saved.\n"
		+ e.getMessage(), this, "Regular Expression Save Error");
      dg.show();
    }
    catch (NoSuchElementException e) {
      OKDialog dg = new OKDialog("Tokenizer Error.\nFile not saved.\n"
		+ e.getMessage(), this, "Regular Expression Save Error");
      dg.show();
    }
    catch (BadInputException e) {
      OKDialog dg = new OKDialog("Grammar incorrect.\nFile not saved.\n" 
		+ e.getMessage(), this, "Regular Expression Save Error");
      dg.show();
    }
    catch (Exception e) {
      OKDialog dg = new OKDialog("File Error.\nFile not saved.\n"
		+ e.getMessage(), this,"Regular Expression Save Error");
      dg.show();
    }
    return answer;
  }

  /**
   * load a grammar
   */
  public void load() {
    
    FileDialog fd = new FileDialog(this, "Open Regular Expression", FileDialog.LOAD);
    fd.setBackground(Params._dg_backcolor);
    if (currentDir!= null)
      fd.setDirectory(currentDir);
    fd.show();
    String strFile = fd.getFile();
    String strDir = fd.getDirectory();
    if (strDir == null || strFile == null) {
	setEnabled(true);
	return;
    }
    if (strFile.endsWith(".*.*"))  // ugly bug in JDK 1.0.2 for win32.
      strFile = strFile.substring(0, strFile.length() - 4);
    if (!strDir.endsWith(MainMenu.fileSeparator))
      strDir += MainMenu.fileSeparator;
    currentDir = strDir;
    String aName = strDir + strFile;
    if (!aName.endsWith(".REX"))
      aName += ".REX";
    try {
      boolean	answer = false;
      BufferedReader dis =  new BufferedReader(new FileReader(aName));
      String line = dis.readLine();
      while(line != null)
      {
	 if(line.length() > 0 && line.charAt(0) != '#')
	 {
	    regexpfield.setText(line);
	    setEnabled(true);
	    return;
	 }
	 line = dis.readLine();
       }

      fileName = aName;
    }
    catch (FileNotFoundException e) {
      OKDialog dg = new OKDialog("Could not find file\n"+"'" + aName + "'", 
		this, "Regular Expression Open Error");
      dg.findResult();
    }
    catch (EOFException e) {
      OKDialog dg = new OKDialog("Unexpected end of file.", this, 
	       "Regular Expression Open Error");
      dg.findResult();
    }
    catch (NumberFormatException e) {
      OKDialog dg = new OKDialog("Numbers not found where\nthey were needed...",
		this, "Regular Expression Open Error");
      dg.findResult();
    }
    catch (IOException e) {
      OKDialog dg = new OKDialog("An I/O error occured.", this, 
		"Regular Expression Open Error");
      dg.findResult();
    }
    setEnabled(true);
  }

    /* 
     * starts a functionThread with the given function inside
     */
  public void  startThread(String functionName)
  {
	FunctionThread ft;
	Class source;
       
	try {
	    source = this.getClass();
	    ft = new FunctionThread(source.getMethod(functionName, new Class[0]), this, new Object[0]);
	    ft.start();
	}
	catch(NoSuchMethodException h) {
	    System.out.println("no " + functionName + " method found.");
	}
  }
}

  