JAL-2759 First pass instantiate hiddenColumns collection in constructor
[jalview.git] / src / jalview / datamodel / HiddenColumnsCursor.java
index a002232..a875f87 100644 (file)
@@ -20,6 +20,7 @@
  */
 package jalview.datamodel;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -28,7 +29,7 @@ public class HiddenColumnsCursor
   // absolute position of first hidden column
   private int firstColumn;
 
-  private List<int[]> hiddenColumns;
+  private List<int[]> hiddenColumns = new ArrayList<>();
 
   // AtomicReference to hold the current region index and hidden column count
   // Could be done with synchronisation but benchmarking shows this way is 2x
@@ -48,15 +49,34 @@ public class HiddenColumnsCursor
    * already exist.
    * 
    * @param hiddenCols
+   *          new hidden columns collection
    */
   protected void resetCursor(List<int[]> hiddenCols)
   {
+    resetCursor(hiddenCols, 0, 0);
+  }
+
+  /**
+   * Reset the cursor with a new hidden columns collection, where we know in
+   * advance the index and hidden columns count of a particular location.
+   * 
+   * @param hiddenCols
+   *          new hidden columns collection
+   * @param index
+   *          cursor index to reset to
+   * @param hiddencount
+   *          hidden columns count to reset to
+   */
+  protected void resetCursor(List<int[]> hiddenCols, int index,
+          int hiddencount)
+  {
     hiddenColumns = hiddenCols;
-    if ((hiddenCols != null) && (!hiddenCols.isEmpty()))
+    if (!hiddenCols.isEmpty())
     {
       firstColumn = hiddenColumns.get(0)[0];
       HiddenCursorPosition oldpos = cursorPos.get();
-      HiddenCursorPosition newpos = new HiddenCursorPosition(0, 0);
+      HiddenCursorPosition newpos = new HiddenCursorPosition(index,
+              hiddencount);
       cursorPos.compareAndSet(oldpos, newpos);
     }
   }
@@ -74,7 +94,7 @@ public class HiddenColumnsCursor
   protected void updateForDeletedRegion(List<int[]> hiddenCols)
   {
 
-    if ((hiddenCols != null) && (!hiddenCols.isEmpty()))
+    if (!hiddenCols.isEmpty())
     {
       // if there is a region to the right of the current region,
       // nothing changes; otherwise
@@ -87,29 +107,31 @@ public class HiddenColumnsCursor
       {
         // deleted last region, index is now end of alignment
         index = hiddenCols.size();
-      }
 
-      // update the cursor position
-      HiddenCursorPosition newpos = new HiddenCursorPosition(index,
-              oldpos.getHiddenSoFar());
-      cursorPos.compareAndSet(oldpos, newpos);
+        HiddenCursorPosition newpos = new HiddenCursorPosition(index,
+                oldpos.getHiddenSoFar());
+        cursorPos.compareAndSet(oldpos, newpos);
+      }
     }
     hiddenColumns = hiddenCols;
   }
 
   /**
-   * Get the index of the region that column is within (if column is hidden) or
-   * which is to the right of column (if column is visible). If no hidden
-   * columns are to the right, will return size of hiddenColumns. If hidden
-   * columns is empty returns -1.
+   * Get the cursor pointing to the hidden region that column is within (if
+   * column is hidden) or which is to the right of column (if column is
+   * visible). If no hidden columns are to the right, returns a cursor pointing
+   * to an imaginary hidden region beyond the end of the hidden columns
+   * collection (this ensures the count of previous hidden columns is correct).
+   * If hidden columns is empty returns null.
    * 
    * @param column
    *          absolute position of a column in the alignment
-   * @return region index
+   * @return cursor pointing to hidden region containing the column (if hidden)
+   *         or to the right of the column (if visible)
    */
   protected HiddenCursorPosition findRegionForColumn(int column)
   {
-    if (hiddenColumns == null)
+    if (hiddenColumns.isEmpty())
     {
       return null;
     }
@@ -126,21 +148,15 @@ public class HiddenColumnsCursor
       hiddenCount -= region[1] - region[0] + 1;
     }
 
-    if ((hiddenColumns.get(index)[0] <= column)
-            && hiddenColumns.get(index)[1] >= column)
-    {
-      // column is in the current region
-      // we hit the jackpot
-      // don't need to move index
-    }
-    else if (column < firstColumn)
+    // this if statement excludes case where column is in current region
+    // - no changes needed
+    if (column < firstColumn)
     {
       index = 0;
       hiddenCount = 0;
     }
     // column is after current region
-    else if (column > hiddenColumns.get(index)[1]) // includes if column >
-                                                   // lastColumn
+    else if (column > hiddenColumns.get(index)[1])
     {
       // iterate from where we are now, if we're lucky we'll be close by
       // (but still better than iterating from 0)
@@ -154,38 +170,40 @@ public class HiddenColumnsCursor
         index++;
       }
     }
-
     // column is before current region
     else if (column < hiddenColumns.get(index)[0])
     {
       // column is before or in the previous region
-      if ((index > 0) && (hiddenColumns.get(index - 1)[1] >= column))
+      while ((index > 0) && (hiddenColumns.get(index - 1)[1] >= column))
       {
-        while ((index > 0) && (hiddenColumns.get(index - 1)[1] >= column))
-        {
-          index--;
-          int[] region = hiddenColumns.get(index);
-          hiddenCount -= region[1] - region[0] + 1;
-        }
+        index--;
+        int[] region = hiddenColumns.get(index);
+        hiddenCount -= region[1] - region[0] + 1;
       }
     }
-    HiddenCursorPosition newpos = new HiddenCursorPosition(index,
-            hiddenCount);
-    cursorPos.compareAndSet(oldpos, newpos);
-    return newpos;
+
+    if (index != oldpos.getRegionIndex()
+            || hiddenCount != oldpos.getHiddenSoFar())
+    {
+      HiddenCursorPosition newpos = new HiddenCursorPosition(index,
+              hiddenCount);
+      cursorPos.compareAndSet(oldpos, newpos);
+      return newpos;
+    }
+    return oldpos;
   }
 
   /**
-   * Get the number of hidden columns in regions before column i.e. excludes
-   * hidden columns in the region column is in, if any
+   * Get the cursor pointing to the hidden region just after a visible column
    * 
    * @param column
-   *          index of column in visible alignment
-   * @return
+   *          index of column in *visible* alignment (therefore by definition
+   *          column is visible)
+   * @return cursor pointing to hidden region to the right of the column
    */
-  protected HiddenCursorPosition getHiddenOffset(int column)
+  protected HiddenCursorPosition findRegionForVisColumn(int column)
   {
-    if (hiddenColumns == null)
+    if (hiddenColumns.isEmpty())
     {
       return null;
     }
@@ -224,9 +242,14 @@ public class HiddenColumnsCursor
 
     }
 
-    HiddenCursorPosition newpos = new HiddenCursorPosition(index,
-            hiddenCount);
-    cursorPos.compareAndSet(oldpos, newpos);
-    return newpos;
+    if (index != oldpos.getRegionIndex()
+            || hiddenCount != oldpos.getHiddenSoFar())
+    {
+      HiddenCursorPosition newpos = new HiddenCursorPosition(index,
+              hiddenCount);
+      cursorPos.compareAndSet(oldpos, newpos);
+      return newpos;
+    }
+    return oldpos;
   }
 }