package extensions.awt;
import java.awt.*;
import java.io.*;
import extensions.io.*;

class EditFrameExitAdapter extends Action
{
  public final void run() { ((EditFrame)forward).exit(); }
}

/*
class EditFrameEditMenuAdapter implements ActionProtocol
{
  public final void action(Component forward, Event evt, Object what)
  {
    EditFrame ef = (EditFrame) forward;
    ef.deliverEvent(new Event((TextArea)(ef.fta),
      System.currentTimeMillis(),Event.MOUSE_UP,
      1,1,0,Event.META_MASK));
  }
}
*/

class EditFrameGotoAdapter extends Action
{
  public final void run()
  {
    EditFrame ef = (EditFrame) forward;
    PromptDialog pd = new PromptDialog(ef,"Go to Line: ",10);
    pd.show();
    if (pd.okClicked() && pd.response != null)
      try {
        ef.gotoRow(Integer.parseInt(pd.response));
      } catch (Throwable t) {
        new DialogExtended(ef,t);
      }
  }
}

/** Basic Text Editor Frame
  * @version 1.0.2
  * @author John Webster Small
  */
public class EditFrame
  extends FrameExtended
  implements Cloneable
{
  private FileTextArea fta;
  private Label statusLine;
  private MenuItemAction saveMI;
  private MenuItemAction saveAsMI;

  public boolean constructorUserCanceled = false;

  /** Launch a FileDialog to open a file upon construction. */
  public final static int OPEN = FileTextArea.OPEN;

  /** Launch a FileDialog to open a file for browsing
   a file upon construction. */
  public final static int BROWSE = FileTextArea.BROWSE;

  /** Indicates a new file event. */  
  public final static int NEW_FILE = FileTextArea.NEW_FILE;

  /** Default EditFrame width. */
  public final static int WIDTH = 500;

  /** Default EditFrame height. */
  public final static int HEIGHT = 270;

  /** Exit the edit frame. */
  void exit() { destroy(); }

  /** Set title indicating browse mode with an "!" */
  public void setTitle(String title)
    { super.setTitle((fta.isEditable()?" ":"!")+title); }

  /** Implements a universal observer interface. */
  public boolean update(Object anySubject, Object what)
  {
    if (anySubject == fta)  {
       setTitle((String)what);
       switch (fta.event)  {
         case FileTextArea.BROWSE:
           saveMI.disable();
           saveAsMI.disable();
           break;
         case FileTextArea.NEW_FILE:
         case FileTextArea.OPEN:
         case FileTextArea.SAVE:
           saveMI.enable();
           saveAsMI.enable();
           break;
       }
    }
    return true;
  }

  private void init()
  {
    destroyMayBlock = true;
    setFont(new Font("Courier",Font.PLAIN,14));
    if (fta == null)
      this.fta = new FileTextArea(this);
      // browse mode set!
    add("Center",fta);
    MenuBar mb = new MenuBar();
    Menu m = new Menu("File");
    m.add(new MenuItemAction("New",fta.newAdapter()));
    m.add(new MenuItemAction("Browse ...",fta.browseAdapter()));
    m.add(new MenuItemAction("Open ...",fta.openAdapter()));
    m.add(saveMI = new MenuItemAction("Save",fta.saveAdapter()));
    m.add(saveAsMI = new MenuItemAction("Save As ...",fta.saveAsAdapter()));
    m.addSeparator();
    m.add(new MenuItemAction("Exit",new EditFrameExitAdapter()));
    mb.add(m);
    m = new Menu("Edit");
    m.add(new MenuItem("Click right mouse button over text area for clipboard menu"));
    m.addSeparator();
    m.add(new MenuItemAction("Insert file",fta.insertFileAdapter()));
    m.add(new MenuItemAction("Append file",fta.appendFileAdapter()));
    m.addSeparator();
    m.add(new MenuItemAction("Bookmark",fta.bookmarkAdapter()));
    m.add(new MenuItemAction("Go to bookmark",fta.gotoBookmarkAdapter()));
    m.add(new MenuItemAction("Goto Line",new EditFrameGotoAdapter()));
    mb.add(m);
    m = new Menu("Search");
    m.add(new MenuItemAction("Find ...",fta.showFindDialogAdapter()));
    m.add(new MenuItemAction("Replace ...",fta.showReplaceDialogAdapter()));
    mb.add(m);
    setMenuBar(mb);
    resize(WIDTH,HEIGHT);
    update(fta,fta.getFile().getName());
    requestFocus();
  }

  private void copyInit(FileTextArea fta)
  {
    this.fta = new FileTextArea(this,fta);
    init();
  }

  /** Construct an EditFrame for editing. */
  public EditFrame()
    { init(); }

  /** Copy initializer constructor. */
  public EditFrame(EditFrame ef)
    { copyInit(ef.fta); }

  /** Construct an EditFrame with the supplied
    * text.
    * @param text initial text
    */
  public EditFrame(String text)
  {
    fta = new FileTextArea(this,text);
    init();
  }

  /** Construct an EditFrame.
    * @param f file to edit
    * @param readOnly is the user allowed to modify
    * @param promptUser allow user to modify file requested
    */
  public EditFrame(File f, boolean readOnly, boolean promptUser)
  {
    fta = new FileTextArea(this,f,readOnly,promptUser);
    init();
  }

  /** Clone this EditFrame along with its contents.
    * The cloned EditFrame is in browse (read only) mode
    */
  public Object clone()
    { return new EditFrame(this); }

  /** Hide this window save any changes if required to.
    * An interaction dialog appears if the dirty bit is set.
    */
  public void destroy()
  {
    if (fta.saveFile(this,true,false))
      super.destroy();
  }

  /** Causes the focus to shift to the TextArea. */
  public void requestFocus()
    { fta.requestFocus(); }

  /** Causes the focus to shift to the TextArea. */
  public void show()
  {
    super.show();
    requestFocus();
  }

  /** Refresh contents from file. */
  public void refresh()
    { fta.refresh(); }

  /** Save to file if modified.
    * @param parent frame requesting the save
    */
  public void save(Frame parent)
    { fta.save(parent); }

  /** Save to file if modified.
    * @param parent frame requesting the save
    * @param dirtyPrompt allow user to cancel save
    */
  public boolean save(Frame parent, boolean dirtyPrompt)
    { return fta.saveFile(parent,dirtyPrompt,false); }

  /** @return true if the contents have been modified */
  public boolean dirty()
    { return fta.dirty(); }

  /** Return flag indicating whether or not the user
    * canceled opening file in constructor.
    */
  public boolean userCanceled()
    { return fta.userCanceled; }

  /** Return text string. */
  public String getText()
    { return fta.getText(); }

  /** Return File. */
  public FileExtended getFile()
    { return fta.getFile(); }

  /** Return last FileTextArea event.
    * @see extensions.awt.FileTextArea#event
    */
  public int getEvent()
    { return fta.event; }
  /**
    * Position cursor. Top-left is 0.
    * @pos linear position of cursor
    */
  public void gotoPos(int pos)
    { fta.gotoPos(pos); }

  /**
    * Position cursor.  Top-left is (1,1)
    * @param row cursor row
    * @param col cursor column
    */
  public void gotoRC(int row, int col)
    { fta.gotoRC(row,col); }

  /**
    * Position cursor at the start of row.
    * Top line is row 1.
    * @param row cursor row
    */
  public void gotoRow(int row)
    { fta.gotoRow(row); }

  /** Start an EditFrame application assuming the
    * first command line parameter is a file to be
    * edited if supplied.
    */
  public static void main(String[] args)
  {
    EditFrame ef;
    exitOnDestroyAll = true;
    if (args.length > 0)
      ef = new EditFrame(new File(args[0]),false,false);
    else
      ef = new EditFrame();
    ef.show();
 }
}
