JAL-147 ViewportRanges calculate wrapped vertical scroll position
[jalview.git] / src / jalview / appletgui / AlignmentPanel.java
index d7f2d5e..edf6ad4 100644 (file)
@@ -407,7 +407,8 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
       {
         int offset = (vpRanges.getEndRes() - vpRanges.getStartRes() + 1) / 2 - 1;
         start = Math.max(start - offset, 0);
-        end = Math.min(end + offset, seq.getEnd() - 1);
+        end = end + offset - 1;
+        // end = Math.min(end + offset, seq.getEnd() - 1);
       }
 
       if (start < 0)
@@ -436,11 +437,12 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
     int start = -1;
     if (av.hasHiddenColumns())
     {
-      start = av.getColumnSelection().findColumnPosition(ostart);
-      end = av.getColumnSelection().findColumnPosition(end);
+      AlignmentI al = av.getAlignment();
+      start = al.getHiddenColumns().findColumnPosition(ostart);
+      end = al.getHiddenColumns().findColumnPosition(end);
       if (start == end)
       {
-        if (!scrollToNearest && !av.getColumnSelection().isVisible(ostart))
+        if (!scrollToNearest && !al.getHiddenColumns().isVisible(ostart))
         {
           // don't scroll - position isn't visible
           return false;
@@ -673,21 +675,24 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
 
   int vextent = 0;
 
-  public void setScrollValues(int x, int y)
+  public void setScrollValues(int xpos, int ypos)
   {
+    int x = xpos;
+    int y = ypos;
+
     if (av.getWrapAlignment())
     {
       setScrollingForWrappedPanel(x);
     }
     else
     {
-
       int width = av.getAlignment().getWidth();
       int height = av.getAlignment().getHeight();
 
       if (av.hasHiddenColumns())
       {
-        width = av.getColumnSelection().findColumnPosition(width);
+        width = av.getAlignment().getHiddenColumns()
+                .findColumnPosition(width);
       }
       if (x < 0)
       {
@@ -733,127 +738,115 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
       hscroll.setValues(x, hextent, 0, width);
       vscroll.setValues(y, vextent, 0, height);
 
+      // AWT scrollbar does not fire adjustmentValueChanged for setValues
+      // so also call adjustment code!
+      adjustHorizontal(x);
+      adjustVertical(y);
+
       sendViewPosition();
     }
   }
 
+  /**
+   * Respond to adjustment event when horizontal or vertical scrollbar is
+   * changed
+   * 
+   * @param evt
+   *          adjustment event encoding whether apvscroll, hscroll or vscroll
+   *          changed
+   */
   @Override
   public void adjustmentValueChanged(AdjustmentEvent evt)
   {
-    int oldX = vpRanges.getStartRes();
-    int oldwidth = vpRanges.getViewportWidth();
-    int oldY = vpRanges.getStartSeq();
-    int oldheight = vpRanges.getViewportHeight();
-
+    // Note that this event is NOT fired by the AWT scrollbar when setValues is
+    // called. Instead manually call adjustHorizontal and adjustVertical
+    // directly.
     if (evt == null || evt.getSource() == apvscroll)
     {
       annotationPanel.setScrollOffset(apvscroll.getValue(), false);
       alabels.setScrollOffset(apvscroll.getValue(), false);
-      // annotationPanel.image=null;
-      // alabels.image=null;
-      // alabels.repaint();
-      // annotationPanel.repaint();
     }
     if (evt == null || evt.getSource() == hscroll)
     {
       int x = hscroll.getValue();
-      int width = seqPanel.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))
-      {
-        return;
-      }
-      vpRanges.setViewportStartAndWidth(x, width);
+      adjustHorizontal(x);
     }
 
     if (evt == null || evt.getSource() == vscroll)
     {
       int offy = vscroll.getValue();
-      if (av.getWrapAlignment())
-      {
-        int rowSize = seqPanel.seqCanvas
-                .getWrappedCanvasWidth(seqPanel.seqCanvas.getWidth());
+      adjustVertical(offy);
+    }
 
-        // 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 ((offy * rowSize == oldX) && (oldwidth == rowSize))
-        {
-          return;
-        }
-        else if (offy > -1)
-        {
-          vpRanges.setViewportStartAndWidth(offy * rowSize, rowSize);
-        }
-      }
-      else
-      {
-        int height = seqPanel.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 ((offy == oldY) && (height == oldheight))
-        {
-          return;
-        }
-        vpRanges.setViewportStartAndHeight(offy, height);
-      }
-    }
+  private void adjustHorizontal(int x)
+  {
+    int oldX = vpRanges.getStartRes();
+    int oldwidth = vpRanges.getViewportWidth();
+    int width = seqPanel.seqCanvas.getWidth() / av.getCharWidth();
 
-    /*    if (overviewPanel != null)
-        {
-          overviewPanel.setBoxPosition();
-        }
+    // 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);
 
-        int scrollX = vpRanges.getStartRes() - oldX;
-        int scrollY = vpRanges.getStartSeq() - oldY;
-    */
-    if (av.getWrapAlignment() || !fastPaint || av.MAC)
+    if (av.getWrapAlignment() || !fastPaint)
     {
       repaint();
     }
-    /*    else
-        {
-          // Make sure we're not trying to draw a panel
-          // larger than the visible window
-          if (scrollX > vpRanges.getEndRes() - vpRanges.getStartRes())
-          {
-            scrollX = vpRanges.getEndRes() - vpRanges.getStartRes();
-          }
-          else if (scrollX < vpRanges.getStartRes() - vpRanges.getEndRes())
-          {
-            scrollX = vpRanges.getStartRes() - vpRanges.getEndRes();
-          }
-
-          idPanel.idCanvas.fastPaint(scrollY);
-          seqPanel.seqCanvas.fastPaint(scrollX, scrollY);
-
-          scalePanel.repaint();
-          if (av.isShowAnnotation())
-          {
-            annotationPanel.fastPaint(vpRanges.getStartRes() - oldX);
-          }
-        }*/
     sendViewPosition();
+  }
 
-    /*
-     * If there is one, scroll the (Protein/cDNA) complementary alignment to
-     * match, unless we are ourselves doing that.
-     */
-    /*    if (isFollowingComplementScroll())
-        {
-          setFollowingComplementScroll(false);
-        }
-        else
-        {
-          AlignmentPanel ap = getComplementPanel();
-          av.scrollComplementaryAlignment(ap);
-        }*/
+  private void adjustVertical(int newY)
+  {
+    if (av.getWrapAlignment())
+    {
+      /*
+       * 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)
+      {
+        return;
+      }
+      else if (newY > -1)
+      {
+        /*
+         * 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
+    {
+      int height = seqPanel.seqCanvas.getHeight() / av.getCharHeight();
+      int oldY = vpRanges.getStartSeq();
+      int oldheight = vpRanges.getViewportHeight();
 
+      // 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 ((newY == oldY) && (height == oldheight))
+      {
+        return;
+      }
+      vpRanges.setViewportStartAndHeight(newY, height);
+    }
+    if (av.getWrapAlignment() || !fastPaint)
+    {
+      repaint();
+    }
+    sendViewPosition();
   }
 
   /**
@@ -922,8 +915,6 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
      * Scroll to position but centring the target residue. Also set a state flag
      * to prevent adjustmentValueChanged performing this recursively.
      */
-    setFollowingComplementScroll(true);
-    // this should be scrollToPosition(sr,verticalOffset,
     scrollToPosition(sr, seqOffset, true, true);
   }
 
@@ -994,34 +985,20 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
 
   }
 
-  /*
+  /**
    * Set vertical scroll bar parameters for wrapped panel
-   * @param res 
-   *    the residue to scroll to
+   * 
+   * @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.getColumnSelection().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 = seqPanel.seqCanvas
-            .getWrappedCanvasWidth(seqPanel.seqCanvas.getSize().width);
-    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);
   }
 
   protected Panel sequenceHolderPanel = new Panel();
@@ -1048,9 +1025,9 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
 
   /*
    * Flag set while scrolling to follow complementary cDNA/protein scroll. When
-   * true, suppresses invoking the same method recursively.
+   * false, suppresses invoking the same method recursively.
    */
-  private boolean followingComplementScroll;
+  private boolean scrollComplementaryPanel = true;
 
   private void jbInit() throws Exception
   {
@@ -1159,14 +1136,19 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
    * 
    * @param b
    */
-  protected void setFollowingComplementScroll(boolean b)
+  protected void setToScrollComplementPanel(boolean b)
   {
-    this.followingComplementScroll = b;
+    this.scrollComplementaryPanel = b;
   }
 
-  protected boolean isFollowingComplementScroll()
+  /**
+   * Get whether to scroll complement panel
+   * 
+   * @return true if cDNA/protein complement panels should be scrolled
+   */
+  protected boolean isSetToScrollComplementPanel()
   {
-    return this.followingComplementScroll;
+    return this.scrollComplementaryPanel;
   }
 
   @Override
@@ -1183,11 +1165,11 @@ public class AlignmentPanel extends Panel implements AdjustmentListener,
 
     // now update any complementary alignment (its viewport ranges object
     // is different so does not get automatically updated)
-    if (isFollowingComplementScroll())
+    if (isSetToScrollComplementPanel())
     {
-      setFollowingComplementScroll(false);
+      setToScrollComplementPanel(false);
       av.scrollComplementaryAlignment(getComplementPanel());
-      setFollowingComplementScroll(true);
+      setToScrollComplementPanel(true);
     }
 
   }