GPL license added
[jalview.git] / src / jalview / gui / AlignFrame.java
index 846ab24..8cb12d1 100755 (executable)
@@ -1,30 +1,40 @@
-/********************
- * 2004 Jalview Reengineered
- * Barton Group
- * Dundee University
- *
- * AM Waterhouse
- *******************/
-
-
-
+/*
+* Jalview - A Sequence Alignment Editor and Viewer
+* Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
+*
+* 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+*/
 
 package jalview.gui;
 
-import jalview.jbgui.GAlignFrame;
-import jalview.schemes.*;
-import jalview.datamodel.*;
-import jalview.analysis.*;
-import jalview.io.*;
-import jalview.ws.*;
+import java.util.*;
+
 import java.awt.*;
+import java.awt.datatransfer.*;
 import java.awt.event.*;
 import java.awt.print.*;
 import javax.swing.*;
 import javax.swing.event.*;
-import java.util.*;
-import java.awt.datatransfer.*;
 
+import jalview.analysis.*;
+import jalview.datamodel.*;
+import jalview.io.*;
+import jalview.jbgui.*;
+import jalview.schemes.*;
+import jalview.ws.*;
+import java.beans.PropertyChangeEvent;
 
 public class AlignFrame extends GAlignFrame
 {
@@ -76,11 +86,15 @@ public class AlignFrame extends GAlignFrame
     if(value == JalviewFileChooser.APPROVE_OPTION)
     {
       currentFileFormat  = chooser.getSelectedFormat();
+      jalview.bin.Cache.setProperty("DEFAULT_FILE_FORMAT", currentFileFormat);
 
       if (currentFileFormat.equals("Jalview"))
       {
-        String shortName = title.replace('/', '_');
-        title = title.replace('\\', '_');
+        String shortName = title;
+        if(shortName.indexOf(java.io.File.separatorChar)>-1)
+              shortName = shortName.substring(
+                    shortName.lastIndexOf(java.io.File.separatorChar)+1);
+
         String choice = chooser.getSelectedFile().getPath();
         Jalview2XML.SaveState(this, choice, shortName);
         // USE Jalview2XML to save this file
@@ -102,18 +116,14 @@ public class AlignFrame extends GAlignFrame
 
   protected void outputText_actionPerformed(ActionEvent e)
   {
-     CutAndPasteTransfer cap = new CutAndPasteTransfer(false);
-     JInternalFrame frame = new JInternalFrame();
-     cap.formatForOutput();
-     frame.setContentPane(cap);
-     Desktop.addInternalFrame(frame, "Alignment output - "+e.getActionCommand(), 600, 500);
+     CutAndPasteTransfer cap = new CutAndPasteTransfer();
+     Desktop.addInternalFrame(cap, "Alignment output - "+e.getActionCommand(), 600, 500);
      cap.setText( FormatAdapter.formatSequences(e.getActionCommand(), viewport.getAlignment().getSequences()));
   }
 
   protected void htmlMenuItem_actionPerformed(ActionEvent e)
   {
-    HTMLOutput htmlOutput = new HTMLOutput(viewport);
-    htmlOutput = null;
+    new HTMLOutput(viewport);
   }
 
   protected void createPNG_actionPerformed(ActionEvent e)
@@ -168,6 +178,7 @@ public class AlignFrame extends GAlignFrame
 
   Stack historyList = new Stack();
   Stack redoList = new Stack();
+  private int treeCount = 0;
 
   void updateEditMenuBar()
    {
@@ -250,13 +261,13 @@ public class AlignFrame extends GAlignFrame
             viewport.alignment.deleteSequence(i);
         }
       }
+      updateEditMenuBar();
 
-       updateEditMenuBar();
-
-       viewport.updateConsensus();
-       viewport.updateConservation();
-       alignPanel.repaint();
-   }
+      viewport.updateConsensus();
+      viewport.updateConservation();
+      alignPanel.repaint();
+      viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());
+  }
 
   public void moveSelectedSequences(boolean up)
   {
@@ -395,6 +406,7 @@ public class AlignFrame extends GAlignFrame
       }
       else
       {
+        viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());
         viewport.setEndSeq(viewport.alignment.getHeight());
         viewport.alignment.getWidth();
         viewport.updateConservation();
@@ -415,26 +427,32 @@ public class AlignFrame extends GAlignFrame
 
   protected void delete_actionPerformed(ActionEvent e)
   {
-    addHistoryItem(new HistoryItem("Delete Sequences", viewport.alignment, HistoryItem.HIDE));
+    boolean seqsdeleted=false;
 
     if (viewport.getSelectionGroup() == null)
       return;
 
+    addHistoryItem(new HistoryItem("Delete Sequences", viewport.alignment, HistoryItem.HIDE));
+
      SequenceGroup sg = viewport.getSelectionGroup();
      for (int i=0;i < sg.sequences.size(); i++)
      {
        SequenceI seq = sg.getSequenceAt(i);
        int index = viewport.getAlignment().findIndex(seq);
-       seq.deleteChars(sg.getStartRes(), sg.getEndRes()+1);
+       seq.deleteChars(sg.getStartRes(),sg.getEndRes()+1);
 
-       if(seq.getSequence().length()<1)
-          viewport.getAlignment().deleteSequence(seq);
-      else
-          viewport.getAlignment().getSequences().setElementAt(seq, index);
+       if(seq.getSequence().length()<1) {
+         seqsdeleted=true;
+         viewport.getAlignment().deleteSequence(seq);
+        } else {
+         viewport.getAlignment().getSequences().setElementAt(seq, index);
+       }
      }
 
      viewport.setSelectionGroup(null);
      viewport.alignment.deleteGroup(sg);
+     if (seqsdeleted)
+       viewport.firePropertyChange("alignment", null, viewport.getAlignment().getSequences());
      viewport.resetSeqLimits( alignPanel.seqPanel.seqCanvas.getHeight());
      if(viewport.getAlignment().getHeight()<1)
      try
@@ -443,9 +461,8 @@ public class AlignFrame extends GAlignFrame
      }catch(Exception ex){}
    viewport.updateConservation();
    viewport.updateConsensus();
-     alignPanel.repaint();
-
-  }
+   alignPanel.repaint();
+ }
 
 
   protected void deleteGroups_actionPerformed(ActionEvent e)
@@ -575,6 +592,26 @@ public class AlignFrame extends GAlignFrame
   }
 
 
+  public void padGapsMenuitem_actionPerformed(ActionEvent e)
+    {
+      addHistoryItem(new HistoryItem("Pad Gaps",
+                                     viewport.alignment,
+                                     HistoryItem.HIDE));
+      SequenceI current;
+      int Width = viewport.getAlignment().getWidth()-1;
+      for (int i=0; i < viewport.getAlignment().getSequences().size();i++)
+      {
+        current = viewport.getAlignment().getSequenceAt(i);
+
+        if (current.getLength()<Width)
+          current.insertCharAt(Width, viewport.getGapCharacter());
+      }
+      viewport.updateConservation();
+      viewport.updateConsensus();
+      alignPanel.repaint();
+  }
+
+
   public void findMenuItem_actionPerformed(ActionEvent e)
   {
     JInternalFrame frame = new JInternalFrame();
@@ -708,7 +745,6 @@ public class AlignFrame extends GAlignFrame
 
   public void clustalColour_actionPerformed(ActionEvent e)
   {
-    abovePIDThreshold.setSelected(false);
     changeColour(new ClustalxColourScheme(viewport.alignment.getSequences(), viewport.alignment.getWidth()));
   }
 
@@ -805,7 +841,7 @@ public class AlignFrame extends GAlignFrame
       ccs.setConsensus( viewport.vconsensus );
       viewport.setGlobalColourScheme(ccs);
 
-      SliderPanel.setConservationSlider(alignPanel, ccs, "Background");
+      ccs.inc = SliderPanel.setConservationSlider(alignPanel, ccs, "Background");
 
     }
     else
@@ -824,16 +860,16 @@ public class AlignFrame extends GAlignFrame
       {
         SequenceGroup sg = (SequenceGroup)groups.elementAt(i);
 
-        if (cs instanceof ClustalxColourScheme)
-        {
+        if(cs==null)
+          sg.cs = null;
+        else if (cs instanceof ClustalxColourScheme)
           sg.cs = new ClustalxColourScheme(sg.sequences, sg.getWidth());
-        }
-        else if(cs!=null)
-        {
+        else if (cs instanceof UserColourScheme)
+          sg.cs = new UserColourScheme( ((UserColourScheme)cs).getColours());
+        else
           try{
             sg.cs = (ColourSchemeI) cs.getClass().newInstance();
-          }catch(Exception ex){ex.printStackTrace();}
-        }
+          }catch(Exception ex){}
 
         if(viewport.getAbovePIDThreshold())
         {
@@ -930,7 +966,7 @@ public class AlignFrame extends GAlignFrame
 
   public void userDefinedColour_actionPerformed(ActionEvent e)
   {
-    UserDefinedColours chooser = new UserDefinedColours( alignPanel, null);
+    new UserDefinedColours( alignPanel, null);
   }
 
   public void PIDColour_actionPerformed(ActionEvent e)
@@ -963,14 +999,14 @@ public class AlignFrame extends GAlignFrame
   public void sortGroupMenuItem_actionPerformed(ActionEvent e)
   {
     addHistoryItem(new HistoryItem("Group Sort", viewport.alignment, HistoryItem.SORT));
-    AlignmentSorter.sortByGroup(viewport.getAlignment());
+  //  AlignmentSorter.sortByGroup(viewport.getAlignment());
     AlignmentSorter.sortGroups(viewport.getAlignment());
     alignPanel.repaint();
   }
 
   public void removeRedundancyMenuItem_actionPerformed(ActionEvent e)
   {
-    RedundancyPanel sp = new RedundancyPanel(alignPanel);
+    RedundancyPanel sp = new RedundancyPanel(alignPanel,this);
     JInternalFrame frame = new JInternalFrame();
     frame.setContentPane(sp);
     Desktop.addInternalFrame(frame, "Redundancy threshold selection", 400, 100, false);
@@ -979,7 +1015,8 @@ public class AlignFrame extends GAlignFrame
 
   public void pairwiseAlignmentMenuItem_actionPerformed(ActionEvent e)
   {
-    if(viewport.getSelectionGroup().getSize()<2)
+    if((viewport.getSelectionGroup()==null) ||
+       viewport.getSelectionGroup().getSize()<2)
       JOptionPane.showInternalMessageDialog(this, "You must select at least 2 sequences.", "Invalid Selection", JOptionPane.WARNING_MESSAGE);
     else
     {
@@ -1034,41 +1071,61 @@ public class AlignFrame extends GAlignFrame
 
   protected void avTreeBlosumMenuItem_actionPerformed(ActionEvent e)
   {
-    NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62PID");
+    NewTreePanel("AV", "BL", "Average distance tree using BLOSUM62");
   }
 
   void NewTreePanel(String type, String pwType, String title)
   {
-    //are the sequences aligned?
-    if(!viewport.alignment.isAligned())
-    {
-      JOptionPane.showMessageDialog(Desktop.desktop, "The sequences must be aligned before creating a tree.",
-                                    "Sequences not aligned", JOptionPane.WARNING_MESSAGE);
-      return;
-    }
-
+    String ltitle;
     final TreePanel tp;
     if (viewport.getSelectionGroup() != null &&
         viewport.getSelectionGroup().getSize() > 3)
     {
+      int s=0;
+      SequenceGroup sg = viewport.getSelectionGroup();
+
+      /* Decide if the selection is a column region */
+      while (s<sg.sequences.size()) {
+        if (((SequenceI) sg.sequences.elementAt(s++)).getLength()<sg.getEndRes()) {
+          JOptionPane.showMessageDialog(Desktop.desktop,
+                                        "The selected region to create a tree may\nonly contain residues or gaps.\n"
+                                       +"Try using the Pad function in the edit menu,\n"
+                                      +"or one of the multiple sequence alignment web services.",
+                                        "Sequences in selection are not aligned", JOptionPane.WARNING_MESSAGE);
+          return;
+        }
+
+      }
+      title=title+" on region";
       tp = new TreePanel(viewport, viewport.getSelectionGroup().sequences, type,
                          pwType,
-                         0, viewport.alignment.getWidth());
+                         sg.getStartRes(), sg.getEndRes());
     }
     else
     {
-      tp = new TreePanel(viewport, viewport.getAlignment().getSequences(),
-                         type, pwType, 0, viewport.alignment.getWidth());
-    }
+
+     //are the sequences aligned?
+     if(!viewport.alignment.isAligned())
+     {
+       JOptionPane.showMessageDialog(Desktop.desktop, "The sequences must be aligned before creating a tree.\n"
+                                     +"Try using the Pad function in the edit menu,\n"
+                                     +"or one of the multiple sequence alignment web services.",
+                                     "Sequences not aligned", JOptionPane.WARNING_MESSAGE);
+       return;
+     }
+     tp = new TreePanel(viewport, viewport.getAlignment().getSequences(),
+                        type, pwType, 0, viewport.alignment.getWidth());
+   }
 
    addTreeMenuItem(tp, title);
+   viewport.setCurrentTree(tp.getTree());
 
-   Desktop.addInternalFrame(tp, title, 600, 500);
+   Desktop.addInternalFrame(tp, title+" from "+this.title, 600, 500);
   }
 
   public void addSortByOrderMenuItem(String title, final AlignmentOrder order) {
-    final JMenuItem item = new JMenuItem(title);
-    sortByTreeMenu.add(item);
+    final JMenuItem item = new JMenuItem("by "+title);
+    sort.add(item);
     item.addActionListener(new java.awt.event.ActionListener()
     {
       public void actionPerformed(ActionEvent e)
@@ -1085,6 +1142,12 @@ public class AlignFrame extends GAlignFrame
   void addTreeMenuItem(final TreePanel treePanel, String title)
   {
     final JMenuItem item = new JMenuItem(title);
+
+    treeCount++;
+
+    if (treeCount==1)
+      sort.add(sortByTreeMenu);
+
     sortByTreeMenu.add(item);
     item.addActionListener(new java.awt.event.ActionListener()
     {
@@ -1101,10 +1164,23 @@ public class AlignFrame extends GAlignFrame
     {
       public void internalFrameClosed(javax.swing.event.InternalFrameEvent evt)
       {
+        treeCount--;
         sortByTreeMenu.remove(item);
+        if (treeCount==0)
+          sort.remove(sortByTreeMenu);
       };
     });
+    viewport.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
+      public void propertyChange(PropertyChangeEvent evt)
+      {
+        if (evt.getPropertyName().equals("alignment")) {
+          treePanel.getTree().UpdatePlaceHolders( (Vector) evt.getNewValue());
+          treePanel.repaint();
+        }
+      }
 
+    }
+    );
   }
 
 
@@ -1140,12 +1216,50 @@ public class AlignFrame extends GAlignFrame
 
         }
         if (msa!=null) {
+          jalview.ws.MsaWSClient ct = new jalview.ws.MsaWSClient("ClustalWS", title, msa, false, true);
+        }
+  }
+  public void ClustalRealign_actionPerformed(ActionEvent e)
+  {
+      // TODO:resolve which menu item was actually selected
+      // Now, check we have enough sequences
+        SequenceI[] msa=null;
+        if (viewport.getSelectionGroup() != null && viewport.getSelectionGroup().getSize()>1)
+        {
+          // JBPNote UGLY! To prettify, make SequenceGroup and Alignment conform to some common interface!
+          SequenceGroup seqs = viewport.getSelectionGroup();
+          int sz;
+          msa = new SequenceI[sz=seqs.getSize()];
+          for (int i = 0; i < sz; i++)
+          {
+            msa[i] = (SequenceI) seqs.getSequenceAt(i);
+          }
+
+          }
+        else
+        {
+          Vector seqs = viewport.getAlignment().getSequences();
+
+          if (seqs.size() > 1) {
+            msa = new SequenceI[seqs.size()];
+            for (int i = 0; i < seqs.size(); i++)
+            {
+              msa[i] = (SequenceI) seqs.elementAt(i);
+            }
+
+          }
+
+        }
+        if (msa!=null) {
           jalview.ws.MsaWSClient ct = new jalview.ws.MsaWSClient("ClustalWS", title, msa, true, true);
         }
   }
 
+
   protected void jpred_actionPerformed(ActionEvent e)
 {
+    SequenceI seq=null;
+    SequenceI[] msa=null;
 
     if (viewport.getSelectionGroup() != null && viewport.getSelectionGroup().getSize()>0)
     {
@@ -1153,20 +1267,17 @@ public class AlignFrame extends GAlignFrame
       SequenceGroup seqs = viewport.getSelectionGroup();
       if (seqs.getSize() == 1 || !viewport.alignment.isAligned())
       {
-        JPredClient ct = new JPredClient( (SequenceI)seqs.getSequenceAt(0));
+        seq = (SequenceI)seqs.getSequenceAt(0);
       }
       else
       {
         int sz;
-        SequenceI[] msa = new SequenceI[sz=seqs.getSize()];
+        msa = new SequenceI[sz=seqs.getSize()];
         for (int i = 0; i < sz; i++)
         {
           msa[i] = (SequenceI) seqs.getSequenceAt(i);
         }
-
-        JPredClient ct = new JPredClient(msa);
       }
-
     }
     else
     {
@@ -1174,20 +1285,24 @@ public class AlignFrame extends GAlignFrame
 
       if (seqs.size() == 1 || !viewport.alignment.isAligned())
       {
-        JPredClient ct = new JPredClient( (SequenceI)
-                                         seqs.elementAt(0));
+        seq = (SequenceI) seqs.elementAt(0);
       }
       else
       {
-        SequenceI[] msa = new SequenceI[seqs.size()];
+        msa = new SequenceI[seqs.size()];
         for (int i = 0; i < seqs.size(); i++)
         {
           msa[i] = (SequenceI) seqs.elementAt(i);
         }
-
-        JPredClient ct = new JPredClient(msa);
       }
-
+    }
+    if (msa!=null) {
+      JPredClient ct = new JPredClient(title, msa);
+    } else
+    if (seq!=null) {
+      JPredClient ct = new JPredClient(title, seq);
+    } else {
+      System.err.print("JALVIEW ERROR! - Unexpected JPred selection state!\n");
     }
   }
   protected void msaAlignMenuItem_actionPerformed(ActionEvent e)
@@ -1223,7 +1338,7 @@ public class AlignFrame extends GAlignFrame
 
       }
       if (msa!=null) {
-        MsaWSClient ct = new jalview.ws.MsaWSClient("MuscleWS",title, msa, true, true);
+        MsaWSClient ct = new jalview.ws.MsaWSClient("MuscleWS",title, msa, false, true);
       }
   }
     protected void LoadtreeMenuItem_actionPerformed(ActionEvent e) {
@@ -1270,5 +1385,4 @@ public class AlignFrame extends GAlignFrame
      }catch(Exception ex){ex.printStackTrace();}
   }
 
-
 }