JAL-2674 testing
[jalview.git] / src / jalview / gui / SeqCanvas.java
index 8004cac..f72acae 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;
@@ -41,7 +42,7 @@ import java.awt.RenderingHints;
 import java.awt.Shape;
 import java.awt.image.BufferedImage;
 import java.beans.PropertyChangeEvent;
-import java.util.List;
+import java.util.Iterator;
 
 import javax.swing.JComponent;
 
@@ -283,7 +284,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
    */
   public void fastPaint(int horizontal, int vertical)
   {
-    if (fastpainting || gg == null)
+    if (fastpainting || gg == null || img == null)
     {
       return;
     }
@@ -429,12 +430,16 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
   public void drawPanelForPrinting(Graphics g1, int startRes, int endRes,
           int startSeq, int endSeq)
   {
+    drawPanel(g1, startRes, endRes, startSeq, endSeq, 0);
+
     BufferedImage selectImage = drawSelectionGroup(startRes, endRes,
             startSeq, endSeq);
-    drawPanel(g1, startRes, endRes, startSeq, endSeq, 0);
-    ((Graphics2D) g1).setComposite(
-            AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
-    g1.drawImage(selectImage, 0, 0, this);
+    if (selectImage != null)
+    {
+      ((Graphics2D) g1).setComposite(AlphaComposite
+              .getInstance(AlphaComposite.SRC_OVER));
+      g1.drawImage(selectImage, 0, 0, this);
+    }
   }
 
   /**
@@ -453,18 +458,34 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
           int canvasHeight, int startRes)
   {
     SequenceGroup group = av.getSelectionGroup();
-    BufferedImage selectImage = new BufferedImage(canvasWidth, canvasHeight,
-            BufferedImage.TYPE_INT_ARGB); // ARGB so alpha compositing works
+
+    drawWrappedPanel(g, canvasWidth, canvasHeight, startRes);
 
     if (group != null)
     {
-      Graphics2D g2 = selectImage.createGraphics();
-      setupSelectionGroup(g2, selectImage);
-      drawWrappedSelection(g2, group, canvasWidth, canvasHeight, startRes);
-      drawWrappedPanel(g, canvasWidth, canvasHeight, startRes);
-      g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
-      g.drawImage(selectImage, 0, 0, this);
-      g2.dispose();
+      BufferedImage selectImage = null;
+      try
+      {
+        selectImage = new BufferedImage(canvasWidth, canvasHeight,
+                BufferedImage.TYPE_INT_ARGB); // ARGB so alpha compositing works
+      } catch (OutOfMemoryError er)
+      {
+        System.gc();
+        System.err.println("Print image OutOfMemory Error.\n" + er);
+        new OOMWarning("Creating wrapped alignment image for printing", er);
+      }
+      if (selectImage != null)
+      {
+        Graphics2D g2 = selectImage.createGraphics();
+        setupSelectionGroup(g2, selectImage);
+        drawWrappedSelection(g2, group, canvasWidth, canvasHeight,
+                startRes);
+
+        g2.setComposite(
+                AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
+        g.drawImage(selectImage, 0, 0, this);
+        g2.dispose();
+      }
     }
   }
 
@@ -676,25 +697,19 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
         g.setColor(Color.blue);
         int res;
         HiddenColumns hidden = av.getAlignment().getHiddenColumns();
-        List<Integer> positions = hidden.findHiddenRegionPositions();
-        for (int pos : positions)
-        {
-          res = pos - startRes;
-
-          if (res < 0 || res > endx - startRes)
-          {
-            continue;
-          }
 
+        Iterator<Integer> it = hidden.getBoundedStartIterator(startRes,
+                endx + 1);
+        while (it.hasNext())
+        {
+          res = it.next() - startRes;
           gg.fillPolygon(
                   new int[]
-                  { res * charWidth - charHeight / 4,
-                      res * charWidth + charHeight / 4, res * charWidth },
+          { res * charWidth - charHeight / 4,
+              res * charWidth + charHeight / 4, res * charWidth },
                   new int[]
-                  { ypos - (charHeight / 2), ypos - (charHeight / 2),
-                      ypos - (charHeight / 2) + 8 },
-                  3);
-
+          { ypos - (charHeight / 2), ypos - (charHeight / 2),
+              ypos - (charHeight / 2) + 8 }, 3);
         }
       }
 
@@ -807,7 +822,6 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
     return annotations.adjustPanelHeight();
   }
 
-
   /**
    * Draws the visible region of the alignment on the graphics context. If there
    * are hidden column markers in the visible region, then each sub-region
@@ -827,9 +841,8 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
    * @param yOffset
    *          vertical offset at which to draw (for wrapped alignments)
    */
-  private void drawPanel(Graphics g1, int startRes, int endRes,
-          int startSeq, int endSeq, int yOffset)
-
+  public void drawPanel(Graphics g1, final int startRes, final int endRes,
+          final int startSeq, final int endSeq, final int yOffset)
   {
     updateViewport();
     if (!av.hasHiddenColumns())
@@ -839,29 +852,23 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
     else
     {
       int screenY = 0;
-      final int screenYMax = endRes - startRes;
-      int blockStart = startRes;
-      int blockEnd = endRes;
+      int blockStart;
+      int blockEnd;
 
-      for (int[] region : av.getAlignment().getHiddenColumns()
-              .getHiddenColumnsCopy())
-      {
-        int hideStart = region[0];
-        int hideEnd = region[1];
+      HiddenColumns hidden = av.getAlignment().getHiddenColumns();
+      VisibleBlocksVisBoundsIterator regions = (VisibleBlocksVisBoundsIterator) hidden
+              .getVisibleBlocksIterator(startRes, endRes, true);
 
-        if (hideStart <= blockStart)
-        {
-          blockStart += (hideEnd - hideStart) + 1;
-          continue;
-        }
+      while (regions.hasNext())
+      {
+        int[] region = regions.next();
+        blockEnd = region[1];
+        blockStart = region[0];
 
         /*
          * 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);
-
         g1.translate(screenY * charWidth, 0);
 
         draw(g1, blockStart, blockEnd, startSeq, endSeq, yOffset);
@@ -870,7 +877,8 @@ 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()))
         {
           g1.setColor(Color.blue);
 
@@ -881,29 +889,11 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
 
         g1.translate(-screenY * charWidth, 0);
         screenY += blockEnd - blockStart + 1;
-        blockStart = hideEnd + 1;
-
-        if (screenY > screenYMax)
-        {
-          // already rendered last block
-          return;
-        }
-      }
-
-      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);
       }
     }
 
   }
 
-
   /**
    * Draws a region of the visible alignment
    * 
@@ -1010,7 +1000,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
       {
         drawPartialGroupOutline(g, group, startRes, endRes, startSeq,
                 endSeq, offset);
-        
+
         groupIndex++;
 
         g.setStroke(new BasicStroke());
@@ -1110,22 +1100,17 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
     {
       // package into blocks of visible columns
       int screenY = 0;
-      int blockStart = startRes;
-      int blockEnd = endRes;
+      int blockStart;
+      int blockEnd;
 
-      for (int[] region : av.getAlignment().getHiddenColumns()
-              .getHiddenColumnsCopy())
+      HiddenColumns hidden = av.getAlignment().getHiddenColumns();
+      VisibleBlocksVisBoundsIterator regions = (VisibleBlocksVisBoundsIterator) hidden
+              .getVisibleBlocksIterator(startRes, endRes, true);
+      while (regions.hasNext())
       {
-        int hideStart = region[0];
-        int hideEnd = region[1];
-
-        if (hideStart <= blockStart)
-        {
-          blockStart += (hideEnd - hideStart) + 1;
-          continue;
-        }
-
-        blockEnd = hideStart - 1;
+        int[] region = regions.next();
+        blockEnd = region[1];
+        blockStart = region[0];
 
         g.translate(screenY * charWidth, 0);
         drawPartialGroupOutline(g, group,
@@ -1133,24 +1118,6 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
 
         g.translate(-screenY * charWidth, 0);
         screenY += blockEnd - blockStart + 1;
-        blockStart = hideEnd + 1;
-
-        if (screenY > (endRes - startRes))
-        {
-          // already rendered last block
-          break;
-        }
-      }
-
-      if (screenY <= (endRes - startRes))
-      {
-        // remaining visible region to render
-        blockEnd = blockStart + (endRes - startRes) - screenY;
-        g.translate(screenY * charWidth, 0);
-        drawPartialGroupOutline(g, group,
-                blockStart, blockEnd, startSeq, endSeq, offset);
-        
-        g.translate(-screenY * charWidth, 0);
       }
     }
   }