JAL-2759 improvements to speed up synchronisation; caching of size
[jalview.git] / src / jalview / datamodel / HiddenColumns.java
index 8c1a0fb..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;
@@ -291,16 +302,18 @@ public class HiddenColumns
     {
       LOCK.readLock().lock();
       int result = hiddenColumn;
-      // int[] region = null;
+
       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
         result = hiddenColumn - hiddenBeforeCol;
-
+    
         // now check in case column is hidden - it will be in the returned
         // hidden region
         if (index < hiddenColumns.size())
@@ -321,6 +334,7 @@ public class HiddenColumns
           }
         }
       }
+
       return result; // return the shifted position after removing hidden
                      // columns.
     } finally
@@ -396,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);
@@ -437,7 +451,7 @@ public class HiddenColumns
 
       if (hiddenColumns != null)
       {
-        int index = cursor.findRegionForColumn(alPos);
+        int index = cursor.findRegionForColumn(alPos).getRegionIndex();
 
         if (index > 0)
         {
@@ -504,6 +518,9 @@ public class HiddenColumns
       if (!wasAlreadyLocked)
       {
         cursor.resetCursor(hiddenColumns);
+
+        // reset the number of columns so they will be recounted
+        numColumns = 0;
       }
     } finally
     {
@@ -592,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();
@@ -897,6 +913,7 @@ public class HiddenColumns
         hideColumns(r[0], r[1]);
       }
       cursor.resetCursor(hiddenColumns);
+      numColumns = 0;
     } finally
     {
       LOCK.writeLock().unlock();
@@ -924,6 +941,7 @@ public class HiddenColumns
         }
         hiddenColumns = null;
         cursor.resetCursor(hiddenColumns);
+        numColumns = 0;
       }
     } finally
     {
@@ -942,31 +960,40 @@ public class HiddenColumns
     try
     {
       LOCK.writeLock().lock();
-      Iterator<int[]> it = new RegionsIterator(start, start, hiddenColumns,
-              cursor);
-      while (it.hasNext())
+
+      if (hiddenColumns != null)
       {
-        int[] region = it.next();
-        if (start == region[0])
+        int regionIndex = cursor.findRegionForColumn(start)
+                .getRegionIndex();
+
+        if (regionIndex != -1 && regionIndex != hiddenColumns.size())
         {
-          for (int j = region[0]; j < region[1] + 1; j++)
+          // regionIndex is the region which either contains start
+          // or lies to the right of start
+          int[] region = hiddenColumns.get(regionIndex);
+          if (start == region[0])
           {
-            sel.addElement(j);
+            for (int j = region[0]; j < region[1] + 1; j++)
+            {
+              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);
+
           }
-          it.remove();
-          break;
-        }
-        else if (start < region[0])
-        {
-          break; // passed all possible matching regions
         }
       }
-
-      if (hiddenColumns.size() == 0)
-      {
-        hiddenColumns = null;
-      }
-      cursor.resetCursor(hiddenColumns);
     } finally
     {
       LOCK.writeLock().unlock();
@@ -1072,6 +1099,7 @@ public class HiddenColumns
       }
       hiddenColumns = newhidden;
       cursor.resetCursor(hiddenColumns);
+      numColumns = 0;
     } finally
     {
       LOCK.writeLock().unlock();
@@ -1176,6 +1204,7 @@ public class HiddenColumns
         hideColumns(firstSet, lastSet - 1);
       }
       cursor.resetCursor(hiddenColumns);
+      numColumns = 0;
     } finally
     {
       LOCK.writeLock().unlock();
@@ -1282,15 +1311,26 @@ public class HiddenColumns
 
       if (hiddenColumns != null)
       {
-        int regionindex = cursor.findRegionForColumn(adjres - 1);
-        if (hiddenColumns.get(regionindex)[1] == 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);
-          if (hiddenColumns.get(regionindex)[0] == adjres + 1)
+          regionindex++;
+          if (regionindex < hiddenColumns.size()
+                  && hiddenColumns.get(regionindex)[0] == adjres + 1)
           {
             reveal = hiddenColumns.get(regionindex);
           }