JAL-2759 improvements to speed up synchronisation; caching of size
[jalview.git] / src / jalview / datamodel / HiddenColumns.java
index 4c3560e..0a4d04b 100644 (file)
@@ -34,6 +34,8 @@ public class HiddenColumns
 
   private HiddenColumnsCursor cursor = new HiddenColumnsCursor();
 
+  private int numColumns = 0;
+
   /*
    * list of hidden column [start, end] ranges; the list is maintained in
    * ascending start column order
@@ -99,6 +101,7 @@ public class HiddenColumns
       if (copy != null)
       {
         hiddenColumns = new ArrayList<>();
+        numColumns = 0;
         Iterator<int[]> it = copy.getBoundedIterator(start, end);
         while (it.hasNext())
         {
@@ -110,6 +113,7 @@ public class HiddenColumns
             hiddenColumns.add(
                     new int[]
             { region[0] - offset, region[1] - offset });
+            numColumns += region[1] - region[0] + 1;
           }
         }
         cursor.resetCursor(hiddenColumns);
@@ -167,17 +171,24 @@ public class HiddenColumns
     try
     {
       LOCK.readLock().lock();
-      int size = 0;
-      if (hiddenColumns != null)
+
+      if (numColumns == 0 && hiddenColumns != null)
       {
-        Iterator<int[]> it = hiddenColumns.iterator();
-        while (it.hasNext())
+        // numColumns is out of date, so recalculate
+        int size = 0;
+        if (hiddenColumns != null)
         {
-          int[] range = it.next();
-          size += range[1] - range[0] + 1;
+          Iterator<int[]> it = hiddenColumns.iterator();
+          while (it.hasNext())
+          {
+            int[] range = it.next();
+            size += range[1] - range[0] + 1;
+          }
         }
+        numColumns = size;
       }
-      return size;
+
+      return numColumns;
     } finally
     {
       LOCK.readLock().unlock();
@@ -266,7 +277,7 @@ public class HiddenColumns
 
       if (hiddenColumns != null)
       {
-        result += cursor.getHiddenOffset(column);
+        result += cursor.getHiddenOffset(column).getHiddenSoFar();
       }
 
       return result;
@@ -294,8 +305,10 @@ public class HiddenColumns
 
       if (hiddenColumns != null)
       {
-        int index = cursor.findRegionForColumn(hiddenColumn);
-        int hiddenBeforeCol = cursor.getHiddenSoFar();
+        HiddenCursorPosition cursorPos = cursor
+                .findRegionForColumn(hiddenColumn);
+        int index = cursorPos.getRegionIndex();
+        int hiddenBeforeCol = cursorPos.getHiddenSoFar();
     
         // just subtract hidden cols count - this works fine if column is
         // visible
@@ -397,7 +410,7 @@ public class HiddenColumns
       LOCK.readLock().lock();
       if (hiddenColumns != null)
       {
-        int index = cursor.findRegionForColumn(alPos);
+        int index = cursor.findRegionForColumn(alPos).getRegionIndex();
         if (index < hiddenColumns.size())
         {
           int[] region = hiddenColumns.get(index);
@@ -438,7 +451,7 @@ public class HiddenColumns
 
       if (hiddenColumns != null)
       {
-        int index = cursor.findRegionForColumn(alPos);
+        int index = cursor.findRegionForColumn(alPos).getRegionIndex();
 
         if (index > 0)
         {
@@ -505,6 +518,9 @@ public class HiddenColumns
       if (!wasAlreadyLocked)
       {
         cursor.resetCursor(hiddenColumns);
+
+        // reset the number of columns so they will be recounted
+        numColumns = 0;
       }
     } finally
     {
@@ -593,18 +609,17 @@ public class HiddenColumns
     {
       LOCK.readLock().lock();
 
-      Iterator<int[]> it = new RegionsIterator(column, column,
-              hiddenColumns, cursor);
-      while (it.hasNext())
+      int regionindex = cursor.findRegionForColumn(column).getRegionIndex();
+      if (regionindex > -1 && regionindex < hiddenColumns.size())
       {
-        int[] region = it.next();
+        int[] region = hiddenColumns.get(regionindex);
         if (column >= region[0] && column <= region[1])
         {
           return false;
         }
       }
-
       return true;
+
     } finally
     {
       LOCK.readLock().unlock();
@@ -898,6 +913,7 @@ public class HiddenColumns
         hideColumns(r[0], r[1]);
       }
       cursor.resetCursor(hiddenColumns);
+      numColumns = 0;
     } finally
     {
       LOCK.writeLock().unlock();
@@ -925,6 +941,7 @@ public class HiddenColumns
         }
         hiddenColumns = null;
         cursor.resetCursor(hiddenColumns);
+        numColumns = 0;
       }
     } finally
     {
@@ -946,7 +963,8 @@ public class HiddenColumns
 
       if (hiddenColumns != null)
       {
-        int regionIndex = cursor.findRegionForColumn(start);
+        int regionIndex = cursor.findRegionForColumn(start)
+                .getRegionIndex();
 
         if (regionIndex != -1 && regionIndex != hiddenColumns.size())
         {
@@ -959,13 +977,20 @@ public class HiddenColumns
             {
               sel.addElement(j);
             }
+            int colsToRemove = region[1] - region[0] + 1;
             hiddenColumns.remove(regionIndex);
 
             if (hiddenColumns.isEmpty())
             {
               hiddenColumns = null;
+              numColumns = 0;
+            }
+            else
+            {
+              numColumns -= colsToRemove;
             }
             cursor.updateForDeletedRegion(hiddenColumns);
+
           }
         }
       }
@@ -1074,6 +1099,7 @@ public class HiddenColumns
       }
       hiddenColumns = newhidden;
       cursor.resetCursor(hiddenColumns);
+      numColumns = 0;
     } finally
     {
       LOCK.writeLock().unlock();
@@ -1178,6 +1204,7 @@ public class HiddenColumns
         hideColumns(firstSet, lastSet - 1);
       }
       cursor.resetCursor(hiddenColumns);
+      numColumns = 0;
     } finally
     {
       LOCK.writeLock().unlock();
@@ -1284,15 +1311,24 @@ public class HiddenColumns
 
       if (hiddenColumns != null)
       {
-        int regionindex = cursor.findRegionForColumn(adjres - 1);
+        // look for a region ending just before adjres
+        int regionindex = cursor.findRegionForColumn(adjres - 1)
+                .getRegionIndex();
         if (regionindex < hiddenColumns.size()
                 && hiddenColumns.get(regionindex)[1] == adjres - 1)
         {
           reveal = hiddenColumns.get(regionindex);
         }
+        // check if the region ends just after adjres
+        else if (regionindex < hiddenColumns.size()
+                && hiddenColumns.get(regionindex)[0] == adjres + 1)
+        {
+          reveal = hiddenColumns.get(regionindex);
+        }
+        // or try the next region
         else
         {
-          regionindex = cursor.findRegionForColumn(adjres + 1);
+          regionindex++;
           if (regionindex < hiddenColumns.size()
                   && hiddenColumns.get(regionindex)[0] == adjres + 1)
           {