JAL-2674 2nd attempt to refactor seqcanvas drawing to iterator
authorkiramt <k.mourao@dundee.ac.uk>
Tue, 3 Oct 2017 06:45:06 +0000 (07:45 +0100)
committerkiramt <k.mourao@dundee.ac.uk>
Tue, 3 Oct 2017 06:45:06 +0000 (07:45 +0100)
src/jalview/appletgui/SeqCanvas.java
src/jalview/datamodel/HiddenColumns.java
src/jalview/gui/SeqCanvas.java

index 74a9f7f..67b21bc 100755 (executable)
@@ -562,7 +562,7 @@ public class SeqCanvas extends Panel implements ViewportListenerI
       int screenY = 0;
       final int screenYMax = endRes - startRes;
       int blockStart = startRes;
-      int blockEnd = endRes;
+      int blockEnd = endRes; // equals blockStart + screenYMax - screenY;
 
       HiddenColumns hidden = av.getAlignment().getHiddenColumns();
       Iterator<int[]> regions = hidden.iterator();
@@ -575,6 +575,7 @@ public class SeqCanvas extends Panel implements ViewportListenerI
         if (hideStart <= blockStart)
         {
           blockStart += (hideEnd - hideStart) + 1;
+          blockEnd += (hideEnd - hideStart) + 1;
           continue;
         }
 
@@ -582,8 +583,7 @@ public class SeqCanvas extends Panel implements ViewportListenerI
          * draw up to just before the next hidden region, or the end of
          * the visible region, whichever comes first
          */
-        blockEnd = Math.min(hideStart - 1,
-                blockStart + screenYMax - screenY);
+        blockEnd = Math.min(blockEnd, hideStart - 1);
         g1.translate(screenY * avcharWidth, 0);
 
         draw(g1, blockStart, blockEnd, startSeq, endSeq, offset);
@@ -603,6 +603,7 @@ public class SeqCanvas extends Panel implements ViewportListenerI
         g1.translate(-screenY * avcharWidth, 0);
         screenY += blockEnd - blockStart + 1;
         blockStart = hideEnd + 1;
+        blockEnd = blockStart + screenYMax - screenY;
 
         if (screenY > screenYMax)
         {
@@ -614,10 +615,8 @@ public class SeqCanvas extends Panel implements ViewportListenerI
       if (screenY <= screenYMax)
       {
         // remaining visible region to render
-        blockEnd = blockStart + screenYMax - screenY;
         g1.translate(screenY * avcharWidth, 0);
         draw(g1, blockStart, blockEnd, startSeq, endSeq, offset);
-
         g1.translate(-screenY * avcharWidth, 0);
       }
     }
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;
+    }
+  }
+
 }
index f61c7c6..2c8a5df 100755 (executable)
@@ -22,6 +22,7 @@ package jalview.gui;
 
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.HiddenColumns.VisibleBlocksVisBoundsIterator;
 import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
@@ -853,28 +854,33 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
       int screenY = 0;
       final int screenYMax = endRes - startRes;
       int blockStart = startRes;
-      int blockEnd = endRes;
+      int blockEnd = endRes; // equals blockStart + screenYMax - screenY;
 
       HiddenColumns hidden = av.getAlignment().getHiddenColumns();
-      Iterator<int[]> regions = hidden.iterator();
+      VisibleBlocksVisBoundsIterator regions = (VisibleBlocksVisBoundsIterator) hidden
+              .getVisibleBlocksIterator(startRes, endRes, true);// hidden.iterator();
       while (regions.hasNext())
       {
         int[] region = regions.next();
-        int hideStart = region[0];
+        blockEnd = region[1];
+        blockStart = region[0];
+/*        int hideStart = region[0];
         int hideEnd = region[1];
 
         if (hideStart <= blockStart)
         {
-          blockStart += (hideEnd - hideStart) + 1;
+          blockStart += (hideEnd - hideStart) + 1; // convert startRes to an
+                                                   // absolute value
+          blockEnd += (hideEnd - hideStart) + 1;
           continue;
         }
-
+*/
         /*
          * draw up to just before the next hidden region, or the end of
          * the visible region, whichever comes first
          */
-        blockEnd = Math.min(hideStart - 1,
-                blockStart + screenYMax - screenY);
+//        blockEnd = Math.min(hideStart - 1,
+//                blockEnd);
         g1.translate(screenY * charWidth, 0);
 
         draw(g1, blockStart, blockEnd, startSeq, endSeq, yOffset);
@@ -883,7 +889,9 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
          * draw the downline of the hidden column marker (ScalePanel draws the
          * triangle on top) if we reached it
          */
-        if (av.getShowHiddenMarkers() && blockEnd == hideStart - 1)
+        if (av.getShowHiddenMarkers()
+                && (regions.hasNext() || regions.endsAtHidden()))// blockEnd ==
+                                                           // hideStart - 1)
         {
           g1.setColor(Color.blue);
 
@@ -894,24 +902,25 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
 
         g1.translate(-screenY * charWidth, 0);
         screenY += blockEnd - blockStart + 1;
-        blockStart = hideEnd + 1;
-
+        /*       blockStart = hideEnd + 1;
+        blockEnd = blockStart + screenYMax - screenY;
+        
         if (screenY > screenYMax)
         {
           // already rendered last block
           return;
-        }
+        }*/
       }
 
-      if (screenY <= screenYMax)
+      /*      if (screenY <= screenYMax)
       {
         // remaining visible region to render
         blockEnd = blockStart + screenYMax - screenY;
         g1.translate(screenY * charWidth, 0);
         draw(g1, blockStart, blockEnd, startSeq, endSeq, yOffset);
-
+      
         g1.translate(-screenY * charWidth, 0);
-      }
+      }*/
     }
 
   }