JAL-2759 Refactor of hideInsertionsFor after review
[jalview.git] / src / jalview / datamodel / HiddenColumns.java
index 3b1a574..2b5185f 100644 (file)
@@ -42,7 +42,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
  * 
  * - getVisibleColsIterator: iterates over the visible *columns*
  * 
- * For performance reasons, provide bounds where possible.
+ * For performance reasons, provide bounds where possible. Note that column
+ * numbering begins at 0 throughout this class.
  * 
  * @author kmourao
  *
@@ -68,7 +69,7 @@ public class HiddenColumns
    * list of hidden column [start, end] ranges; the list is maintained in
    * ascending start column order
    */
-  private ArrayList<int[]> hiddenColumns;
+  private List<int[]> hiddenColumns;
 
   /**
    * Constructor
@@ -93,29 +94,7 @@ public class HiddenColumns
    */
   public HiddenColumns(HiddenColumns copy)
   {
-    try
-    {
-      LOCK.writeLock().lock();
-      numColumns = 0;
-      if (copy != null)
-      {
-        if (copy.hiddenColumns != null)
-        {
-          hiddenColumns = new ArrayList<>();
-          Iterator<int[]> it = copy.iterator();
-          while (it.hasNext())
-          {
-            int[] region = it.next();
-            hiddenColumns.add(region);
-            numColumns += region[1] - region[0] + 1;
-          }
-          cursor.resetCursor(hiddenColumns);
-        }
-      }
-    } finally
-    {
-      LOCK.writeLock().unlock();
-    }
+    this(copy, Integer.MIN_VALUE, Integer.MAX_VALUE, 0);
   }
 
   /**
@@ -324,14 +303,13 @@ public class HiddenColumns
    * mark the columns corresponding to gap characters as hidden in the column
    * selection
    * 
-   * @param sr
+   * @param insertions
    */
-  public void hideInsertionsFor(SequenceI sr)
+  public void hideInsertionsFor(List<int[]> inserts)
   {
     try
     {
       LOCK.writeLock().lock();
-      List<int[]> inserts = sr.getInsertions();
       for (int[] r : inserts)
       {
         hideColumns(r[0], r[1]);
@@ -483,14 +461,14 @@ public class HiddenColumns
       markHiddenRegions(hidden);
       hidden.andNot(gaps);
       hiddenColumns = null;
-      this.hideMarkedBits(hidden);
+      this.hideColumns(hidden);
 
       // for each sequence in the alignment, except the profile sequence,
       // insert gaps corresponding to each hidden region but where each hidden
       // column region is shifted backwards by the number of preceding visible
       // gaps update hidden columns at the same time
       Iterator<int[]> regions = hiddenColumns.iterator();
-      ArrayList<int[]> newhidden = new ArrayList<>();
+      List<int[]> newhidden = new ArrayList<>();
 
       int numGapsBefore = 0;
       int gapPosition = 0;
@@ -735,7 +713,7 @@ public class HiddenColumns
    *          int column index in alignment view (count from zero)
    * @return alignment column index for column
    */
-  public int adjustForHiddenColumns(int column)
+  public int visibleToAbsoluteColumn(int column)
   {
     try
     {
@@ -744,7 +722,7 @@ public class HiddenColumns
 
       if (hiddenColumns != null)
       {
-        result += cursor.getHiddenOffset(column).getHiddenSoFar();
+        result += cursor.findRegionForVisColumn(column).getHiddenSoFar();
       }
 
       return result;
@@ -757,13 +735,14 @@ public class HiddenColumns
   /**
    * Use this method to find out where a column will appear in the visible
    * alignment when hidden columns exist. If the column is not visible, then the
-   * left-most visible column will always be returned.
+   * index of the next visible column on the left will be returned (or 0 if
+   * there is no visible column on the left)
    * 
    * @param hiddenColumn
    *          the column index in the full alignment including hidden columns
    * @return the position of the column in the visible alignment
    */
-  public int findColumnPosition(int hiddenColumn)
+  public int absoluteToVisibleColumn(int hiddenColumn)
   {
     try
     {
@@ -829,7 +808,7 @@ public class HiddenColumns
       int distance = visibleDistance;
 
       // in case startColumn is in a hidden region, move it to the left
-      int start = adjustForHiddenColumns(findColumnPosition(startColumn));
+      int start = visibleToAbsoluteColumn(absoluteToVisibleColumn(startColumn));
 
       Iterator<int[]> it = new ReverseRegionsIterator(0, start,
               hiddenColumns);
@@ -868,6 +847,8 @@ public class HiddenColumns
    * @param alPos
    *          the absolute (visible) alignmentPosition to find the next hidden
    *          column for
+   * @return the index of the next hidden column, or alPos if there is no next
+   *         hidden column
    */
   public int getHiddenBoundaryRight(int alPos)
   {
@@ -1084,7 +1065,7 @@ public class HiddenColumns
 
       if (foundStart)
       {
-        return findColumnPosition(start);
+        return absoluteToVisibleColumn(start);
       }
       // otherwise, sequence was completely hidden
       return visPrev;
@@ -1217,6 +1198,9 @@ public class HiddenColumns
     try
     {
       LOCK.readLock().lock();
+
+      // we don't use getSize()>0 here because it has to iterate over
+      // the full hiddenColumns collection and so will be much slower
       return hiddenColumns != null && hiddenColumns.size() > 0;
     } finally
     {
@@ -1226,9 +1210,9 @@ public class HiddenColumns
 
   /**
    * 
-   * @return true if there are more than one set of columns hidden
+   * @return true if there is more than one hidden column region
    */
-  public boolean hasManyHiddenColumns()
+  public boolean hasMultiHiddenColumnRegions()
   {
     try
     {
@@ -1271,7 +1255,7 @@ public class HiddenColumns
    * @param inserts
    *          - columns map to bits starting from zero
    */
-  public void hideMarkedBits(BitSet inserts)
+  public void hideColumns(BitSet inserts)
   {
     try
     {
@@ -1378,14 +1362,15 @@ public class HiddenColumns
    * 
    * @param res
    *          visible residue position, unadjusted for hidden columns
-   * @return region as [start,end] or null if no matching region is found
+   * @return region as [start,end] or null if no matching region is found. If
+   *         res is adjacent to two regions, returns the left region.
    */
   public int[] getRegionWithEdgeAtRes(int res)
   {
     try
     {
       LOCK.readLock().lock();
-      int adjres = adjustForHiddenColumns(res);
+      int adjres = visibleToAbsoluteColumn(res);
 
       int[] reveal = null;
 
@@ -1422,7 +1407,7 @@ public class HiddenColumns
     try
     {
       LOCK.readLock().lock();
-      return new BoundedHiddenColsIterator(hiddenColumns);
+      return new HiddenColsIterator(hiddenColumns);
     } finally
     {
       LOCK.readLock().unlock();
@@ -1443,7 +1428,7 @@ public class HiddenColumns
     try
     {
       LOCK.readLock().lock();
-      return new BoundedHiddenColsIterator(start, end, hiddenColumns);
+      return new HiddenColsIterator(start, end, hiddenColumns);
     } finally
     {
       LOCK.readLock().unlock();
@@ -1466,7 +1451,7 @@ public class HiddenColumns
       LOCK.readLock().lock();
 
       // get absolute position of column in alignment
-      int absoluteStart = adjustForHiddenColumns(start);
+      int absoluteStart = visibleToAbsoluteColumn(start);
 
       // Get cursor position and supply it to the iterator:
       // Since we want visible region start, we look for a cursor for the
@@ -1524,8 +1509,8 @@ public class HiddenColumns
     int adjend = end;
     if (useVisibleCoords)
     {
-      adjstart = adjustForHiddenColumns(start);
-      adjend = adjustForHiddenColumns(end);
+      adjstart = visibleToAbsoluteColumn(start);
+      adjend = visibleToAbsoluteColumn(end);
     }
 
     try