/* RunMenu.java
 *
 * created: Fri Jan 22 1999
 *
 * This file is part of Artemis
 *
 * Copyright (C) 1998,1999,2000  Genome Research Limited
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * $Header: /nfs/disk222/yeastpub/Repository/powmap/diana/components/RunMenu.java,v 1.12 2000/07/25 14:20:47 kmr Exp $
 **/

package diana.components;

import diana.*;
import uk.ac.sanger.pathogens.ReadOnlyException;
import uk.ac.sanger.pathogens.embl.EntryInformationException;
import uk.ac.sanger.pathogens.embl.InvalidKeyException;

import java.io.*;
import java.awt.*;
import java.awt.event.*;

/**
 *  A Menu of external commands/functions.
 *
 *  @author Kim Rutherford
 *  @version $Id: RunMenu.java,v 1.12 2000/07/25 14:20:47 kmr Exp $
 **/

public class RunMenu extends SelectionMenu {
  /**
   *  Create a new RunMenu object.
   *  @param frame The Frame that owns this Menu.
   *  @param selection The Selection that the commands in the menu will
   *    operate on.
   **/
  public RunMenu (final Frame frame, final Selection selection) {
    super (frame, "Run", selection);

    final ExternalProgramVector external_programs =
      Options.getOptions ().getExternalPrograms ();

    for (int i = 0 ; i < external_programs.size () ; ++i) {
      makeMenuItem (external_programs.elementAt (i));
    }

    addSeparator ();

    for (int i = 0 ; i < external_programs.size () ; ++i) {
      makeOptionsMenuItem (external_programs.elementAt (i));
    }
  }

  /**
   *  Make a new menu item for running the given ExternalProgram object.
   *  @param program Create two menu items for this program.
   **/
  private void makeMenuItem (final ExternalProgram program) {
    final MenuItem new_menu =
      new MenuItem ("Run " + program.getName () + " on selected features");

    new_menu.addActionListener (new ActionListener () {
      public void actionPerformed (ActionEvent event) {
        if (!checkForSelectionFeatures ()) {
          return;
        }

        final FeatureVector selection_features =
          getSelection ().getAllFeatures ();

        try {
          final Process process = program.run (selection_features);

          final Thread thread;

          if (program instanceof ExternalApplication) {
            thread =
              new Thread (new ProcessWatcher (process,
                                              program.getName (), false));
          } else {
            thread =
              new Thread (new ProcessWatcher (process,
                                              program.getName (), true));
          }

          thread.start ();
        } catch (InvalidKeyException e) {
          new MessageDialog (getParentFrame (),
                             "execution failed: " + e.getMessage ());
        } catch (EntryInformationException e) {
          throw new Error ("internal error - unexpected exception: " + e);
        } catch (ReadOnlyException e) {
          new MessageDialog (getParentFrame (),
                             "execution of " + program.getName () +
                             " failed because one of the features is in a " +
                             "read only entry");
        } catch (IOException e) {
          new MessageDialog (getParentFrame (),
                             "execution of " + program.getName () +
                             " failed because of an I/O error: " +
                             e);
        } catch (ExternalProgramException e) {
          new MessageDialog (getParentFrame (),
                             "execution of " + program.getName () +
                             " failed: " + e.getMessage ());
        }
      }
    });

    add (new_menu);
  }

  /**
   *  Make a new options menu item for the given ExternalProgram object.
   *  @param program Create two menu items for this program.
   **/
  private void makeOptionsMenuItem (final ExternalProgram program) {
    final MenuItem new_options_menu =
      new MenuItem ("Set " + program.getName () + " options");

    new_options_menu.addActionListener (new ActionListener () {
      public void actionPerformed (ActionEvent event) {
        new ExternalProgramOptions (program);
      }
    });

    add (new_options_menu);
  }
}
