JAL-147 ViewportRanges calculate wrapped vertical scroll position
[jalview.git] / src / jalview / gui / AlignmentPanel.java
index 437e678..9d21a6c 100644 (file)
@@ -629,21 +629,24 @@ public class AlignmentPanel extends GAlignmentPanel implements
       annotationSpaceFillerHolder.setVisible(true);
     }
 
-    if (wrap)
-    {
-      int widthInRes = getSeqPanel().seqCanvas
-              .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth());
-      vpRanges.setViewportWidth(widthInRes);
-    }
-    else
-    {
-      int widthInRes = (getSeqPanel().seqCanvas.getWidth() / av
-              .getCharWidth()) - 1;
-      int heightInSeq = (getSeqPanel().seqCanvas.getHeight() / av
-              .getCharHeight()) - 1;
+    int canvasWidth = getSeqPanel().seqCanvas.getWidth();
+    if (canvasWidth > 0)
+    { // may not yet be laid out
+      if (wrap)
+      {
+        int widthInRes = getSeqPanel().seqCanvas
+                .getWrappedCanvasWidth(canvasWidth);
+        vpRanges.setViewportWidth(widthInRes);
+      }
+      else
+      {
+        int widthInRes = (canvasWidth / av.getCharWidth()) - 1;
+        int heightInSeq = (getSeqPanel().seqCanvas.getHeight() / av
+                .getCharHeight()) - 1;
 
-      vpRanges.setViewportWidth(widthInRes);
-      vpRanges.setViewportHeight(heightInSeq);
+        vpRanges.setViewportWidth(widthInRes);
+        vpRanges.setViewportHeight(heightInSeq);
+      }
     }
 
     idSpaceFillerPanel1.setVisible(!wrap);
@@ -735,101 +738,111 @@ public class AlignmentPanel extends GAlignmentPanel implements
   @Override
   public void adjustmentValueChanged(AdjustmentEvent evt)
   {
-    int oldX = vpRanges.getStartRes();
-    int oldwidth = vpRanges.getViewportWidth();
-    int oldY = vpRanges.getStartSeq();
-    int oldheight = vpRanges.getViewportHeight();
-
     if (av.getWrapAlignment())
     {
-      if (evt.getSource() == hscroll)
-      {
-        return; // no horizontal scroll when wrapped
-      }
-      else if (evt.getSource() == vscroll)
+      adjustScrollingWrapped(evt);
+      return;
+    }
+
+    if (evt.getSource() == hscroll)
+    {
+      int oldX = vpRanges.getStartRes();
+      int oldwidth = vpRanges.getViewportWidth();
+      int x = hscroll.getValue();
+      int width = getSeqPanel().seqCanvas.getWidth() / av.getCharWidth();
+
+      // if we're scrolling to the position we're already at, stop
+      // this prevents infinite recursion of events when the scroll/viewport
+      // ranges values are the same
+      if ((x == oldX) && (width == oldwidth))
       {
-        int offy = vscroll.getValue();
-        int rowSize = getSeqPanel().seqCanvas
-                .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth());
-
-        // if we're scrolling to the position we're already at, stop
-        // this prevents infinite recursion of events when the scroll/viewport
-        // ranges values are the same
-        int newX = offy * rowSize;
-        newX += oldX % rowSize; // horizontal scroll offset if any
-        if ((newX == oldX) && (oldwidth == rowSize))
-        {
-          return;
-        }
-        else if (offy > -1)
-        {
-          // limit page up/down to one width's worth of positions
-          newX = newX > oldX ? oldX + rowSize : oldX - rowSize;
-          vpRanges.setViewportStartAndWidth(newX, rowSize);
-        }
+        return;
       }
-      else
+      vpRanges.setViewportStartAndWidth(x, width);
+    }
+    else if (evt.getSource() == vscroll)
+    {
+      int oldY = vpRanges.getStartSeq();
+      int oldheight = vpRanges.getViewportHeight();
+      int y = vscroll.getValue();
+      int height = getSeqPanel().seqCanvas.getHeight() / av.getCharHeight();
+
+      // if we're scrolling to the position we're already at, stop
+      // this prevents infinite recursion of events when the scroll/viewport
+      // ranges values are the same
+      if ((y == oldY) && (height == oldheight))
       {
-        // This is only called if file loaded is a jar file that
-        // was wrapped when saved and user has wrap alignment true
-        // as preference setting
-        SwingUtilities.invokeLater(new Runnable()
-        {
-          @Override
-          public void run()
-        {
-            // When updating scrolling to use ViewportChange events, this code
-            // could not be validated and it is not clear if it is now being
-            // called. Log warning here in case it is called and unforeseen
-            // problems occur
-            Cache.log
-                    .warn("Unexpected path through code: Wrapped jar file opened with wrap alignment set in preferences");
-
-            // scroll to start of panel
-            vpRanges.setStartRes(0);
-            vpRanges.setStartSeq(0);
-          }
-        });
+        return;
       }
+      vpRanges.setViewportStartAndHeight(y, height);
+    }
+    if (!fastPaint)
+    {
       repaint();
     }
-    else
+  }
+
+  /**
+   * Responds to a scroll change by setting the start position of the viewport.
+   * Does
+   * 
+   * @param evt
+   */
+  protected void adjustScrollingWrapped(AdjustmentEvent evt)
+  {
+    if (evt.getSource() == hscroll)
     {
-      // horizontal scroll
-      if (evt.getSource() == hscroll)
-      {
-        int x = hscroll.getValue();
-        int width = getSeqPanel().seqCanvas.getWidth() / av.getCharWidth();
+      return; // no horizontal scroll when wrapped
+    }
+    if (evt.getSource() == vscroll)
+    {
+      int newY = vscroll.getValue();
 
-        // if we're scrolling to the position we're already at, stop
-        // this prevents infinite recursion of events when the scroll/viewport
-        // ranges values are the same
-        if ((x == oldX) && (width == oldwidth))
-        {
-          return;
-        }
-        vpRanges.setViewportStartAndWidth(x, width);
-      }
-      else if (evt.getSource() == vscroll)
+      /*
+       * if we're scrolling to the position we're already at, stop
+       * this prevents infinite recursion of events when the scroll/viewport
+       * ranges values are the same
+       */
+      int oldX = vpRanges.getStartRes();
+      int oldY = vpRanges.getWrappedScrollPosition(oldX);
+      if (oldY == newY)
       {
-        int y = vscroll.getValue();
-        int height = getSeqPanel().seqCanvas.getHeight()
-                / av.getCharHeight();
-
-        // if we're scrolling to the position we're already at, stop
-        // this prevents infinite recursion of events when the scroll/viewport
-        // ranges values are the same
-        if ((y == oldY) && (height == oldheight))
-        {
-          return;
-        }
-        vpRanges.setViewportStartAndHeight(y, height);
+        return;
       }
-      if (!fastPaint)
+      else if (newY > -1)
       {
-        repaint();
+        /*
+         * limit page up/down to one width's worth of positions
+         */
+        int rowSize = vpRanges.getViewportWidth();
+        int newX = newY > oldY ? oldX + rowSize : oldX - rowSize;
+        vpRanges.setViewportStartAndWidth(newX, rowSize);
       }
     }
+    else
+    {
+      // This is only called if file loaded is a jar file that
+      // was wrapped when saved and user has wrap alignment true
+      // as preference setting
+      SwingUtilities.invokeLater(new Runnable()
+      {
+        @Override
+        public void run()
+      {
+          // When updating scrolling to use ViewportChange events, this code
+          // could not be validated and it is not clear if it is now being
+          // called. Log warning here in case it is called and unforeseen
+          // problems occur
+          Cache.log
+                  .warn("Unexpected path through code: Wrapped jar file opened with wrap alignment set in preferences");
+
+          // scroll to start of panel
+          vpRanges.setStartRes(0);
+          vpRanges.setStartSeq(0);
+        }
+      });
+    }
+    repaint();
   }
 
   /**
@@ -879,35 +892,21 @@ public class AlignmentPanel extends GAlignmentPanel implements
     setScrollValues(vpRanges.getStartRes(), vpRanges.getStartSeq());
   }
 
-  /*
-   * Set vertical scroll bar parameters for wrapped panel
-   * @param res 
-   *    the residue to scroll to
+  /**
+   * Set vertical scroll bar position, and number of increments, for wrapped
+   * panel
+   * 
+   * @param topLeftColumn
+   *          the column position at top left (0..)
    */
-  private void setScrollingForWrappedPanel(int res)
+  private void setScrollingForWrappedPanel(int topLeftColumn)
   {
-    // get the width of the alignment in residues
-    int maxwidth = av.getAlignment().getWidth();
-    if (av.hasHiddenColumns())
-    {
-        maxwidth = av.getAlignment().getHiddenColumns()
-                .findColumnPosition(maxwidth) - 1;
-    }
+    int scrollPosition = vpRanges.getWrappedScrollPosition(topLeftColumn);
+    int maxScroll = vpRanges.getWrappedScrollPosition(vpRanges
+            .getVisibleAlignmentWidth() - 1);
 
-    // get the width of the canvas in residues
-    int canvasWidth = getSeqPanel().seqCanvas
-            .getWrappedCanvasWidth(getSeqPanel().seqCanvas.getWidth());
-    if (canvasWidth > 0)
-    {
-      // position we want to scroll to is number of canvasWidth's to get there
-      int current = res / canvasWidth;
-
-      // max scroll position: add one because extent is 1 and scrollbar value
-      // can only be set to at most max - extent
-      int max = maxwidth / canvasWidth + 1;
-      vscroll.setUnitIncrement(1);
-      vscroll.setValues(current, 1, 0, max);
-    }
+    vscroll.setUnitIncrement(1);
+    vscroll.setValues(scrollPosition, 1, 0, maxScroll);
   }
 
   /**