JAL-1738 JAL-345 new controller method based on mark columns containing features...
[jalview.git] / src / jalview / controller / AlignViewController.java
index f966072..9451c3b 100644 (file)
@@ -182,23 +182,24 @@ public class AlignViewController implements AlignViewControllerI
 
     if (bs.cardinality() > 0 || invert)
     {
-      boolean changed = selectMarkedColumns(cs, invert, extendCurrent,
-              toggle, bs, sqcol.getStartRes(), sqcol.getEndRes());
+      boolean changed = cs.markColumns(bs, sqcol.getStartRes(),
+              sqcol.getEndRes(), invert, extendCurrent, toggle);
       if (changed)
       {
         viewport.setColumnSelection(cs);
         alignPanel.paintAlignment(true);
         int columnCount = invert ? (sqcol.getEndRes() - sqcol.getStartRes() + 1)
-                - bs.cardinality() : bs.cardinality();
+                - bs.cardinality()
+                : bs.cardinality();
         avcg.setStatus(MessageManager.formatMessage(
                 "label.view_controller_toggled_marked",
                 new String[] {
-                    MessageManager.getString(toggle ? "label.toggled"
-                            : "label.marked"),
+                    toggle ? MessageManager.getString("label.toggled")
+                            : MessageManager.getString("label.marked"),
                     String.valueOf(columnCount),
-                    MessageManager
-                            .getString(invert ? "label.not_containing"
-                                    : "label.containing"),
+                    invert ? MessageManager
+                            .getString("label.not_containing")
+                            : MessageManager.getString("label.containing"),
                     featureType, Integer.valueOf(nseq).toString() }));
         return true;
       }
@@ -208,7 +209,7 @@ public class AlignViewController implements AlignViewControllerI
       avcg.setStatus(MessageManager.formatMessage(
               "label.no_feature_of_type_found",
               new String[] { featureType }));
-      if (!extendCurrent && cs != null)
+      if (!extendCurrent)
       {
         cs.clear();
         alignPanel.paintAlignment(true);
@@ -218,85 +219,9 @@ public class AlignViewController implements AlignViewControllerI
   }
 
   /**
-   * Updates the column selection depending on the parameters, and returns true
-   * if any change was made to the selection.
-   * 
-   * @param columnSelection
-   *          the current column selection
-   * @param invert
-   *          if true, deselect marked columns and select unmarked
-   * @param extendCurrent
-   *          if true, extend rather than replacing the current column selection
-   * @param toggle
-   *          if true, toggle the selection state of marked columns
-   * @param markedColumns
-   *          a set identify marked columns
-   * @param startCol
-   *          the first column of the range to operate over
-   * @param endCol
-   *          the last column of the range to operate over
-   * @return
-   */
-  static boolean selectMarkedColumns(ColumnSelection columnSelection,
-          boolean invert, boolean extendCurrent, boolean toggle,
-          BitSet markedColumns, int startCol, int endCol)
-  {
-    boolean changed = false;
-    if (!extendCurrent && !toggle)
-    {
-      changed = !columnSelection.isEmpty();
-      columnSelection.clear();
-    }
-    if (invert)
-    {
-      // invert only in the currently selected sequence region
-      int i = markedColumns.nextClearBit(startCol);
-      int ibs = markedColumns.nextSetBit(startCol);
-      while (i >= startCol && i <= endCol)
-      {
-        if (ibs < 0 || i < ibs)
-        {
-          changed = true;
-          if (toggle && columnSelection.contains(i))
-          {
-            columnSelection.removeElement(i++);
-          }
-          else
-          {
-            columnSelection.addElement(i++);
-          }
-        }
-        else
-        {
-          i = markedColumns.nextClearBit(ibs);
-          ibs = markedColumns.nextSetBit(i);
-        }
-      }
-    }
-    else
-    {
-      int i = markedColumns.nextSetBit(startCol);
-      while (i >= startCol && i <= endCol)
-      {
-        changed = true;
-        if (toggle && columnSelection.contains(i))
-        {
-          columnSelection.removeElement(i);
-        }
-        else
-        {
-          columnSelection.addElement(i);
-        }
-        i = markedColumns.nextSetBit(i + 1);
-      }
-    }
-    return changed;
-  }
-
-  /**
-   * Sets a bit in the BitSet for each column in the sequence collection which
-   * includes the specified feature type. Returns the number of sequences which
-   * have the feature in the selected range.
+   * Sets a bit in the BitSet for each column (base 0) in the sequence
+   * collection which includes the specified feature type. Returns the number of
+   * sequences which have the feature in the selected range.
    * 
    * @param featureType
    * @param sqcol
@@ -304,8 +229,7 @@ public class AlignViewController implements AlignViewControllerI
    * @return
    */
   static int findColumnsWithFeature(String featureType,
-          SequenceCollectionI sqcol,
-          BitSet bs)
+          SequenceCollectionI sqcol, BitSet bs)
   {
     final int startPosition = sqcol.getStartRes() + 1; // converted to base 1
     final int endPosition = sqcol.getEndRes() + 1;
@@ -319,6 +243,10 @@ public class AlignViewController implements AlignViewControllerI
         SequenceFeature[] sfs = sq.getSequenceFeatures();
         if (sfs != null)
         {
+          /*
+           * check whether the feature start/end (base 1) 
+           * overlaps the selection start/end
+           */
           int ist = sq.findIndex(sq.getStart());
           int iend = sq.findIndex(sq.getEnd());
           if (iend < startPosition || ist > endPosition)
@@ -358,7 +286,7 @@ public class AlignViewController implements AlignViewControllerI
               }
               for (; i <= j; i++)
               {
-                bs.set(i - 1);
+                bs.set(i - 1); // convert to base 0
               }
             }
           }
@@ -453,4 +381,66 @@ public class AlignViewController implements AlignViewControllerI
     return featuresFile;
 
   }
+
+  @Override
+  public boolean markHighlightedColumns(boolean invert,
+          boolean extendCurrent, boolean toggle)
+  {
+    if (!viewport.hasSearchResults())
+    {
+      // do nothing if no selection exists
+      return false;
+    }
+    // JBPNote this routine could also mark rows, not just columns.
+    BitSet bs = new BitSet();
+    SequenceCollectionI sqcol = (viewport.getSelectionGroup() == null || extendCurrent) ? viewport
+            .getAlignment() : viewport.getSelectionGroup();
+
+    // this could be a lambda... - the remains of the method is boilerplate,
+    // except for the different messages for reporting selection.
+    int nseq = viewport.getSearchResults().markColumns(sqcol, bs);
+
+    ColumnSelection cs = viewport.getColumnSelection();
+    if (cs == null)
+    {
+      cs = new ColumnSelection();
+    }
+
+    if (bs.cardinality() > 0 || invert)
+    {
+      boolean changed = cs.markColumns(bs, sqcol.getStartRes(),
+              sqcol.getEndRes(), invert, extendCurrent, toggle);
+      if (changed)
+      {
+        viewport.setColumnSelection(cs);
+        alignPanel.paintAlignment(true);
+        int columnCount = invert ? (sqcol.getEndRes() - sqcol.getStartRes() + 1)
+                - bs.cardinality()
+                : bs.cardinality();
+        avcg.setStatus(MessageManager.formatMessage(
+                "label.view_controller_toggled_marked",
+                new String[] {
+                    toggle ? MessageManager.getString("label.toggled")
+                            : MessageManager.getString("label.marked"),
+                    String.valueOf(columnCount),
+                    invert ? MessageManager
+                            .getString("label.not_containing")
+                            : MessageManager.getString("label.containing"),
+                    "Highlight", Integer.valueOf(nseq).toString() }));
+        return true;
+      }
+    }
+    else
+    {
+      avcg.setStatus(MessageManager
+              .formatMessage("No highlighted regions marked"));
+      if (!extendCurrent)
+      {
+        cs.clear();
+        alignPanel.paintAlignment(true);
+      }
+    }
+    return false;
+  }
+
 }