JAL-1445 extend functionality to select or toggle selection for columns containing...
authorJim Procter <jprocter@dundee.ac.uk>
Fri, 23 May 2014 10:57:27 +0000 (11:57 +0100)
committerJim Procter <jprocter@dundee.ac.uk>
Fri, 23 May 2014 10:57:27 +0000 (11:57 +0100)
src/jalview/api/AlignViewControllerI.java
src/jalview/controller/AlignViewController.java
src/jalview/gui/FeatureSettings.java

index 1d1e5fb..cac3776 100644 (file)
@@ -21,6 +21,14 @@ public interface AlignViewControllerI<ViewportI>
 
   public void setViewportAndAlignmentPanel(AlignViewportI viewport, AlignmentViewPanel alignPanel);
 
-  boolean markColumnsContainingFeatures(boolean invert, String featureType);
+  /**
+   * Mark columns in the current column selection according to positions of sequence features
+   * @param invert - when set, mark all but columns containing given type
+   * @param extendCurrent - when set, do not clear existing column selection
+   * @param toggle - rather than explicitly set, toggle selection state
+   * @param featureType - feature type string
+   * @return true if operation affected state
+   */
+  boolean markColumnsContainingFeatures(boolean invert, boolean extendCurrent, boolean clearColumns, String featureType);
 
 }
index 1a1d219..329267e 100644 (file)
@@ -8,7 +8,10 @@ import jalview.api.AlignViewControllerGuiI;
 import jalview.api.AlignViewControllerI;
 import jalview.api.AlignViewportI;
 import jalview.api.AlignmentViewPanel;
+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;
@@ -109,14 +112,16 @@ public class AlignViewController implements AlignViewControllerI
   }
    
   @Override
-  public boolean markColumnsContainingFeatures(boolean invert,
-          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();
-    List<SequenceI> seqs = viewport.getAlignment().getSequences();
-    int alw = viewport.getAlignment().getWidth();
+    int alw,alStart;
+    SequenceCollectionI sqcol = (viewport.getSelectionGroup() == null ? viewport.getAlignment() : viewport.getSelectionGroup()); 
+    alStart = sqcol.getStartRes();
+    alw = sqcol.getEndRes()+1;
+    List<SequenceI> seqs = sqcol.getSequences();
     int nseq = 0;
     for (SequenceI sq : seqs)
     {
@@ -132,6 +137,13 @@ public class AlignViewController implements AlignViewControllerI
         SequenceFeature[] sf = dsq.getSequenceFeatures();
         if (sf != null)
         {
+          int ist = sq.findIndex(sq.getStart());
+          int iend = sq.findIndex(sq.getEnd());
+          if (iend < alStart || ist> alw)
+          {
+            // sequence not in region
+            continue;
+          }
           for (SequenceFeature sfpos : sf)
           {
             // future functionalty - featureType == null means mark columns
@@ -144,12 +156,19 @@ public class AlignViewController implements AlignViewControllerI
               // counting
 
               int i = sq.findIndex(sfpos.getBegin());
-              int ist = sq.findIndex(sq.getStart());
-              if (i < ist)
+              int j = sq.findIndex(sfpos.getEnd());
+              if (j<alStart || i>alw)
+              {
+                // feature is outside selected region
+                continue;
+              }
+              if (i < alStart)
               {
+                i = alStart;
+              }
+              if (i< ist) {
                 i = ist;
               }
-              int j = sq.findIndex(sfpos.getEnd());
               if (j > alw)
               {
                 j = alw;
@@ -168,21 +187,33 @@ public class AlignViewController implements AlignViewControllerI
         }
       }
     }
+    ColumnSelection cs = viewport.getColumnSelection();
     if (bs.cardinality() > 0 || invert)
     {
-      ColumnSelection cs = viewport.getColumnSelection();
       if (cs == null)
       {
         cs = new ColumnSelection();
+      } else {
+        if (!extendCurrent)
+        {
+          cs.clear();
+        }
       }
       if (invert)
       {
-        for (int i = bs.nextClearBit(0), ibs = bs.nextSetBit(0); i >= 0
-                && i < alw;)
+        // invert only in the currently selected sequence region
+        for (int i = bs.nextClearBit(alStart), ibs = bs.nextSetBit(alStart); i >= alStart
+                && i < (alw);)
         {
           if (ibs < 0 || i < ibs)
           {
-            cs.addElement(i++);
+            if (toggle && cs.contains(i))
+              {
+                cs.removeElement(i++);
+              } else 
+              {
+                cs.addElement(i++);
+              }
           }
           else
           {
@@ -193,22 +224,33 @@ public class AlignViewController implements AlignViewControllerI
       }
       else
       {
-        for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1))
+        for (int i = bs.nextSetBit(alStart); i >= alStart; i = bs.nextSetBit(i + 1))
         {
-          cs.addElement(i);
+          if (toggle && cs.contains(i))
+          {
+            cs.removeElement(i);
+          } else 
+          {
+            cs.addElement(i);
+          }
         }
       }
       viewport.setColumnSelection(cs);
       alignPanel.paintAlignment(true);
-      avcg.setStatus("Marked "
-              + (invert ? alw - bs.cardinality() : bs.cardinality())
-              + " columns containing features of type " + featureType
-              + " across " + nseq);
+      avcg.setStatus((toggle ? "Toggled ": "Marked ")
+              + (invert ? (alw-alStart) - bs.cardinality() : bs.cardinality())
+              + " columns "+(invert ? "not " : "") + "containing features of type " + featureType
+              + " across " + nseq + " sequence(s)");
       return true;
     }
     else
     {
       avcg.setStatus("No features of type " + featureType + " found.");
+      if (!extendCurrent && cs!=null)
+      {
+        cs.clear();
+        alignPanel.paintAlignment(true);
+      }
       return false;
     }
   }
index 2bd98d5..3787efa 100644 (file)
@@ -108,7 +108,7 @@ public class FeatureSettings extends JPanel
         else if (evt.getClickCount() == 2)
         {
           fr.ap.alignFrame.avc.markColumnsContainingFeatures(
-                  evt.isShiftDown(),
+                  evt.isAltDown(),evt.isShiftDown() || evt.isMetaDown(), evt.isMetaDown(),
                   (String) table.getValueAt(selectedRow, 0));
         }
       }
@@ -138,7 +138,8 @@ public class FeatureSettings extends JPanel
         }
       }
     });
-
+    table.setToolTipText("<html>"+JvSwingUtils
+            .wrapTooltip("Click/drag feature types up or down to change render order.<br/>Double click to select columns containing feature in alignment/current selection<br/>Pressing Alt will select columns outside features rather than inside<br/>Pressing Shift to modify current selection (rather than clear current selection)<br/>Press CTRL or Command/Meta to toggle columns in/outside features<br/>")+"</html>");
     scrollPane.setViewportView(table);
 
     dassourceBrowser = new DasSourceBrowser(this);
@@ -304,7 +305,7 @@ public class FeatureSettings extends JPanel
       @Override
       public void actionPerformed(ActionEvent arg0)
       {
-        fr.ap.alignFrame.avc.markColumnsContainingFeatures(false, type);
+        fr.ap.alignFrame.avc.markColumnsContainingFeatures(false, false, false, type);
       }
     });
     JMenuItem clearCols = new JMenuItem(MessageManager.getString("label.select_columns_not_containing"));
@@ -314,7 +315,7 @@ public class FeatureSettings extends JPanel
       @Override
       public void actionPerformed(ActionEvent arg0)
       {
-        fr.ap.alignFrame.avc.markColumnsContainingFeatures(true, type);
+        fr.ap.alignFrame.avc.markColumnsContainingFeatures(true, false, false, type);
       }
     });
     men.add(selCols);