Merge develop to Release_2_8_3_Branch
[jalview.git] / src / jalview / controller / AlignViewController.java
index 74161c8..972b6ab 100644 (file)
@@ -1,6 +1,6 @@
 /*
- * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
- * Copyright (C) 2014 The Jalview Authors
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
  * 
  * This file is part of Jalview.
  * 
  */
 package jalview.controller;
 
-import java.awt.Color;
-import java.util.BitSet;
-import java.util.List;
-
+import jalview.analysis.AlignmentSorter;
 import jalview.api.AlignViewControllerGuiI;
 import jalview.api.AlignViewControllerI;
 import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
+import jalview.api.FeatureRenderer;
+import jalview.commands.OrderCommand;
 import jalview.datamodel.AlignmentI;
-import jalview.datamodel.AnnotatedCollectionI;
 import jalview.datamodel.ColumnSelection;
 import jalview.datamodel.SequenceCollectionI;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
+import jalview.util.MessageManager;
+
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.List;
 
 public class AlignViewController implements AlignViewControllerI
 {
-  AlignViewportI viewport=null;
-  AlignmentViewPanel alignPanel=null;
+  AlignViewportI viewport = null;
+
+  AlignmentViewPanel alignPanel = null;
+
   /**
    * the GUI container that is handling interactions with the user
    */
   private AlignViewControllerGuiI avcg;
+
   @Override
-  protected void finalize() throws Throwable {
+  protected void finalize() throws Throwable
+  {
     viewport = null;
     alignPanel = null;
     avcg = null;
   };
-  
-  public AlignViewController(AlignViewControllerGuiI alignFrame, AlignViewportI viewport,
-          AlignmentViewPanel alignPanel)
+
+  public AlignViewController(AlignViewControllerGuiI alignFrame,
+          AlignViewportI viewport, AlignmentViewPanel alignPanel)
   {
     this.avcg = alignFrame;
-    this.viewport=viewport;
+    this.viewport = viewport;
     this.alignPanel = alignPanel;
   }
+
   @Override
-  public void setViewportAndAlignmentPanel(AlignViewportI viewport,AlignmentViewPanel alignPanel)
+  public void setViewportAndAlignmentPanel(AlignViewportI viewport,
+          AlignmentViewPanel alignPanel)
   {
     this.alignPanel = alignPanel;
     this.viewport = viewport;
-    
+
   }
+
   @Override
   public boolean makeGroupsFromSelection()
   {
-
-    if (viewport.getSelectionGroup() != null)
+    SequenceGroup sg = viewport.getSelectionGroup();
+    ColumnSelection cs = viewport.getColumnSelection();
+    SequenceGroup[] gps = null;
+    if (sg != null
+            && (cs == null || cs.getSelected() == null || cs.size() == 0))
     {
-      SequenceGroup[] gps = jalview.analysis.Grouping.makeGroupsFrom(
+      gps = jalview.analysis.Grouping.makeGroupsFrom(
               viewport.getSequenceSelection(),
               viewport.getAlignmentView(true).getSequenceStrings(
                       viewport.getGapCharacter()), viewport.getAlignment()
                       .getGroups());
+    } else {
+      if (cs!=null) {
+        gps = jalview.analysis.Grouping.makeGroupsFromCols(
+                (sg == null) ? viewport.getAlignment().getSequencesArray()
+                        : sg.getSequences().toArray(new SequenceI[0]), cs,
+                viewport.getAlignment().getGroups());
+      }
+    }
+    if (gps!=null) {
       viewport.getAlignment().deleteAllGroups();
       viewport.clearSequenceColours();
       viewport.setSelectionGroup(null);
@@ -89,58 +112,66 @@ public class AlignViewController implements AlignViewControllerI
                 (int) (Math.random() * 255), (int) (Math.random() * 255));
         col = col.brighter();
         for (SequenceI sq : gps[g].getSequences(null))
+        {
           viewport.setSequenceColour(sq, col);
+        }
       }
       return true;
     }
     return false;
-}
+  }
+
   @Override
   public boolean createGroup()
   {
 
     SequenceGroup sg = viewport.getSelectionGroup();
-    if (sg!=null)
+    if (sg != null)
     {
-        viewport.getAlignment().addGroup(sg);
-        return true;
-      } 
+      viewport.getAlignment().addGroup(sg);
+      return true;
+    }
     return false;
   }
+
   @Override
   public boolean unGroup()
   {
     SequenceGroup sg = viewport.getSelectionGroup();
-    if (sg!=null)
+    if (sg != null)
     {
-        viewport.getAlignment().deleteGroup(sg);
-        return true;
+      viewport.getAlignment().deleteGroup(sg);
+      return true;
     }
     return false;
   }
+
   @Override
   public boolean deleteGroups()
   {
-    if (viewport.getAlignment().getGroups()!=null && viewport.getAlignment().getGroups().size()>0)
+    if (viewport.getAlignment().getGroups() != null
+            && viewport.getAlignment().getGroups().size() > 0)
     {
-    viewport.getAlignment().deleteAllGroups();
-    viewport.clearSequenceColours();
-    viewport.setSelectionGroup(null);
-    return true;
+      viewport.getAlignment().deleteAllGroups();
+      viewport.clearSequenceColours();
+      viewport.setSelectionGroup(null);
+      return true;
     }
     return false;
   }
-   
+
   @Override
-  public boolean markColumnsContainingFeatures(boolean invert, boolean extendCurrent, boolean toggle, String featureType)
+  public boolean markColumnsContainingFeatures(boolean invert,
+          boolean extendCurrent, boolean toggle, String featureType)
   {
     // JBPNote this routine could also mark rows, not just columns.
     // need a decent query structure to allow all types of feature searches
     BitSet bs = new BitSet();
-    int alw,alStart;
-    SequenceCollectionI sqcol = (viewport.getSelectionGroup() == null ? viewport.getAlignment() : viewport.getSelectionGroup()); 
+    int alw, alStart;
+    SequenceCollectionI sqcol = (viewport.getSelectionGroup() == null ? viewport
+            .getAlignment() : viewport.getSelectionGroup());
     alStart = sqcol.getStartRes();
-    alw = sqcol.getEndRes()+1;
+    alw = sqcol.getEndRes() + 1;
     List<SequenceI> seqs = sqcol.getSequences();
     int nseq = 0;
     for (SequenceI sq : seqs)
@@ -148,18 +179,12 @@ public class AlignViewController implements AlignViewControllerI
       int tfeat = 0;
       if (sq != null)
       {
-        SequenceI dsq = sq.getDatasetSequence();
-        while (dsq.getDatasetSequence() != null)
-        {
-          dsq = dsq.getDatasetSequence();
-        }
-        ;
-        SequenceFeature[] sf = dsq.getSequenceFeatures();
+        SequenceFeature[] sf = sq.getSequenceFeatures();
         if (sf != null)
         {
           int ist = sq.findIndex(sq.getStart());
           int iend = sq.findIndex(sq.getEnd());
-          if (iend < alStart || ist> alw)
+          if (iend < alStart || ist > alw)
           {
             // sequence not in region
             continue;
@@ -177,7 +202,7 @@ public class AlignViewController implements AlignViewControllerI
 
               int i = sq.findIndex(sfpos.getBegin());
               int j = sq.findIndex(sfpos.getEnd());
-              if (j<alStart || i>alw)
+              if (j < alStart || i > alw)
               {
                 // feature is outside selected region
                 continue;
@@ -186,7 +211,8 @@ public class AlignViewController implements AlignViewControllerI
               {
                 i = alStart;
               }
-              if (i< ist) {
+              if (i < ist)
+              {
                 i = ist;
               }
               if (j > alw)
@@ -213,7 +239,9 @@ public class AlignViewController implements AlignViewControllerI
       if (cs == null)
       {
         cs = new ColumnSelection();
-      } else {
+      }
+      else
+      {
         if (!extendCurrent)
         {
           cs.clear();
@@ -228,12 +256,13 @@ public class AlignViewController implements AlignViewControllerI
           if (ibs < 0 || i < ibs)
           {
             if (toggle && cs.contains(i))
-              {
-                cs.removeElement(i++);
-              } else 
-              {
-                cs.addElement(i++);
-              }
+            {
+              cs.removeElement(i++);
+            }
+            else
+            {
+              cs.addElement(i++);
+            }
           }
           else
           {
@@ -244,12 +273,14 @@ public class AlignViewController implements AlignViewControllerI
       }
       else
       {
-        for (int i = bs.nextSetBit(alStart); i >= alStart; i = bs.nextSetBit(i + 1))
+        for (int i = bs.nextSetBit(alStart); i >= alStart; i = bs
+                .nextSetBit(i + 1))
         {
           if (toggle && cs.contains(i))
           {
             cs.removeElement(i);
-          } else 
+          }
+          else
           {
             cs.addElement(i);
           }
@@ -257,16 +288,18 @@ public class AlignViewController implements AlignViewControllerI
       }
       viewport.setColumnSelection(cs);
       alignPanel.paintAlignment(true);
-      avcg.setStatus((toggle ? "Toggled ": "Marked ")
-              + (invert ? (alw-alStart) - bs.cardinality() : bs.cardinality())
-              + " columns "+(invert ? "not " : "") + "containing features of type " + featureType
-              + " across " + nseq + " sequence(s)");
+      avcg.setStatus(MessageManager.formatMessage("label.view_controller_toggled_marked",
+                 new String[]{
+                               (toggle ? MessageManager.getString("label.toggled") : MessageManager.getString("label.marked")),
+                               (invert ? (Integer.valueOf((alw - alStart) - bs.cardinality()).toString()):(Integer.valueOf(bs.cardinality()).toString())),
+                               featureType, Integer.valueOf(nseq).toString()
+                       }));
       return true;
     }
     else
     {
-      avcg.setStatus("No features of type " + featureType + " found.");
-      if (!extendCurrent && cs!=null)
+      avcg.setStatus(MessageManager.formatMessage("label.no_feature_of_type_found", new String[]{featureType}));
+      if (!extendCurrent && cs != null)
       {
         cs.clear();
         alignPanel.paintAlignment(true);
@@ -274,4 +307,76 @@ public class AlignViewController implements AlignViewControllerI
       return false;
     }
   }
+
+
+
+  @Override
+  public void sortAlignmentByFeatureDensity(String[] typ)
+  {
+    sortBy(typ, "Sort by Density", AlignmentSorter.FEATURE_DENSITY);
+  }
+
+  protected void sortBy(String[] typ, String methodText, final String method)
+  {
+    FeatureRenderer fr = alignPanel.getFeatureRenderer();
+    if (typ == null)
+    {
+      typ = fr==null ? null : fr.getDisplayedFeatureTypes();
+    }
+    String gps[] = null;
+    gps = fr==null ? null : fr.getDisplayedFeatureGroups();
+    if (typ != null)
+    {
+      ArrayList types = new ArrayList();
+      for (int i = 0; i < typ.length; i++)
+      {
+        if (typ[i] != null)
+        {
+          types.add(typ[i]);
+        }
+        typ = new String[types.size()];
+        types.toArray(typ);
+      }
+    }
+    if (gps != null)
+    {
+      ArrayList grps = new ArrayList();
+
+      for (int i = 0; i < gps.length; i++)
+      {
+        if (gps[i] != null)
+        {
+          grps.add(gps[i]);
+        }
+      }
+      gps = new String[grps.size()];
+      grps.toArray(gps);
+    }
+    AlignmentI al = viewport.getAlignment();
+
+    int start, stop;
+    SequenceGroup sg = viewport.getSelectionGroup();
+    if (sg != null)
+    {
+      start = sg.getStartRes();
+      stop = sg.getEndRes();
+    }
+    else
+    {
+      start = 0;
+      stop = al.getWidth();
+    }
+    SequenceI[] oldOrder = al.getSequencesArray();
+    AlignmentSorter.sortByFeature(typ, gps, start, stop, al, method);
+    avcg.addHistoryItem(new OrderCommand(methodText, oldOrder, viewport
+            .getAlignment()));
+    alignPanel.paintAlignment(true);
+
+  }
+
+  @Override
+  public void sortAlignmentByFeatureScore(String[] typ)
+  {
+    sortBy(typ, "Sort by Feature Score", AlignmentSorter.FEATURE_SCORE);
+  }
 }