Merge branch 'releases/Release_2_11_3_Branch'
[jalview.git] / src / jalview / datamodel / HiddenColumns.java
index d2e46c6..89fb1ab 100644 (file)
@@ -75,7 +75,8 @@ public class HiddenColumns
   private HiddenColumnsCursor cursor = new HiddenColumnsCursor();
 
   /*
-   * cache of the number of hidden columns
+   * cache of the number of hidden columns: must be kept up to date by methods 
+   * which add or remove hidden columns
    */
   private int numColumns = 0;
 
@@ -134,9 +135,9 @@ public class HiddenColumns
           // all overlapping regions and we need contained regions
           if (region[0] >= start && region[1] <= end)
           {
-            hiddenColumns.add(
-                    new int[]
-            { region[0] - offset, region[1] - offset });
+            hiddenColumns
+                    .add(new int[]
+                    { region[0] - offset, region[1] - offset });
             numColumns += region[1] - region[0] + 1;
           }
         }
@@ -168,7 +169,8 @@ public class HiddenColumns
       if (!hiddenColumns.isEmpty())
       {
         // set up cursor reset values
-        HiddenCursorPosition cursorPos = cursor.findRegionForColumn(start, false);
+        HiddenCursorPosition cursorPos = cursor.findRegionForColumn(start,
+                false);
         regionindex = cursorPos.getRegionIndex();
 
         if (regionindex > 0)
@@ -251,7 +253,7 @@ public class HiddenColumns
       int oldstart = region[0];
       region[0] = Math.min(region[0], start);
       numColumns += oldstart - region[0]; // new columns are between old and
-                                              // adjusted starts
+                                          // adjusted starts
       added = true;
     }
     else if (start <= region[1] + 1)
@@ -287,7 +289,6 @@ public class HiddenColumns
     region[1] = Math.max(region[1], end);
 
     numColumns += oldstart - region[0];
-    numColumns += region[1] - oldend;
 
     /*
      * also update or remove any subsequent ranges 
@@ -305,11 +306,10 @@ public class HiddenColumns
         break;
       }
       numColumns -= nextRegion[1] - nextRegion[0] + 1;
-      oldend = nextRegion[1];
       region[1] = Math.max(nextRegion[1], end);
-      numColumns += region[1] - oldend + 1;
       endi++;
     }
+    numColumns += region[1] - oldend;
     hiddenColumns.subList(i + 1, endi + 1).clear();
   }
 
@@ -395,8 +395,6 @@ public class HiddenColumns
             int colsToRemove = region[1] - region[0] + 1;
             hiddenColumns.remove(regionIndex);
             numColumns -= colsToRemove;
-
-            cursor.updateForDeletedRegion(hiddenColumns);
           }
         }
       }
@@ -472,6 +470,10 @@ public class HiddenColumns
     }
   }
 
+  /**
+   * Answers true if obj is an instance of HiddenColumns, and holds the same
+   * array of start-end column ranges as this, else answers false
+   */
   @Override
   public boolean equals(Object obj)
   {
@@ -527,8 +529,7 @@ public class HiddenColumns
 
       if (!hiddenColumns.isEmpty())
       {
-        result += cursor.findRegionForColumn(column, true)
-                .getHiddenSoFar();
+        result += cursor.findRegionForColumn(column, true).getHiddenSoFar();
       }
 
       return result;
@@ -561,11 +562,11 @@ public class HiddenColumns
                 .findRegionForColumn(hiddenColumn, false);
         int index = cursorPos.getRegionIndex();
         int hiddenBeforeCol = cursorPos.getHiddenSoFar();
-    
+
         // just subtract hidden cols count - this works fine if column is
         // visible
         result = hiddenColumn - hiddenBeforeCol;
-    
+
         // now check in case column is hidden - it will be in the returned
         // hidden region
         if (index < hiddenColumns.size())
@@ -685,16 +686,19 @@ public class HiddenColumns
     {
       LOCK.readLock().lock();
 
-      int regionindex = cursor.findRegionForColumn(column, false)
-              .getRegionIndex();
-      if (regionindex > -1 && regionindex < hiddenColumns.size())
+      if (!hiddenColumns.isEmpty())
       {
-        int[] region = hiddenColumns.get(regionindex);
-        // already know that column <= region[1] as cursor returns containing
-        // region or region to right
-        if (column >= region[0])
+        int regionindex = cursor.findRegionForColumn(column, false)
+                .getRegionIndex();
+        if (regionindex > -1 && regionindex < hiddenColumns.size())
         {
-          return false;
+          int[] region = hiddenColumns.get(regionindex);
+          // already know that column <= region[1] as cursor returns containing
+          // region or region to right
+          if (column >= region[0])
+          {
+            return false;
+          }
         }
       }
       return true;
@@ -740,7 +744,6 @@ public class HiddenColumns
     }
   }
 
-
   /**
    * Returns a hashCode built from hidden column ranges
    */
@@ -772,15 +775,39 @@ public class HiddenColumns
    */
   public void hideColumns(BitSet inserts)
   {
+    hideColumns(inserts, 0, inserts.length() - 1);
+  }
+
+  /**
+   * Hide columns corresponding to the marked bits, within the range
+   * [start,end]. Entries in tohide which are outside [start,end] are ignored.
+   * 
+   * @param tohide
+   *          columns mapped to bits starting from zero
+   * @param start
+   *          start of range to hide columns within
+   * @param end
+   *          end of range to hide columns within
+   */
+  private void hideColumns(BitSet tohide, int start, int end)
+  {
     try
     {
       LOCK.writeLock().lock();
-      for (int firstSet = inserts
-              .nextSetBit(0), lastSet = 0; firstSet >= 0; firstSet = inserts
-                      .nextSetBit(lastSet))
+      for (int firstSet = tohide
+              .nextSetBit(start), lastSet = start; firstSet >= start
+                      && lastSet <= end; firstSet = tohide
+                              .nextSetBit(lastSet))
       {
-        lastSet = inserts.nextClearBit(firstSet);
-        hideColumns(firstSet, lastSet - 1);
+        lastSet = tohide.nextClearBit(firstSet);
+        if (lastSet <= end)
+        {
+          hideColumns(firstSet, lastSet - 1);
+        }
+        else if (firstSet <= end)
+        {
+          hideColumns(firstSet, end);
+        }
       }
       cursor = new HiddenColumnsCursor(hiddenColumns);
     } finally
@@ -792,6 +819,7 @@ public class HiddenColumns
   /**
    * Hide columns corresponding to the marked bits, within the range
    * [start,end]. Entries in tohide which are outside [start,end] are ignored.
+   * NB Existing entries in [start,end] are cleared.
    * 
    * @param tohide
    *          columns mapped to bits starting from zero
@@ -800,19 +828,10 @@ public class HiddenColumns
    * @param end
    *          end of range to hide columns within
    */
-  public void hideColumns(BitSet tohide, int start, int end)
+  public void clearAndHideColumns(BitSet tohide, int start, int end)
   {
     clearHiddenColumnsInRange(start, end);
-
-    // make sure only bits between start and end are set
-    if (!tohide.isEmpty())
-    {
-      tohide.clear(0, start);
-      tohide.clear(Math.min(end + 1, tohide.length() + 1),
-              tohide.length() + 1);
-    }
-
-    hideColumns(tohide);
+    hideColumns(tohide, start, end);
   }
 
   /**
@@ -828,7 +847,7 @@ public class HiddenColumns
     try
     {
       LOCK.writeLock().lock();
-      
+
       if (!hiddenColumns.isEmpty())
       {
         HiddenCursorPosition pos = cursor.findRegionForColumn(start, false);
@@ -992,7 +1011,7 @@ public class HiddenColumns
     try
     {
       LOCK.readLock().lock();
-      return new HiddenColsIterator(hiddenColumns);
+      return new RangeIterator(hiddenColumns);
     } finally
     {
       LOCK.readLock().unlock();
@@ -1013,7 +1032,7 @@ public class HiddenColumns
     try
     {
       LOCK.readLock().lock();
-      return new HiddenColsIterator(start, end, hiddenColumns);
+      return new RangeIterator(start, end, hiddenColumns);
     } finally
     {
       LOCK.readLock().unlock();
@@ -1029,7 +1048,7 @@ public class HiddenColumns
    * @param end
    *          position to end at (inclusive, visible column position)
    */
-  public Iterator<Integer> getBoundedStartIterator(int start, int end)
+  public Iterator<Integer> getStartRegionIterator(int start, int end)
   {
     try
     {
@@ -1046,8 +1065,7 @@ public class HiddenColumns
       HiddenCursorPosition pos = cursor
               .findRegionForColumn(absoluteStart - 1, false);
 
-      return new BoundedStartRegionIterator(pos, start, end,
-              hiddenColumns);
+      return new StartRegionIterator(pos, start, end, hiddenColumns);
     } finally
     {
       LOCK.readLock().unlock();
@@ -1068,7 +1086,8 @@ public class HiddenColumns
     try
     {
       LOCK.readLock().lock();
-      return new VisibleColsIterator(start, end, hiddenColumns);
+      return new RangeElementsIterator(
+              new VisibleContigsIterator(start, end + 1, hiddenColumns));
     } finally
     {
       LOCK.readLock().unlock();
@@ -1087,8 +1106,7 @@ public class HiddenColumns
    *          if true, start and end are visible column positions, not absolute
    *          positions*
    */
-  public VisibleContigsIterator getVisContigsIterator(int start,
-          int end,
+  public VisibleContigsIterator getVisContigsIterator(int start, int end,
           boolean useVisibleCoords)
   {
     int adjstart = start;