Skip to content
Snippets Groups Projects
GeneBuilderFrame.java 21.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • tjc's avatar
    tjc committed
    /* GeneBuilderFrame.java
     *
     * created: 2006
     *
     * This file is part of Artemis
     *
     * Copyright(C) 2006  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.
     *
    
    tjc's avatar
    tjc committed
     * $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/genebuilder/GeneBuilderFrame.java,v 1.45 2009-03-19 11:05:27 tjc Exp $
    
    tjc's avatar
    tjc committed
     */
    
    package uk.ac.sanger.artemis.components.genebuilder;
    
    
    tjc's avatar
    tjc committed
    
    import javax.swing.BorderFactory;
    import javax.swing.Box;
    import javax.swing.JCheckBox;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JMenu;
    import javax.swing.JMenuBar;
    import javax.swing.JMenuItem;
    import javax.swing.JOptionPane;
    import javax.swing.JScrollPane;
    import javax.swing.JSplitPane;
    import javax.swing.JTabbedPane;
    
    tjc's avatar
    tjc committed
    import javax.swing.border.Border;
    
    tjc's avatar
    tjc committed
    
    
    tjc's avatar
    tjc committed
    import java.awt.Color;
    import java.awt.Component;
    
    import java.awt.Cursor;
    
    tjc's avatar
    tjc committed
    import java.awt.Dimension;
    import java.awt.FontMetrics;
    
    tjc's avatar
    tjc committed
    import java.awt.Toolkit;
    
    tjc's avatar
    tjc committed
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.ItemEvent;
    
    tjc's avatar
    tjc committed
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    
    tjc's avatar
    tjc committed
    import java.awt.event.ItemListener;
    import java.util.List;
    
    import java.util.Hashtable;
    
    tjc's avatar
    tjc committed
    
    import uk.ac.sanger.artemis.Entry;
    import uk.ac.sanger.artemis.EntryChangeEvent;
    import uk.ac.sanger.artemis.EntryChangeListener;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.Options;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.SelectionChangeEvent;
    import uk.ac.sanger.artemis.SelectionChangeListener;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.EntryGroup;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.Feature;
    
    import uk.ac.sanger.artemis.io.Qualifier;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.FeatureChangeEvent;
    import uk.ac.sanger.artemis.FeatureChangeListener;
    import uk.ac.sanger.artemis.GotoEventSource;
    import uk.ac.sanger.artemis.Selection;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.chado.ChadoTransactionManager;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.components.FeatureEdit;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.components.Utilities;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.GFFStreamFeature;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.ChadoCanonicalGene;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.io.InvalidRelationException;
    import uk.ac.sanger.artemis.io.QualifierVector;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.util.DatabaseDocument;
    
    tjc's avatar
    tjc committed
    import uk.ac.sanger.artemis.FeatureVector;
    
    tjc's avatar
    tjc committed
    
    public class GeneBuilderFrame extends JFrame
    
    tjc's avatar
    tjc committed
           implements EntryChangeListener, FeatureChangeListener
    
    tjc's avatar
    tjc committed
    {
      
    
    tjc's avatar
    tjc committed
      /** */
      private static final long serialVersionUID = 1L;
    
    tjc's avatar
    tjc committed
      private Feature active_feature; 
      private FeatureEdit feature_editor;
    
    tjc's avatar
    tjc committed
      private GeneViewerPanel viewer;
      private GeneComponentTree tree;
    
      private Box yBox;
      private Hashtable transcriptBoxes = new Hashtable();
      private Component glue = Box.createVerticalGlue();
      private Selection selection;
      private ChadoCanonicalGene chado_gene;
    
    tjc's avatar
    tjc committed
      private JLabel status_line = new JLabel("");
    
      private GeneBuilderSelectionChangeListener geneBuilderSelectionChangeListener;
    
    tjc's avatar
    tjc committed
      private JTabbedPane tabpane;
    
    tjc's avatar
    tjc committed
      private ChadoTransactionManager chadoTransactionManager;
    
      private EntryGroup entry_group;
      private GotoEventSource goto_event_source;
    
      private Hashtable geneBuilderHash;
    
    tjc's avatar
    tjc committed
      
    
      public GeneBuilderFrame(Feature feature,
    
    tjc's avatar
    tjc committed
                              final EntryGroup entry_group,
    
    tjc's avatar
    tjc committed
                              final Selection selection,
    
    tjc's avatar
    tjc committed
                              final GotoEventSource goto_event_source)
    
    tjc's avatar
    tjc committed
      {
        this(feature, entry_group, selection, goto_event_source, null);
      }
      
    
      public GeneBuilderFrame(Feature feature,
    
    tjc's avatar
    tjc committed
          final EntryGroup entry_group,
          final Selection selection,
          final GotoEventSource goto_event_source,
          final ChadoTransactionManager chadoTransactionManager)
    
    tjc's avatar
    tjc committed
      {
    
    tjc's avatar
    tjc committed
        
    
        this.entry_group = entry_group;
        this.goto_event_source = goto_event_source;
        
    
        // set title
        final String title = "Artemis Gene Builder: " + 
              ((Feature)((GFFStreamFeature)feature.getEmblFeature()).getChadoGene().getGene().getUserData()).getIDString() +
               (feature.isReadOnly() ?
              "  -  (read only)" : "");
    
    tjc's avatar
    tjc committed
    
    
        setTitle(title);
        
        this.selection = selection;
        if(feature.getKey().getKeyString().equals(DatabaseDocument.EXONMODEL))
        {
          Feature proteinFeature = getProteinFeature(feature, selection);
          if(proteinFeature != null)
            feature = proteinFeature;
        }
    
        this.active_feature = feature;
        this.chadoTransactionManager = chadoTransactionManager;
     
    
        if(selection != null)
    
        {
          geneBuilderSelectionChangeListener = new GeneBuilderSelectionChangeListener();
          selection.addSelectionChangeListener(geneBuilderSelectionChangeListener);
        }
    
    tjc's avatar
    tjc committed
        
    
    tjc's avatar
    tjc committed
        final GFFStreamFeature gff_feature = (GFFStreamFeature)feature.getEmblFeature();
    
        chado_gene = gff_feature.getChadoGene();
    
    tjc's avatar
    tjc committed
        
        try
        {
          addListeners(chado_gene);
        }
        catch(InvalidRelationException e)
        {
          e.printStackTrace();
        }
        
    
    tjc's avatar
    tjc committed
        tree = new GeneComponentTree(chado_gene, this, selection);
    
        final JScrollPane jsp_tree = new JScrollPane(tree);
    
    tjc's avatar
    tjc committed
        jsp_tree.setPreferredSize( new Dimension(150, jsp_tree.getPreferredSize().height) );
    
    tjc's avatar
    tjc committed
        
    
    tjc's avatar
    tjc committed
        viewer = new GeneViewerPanel(
    
    tjc's avatar
    tjc committed
                    gff_feature.getChadoGene(), selection, 
                    entry_group, this, status_line);
    
    tjc's avatar
    tjc committed
    
        Box xBox = Box.createHorizontalBox();
    
        xBox.add(buildCheckBoxes(viewer, chado_gene));
    
    tjc's avatar
    tjc committed
        xBox.add(viewer);
        
    
    tjc's avatar
    tjc committed
        final JTabbedPane tabMapViewer = new JTabbedPane();
        
        final JScrollPane jsp_viewer = new JScrollPane(xBox);
    
    tjc's avatar
    tjc committed
        jsp_viewer.getViewport().setBackground(Color.white);
    
    tjc's avatar
    tjc committed
        jsp_viewer.setPreferredSize( viewer.getPreferredSize() );
    
    tjc's avatar
    tjc committed
        tabMapViewer.addTab("Gene Map", jsp_viewer);
        
        //
        // protein map
    
        List proteins = ProteinMapPanel.getProteinsWithProteinMapElement(gff_feature);
        if(proteins != null)
    
    tjc's avatar
    tjc committed
        {
          final ProteinMapPanel proteinMap = 
    
            new ProteinMapPanel((GFFStreamFeature) proteins.get(0), 
    
    tjc's avatar
    tjc committed
                                gff_feature.getChadoGene(), selection);
          
          final JScrollPane jsp_ppviewer = new JScrollPane(proteinMap);
          jsp_ppviewer.getViewport().setBackground(Color.white);
          jsp_ppviewer.setPreferredSize( proteinMap.getPreferredSize() );
          tabMapViewer.addTab("Protein Map", jsp_ppviewer);
        }
    
    tjc's avatar
    tjc committed
        
    
    tjc's avatar
    tjc committed
        ///
        status_line.setFont(Options.getOptions().getFont());
        final FontMetrics fm =
          this.getFontMetrics(status_line.getFont());
    
        final int font_height = fm.getHeight()+10;
    
        status_line.setMinimumSize(new Dimension(100, font_height));
        status_line.setPreferredSize(new Dimension(100, font_height));
    
        Border loweredbevel = BorderFactory.createLoweredBevelBorder();
        Border raisedbevel = BorderFactory.createRaisedBevelBorder();
        Border compound = BorderFactory.createCompoundBorder(raisedbevel,loweredbevel);
        status_line.setBorder(compound);
        jsp_viewer.setColumnHeaderView(status_line);
        ///
        
    
    tjc's avatar
    tjc committed
        JSplitPane top = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, jsp_tree, tabMapViewer);
    
    tjc's avatar
    tjc committed
        JSplitPane all = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
        all.setTopComponent(top);
        
    
    tjc's avatar
    tjc committed
        feature_editor = new FeatureEdit(feature, entry_group,
    
    tjc's avatar
    tjc committed
                            selection, goto_event_source, this);
    
    tjc's avatar
    tjc committed
        tabpane = new JTabbedPane();
    
    tjc's avatar
    tjc committed
        tabpane.addTab("Annotation", feature_editor);
    
    tjc's avatar
    tjc committed
        setTabTitle();
    
    tjc's avatar
    tjc committed
        all.setBottomComponent(tabpane);
        
    
    tjc's avatar
    tjc committed
        getContentPane().add(all);
    
    tjc's avatar
    tjc committed
        
        addWindowListener(new WindowAdapter() 
        {
          public void windowClosing(WindowEvent event) 
          {
            dispose();
          }
        });
    
    tjc's avatar
    tjc committed
        
    
    tjc's avatar
    tjc committed
        // add menus
        JMenuBar menuBar = new JMenuBar();
        
    
        JMenu fileMenu = new JMenu("File");
        menuBar.add(fileMenu);
        JMenuItem close = new JMenuItem("Close");
        close.addActionListener(new ActionListener()
        {
          public void actionPerformed(ActionEvent event)  
          {
            dispose();
          }
        });
        fileMenu.add(close);
        
    
    tjc's avatar
    tjc committed
        JMenu editMenu = new JMenu("Edit");
        menuBar.add(editMenu);
    
        viewer.createMenus(editMenu, entry_group);
    
    tjc's avatar
    tjc committed
        setJMenuBar(menuBar);
        
    
    tjc's avatar
    tjc committed
        pack();
    
    tjc's avatar
    tjc committed
        
    
    tjc's avatar
    tjc committed
        final Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
    
        int height = getPreferredSize().height;
        if(height > (screen.height*0.9))
    
    tjc's avatar
    tjc committed
        {    
          setSize(getPreferredSize().width, (int)(screen.height*0.9));
    
    tjc's avatar
    tjc committed
        Utilities.centreFrame(this);
    
    tjc's avatar
    tjc committed
        setVisible(true);
    
    tjc's avatar
    tjc committed
        all.setDividerLocation(0.30);
    
    tjc's avatar
    tjc committed
      }
    
    tjc's avatar
    tjc committed
      
    
      
      private Feature getProteinFeature(final Feature feature, final Selection selection)
      {
        Feature proteinFeature = null;
        try
        {
          Qualifier idQualifier = feature.getQualifierByName("ID");
          if(idQualifier != null)
          {
            final ChadoCanonicalGene chadoGene = ((GFFStreamFeature)feature.getEmblFeature()).getChadoGene();
            final String ID = (String)idQualifier.getValues().get(0);
            final String transcriptName = chadoGene.getTranscriptFromName(ID);
            proteinFeature = (Feature)chadoGene.getProteinOfTranscript(transcriptName).getUserData();
            selection.clear();
            selection.add(proteinFeature);
          }
        }
        catch(Exception e){}
        return proteinFeature;
      }
      
    
      public void dispose()
      {
        dispose(false);
      }
      
    
      /**
       * Override to ensure the GeneBuilderFrame removes all listeners
       */
    
      public void dispose(final boolean reopen)
    
      {
        try
        {
          stopListeningAll();
        }
        catch(InvalidRelationException e)
        {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
    
    tjc's avatar
    tjc committed
        
    
    tjc's avatar
    tjc committed
        if(chadoTransactionManager != null &&
           chadoTransactionManager.hasTransactions())
    
    tjc's avatar
    tjc committed
        { 
          int select = JOptionPane.showConfirmDialog(this, 
              "Commit changes back to the database?", 
              "Commit", JOptionPane.YES_NO_OPTION);
          
          if(select == JOptionPane.YES_OPTION)
          {
            DatabaseDocument dbDoc =
              (DatabaseDocument)(
                (GFFStreamFeature)active_feature.getEmblFeature()).getDocumentEntry().getDocument();
    
            ChadoTransactionManager.commit(dbDoc, false,chadoTransactionManager);
    
    tjc's avatar
    tjc committed
          }
        }
        
    
        if(geneBuilderHash != null)
        {
          geneBuilderHash.remove(chado_gene.getGeneUniqueName());
        }
        
    
        if(reopen)
    
        {
          final GeneBuilderFrame gbFrame =
            new GeneBuilderFrame(active_feature, entry_group, 
                                 selection, goto_event_source, 
                                 chadoTransactionManager);
          if(geneBuilderHash != null)
          {
            gbFrame.addGeneBuilderHash(geneBuilderHash);
            geneBuilderHash.put(chado_gene.getGeneUniqueName(), gbFrame);
          }
        }
    
        else if(!GeneUtils.isBoundaryOK(chado_gene))
        {
          int result = JOptionPane.showConfirmDialog(this, 
              "Gene model boundary needs fixing.\nFix this now?", 
              "Gene Boundary", JOptionPane.YES_NO_OPTION);
          if(result == JOptionPane.YES_OPTION)
            GeneUtils.checkGeneBoundary(chado_gene);
        }
    
      /**
       * Add the hash from EditMenu. This records what gene builders are
       * open.
       * @param geneBuilderFocusHash
       */
      public void addGeneBuilderHash(final Hashtable geneBuilderHash)
      {
        this.geneBuilderHash = geneBuilderHash;
      }
      
    
    tjc's avatar
    tjc committed
      /**
       * Create a Box component with the checkboxes used to determine if
       * a transcripts exons are visible in artemis.
       * @param viewer
       * @param chado_gene
       * @return
       */
      private Box buildCheckBoxes(final GeneViewerPanel viewer,
    
                                  final ChadoCanonicalGene chado_gene)
    
    tjc's avatar
    tjc committed
      {
    
        yBox = Box.createVerticalBox();
    
    tjc's avatar
    tjc committed
        yBox.add(Box.createVerticalStrut(viewer.getViewerBorder()*3));
        
        java.util.List transcripts = chado_gene.getTranscripts();
        
        for(int i=0; i<transcripts.size(); i++)
        {
          final GFFStreamFeature transcript = 
            (GFFStreamFeature)((uk.ac.sanger.artemis.io.Feature)transcripts.get(i));
    
          final String transcript_name =
            (String)transcript.getQualifierByName("ID").getValues().get(0);
    
    tjc's avatar
    tjc committed
          
    
          Box transcriptBox =  createTranscriptBox(transcript, transcript_name);
          yBox.add(transcriptBox);
        }
        yBox.add(glue);
        return yBox;
      }
      
    
    tjc's avatar
    tjc committed
      /**
       * Create a Box containing the checkbox for a transcript
       * @param transcript
       * @param transcript_name
       * @return
       */
    
      private Box createTranscriptBox(final GFFStreamFeature transcript,
                                      final String transcript_name)
      {
    
    tjc's avatar
    tjc committed
        final JCheckBox cb = new JCheckBox();
    
        List exons = chado_gene.getSpliceSitesOfTranscript(transcript_name, 
            DatabaseDocument.EXONMODEL);
        if(exons != null && exons.size() > 0)
          cb.setSelected(((GFFStreamFeature)exons.get(0)).isVisible());
        else
          cb.setSelected(transcript.isVisible());
        
    
    tjc's avatar
    tjc committed
        cb.setOpaque(false);
    
        cb.addItemListener(new ItemListener()
        {
          public void itemStateChanged(ItemEvent e)
    
    tjc's avatar
    tjc committed
          { 
            final List exons = chado_gene.getSpliceSitesOfTranscript(transcript_name, 
                DatabaseDocument.EXONMODEL);
    
            if(exons == null)
              return;
            
            boolean visible = true;
            if(e.getStateChange() == ItemEvent.DESELECTED)
              visible = false;        
            
            for(int j=0; j<exons.size(); j++)
    
    tjc's avatar
    tjc committed
            {
    
              GFFStreamFeature embl_exon = (GFFStreamFeature)exons.get(j);
              embl_exon.setVisible(visible);
    
    tjc's avatar
    tjc committed
            }
    
            
            FeatureVector fv = selection.getAllFeatures();
            selection.clear();
            selection.set(fv);
          }
        });
        
        Box transcriptBox = Box.createVerticalBox();
    
        transcriptBox.add(cb);
        transcriptBox.add(Box.createVerticalStrut(
            viewer.getTranscriptSize() - cb.getPreferredSize().height)); 
        transcriptBoxes.put(transcript_name, transcriptBox);
        return transcriptBox;
    
    tjc's avatar
    tjc committed
      }
      
    
    tjc's avatar
    tjc committed
      protected void setActiveFeature(final Feature active_feature,
                                      final boolean isSet)
    
    tjc's avatar
    tjc committed
      {  
    
        setCursor(new Cursor(Cursor.WAIT_CURSOR));
    
    tjc's avatar
    tjc committed
        this.active_feature = active_feature;
    
    tjc's avatar
    tjc committed
        feature_editor.setActiveFeature(active_feature, isSet);
    
    tjc's avatar
    tjc committed
        setTabTitle();
    
        setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
    
    tjc's avatar
    tjc committed
      }
      
      private void setTabTitle()
      {
        try
        {
          tabpane.setTitleAt(0, "Annotation :: "+
              (String)active_feature.getQualifierByName("ID").getValues().get(0));
        }
        catch(InvalidRelationException e){}
    
    tjc's avatar
    tjc committed
      }
    
    tjc's avatar
    tjc committed
    
      /**
    
    tjc's avatar
    tjc committed
       *  Remove this object as a feature and entry change listener.
    
    tjc's avatar
    tjc committed
       **/
    
      private void stopListening(final Feature feature) 
    
    tjc's avatar
    tjc committed
      {
    
    tjc's avatar
    tjc committed
        if(getEntry() != null)
          getEntry().removeEntryChangeListener(this);
    
        feature.removeFeatureChangeListener(this);
    
        
        if(selection != null && geneBuilderSelectionChangeListener != null)
          selection.removeSelectionChangeListener(geneBuilderSelectionChangeListener);
    
      }
      
      private void startListening(final Feature feature) 
      {
    
    tjc's avatar
    tjc committed
        if(getEntry() != null)
          getEntry().addEntryChangeListener(this);
    
        feature.addFeatureChangeListener(this);
    
        
        if(selection != null)
        {
          geneBuilderSelectionChangeListener = new GeneBuilderSelectionChangeListener();
          selection.addSelectionChangeListener(geneBuilderSelectionChangeListener);
        }
    
    tjc's avatar
    tjc committed
      }
    
    tjc's avatar
    tjc committed
    
    
    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.
       **/
      public void entryChanged(EntryChangeEvent event) 
      {
    
        Feature feature = event.getFeature();
        stopListening(feature);
        
        QualifierVector qualifiers = feature.getQualifiers();
        String name = (String)qualifiers.getQualifierByName("ID").getValues().get(0);
    
    tjc's avatar
    tjc committed
        switch(event.getType())
    
    tjc's avatar
    tjc committed
        {
    
    tjc's avatar
    tjc committed
          case EntryChangeEvent.FEATURE_DELETED:
    
            feature.removeFeatureChangeListener(this);
            tree.deleteNode( name );
            
            if(chado_gene.isTranscript(name))
            {
              Box transBox = (Box)transcriptBoxes.get(name);
              yBox.remove(transBox);
              yBox.revalidate();
            }
    
    tjc's avatar
    tjc committed
            break;
    
          case EntryChangeEvent.FEATURE_ADDED:
    
            Qualifier parent_qualifier = 
              qualifiers.getQualifierByName("Parent");
            
    
    tjc's avatar
    tjc committed
            Qualifier derives_from_qualifier = 
              qualifiers.getQualifierByName("Derives_from");
            
            if(parent_qualifier == null && derives_from_qualifier == null)
    
    tjc's avatar
    tjc committed
    
    
            tree.addNode(event.getFeature());
            feature.addFeatureChangeListener(this);
            
    
    tjc's avatar
    tjc committed
            // if polypeptide added then we are done
            if(derives_from_qualifier != null)
              return;
               
            final String parent = (String)parent_qualifier.getValues().get(0);
    
    
            String gene_name = null;
            try
            {
    
              gene_name = 
                (String)chado_gene.getGene().getQualifierByName("ID").getValues().get(0);
    
            }
            catch(InvalidRelationException e)
            {
              // TODO Auto-generated catch block
              e.printStackTrace();
            }
            
            if(parent.equals(gene_name) &&
               !transcriptBoxes.containsKey(name))
            {
              Box transcriptBox = createTranscriptBox(
                       (GFFStreamFeature)feature.getEmblFeature(), name);
              yBox.remove(glue);
              yBox.add(transcriptBox);
              yBox.add(glue);
              yBox.revalidate();
            }
    
    tjc's avatar
    tjc committed
          default:
            // do nothing;
            break;
    
    tjc's avatar
    tjc committed
        }
    
        
        startListening(feature);
    
    tjc's avatar
    tjc committed
      }
      
      /**
    
    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
       **/
    
    tjc's avatar
    tjc committed
      public void featureChanged(FeatureChangeEvent event) 
    
    tjc's avatar
    tjc committed
      {
    
    tjc's avatar
    tjc committed
        Feature feature = event.getFeature();
        stopListening(feature);
    
    tjc's avatar
    tjc committed
        active_feature.resetColour();
    
    tjc's avatar
    tjc committed
        
    
    tjc's avatar
    tjc committed
        // re-read the information from the feature
        switch(event.getType()) 
        {
          case FeatureChangeEvent.LOCATION_CHANGED:
            break;
          case FeatureChangeEvent.KEY_CHANGED:
            break;
          case FeatureChangeEvent.QUALIFIER_CHANGED:
            break;
    
    tjc's avatar
    tjc committed
          case FeatureChangeEvent.SEGMENT_CHANGED:
            QualifierVector old_qualifiers = event.getOldQualifiers();
            QualifierVector new_qualifiers = feature.getQualifiers();
            tree.changeNode( 
                (String)old_qualifiers.getQualifierByName("ID").getValues().get(0),
                (String)new_qualifiers.getQualifierByName("ID").getValues().get(0));
    
    tjc's avatar
    tjc committed
          default:
            break;
        }
    
    tjc's avatar
    tjc committed
        viewer.repaint();
    
    tjc's avatar
    tjc committed
        startListening(feature);
    
    tjc's avatar
    tjc committed
      }
      
    
    tjc's avatar
    tjc committed
      protected FeatureEdit getFeatureEdit()
      {
        return feature_editor;
      }
    
    tjc's avatar
    tjc committed
      
      private Entry getEntry()
      {
        return active_feature.getEntry();
      }
      
    
    tjc's avatar
    tjc committed
      /**
       * Add feature listeners for each artemis feature.
       * @throws InvalidRelationException
       */
      private void addListeners(final ChadoCanonicalGene chado_gene) 
                   throws InvalidRelationException
      {
        // add feature listeners
        uk.ac.sanger.artemis.io.Feature embl_gene = 
          (uk.ac.sanger.artemis.io.Feature)chado_gene.getGene();
    
    tjc's avatar
    tjc committed
        Feature gene = (Feature)embl_gene.getUserData();   
    
    tjc's avatar
    tjc committed
        gene.addFeatureChangeListener(this);
    
    tjc's avatar
    tjc committed
        
        if(gene.getEntry() != null)
          gene.getEntry().addEntryChangeListener(this);
    
    tjc's avatar
    tjc committed
        
        List transcripts = chado_gene.getTranscripts();
        for(int i=0; i<transcripts.size(); i++)
        {
          uk.ac.sanger.artemis.io.Feature transcript =
             (uk.ac.sanger.artemis.io.Feature)transcripts.get(i);
          Feature trans = (Feature)transcript.getUserData();
           
           if(trans == null)
             trans = new Feature(transcript);
           
           trans.addFeatureChangeListener(this);
    
    tjc's avatar
    tjc committed
           
           if(trans.getEntry() != null)
             trans.getEntry().addEntryChangeListener(this);
    
    tjc's avatar
    tjc committed
           
    
    tjc's avatar
    tjc committed
           List exons = chado_gene.getSpliceSitesOfTranscript(
    
               (String)trans.getQualifierByName("ID").getValues().get(0), 
               DatabaseDocument.EXONMODEL);
    
    tjc's avatar
    tjc committed
           
    
    tjc's avatar
    tjc committed
           if(exons == null || exons.size() < 1)
    
    tjc's avatar
    tjc committed
             continue;
           
    
           if(exons.get(0) instanceof org.gmod.schema.sequence.Feature)
    
    tjc's avatar
    tjc committed
             return;
           
           for(int j=0; j<exons.size(); j++)
           {
             uk.ac.sanger.artemis.io.Feature embl_exon = 
                (uk.ac.sanger.artemis.io.Feature)exons.get(j);
    
             Feature exon = (Feature)embl_exon.getUserData();
             
             if(exon == null)
               exon = new Feature(embl_exon);
             exon.addFeatureChangeListener(this);
    
    tjc's avatar
    tjc committed
             
             if(exon.getEntry() != null)
               exon.getEntry().addEntryChangeListener(this);
    
    tjc's avatar
    tjc committed
           }
        }
      }
    
    tjc's avatar
    tjc committed
      
    
    tjc's avatar
    tjc committed
      private void stopListeningAll() throws InvalidRelationException
      {
        uk.ac.sanger.artemis.io.Feature embl_gene = 
          (uk.ac.sanger.artemis.io.Feature)chado_gene.getGene();
        Feature gene = (Feature)embl_gene.getUserData();   
        stopListening(gene);
        
        List transcripts = chado_gene.getTranscripts();
        for(int i=0; i<transcripts.size(); i++)
        {
          uk.ac.sanger.artemis.io.Feature transcript =
             (uk.ac.sanger.artemis.io.Feature)transcripts.get(i);
          Feature trans = (Feature)transcript.getUserData();
           
          stopListening(trans);
          
    
    tjc's avatar
    tjc committed
          List exons = chado_gene.getSpliceSitesOfTranscript(
    
              (String)trans.getQualifierByName("ID").getValues().get(0), 
              DatabaseDocument.EXONMODEL);
    
    tjc's avatar
    tjc committed
          
          if(exons == null)
            continue;
          
          for(int j=0; j<exons.size(); j++)
          {
            uk.ac.sanger.artemis.io.Feature embl_exon = 
               (uk.ac.sanger.artemis.io.Feature)exons.get(j);
    
            Feature exon = (Feature)embl_exon.getUserData();
            stopListening(exon);      
          }
        }
      }
    
    
      class GeneBuilderSelectionChangeListener implements SelectionChangeListener
      {
        public void selectionChanged(SelectionChangeEvent event)
        {
          viewer.repaint();
          tree.setSelection(GeneBuilderFrame.this.selection);
    
    tjc's avatar
    tjc committed
    }