Skip to content
Snippets Groups Projects
FeatureEdit.java 60 KiB
Newer Older
  • Learn to ignore specific revisions
  • tjc's avatar
    tjc committed
    /* FeatureEdit.java
     *
     * created: Tue Dec  1 1998
     *
     * This file is part of Artemis
     *
     * Copyright (C) 1998,1999,2000,2001,2002  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: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/FeatureEdit.java,v 1.61 2008-08-01 12:46:56 tjc Exp $
    
    tjc's avatar
    tjc committed
     **/
    
    package uk.ac.sanger.artemis.components;
    
    import uk.ac.sanger.artemis.util.*;
    import uk.ac.sanger.artemis.*;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.sequence.MarkerRange;
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.ChadoCanonicalGene;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.DatabaseDocumentEntry;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.DocumentEntry;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.GFFDocumentEntry;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.GFFStreamFeature;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.OutOfDateException;
    import uk.ac.sanger.artemis.io.LocationParseException;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.PartialSequence;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.QualifierLazyLoading;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.QualifierParseException;
    import uk.ac.sanger.artemis.io.Range;
    import uk.ac.sanger.artemis.io.RangeVector;
    import uk.ac.sanger.artemis.io.Key;
    import uk.ac.sanger.artemis.io.KeyVector;
    import uk.ac.sanger.artemis.io.Location;
    import uk.ac.sanger.artemis.io.Qualifier;
    import uk.ac.sanger.artemis.io.QualifierVector;
    import uk.ac.sanger.artemis.io.EntryInformation;
    import uk.ac.sanger.artemis.io.EntryInformationException;
    import uk.ac.sanger.artemis.io.StreamQualifier;
    import uk.ac.sanger.artemis.io.QualifierInfo;
    
    tjc's avatar
    tjc committed
    
    import uk.ac.sanger.artemis.components.ProgressThread;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.components.genebuilder.GeneBuilderFrame;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.components.genebuilder.GeneEditorPanel;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.components.genebuilder.GeneUtils;
    
    import uk.ac.sanger.artemis.components.genebuilder.ProteinMapPanel;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.components.genebuilder.cv.CVPanel;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.components.genebuilder.gff.PropertiesPanel;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.components.genebuilder.ortholog.MatchPanel;
    
    tjc's avatar
    tjc committed
    
    import java.awt.*;
    import java.awt.event.*;
    import java.io.*;
    import java.util.Date;
    
    import java.util.Hashtable;
    
    tjc's avatar
    tjc committed
    import java.util.Iterator;
    import java.util.Set;
    
    tjc's avatar
    tjc committed
    import java.util.Vector;
    
    import java.util.Collections;
    import java.util.Comparator;
    
    tjc's avatar
    tjc committed
    import javax.swing.*;
    
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
    /**
     *  FeatureEdit class
     *
     *  @author Kim Rutherford
    
     *  @version $Id: FeatureEdit.java,v 1.61 2008-08-01 12:46:56 tjc Exp $
    
    tjc's avatar
    tjc committed
     **/
    
    tjc's avatar
    tjc committed
    public class FeatureEdit extends JPanel
    
    tjc's avatar
    tjc committed
                             implements EntryChangeListener, FeatureChangeListener 
    {
    
    
    tjc's avatar
    tjc committed
      /**
       * 
       */
      private static final long serialVersionUID = 1L;
    
    
    tjc's avatar
    tjc committed
    
      /** The choice of feature keys - created in createComponents(). */
      private KeyChoice key_choice;
    
      /** The choice of qualifiers - created in createComponents(). */
      private QualifierChoice qualifier_choice = null;
    
      private final static int LOCATION_TEXT_WIDTH = 80;
    
      /** The location text - set by updateLocation(). */
    
    tjc's avatar
    tjc committed
      private JTextField location_text = new JTextField(LOCATION_TEXT_WIDTH);
    
    tjc's avatar
    tjc committed
    
      /** When pressed - apply changes and dispose of the component. */
    
    tjc's avatar
    tjc committed
      private JButton ok_button = new JButton("OK");
    
    tjc's avatar
    tjc committed
    
      /** When pressed - discard changes and dispose of the component. */
    
    tjc's avatar
    tjc committed
      private JButton cancel_button = new JButton("Cancel");
    
    tjc's avatar
    tjc committed
    
      /** When pressed - apply changes and keep the component open. */
    
    tjc's avatar
    tjc committed
      private JButton apply_button = new JButton("Apply");
    
    tjc's avatar
    tjc committed
    
      /** Edit area for qualifiers - created by createComponents(). */
      private QualifierTextArea qualifier_text_area;
    
      /** The Feature this object is displaying. */
      private Feature edit_feature;
    
      /**
       *  The GotoEventSource that was passed to the constructor - used for the
       *  "Goto Feature" button.
       **/
      private GotoEventSource goto_event_source;
    
      /** Entry containing the Feature this object is displaying. */
      private Entry edit_entry;
    
      /** EntryGroup that contains this Feature (passed to the constructor). */
      private EntryGroup entry_group;
    
      /**
    
    tjc's avatar
    tjc committed
       *  The datestamp of the RWCorbaFeature when updateFromFeature() was last
    
    tjc's avatar
    tjc committed
       *  called or null if this is not a RWCorbaFeature.
       **/
      private Date datestamp = null;
    
      /** The Selection that was passed to the constructor. */
      private Selection selection;
    
      /**
       *  The contents of the QualifierTextArea before the user edits anything.
       *  This is used to work out if anything has changed since the creation of
       *  the FeatureEdit.
       **/
      final String orig_qualifier_text;
    
    
    tjc's avatar
    tjc committed
      private JFrame frame;
      
    
      /** controlled vocabulary tab */
    
    tjc's avatar
    tjc committed
      private CVPanel cvForm;
    
    tjc's avatar
    tjc committed
      
    
      /** GFF tab */
    
    tjc's avatar
    tjc committed
      private PropertiesPanel propertiesPanel;
    
    tjc's avatar
    tjc committed
      
    
    tjc's avatar
    tjc committed
      /** similarity/ortholog/paralog tab */
      private MatchPanel matchForm;
    
      
      private EntryInformation entry_information;
      
    
    tjc's avatar
    tjc committed
      private static boolean isTabbedView = false;
    
    tjc's avatar
    tjc committed
      private GeneEditorPanel editorPanel;
      
    
    tjc's avatar
    tjc committed
      /**
       *  Create a new FeatureEdit object from the given Feature.
       *  @param entry_group The EntryGroup that contains this Feature.
       *  @param selection The Selection operate on.  The operations are "Remove
       *    Range" and "Grab Range"
    
    tjc's avatar
    tjc committed
       *  @param goto_event_source The object the we will call gotoBase() on.
    
    tjc's avatar
    tjc committed
       **/
    
    tjc's avatar
    tjc committed
      public FeatureEdit(final Feature edit_feature,
                         final EntryGroup entry_group,
                         final Selection selection,
    
    tjc's avatar
    tjc committed
                         final GotoEventSource goto_event_source,
                         final JFrame frame) 
    
    tjc's avatar
    tjc committed
      {
    
        this(edit_feature, entry_group, selection, 
             goto_event_source, frame, 
             edit_feature.getEntry().getEntryInformation());
      }
      
      public FeatureEdit(final Feature edit_feature,
          final EntryGroup entry_group,
          final Selection selection,
          final GotoEventSource goto_event_source,
          final JFrame frame, final EntryInformation entry_information) 
      {
        this.entry_information = entry_information;
    
    tjc's avatar
    tjc committed
        this.frame = frame;
    
    tjc's avatar
    tjc committed
        this.edit_feature = edit_feature;
    
    tjc's avatar
    tjc committed
        this.edit_entry   = edit_feature.getEntry();
    
    tjc's avatar
    tjc committed
        this.entry_group  = entry_group;
        this.selection    = selection;
    
    tjc's avatar
    tjc committed
        this.goto_event_source = goto_event_source;
    
    
    tjc's avatar
    tjc committed
        setLayout(new BorderLayout());
    
    tjc's avatar
    tjc committed
        createComponents();
        updateFromFeature();
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        orig_qualifier_text = qualifier_text_area.getText();
    
    tjc's avatar
    tjc committed
      
    
        if(edit_feature.getEntry() != null)
    
    tjc's avatar
    tjc committed
        {
    
          edit_feature.getEntry().addEntryChangeListener(this);
          edit_feature.addFeatureChangeListener(this);
    
    tjc's avatar
    tjc committed
    
    
          frame.addWindowListener(new WindowAdapter()
          {
            public void windowClosing(WindowEvent event)
            {
              stopListening();
              frame.dispose();
            }
          });
        }
        
    
    tjc's avatar
    tjc committed
        qualifier_text_area.requestFocus();
      }
    
    tjc's avatar
    tjc committed
      
    
    tjc's avatar
    tjc committed
      private boolean isPartialSequence()
      {
        return edit_feature.getEmblFeature().getEntry().getSequence() instanceof PartialSequence;
      }
      
    
    tjc's avatar
    tjc committed
      /**
       * Set the feature to edit
       * @param edit_feature
       * @param isSet
       */
      public void setActiveFeature(final Feature edit_feature,
                                   final boolean isSet)
    
    tjc's avatar
    tjc committed
      {
    
    tjc's avatar
    tjc committed
        if(!isPartialSequence() && isSet)
    
    tjc's avatar
    tjc committed
          setFeature();
    
    tjc's avatar
    tjc committed
        this.edit_feature = edit_feature;
        this.edit_entry   = edit_feature.getEntry();
        updateFromFeature();
      }
    
    tjc's avatar
    tjc committed
    
      /**
       *  Remove this object as a feature and entry change listener.
       **/
    
    tjc's avatar
    tjc committed
      public void stopListening() 
      {
    
    tjc's avatar
    tjc committed
        getEntry().removeEntryChangeListener(this);
        getFeature().removeFeatureChangeListener(this);
    
    tjc's avatar
    tjc committed
        if(cvForm != null)
          getFeature().removeFeatureChangeListener(cvForm);
    
    tjc's avatar
    tjc committed
        if(propertiesPanel != null)
          getFeature().removeFeatureChangeListener(propertiesPanel);
    
    tjc's avatar
    tjc committed
        if(matchForm != null)
          getFeature().removeFeatureChangeListener(matchForm);
    
    tjc's avatar
    tjc committed
      }
    
      /**
       *  Implementation of the EntryChangeListener interface.  We listen to
       *  EntryChange events so we can notify the user if of this component if the
       *  feature gets deleted.
       **/
    
    tjc's avatar
    tjc committed
      public void entryChanged(EntryChangeEvent event) 
    
    tjc's avatar
    tjc committed
      {
        switch(event.getType())
        {
          case EntryChangeEvent.FEATURE_DELETED:
    
    tjc's avatar
    tjc committed
            if(event.getFeature() == edit_feature) 
    
    tjc's avatar
    tjc committed
            {
    
    tjc's avatar
    tjc committed
              stopListening();
    
    tjc's avatar
    tjc committed
              frame.dispose();
    
    tjc's avatar
    tjc committed
            }
            break;
          default:
            // do nothing;
            break;
    
    tjc's avatar
    tjc committed
        }
      }
    
      /**
       *  Add an ActionListener to the Cancel JButton of this FeatureEdit.
       **/
    
    tjc's avatar
    tjc committed
      public void addCancelActionListener(final ActionListener l) 
      {
        cancel_button.addActionListener(l);
    
    tjc's avatar
    tjc committed
      }
    
      /**
       *  Remove an ActionListener from the Cancel JButton of this FeatureEdit.
       **/
    
    tjc's avatar
    tjc committed
      public void removeCancelActionListener(final ActionListener l) 
      {
        cancel_button.removeActionListener(l);
    
    tjc's avatar
    tjc committed
      }
    
      /**
       *  Add an ActionListener to the Apply JButton of this FeatureEdit.
       **/
    
    tjc's avatar
    tjc committed
      public void addApplyActionListener(final ActionListener l) 
      {
    
    tjc's avatar
    tjc committed
        apply_button.addActionListener(l);
    
    tjc's avatar
    tjc committed
      }
    
      /**
       *  Remove an ActionListener from the Apply JButton of this FeatureEdit.
       **/
    
    tjc's avatar
    tjc committed
      public void removeApplyActionListener(final ActionListener l) 
      {
        apply_button.removeActionListener(l);
    
    tjc's avatar
    tjc committed
      }
    
      /**
       *  Implementation of the FeatureChangeListener interface.  We need to
       *  listen to feature change events from the Features in this object so that
       *  we can update the display.
       *  @param event The change event.
       **/
    
    tjc's avatar
    tjc committed
      public void featureChanged(FeatureChangeEvent event) 
      {
    
    tjc's avatar
    tjc committed
        getFeature().resetColour();
    
    tjc's avatar
    tjc committed
        // re-read the information from the feature
    
    tjc's avatar
    tjc committed
        switch(event.getType()) 
    
    tjc's avatar
    tjc committed
        {
    
    tjc's avatar
    tjc committed
          case FeatureChangeEvent.LOCATION_CHANGED:
            updateLocation();
            break;
    
    tjc's avatar
    tjc committed
          case FeatureChangeEvent.SEGMENT_CHANGED:
            updateLocation();
            break;
    
    tjc's avatar
    tjc committed
          case FeatureChangeEvent.KEY_CHANGED:
            updateKey();
            break;
          case FeatureChangeEvent.QUALIFIER_CHANGED:
            if(qualifier_text_area.getText().equals(orig_qualifier_text)) 
              updateFromFeature();
            else
            {
    
    tjc's avatar
    tjc committed
              if(!event.getFeature().getIDString().equals(getFeature().getIDString()))
                break;
              
    
    tjc's avatar
    tjc committed
              final String message =
                "warning: the qualifiers have changed outside the editor - " +
                "view now?";
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
              final YesNoDialog yes_no_dialog =
    
    tjc's avatar
    tjc committed
                new YesNoDialog(frame, message);
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
              if(yes_no_dialog.getResult()) 
                new FeatureViewer(getFeature());
            }
            break;
          default:
            updateFromFeature();
            break;
    
    tjc's avatar
    tjc committed
        }
      }
    
    
      /**
       *  Create all the components for this FeatureEdit component.
       **/
    
    tjc's avatar
    tjc committed
      private void createComponents()
      {
    
    tjc's avatar
    tjc committed
        qualifier_text_area = new QualifierTextArea();
    
        //qualifier_text_area.setWrapStyleWord(true);
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        FlowLayout flowLayoutZeroHgap = new FlowLayout(FlowLayout.LEADING);
        flowLayoutZeroHgap.setHgap(0);
    
    tjc's avatar
    tjc committed
        key_choice =
    
    tjc's avatar
    tjc committed
          new KeyChoice(getEntryInformation(),getFeature().getKey());
    
    tjc's avatar
    tjc committed
        key_choice.setLayout(flowLayoutZeroHgap);
    
    tjc's avatar
    tjc committed
        final JPanel key_and_qualifier_panel = new JPanel();
        location_text.setBackground(Color.white);
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        final JPanel key_panel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
        final JLabel locLabel = new JLabel("Location: ");
        final JLabel keyLabel = new JLabel("Key: ");
        keyLabel.setHorizontalAlignment(SwingConstants.RIGHT);
        keyLabel.setPreferredSize(locLabel.getPreferredSize());
        
        key_panel.add(keyLabel);
    
    tjc's avatar
    tjc committed
        key_panel.add(key_choice);
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        key_and_qualifier_panel.setLayout(new BorderLayout());
        key_and_qualifier_panel.add(key_panel, "West");
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        boolean isGFF = false;
        if(edit_feature.getEmblFeature().getEntry() instanceof GFFDocumentEntry)
          isGFF = true;
        
    
    tjc's avatar
    tjc committed
        qualifier_choice = new QualifierChoice(getEntryInformation(),
    
    tjc's avatar
    tjc committed
                                      key_choice.getSelectedItem(),null,
                                      isGFF);
    
    tjc's avatar
    tjc committed
        
        final JPanel qualifier_panel = new JPanel(new FlowLayout(FlowLayout.TRAILING,0,0));
    
    tjc's avatar
    tjc committed
        final JButton qualifier_add_button = new JButton("Add Qualifier:");
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        qualifier_panel.add(qualifier_add_button);
        qualifier_panel.add(qualifier_choice);
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        key_and_qualifier_panel.add(qualifier_panel, "East");
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        key_choice.addItemListener(new ItemListener() 
        {
          public void itemStateChanged(ItemEvent _) 
          {
    
    tjc's avatar
    tjc committed
            qualifier_choice.setKey(key_choice.getSelectedItem());
    
    tjc's avatar
    tjc committed
          }
        });
    
    
    tjc's avatar
    tjc committed
        qualifier_add_button.addActionListener(new ActionListener() 
        {
          public void actionPerformed(ActionEvent e)
          {
    
    tjc's avatar
    tjc committed
            final String qualifier_name =
    
    tjc's avatar
    tjc committed
              (String)qualifier_choice.getSelectedItem();
    
    tjc's avatar
    tjc committed
    
            QualifierInfo qualifier_info =
    
    tjc's avatar
    tjc committed
              getEntryInformation().getQualifierInfo(qualifier_name);
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
            if(qualifier_info == null) 
              qualifier_info = new QualifierInfo(qualifier_name,
                                  QualifierInfo.OPTIONAL_QUOTED_TEXT,
                                  null, null, false);
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
            qualifier_text_area.append("/" + qualifier_name);
    
    
    tjc's avatar
    tjc committed
            switch(qualifier_info.getType()) 
    
    tjc's avatar
    tjc committed
            {
              case QualifierInfo.QUOTED_TEXT:
                if(qualifier_name.equals("GO")) 
                {
                  // special case for /GO
                  final java.util.Calendar calendar =
                          java.util.Calendar.getInstance();
                    
    
    tjc's avatar
    tjc committed
                  final Date current_time = calendar.getTime();
    
    tjc's avatar
    tjc committed
                
    
    tjc's avatar
    tjc committed
                  final java.text.SimpleDateFormat date_format =
                      new java.text.SimpleDateFormat("yyyyMMdd");
    
    tjc's avatar
    tjc committed
                
    
    tjc's avatar
    tjc committed
                  final StringBuffer result_buffer = new StringBuffer();
    
    tjc's avatar
    tjc committed
                
    
    tjc's avatar
    tjc committed
                  date_format.format(current_time, result_buffer,
                                     new java.text.FieldPosition(java.text.DateFormat.DATE_FIELD));
    
    tjc's avatar
    tjc committed
                
    
    tjc's avatar
    tjc committed
                  final String go_string = "aspect=; term=; GOid=GO:; "+
                                           "evidence=ISS; db_xref=GOC:unpublished; " +
    
    tjc's avatar
    tjc committed
                                           "with=UniProtKB:; date=" + result_buffer;
    
    tjc's avatar
    tjc committed
                  qualifier_text_area.append("=\"" + go_string + "\"");
                } 
    
    tjc's avatar
    tjc committed
                else if(qualifier_name.equals("controlled_curation"))
                {
                  final java.util.Calendar calendar =
                          java.util.Calendar.getInstance();
    
                  final Date current_time = calendar.getTime();
    
                  final java.text.SimpleDateFormat date_format =
                      new java.text.SimpleDateFormat("yyyyMMdd");
    
                  final StringBuffer result_buffer = new StringBuffer();
    
                  date_format.format(current_time, result_buffer,
                                     new java.text.FieldPosition(java.text.DateFormat.DATE_FIELD));
    
                  final String cc_string = "term=; db_xref=; date="+ result_buffer;
                  qualifier_text_area.append("=\"" + cc_string + "\"");
                }
    
    tjc's avatar
    tjc committed
                else 
                  qualifier_text_area.append ("=\"\"");
                break;
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
              case QualifierInfo.NO_VALUE:
              case QualifierInfo.OPTIONAL_QUOTED_TEXT:
                break;
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
              default:
    
    tjc's avatar
    tjc committed
                qualifier_text_area.append("=");
    
    tjc's avatar
    tjc committed
            }
    
    
    tjc's avatar
    tjc committed
            qualifier_text_area.append("\n");
    
    tjc's avatar
    tjc committed
          }
        });
    
    
    tjc's avatar
    tjc committed
        final JPanel middle_panel = new JPanel();
    
    tjc's avatar
    tjc committed
        middle_panel.setLayout(new BorderLayout(0,0));
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        final JPanel lower_panel = new JPanel();
    
    tjc's avatar
    tjc committed
        lower_panel.setLayout(new BorderLayout(0,0));
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        //final JPanel outer_location_button_panel = new JPanel(flowLayoutZeroHgap);
        //outer_location_button_panel.setLayout(new BorderLayout(0,0));
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        final JPanel location_button_panel = new JPanel(flowLayoutZeroHgap);
        //outer_location_button_panel.add(location_button_panel, "West");
        lower_panel.add(location_button_panel, "North");
        
        final JPanel location_panel = new JPanel(new BorderLayout(0,0));
        location_panel.add(locLabel, "West");
    
    tjc's avatar
    tjc committed
        location_panel.add(location_text, "Center");
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        final JButton complement_button = new JButton("Complement");
        location_button_panel.add(complement_button);
        complement_button.addActionListener(new ActionListener () 
        {
          public void actionPerformed(ActionEvent e) 
          {
            complementLocation();
    
    tjc's avatar
    tjc committed
          }
        });
    
    tjc's avatar
    tjc committed
        
    
    tjc's avatar
    tjc committed
        if(GeneUtils.isDatabaseEntry(entry_group))
    
    tjc's avatar
    tjc committed
        {
          final JButton refresh_button = new JButton("Refresh");
          location_button_panel.add(refresh_button);
          refresh_button.addActionListener(new ActionListener()
          {
            public void actionPerformed(ActionEvent e)
            {
              refresh();
            }
          });
        }
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        final JButton grab_button = new JButton("Grab Range");
        location_button_panel.add(grab_button);
        grab_button.addActionListener(new ActionListener()
        {
          public void actionPerformed(ActionEvent e)
          {
    
    tjc's avatar
    tjc committed
            grabSelectedRange();
    
    tjc's avatar
    tjc committed
          }
        });
    
    
    tjc's avatar
    tjc committed
        final JButton remove_button = new JButton("Remove Range");
        location_button_panel.add(remove_button);
        remove_button.addActionListener(new ActionListener() 
        {
          public void actionPerformed(ActionEvent e)
          {
            removeSelectedRange();
    
    tjc's avatar
    tjc committed
          }
        });
    
    
    tjc's avatar
    tjc committed
        final JButton goto_button = new JButton("Goto Feature");
        location_button_panel.add(goto_button);
    
    tjc's avatar
    tjc committed
        goto_button.addActionListener(new ActionListener() 
    
    tjc's avatar
    tjc committed
        {
          public void actionPerformed(ActionEvent e)
          {
            goto_event_source.gotoBase(getFeature().getFirstBaseMarker());
    
    tjc's avatar
    tjc committed
          }
        });
    
    
    tjc's avatar
    tjc committed
        final JButton select_button = new JButton("Select Feature");
        location_button_panel.add(select_button);
        select_button.addActionListener(new ActionListener()
        {
          public void actionPerformed(ActionEvent e) 
          {
            getSelection().set(getFeature());
    
    tjc's avatar
    tjc committed
          }
        });
    
    
    tjc's avatar
    tjc committed
        if(Options.getOptions().getPropertyTruthValue("sanger_options"))
    
    tjc's avatar
    tjc committed
        {
    
    tjc's avatar
    tjc committed
          // a PSU only hack 
    
    tjc's avatar
    tjc committed
          final JButton tidy_button = new JButton("Tidy");
          location_button_panel.add(tidy_button);
          tidy_button.addActionListener(new ActionListener()
          {
            public void actionPerformed(ActionEvent e) 
            {
              try 
              {
    
    tjc's avatar
    tjc committed
                tidy();
    
                tidyGO();
    
    tjc's avatar
    tjc committed
              } 
    
    tjc's avatar
    tjc committed
              catch(QualifierParseException exception) 
    
    tjc's avatar
    tjc committed
              {
                final String error_string = exception.getMessage();
    
    tjc's avatar
    tjc committed
                new MessageDialog(frame,
    
    tjc's avatar
    tjc committed
                                  "Cannot tidy - qualifier error: " +
                                  error_string);
    
    tjc's avatar
    tjc committed
              }
            }
          });
        }
    
    
        /*if(Options.getOptions().getProperty("external_editor") != null)
    
    tjc's avatar
    tjc committed
        {
          final JButton external_fasta_edit_button = new JButton("MESS/FASTA");
          location_button_panel.add(external_fasta_edit_button);
          external_fasta_edit_button.addActionListener(new ActionListener()
          {
            public void actionPerformed(ActionEvent e) 
            {
              try 
              {
                if(getFeature().getQualifierByName("fasta_file") != null) 
                {
    
    tjc's avatar
    tjc committed
                  final String DEFAULT_MAX_EUK_FASTA_HITS = "10";
                  final String max_fasta_hits;
    
                  final String max_fasta_hits_from_options =
    
    tjc's avatar
    tjc committed
                    Options.getOptions().getProperty("mess_fasta_hits");
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
                  if(Options.getOptions().isEukaryoticMode()) 
                  {
                    if (max_fasta_hits_from_options == null) 
    
    tjc's avatar
    tjc committed
                      max_fasta_hits = DEFAULT_MAX_EUK_FASTA_HITS;
    
    tjc's avatar
    tjc committed
                    else 
    
    tjc's avatar
    tjc committed
                      max_fasta_hits = max_fasta_hits_from_options;
    
    
    tjc's avatar
    tjc committed
                    externalEdit(new String[] { "-fasta", "-maxhits",
                                                max_fasta_hits, "-euk" });
    
    tjc's avatar
    tjc committed
                  } 
                  else 
                  {
                    if(max_fasta_hits_from_options == null) 
                    {
    
    tjc's avatar
    tjc committed
                      externalEdit(new String[] { "-fasta" });
    
    tjc's avatar
    tjc committed
                    } 
                    else 
                    {
    
    tjc's avatar
    tjc committed
                      externalEdit(new String[] { "-fasta", "-maxhits",
                                                  max_fasta_hits_from_options });
    
    tjc's avatar
    tjc committed
                    }
                  }
                  return;
                }
    
    tjc's avatar
    tjc committed
              } catch(InvalidRelationException _) {}
    
    tjc's avatar
    tjc committed
              
    
    tjc's avatar
    tjc committed
              new MessageDialog(frame,
    
    tjc's avatar
    tjc committed
                                "nothing to edit - no /fasta_file qualifier");
    
    tjc's avatar
    tjc committed
            }
          });
    
    
    tjc's avatar
    tjc committed
          final JButton external_blastp_edit_button = new JButton("MESS/BLASTP");
          location_button_panel.add(external_blastp_edit_button);
          external_blastp_edit_button.addActionListener(new ActionListener()
          {
            public void actionPerformed(ActionEvent e) 
            {
              try 
              {
                if(getFeature().getQualifierByName("blastp_file") != null)
                {
    
    tjc's avatar
    tjc committed
                  final String DEFAULT_MAX_BLASTP_HITS = "10";
                  final String max_blastp_hits;
    
                  final String max_blastp_hits_from_options =
    
    tjc's avatar
    tjc committed
                    Options.getOptions().getProperty("mess_blastp_hits");
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
                  if(max_blastp_hits_from_options == null) 
    
    tjc's avatar
    tjc committed
                    max_blastp_hits = DEFAULT_MAX_BLASTP_HITS;
    
    tjc's avatar
    tjc committed
                  else 
    
    tjc's avatar
    tjc committed
                    max_blastp_hits = max_blastp_hits_from_options;
    
    
    tjc's avatar
    tjc committed
                  if(Options.getOptions().isEukaryoticMode()) 
                  {
    
    tjc's avatar
    tjc committed
                    externalEdit(new String[] { "-blastp", "-maxhits",
                                                max_blastp_hits, "-euk" });
    
    tjc's avatar
    tjc committed
                  } 
                  else
                  {
    
    tjc's avatar
    tjc committed
                    externalEdit(new String[] { "-blastp", "-maxhits",
                                                max_blastp_hits });
    
    tjc's avatar
    tjc committed
                  }
                  return;
                }
    
    tjc's avatar
    tjc committed
              } catch(InvalidRelationException _) {}
              
    
    tjc's avatar
    tjc committed
              new MessageDialog(frame,
    
    tjc's avatar
    tjc committed
                                "nothing to edit - no /blastp_file qualifier");
    
    tjc's avatar
    tjc committed
            }
          });
    
    
    tjc's avatar
    tjc committed
          final JButton external_go_edit_button = new JButton("MESS/GO");
          location_button_panel.add(external_go_edit_button);
          external_go_edit_button.addActionListener(new ActionListener () 
          {
            public void actionPerformed(ActionEvent e) 
            {
              try
              {
                if(getFeature().getQualifierByName("blastp+go_file") != null) 
                {
    
    tjc's avatar
    tjc committed
                  final String DEFAULT_MAX_GO_BLAST_HITS = "10";
                  final String max_go_blast_hits;
    
                  final String max_go_blast_hits_from_options =
                    Options.getOptions ().getProperty ("mess_blast_go_hits");
    
    
    tjc's avatar
    tjc committed
                  if (max_go_blast_hits_from_options == null) 
    
    tjc's avatar
    tjc committed
                    max_go_blast_hits = DEFAULT_MAX_GO_BLAST_HITS;
    
    tjc's avatar
    tjc committed
                  else 
    
    tjc's avatar
    tjc committed
                    max_go_blast_hits = max_go_blast_hits_from_options;
    
    
    tjc's avatar
    tjc committed
                  if(Options.getOptions().isEukaryoticMode()) 
                  {
    
    tjc's avatar
    tjc committed
                    externalEdit(new String[] { "-blastp+go", "-maxhits",
                                                max_go_blast_hits, "-euk" });
    
    tjc's avatar
    tjc committed
                  } 
                  else
                  {
    
    tjc's avatar
    tjc committed
                    externalEdit(new String[] { "-blastp+go", "-maxhits",
                                                max_go_blast_hits });
    
    tjc's avatar
    tjc committed
                  }
                  return;
                }
    
    tjc's avatar
    tjc committed
              } catch(InvalidRelationException _) {}
    
    tjc's avatar
    tjc committed
              
    
    tjc's avatar
    tjc committed
              new MessageDialog(frame,
    
    tjc's avatar
    tjc committed
                                "nothing to edit - no /blastp+go_file qualifier");
    
    tjc's avatar
    tjc committed
            }
          });
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        if(Options.isUnixHost())
        {
          JButton oo_edit_button = new JButton("ObjectEdit");
          location_button_panel.add(oo_edit_button);
    
          final uk.ac.sanger.artemis.editor.BigPane bp =
    
    tjc's avatar
    tjc committed
                       new uk.ac.sanger.artemis.editor.BigPane(getEntryInformation());
    
    tjc's avatar
    tjc committed
          oo_edit_button.addActionListener(new ActionListener ()
          {
            public void actionPerformed(ActionEvent e)
            {
              String qualifier_txt = qualifier_text_area.getText();
            
    
    tjc's avatar
    tjc committed
              File base_dir = getBaseDirectoryFromEntry(edit_entry);
              String baseDirStr = "";
    
              if(base_dir != null)
                baseDirStr = base_dir.getAbsolutePath() + 
                                  System.getProperty("file.separator");
    
    
    tjc's avatar
    tjc committed
              StringReader strRead = new StringReader(qualifier_txt);
              BufferedReader buff = new BufferedReader(strRead);
              String line;
    
              final Hashtable dataFile = new Hashtable();
    
    tjc's avatar
    tjc committed
              try
              {
    
    tjc's avatar
    tjc committed
                while((line = buff.readLine()) != null)
                {
                  if(line.startsWith("/fasta_file="))
                  {
    
                    if((ind = line.indexOf(':'))>-1)
                      line = baseDirStr+line.substring(ind+1);
                    else
                      line = baseDirStr+line.substring(13);
                    
                    ind = line.lastIndexOf("\"");
    
    tjc's avatar
    tjc committed
                    if(ind > -1)
    
                      line = line.substring(0, ind);
                    
                    Vector v;
                    if(dataFile.containsKey("fasta"))
                      v = (Vector)dataFile.get("fasta");
                    else
                      v = new Vector();
                    v.add(line);
                    dataFile.put("fasta",v);
    
    tjc's avatar
    tjc committed
                  }
                  else if(line.startsWith("/blastp_file="))
                  {
    
                    if((ind = line.indexOf(':'))>-1)
                      line = baseDirStr+line.substring(ind+1);
                    else
                      line = baseDirStr+line.substring(14);
                    
                    ind = line.lastIndexOf("\"");
    
    tjc's avatar
    tjc committed
                    if(ind > -1)
    
                      line = line.substring(0, ind);
                    
                    Vector v;
                    if(dataFile.containsKey("blastp"))
                      v = (Vector)dataFile.get("blastp");
                    else
                      v = new Vector();
                    v.add(line);
                    dataFile.put("blastp",v);
    
    tjc's avatar
    tjc committed
                  }
                  else if(line.startsWith("/blastp+go_file="))
                  {
    
                    if((ind = line.indexOf(':'))>-1)
                      line = line.substring(ind+1);
                    else
                      line = baseDirStr+line.substring(17);
                    ind = line.lastIndexOf("\"");
    
    tjc's avatar
    tjc committed
                    if(ind > -1)
    
                      line = line.substring(0, ind);
                    
                    Vector v;
                    if(dataFile.containsKey("blastp+go"))
                      v = (Vector)dataFile.get("blastp+go");
                    else
                      v = new Vector();
                    v.add(line);
                    dataFile.put("blastp+go",v);
    
    tjc's avatar
    tjc committed
                  }   
                }
              }
              catch(IOException ioe){}
     
              FeatureEdit.this.setCursor(new Cursor(Cursor.WAIT_CURSOR)); 
              final ProgressThread progress = new ProgressThread(null,
                                            "Loading Data....");
              progress.start();
              SwingWorker ooEd = new SwingWorker()
              {
                public Object construct()
                {
    
    tjc's avatar
    tjc committed
                  // find overlaping features
    
    tjc's avatar
    tjc committed
                  final Location this_loc = edit_feature.getLocation();
    
    tjc's avatar
    tjc committed
                  final int this_start = this_loc.getFirstBase();
                  final int this_end   = this_loc.getLastBase();
    
                  FeaturePredicate predicate = new FeaturePredicate()
                  {
                    public boolean testPredicate (final Feature feature) 
                    {
    
    tjc's avatar
    tjc committed
                      final Location loc = feature.getLocation();
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
                      final int start = loc.getFirstBase();
                      final int end   = loc.getLastBase();
    
    tjc's avatar
    tjc committed
    
                      if((start > this_start &&
                          start < this_end) ||
                         (end > this_start &&
                          end < this_end))
                      {
    
    tjc's avatar
    tjc committed
                        final String note = feature.getNote();
    
    tjc's avatar
    tjc committed
                        if(note != null &&
                           note.indexOf("Pfam")>-1)
    
    tjc's avatar
    tjc committed
                          return true;
                      }
                      
                      return false;
                    }
                  };
    
    
    tjc's avatar
    tjc committed
                  final FeatureVector overlapFeatures = new FeatureVector();
                  final FeatureEnumeration featureEnum = entry_group.features();
    
    tjc's avatar
    tjc committed
                  while(featureEnum.hasMoreFeatures()) 
                  {
                    Feature this_feature = featureEnum.nextFeature();
                    if(predicate.testPredicate(this_feature))
                      overlapFeatures.add(this_feature);
                  }
    
                  // show object editor
    
    tjc's avatar
    tjc committed
                    if(dataFile.size() > 0)
                      bp.set(dataFile, qualifier_text_area, overlapFeatures,
    
    tjc's avatar
    tjc committed
                             edit_feature, matchForm, cvForm);
    
    tjc's avatar
    tjc committed
                    else
                      JOptionPane.showMessageDialog(null,"No results files.",
                          "Warning",
                          JOptionPane.WARNING_MESSAGE); 
    
                  }
                  catch(ArrayIndexOutOfBoundsException e)
                  {
                    JOptionPane.showMessageDialog(null,"No results files.",
                            "Warning",
                            JOptionPane.WARNING_MESSAGE);
                  }
    
    
    tjc's avatar
    tjc committed
                  progress.finished();
                  FeatureEdit.this.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
                  return null;
                }
              };
              ooEd.start();   
            }
          });
        }
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        middle_panel.add(location_panel, "North");
    
    tjc's avatar
    tjc committed
        add(key_and_qualifier_panel, "North");
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        cancel_button.addActionListener(new ActionListener()
        {
          public void actionPerformed(ActionEvent e) 
          {
    
            if(edit_feature.getEntry() != null)
              stopListening();
    
    tjc's avatar
    tjc committed
            frame.dispose();
    
    tjc's avatar
    tjc committed
          }
        });
    
    
    tjc's avatar
    tjc committed
        if(!getFeature().isReadOnly())
        {
          ok_button.addActionListener(new ActionListener()
          {
            public void actionPerformed(ActionEvent e)
            {
              if(setFeature()) 
              {
                stopListening();
    
    tjc's avatar
    tjc committed
                
                if(propertiesPanel != null)
                  propertiesPanel.updateObsoleteSettings();
                
    
    tjc's avatar
    tjc committed
                frame.dispose();
    
    tjc's avatar
    tjc committed
              }
            }
          });
    
    
    tjc's avatar
    tjc committed
          apply_button.addActionListener(new ActionListener() 
          {
            public void actionPerformed(ActionEvent e) 
            {
              setFeature();
    
    tjc's avatar
    tjc committed
            }
          });
        }
    
        final FlowLayout flow_layout =
    
    tjc's avatar
    tjc committed
                     new FlowLayout(FlowLayout.CENTER, 18, 1);
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        final JPanel ok_cancel_update_panel = new JPanel(flow_layout);
    
    tjc's avatar
    tjc committed
        Box fillerBox = Box.createHorizontalBox();
    
    tjc's avatar
    tjc committed
        if(GeneUtils.isDatabaseEntry(entry_group))
    
    tjc's avatar
    tjc committed
        {
          cvForm = new CVPanel(getFeature());
    
    tjc's avatar
    tjc committed
          cvForm.setBackground(Color.WHITE);
    
    tjc's avatar
    tjc committed
          matchForm = new MatchPanel(getFeature(), 
              (DocumentEntry)getFeature().getEmblFeature().getEntry());
    
    tjc's avatar
    tjc committed
          matchForm.setBackground(Color.WHITE);
          
    
    tjc's avatar
    tjc committed
          propertiesPanel = new PropertiesPanel(getFeature());
    
    tjc's avatar
    tjc committed
          propertiesPanel.setBackground(Color.WHITE);
    
    tjc's avatar
    tjc committed
    
          addGffAnnotationView(lower_panel);
    
    tjc's avatar
    tjc committed
          
    
    tjc's avatar
    tjc committed
          final JCheckBox tabbedView = new JCheckBox("Tabbed View", isTabbedView);
          tabbedView.addItemListener(new ItemListener()
          {
            public void itemStateChanged(ItemEvent e)
            {
              isTabbedView = tabbedView.isSelected();
              addGffAnnotationView(lower_panel);
              lower_panel.revalidate();
              lower_panel.repaint();
            }
          });
    
    tjc's avatar
    tjc committed
    
          ok_cancel_update_panel.add(tabbedView);
          fillerBox.add(Box.createHorizontalStrut( 
              tabbedView.getPreferredSize().width ));
    
    tjc's avatar
    tjc committed
        }
        else
          lower_panel.add(new JScrollPane(qualifier_text_area), "Center");
        
    
    tjc's avatar
    tjc committed
        if(!getFeature().isReadOnly()) 
          ok_cancel_update_panel.add(ok_button);
    
        ok_cancel_update_panel.add(cancel_button);
    
        if(!getFeature().isReadOnly()) 
          ok_cancel_update_panel.add(apply_button);
        ok_cancel_update_panel.add(fillerBox);
        
        add(ok_cancel_update_panel, "South");
        
    
    tjc's avatar
    tjc committed
        middle_panel.add(lower_panel, "Center");
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
        add(middle_panel, "Center");
    
    tjc's avatar
    tjc committed
      }
    
    
    tjc's avatar
    tjc committed
      /**
       * Refresh the annotation for the active feature
       */
      private void refresh()
      {
        // refresh from the database
        final DatabaseDocument originalDocument =
          (DatabaseDocument)((DocumentEntry)edit_feature.getEmblFeature().getEntry()).getDocument();
    
        final Set uniquenames = ((GFFStreamFeature)edit_feature.getEmblFeature()).getSegmentRangeStore().keySet();
        final Iterator it = uniquenames.iterator();
        final String uniquename = (String)it.next();
        final DatabaseDocument newDocument = new DatabaseDocument(originalDocument,
            uniquename, null, true, null);
        newDocument.setReadChildren(false);
        
        try
        {
          DatabaseDocumentEntry dbentry = new DatabaseDocumentEntry(newDocument, null);
          uk.ac.sanger.artemis.io.Feature databaseFeature = dbentry.getAllFeatures().featureAt(0);
          
          // compare timelastmodified
          Qualifier qualifier = edit_feature.getQualifierByName("timelastmodified");
          String active_timelastmodified = (String)qualifier.getValues().get(0);
          qualifier = databaseFeature.getQualifierByName("timelastmodified");
          String database_timelastmodified = (String)qualifier.getValues().get(0);