JAL-2674 2nd attempt to refactor seqcanvas drawing to iterator
[jalview.git] / src / jalview / datamodel / HiddenColumns.java
index b6e6ce3..2088aba 100644 (file)
@@ -1393,6 +1393,37 @@ public class HiddenColumns
   }
 
   /**
+   * return an iterator over visible segments between the given start and end
+   * boundaries
+   * 
+   * @param start
+   *          (first column - inclusive from 0)
+   * @param end
+   *          (last column - inclusive)
+   * @param useVisibleCoords
+   *          if true, start and end are visible column positions, not absolute
+   *          positions
+   */
+  public Iterator<int[]> getVisibleBlocksIterator(int start, int end,
+          boolean useVisibleCoords)
+  {
+    if (useVisibleCoords)
+    {
+      // TODO
+      // we should really just convert start and end here with
+      // adjustForHiddenColumns
+      // and then create a VisibleBlocksIterator
+      // but without a cursor this will be horribly slow in some situations
+      // ... so until then...
+      return new VisibleBlocksVisBoundsIterator(start, end, true);
+    }
+    else
+    {
+      return new VisibleBlocksIterator(start, end, true);
+    }
+  }
+
+  /**
    * An iterator which iterates over hidden column regions in a range.
    */
   private class BoundedHiddenColsIterator implements Iterator<int[]>
@@ -1891,4 +1922,110 @@ public class HiddenColumns
     }
   }
 
+  /**
+   * An iterator which iterates over visible regions in a range as visible
+   * column positions.
+   */
+  public class VisibleBlocksVisBoundsIterator implements Iterator<int[]>
+  {
+    private List<int[]> vcontigs = new ArrayList<>();
+
+    private int currentPosition = 0;
+
+    private boolean endsAtHidden = true;
+
+    VisibleBlocksVisBoundsIterator(int start, int end, boolean usecopy)
+    {
+      try
+      {
+        if (usecopy)
+        {
+          LOCK.readLock().lock();
+        }
+
+        if (hiddenColumns != null && hiddenColumns.size() > 0)
+        {
+          int blockStart = start;
+          int blockEnd = end;
+          int hiddenSoFar = 0;
+          int visSoFar = 0;
+          int maxVisible = end - start;
+
+          // iterate until a region begins within (start,end]
+          int i = 0;
+          while ((i < hiddenColumns.size())
+                  && (hiddenColumns.get(i)[0] <= blockStart + hiddenSoFar))
+          {
+            hiddenSoFar += hiddenColumns.get(i)[1] - hiddenColumns.get(i)[0]
+                    + 1;
+            i++;
+          }
+
+          blockStart += hiddenSoFar; // convert start to absolute position
+          blockEnd += hiddenSoFar; // convert end too in
+
+          // iterate from start to end, adding each hidden region. Positions are
+          // absolute, and all regions which *overlap* [start,end] are used.
+          while (i < hiddenColumns.size()
+                  && (hiddenColumns.get(i)[0] <= blockEnd))
+          {
+            int[] region = hiddenColumns.get(i);
+
+            blockEnd = Math.min(blockEnd, region[0] - 1);
+
+            int[] contig = new int[] { blockStart, blockEnd };
+            vcontigs.add(contig);
+
+            visSoFar += blockEnd - blockStart + 1;
+            blockStart = region[1] + 1;
+            blockEnd = end + hiddenSoFar;
+            hiddenSoFar += region[1] - region[0] + 1;
+
+            i++;
+          }
+          if (visSoFar < maxVisible)
+          {
+            blockEnd = blockStart + maxVisible - visSoFar;
+            int[] contig = new int[] { blockStart,
+                blockEnd };
+            vcontigs.add(contig);
+
+            endsAtHidden = false;
+          }
+        }
+        else
+        {
+          int[] contig = new int[] { start, end };
+          vcontigs.add(contig);
+          endsAtHidden = false;
+        }
+      } finally
+      {
+        if (usecopy)
+        {
+          LOCK.readLock().unlock();
+        }
+      }
+    }
+
+    @Override
+    public boolean hasNext()
+    {
+      return (currentPosition < vcontigs.size());
+    }
+
+    @Override
+    public int[] next()
+    {
+      int[] result = vcontigs.get(currentPosition);
+      currentPosition++;
+      return result;
+    }
+
+    public boolean endsAtHidden()
+    {
+      return endsAtHidden;
+    }
+  }
+
 }