/* EntryGroupPanel.java
 *
 * created: Wed Jun 21 2000
 *
 * This file is part of Artemis
 * 
 * Copyright (C) 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/EntryGroupPanel.java,v 1.3 2000/08/24 09:02:02 kmr Exp $
 */

package diana.components;

import diana.*;
import diana.sequence.*;

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

/**
 *  A Panel that can show an EntryGroup (in some way).
 *
 *  @author Kim Rutherford <kmr@sanger.ac.uk>
 *  @version $Id: EntryGroupPanel.java,v 1.3 2000/08/24 09:02:02 kmr Exp $
 **/

abstract public class EntryGroupPanel extends CanvasPanel {
  /**
   *  Create a new EntryGroupPanel for the given EntryGroup.
   *  @param entry_group The EntryGroup that this component will display.
   *  @param selection The Selection object for this component.  Selected
   *    objects will be highlighted.
   **/
  public EntryGroupPanel (final EntryGroup entry_group,
                          final Selection selection,
                          final GotoEventSource goto_event_source) {
    this.entry_group       = entry_group;
    this.selection         = selection;
    this.goto_event_source = goto_event_source;

    getCanvas ().addKeyListener (new KeyAdapter () {
      public void keyPressed (final KeyEvent event) {
        handleKeyPress (event);
      }
    });
  }

  /**
   *  Return an object that implements the GotoEventSource interface and which
   *  is relative to the sequence that this DisplayComponent is displaying.
   **/
  public GotoEventSource getGotoEventSource () {
    return goto_event_source;
  }

  /**
   *  Walk up through parents of this Component and return the Frame at the
   *  top.
   **/
  public Frame getParentFrame () {
    Component parent = this.getParent ();

    while (parent != null && !(parent instanceof Frame)) {
      parent = parent.getParent();
    }

    return (Frame) parent;
  }

  /**
   *  Return the EntryGroup object that this FeatureDisplay is displaying.
   **/
  public EntryGroup getEntryGroup () {
    return entry_group;
  }

  /**
   *  Returns the Selection that was passed to the constructor.
   **/
  public Selection getSelection  () {
    return selection;
  }

  /**
   *  This method sends an GotoEvent to all the GotoEvent listeners that will
   *  make the start of the first selected Feature or FeatureSegment visible.
   **/
  protected void makeSelectionVisible () {
    final Marker first_base = getSelection ().getStartBaseOfSelection ();

    final GotoEvent new_event = new GotoEvent (this, first_base);

    getGotoEventSource ().sendGotoEvent (new_event);
  }

  /**
   *  Handle key press events.
   **/
  private void handleKeyPress (final KeyEvent event) {
    final FeatureVector selected_features = getSelection ().getAllFeatures ();

    if (selected_features.size () == 0) {
      return;
    }

    final Feature first_selected_feature = selected_features.elementAt (0);

    final int feature_index =
      getEntryGroup ().indexOf (first_selected_feature);

    if (event.getModifiers () != 0) {
      // this is done so that menu shortcuts don't cause each action to be
      // performed twice
      return;
    }
    
    switch (event.getKeyCode ()) {
    case KeyEvent.VK_UP:
      if (feature_index > 0) {
        selection.set (getEntryGroup ().featureAt (feature_index - 1));
        makeSelectionVisible ();
      } else {
        // do nothing
      }
      break;
    case KeyEvent.VK_DOWN:
      if (feature_index < getEntryGroup ().getAllFeaturesCount () - 1) {
        selection.set (getEntryGroup ().featureAt (feature_index + 1));
        makeSelectionVisible ();
      }
      break;
    case EditMenu.EDIT_FEATURE_KEY:
      EditMenu.editSelectedFeatures (getParentFrame (), getSelection ());
      break;
    case EditMenu.MERGE_FEATURES_KEY:
      EditMenu.mergeFeatures (getParentFrame (), getSelection ());
      break;
    case EditMenu.DUPLICATE_KEY:
      EditMenu.duplicateFeatures (getParentFrame (), getSelection ());
      break;
    case EditMenu.DELETE_FEATURES_KEY:
      EditMenu.deleteSelectedFeatures (getParentFrame (), getSelection ());
      break;
    case ViewMenu.VIEW_FEATURES_KEY:
      ViewMenu.viewSelectedFeatures (getParentFrame (), getSelection ());
      break;
    case ViewMenu.PLOT_FEATURES_KEY:
      ViewMenu.plotSelectedFeatures (getParentFrame (), getSelection ());
      break;
    case ViewMenu.OVERVIEW_KEY:
      new EntryGroupInfoDisplay (getParentFrame (), entry_group);
      break;
    case ViewMenu.FASTA_IN_BROWSER_KEY:
      viewResults ("fasta", true);
      break;
    case ViewMenu.BLASTP_IN_BROWSER_KEY:
      viewResults ("blastp", true);
      break;
    case ViewMenu.VIEW_FASTA_KEY:
      viewResults ("fasta", false);
      break;
    case ViewMenu.VIEW_BLASTP_KEY:
      viewResults ("blastp", false);
      break;
    case ViewMenu.VIEW_HTH_KEY:
      viewResults ("hth", false);
      break;
    }
  }

  /**
   *  Show the output file from an external program (like fasta) for the
   *  selected Feature objects.  The name of the file to read is stored in a
   *  feature qualifier.  The qualifier used is the program name plus "_file".
   *  @param send_to_browser if true the results should be sent straight to
   *    the web browser rather than using a SearchResultViewer object.
   **/
  private void viewResults (final String program_name,
                            final boolean send_to_browser) {
    final boolean sanger_options =
      Options.getOptions ().getPropertyTruthValue ("sanger_options");

    if (sanger_options && send_to_browser) {
      ViewMenu.viewExternalResults (getParentFrame (), getSelection (),
                                    program_name, true);
    } else {
      ViewMenu.viewExternalResults (getParentFrame (), getSelection (),
                                    program_name, false);
    }
  }

  /**
   *  The shortcut for View FASTA in browser.
   **/
  final int fasta_in_browser_key = KeyEvent.VK_F;

  /**
   *  The shortcut for View FASTA.
   **/
  final int view_fasta_key = KeyEvent.VK_R;

  /**
   *  The shortcut for View BLASTP in browser.
   **/
  final int blastp_in_browser_key = KeyEvent.VK_B;

  /**
   *  The shortcut for View BLASTP.
   **/
  final int view_blastp_key = KeyEvent.VK_TAB;

  /**
   *  This is the EntryGroup that this component is displaying (as set by the
   *  constructor).
   **/
  private EntryGroup entry_group;

  /**
   *  This is a reference to the Selection object that was passed to the
   *  constructor.
   **/
  private Selection selection;

  /**
   *  This is a reference to the GotoEventSource object that was passed to the
   *  constructor.
   **/
  private GotoEventSource goto_event_source;
}
