JAL-3253 temporary branch SwingJS upgrade with testNG fixes Java 8
[jalview.git] / src / jalview / viewmodel / ViewportRanges.java
index 4bdaa81..af75b27 100644 (file)
@@ -41,6 +41,8 @@ public class ViewportRanges extends ViewportProperties
 
   public static final String STARTRESANDSEQ = "startresandseq";
 
+  public static final String MOVE_VIEWPORT = "move_viewport";
+
   private boolean wrappedMode = false;
 
   // start residue of viewport
@@ -95,7 +97,7 @@ public class ViewportRanges extends ViewportProperties
    */
   public int getVisibleAlignmentWidth()
   {
-    return al.getWidth() - al.getHiddenColumns().getSize();
+    return al.getVisibleWidth();
   }
 
   /**
@@ -135,11 +137,20 @@ public class ViewportRanges extends ViewportProperties
     int oldstartres = oldvalues[0];
     int oldendres = oldvalues[1];
 
+    if (oldstartres == startRes && oldendres == endRes)
+    {
+      return; // BH 2019.07.27 standard check for no changes
+    }
+
+    // "STARTRES" is a misnomer here -- really "STARTORENDRES"
+    // note that this could be "no change" if the range is just being expanded
     changeSupport.firePropertyChange(STARTRES, oldstartres, startRes);
     if (oldstartres == startRes)
     {
-      // event won't be fired if start positions are same
-      // fire an event for the end positions in case they changed
+      // No listener cares about this
+      // "ENDRES" is a misnomer here -- really "ENDONLYRES"
+      // BH 2019.07.27 adds end change check
+      // fire only if only the end is changed
       changeSupport.firePropertyChange(ENDRES, oldendres, endRes);
     }
   }
@@ -201,12 +212,13 @@ public class ViewportRanges extends ViewportProperties
    */
   public void setStartSeq(int seq)
   {
-    int startseq = seq;
     int height = getViewportHeight();
-    if (startseq + height - 1 > getVisibleAlignmentHeight() - 1)
-    {
-      startseq = getVisibleAlignmentHeight() - height;
-    }
+    int startseq = Math.min(seq, getVisibleAlignmentHeight() - height);
+    // BH 2019.07.27 cosmetic only -- was:
+    // if (startseq + height - 1 > getVisibleAlignmentHeight() - 1)
+    // {
+    // startseq = getVisibleAlignmentHeight() - height;
+    // }
     setStartEndSeq(startseq, startseq + height - 1);
   }
 
@@ -222,15 +234,24 @@ public class ViewportRanges extends ViewportProperties
    */
   public void setStartEndSeq(int start, int end)
   {
+    // System.out.println("ViewportRange setStartEndSeq " + start + " " + end);
     int[] oldvalues = updateStartEndSeq(start, end);
     int oldstartseq = oldvalues[0];
     int oldendseq = oldvalues[1];
 
+    if (oldstartseq == startSeq && oldendseq == endSeq)
+    {
+      return; // BH 2019.07.27 standard check for no changes
+    }
+
+    // "STARTSEQ" is a misnomer here -- really "STARTORENDSEQ"
     changeSupport.firePropertyChange(STARTSEQ, oldstartseq, startSeq);
     if (oldstartseq == startSeq)
     {
-      // event won't be fired if start positions are the same
-      // fire in case the end positions changed
+      // Note that all listeners ignore this - could be removed, or there is a
+      // bug.
+      // "ENDSEQ" is a misnomer here -- really "ENDONLYSEQ"
+      // additional fire, only if only the end is changed
       changeSupport.firePropertyChange(ENDSEQ, oldendseq, endSeq);
     }
   }
@@ -283,12 +304,12 @@ public class ViewportRanges extends ViewportProperties
    * event.
    * 
    * @param seq
-   *          sequence position
+   *          sequence position in the range [0, height)
    */
   public void setEndSeq(int seq)
   {
-    int height = getViewportHeight();
-    setStartEndSeq(seq - height + 1, seq);
+    // BH 2018.04.18 added safety for seq < 0; comment about not being >= height
+    setStartEndSeq(Math.max(0, seq + 1 - getViewportHeight()), seq);
   }
 
   /**
@@ -314,9 +335,9 @@ public class ViewportRanges extends ViewportProperties
     }
     int[] oldseqvalues = updateStartEndSeq(startseq, startseq + height - 1);
 
-    int[] old = new int[] { oldresvalues[0], oldseqvalues[0] };
-    int[] newresseq = new int[] { startRes, startSeq };
-    changeSupport.firePropertyChange(STARTRESANDSEQ, old, newresseq);
+    int[] oldvalues = new int[] { oldresvalues[0], oldseqvalues[0] };
+    int[] newvalues = new int[] { startRes, startSeq };
+    changeSupport.firePropertyChange(STARTRESANDSEQ, oldvalues, newvalues);
   }
 
   /**
@@ -423,17 +444,19 @@ public class ViewportRanges extends ViewportProperties
   public void setViewportStartAndHeight(int start, int h)
   {
     int vpstart = start;
+
+    int visHeight = getVisibleAlignmentHeight();
     if (vpstart < 0)
     {
       vpstart = 0;
     }
-    else if ((h <= getVisibleAlignmentHeight())
-            && (vpstart + h - 1 > getVisibleAlignmentHeight() - 1))
+    else if (h <= visHeight && vpstart + h > visHeight)
     // viewport height is less than the full alignment and we are running off
     // the bottom
     {
-      vpstart = getVisibleAlignmentHeight() - h;
+      vpstart = visHeight - h;
     }
+
     setStartEndSeq(vpstart, vpstart + h - 1);
   }
 
@@ -542,18 +565,33 @@ public class ViewportRanges extends ViewportProperties
    * the startRes changed, else false.
    * 
    * @param res
-   *          residue position to scroll to
+   *          residue position to scroll to NB visible position not absolute
+   *          alignment position
    * @return
    */
   public boolean scrollToWrappedVisible(int res)
   {
-    int oldStartRes = startRes;
-    int width = getViewportWidth();
-
-    if (res >= oldStartRes && res < oldStartRes + width)
+    int newStartRes = calcWrappedStartResidue(res);
+    if (newStartRes == startRes)
     {
       return false;
     }
+    setStartRes(newStartRes);
+
+    return true;
+  }
+
+  /**
+   * Calculate wrapped start residue from visible start residue
+   * 
+   * @param res
+   *          visible start residue
+   * @return left column of panel res will be located in
+   */
+  private int calcWrappedStartResidue(int res)
+  {
+    int oldStartRes = startRes;
+    int width = getViewportWidth();
 
     boolean up = res < oldStartRes;
     int widthsToScroll = Math.abs((res - oldStartRes) / width);
@@ -569,19 +607,16 @@ public class ViewportRanges extends ViewportProperties
     {
       newStartRes = 0;
     }
-
-    setStartRes(newStartRes);
-
-    return true;
+    return newStartRes;
   }
 
   /**
    * Scroll so that (x,y) is visible. Fires a property change event.
    * 
    * @param x
-   *          x position in alignment
+   *          x position in alignment (absolute position)
    * @param y
-   *          y position in alignment
+   *          y position in alignment (absolute position)
    */
   public void scrollToVisible(int x, int y)
   {
@@ -593,16 +628,16 @@ public class ViewportRanges extends ViewportProperties
     {
       scrollUp(false);
     }
-
+    
     HiddenColumns hidden = al.getHiddenColumns();
-    while (x < hidden.adjustForHiddenColumns(startRes))
+    while (x < hidden.visibleToAbsoluteColumn(startRes))
     {
       if (!scrollRight(false))
       {
         break;
       }
     }
-    while (x > hidden.adjustForHiddenColumns(endRes))
+    while (x > hidden.visibleToAbsoluteColumn(endRes))
     {
       if (!scrollRight(true))
       {
@@ -612,6 +647,62 @@ public class ViewportRanges extends ViewportProperties
   }
 
   /**
+   * Set the viewport location so that a position is visible
+   * 
+   * @param x
+   *          column to be visible: absolute position in alignment
+   * @param y
+   *          row to be visible: absolute position in alignment
+   */
+  public boolean setViewportLocation(int x, int y)
+  {
+    boolean changedLocation = false;
+
+    // convert the x,y location to visible coordinates
+    int visX = al.getHiddenColumns().absoluteToVisibleColumn(x);
+    int visY = al.getHiddenSequences().findIndexWithoutHiddenSeqs(y);
+
+    // if (vis_x,vis_y) is already visible don't do anything
+    if (startRes > visX || visX > endRes
+            || startSeq > visY && visY > endSeq)
+    {
+      int[] old = new int[] { startRes, startSeq };
+      int[] newresseq;
+      if (wrappedMode)
+      {
+        int newstartres = calcWrappedStartResidue(visX);
+        setStartRes(newstartres);
+        newresseq = new int[] { startRes, startSeq };
+      }
+      else
+      {
+        // set the viewport x location to contain vis_x
+        int newstartres = visX;
+        int width = getViewportWidth();
+        if (newstartres + width - 1 > getVisibleAlignmentWidth() - 1)
+        {
+          newstartres = getVisibleAlignmentWidth() - width;
+        }
+        updateStartEndRes(newstartres, newstartres + width - 1);
+
+        // set the viewport y location to contain vis_y
+        int newstartseq = visY;
+        int height = getViewportHeight();
+        if (newstartseq + height - 1 > getVisibleAlignmentHeight() - 1)
+        {
+          newstartseq = getVisibleAlignmentHeight() - height;
+        }
+        updateStartEndSeq(newstartseq, newstartseq + height - 1);
+
+        newresseq = new int[] { startRes, startSeq };
+      }
+      changedLocation = true;
+      changeSupport.firePropertyChange(MOVE_VIEWPORT, old, newresseq);
+    }
+    return changedLocation;
+  }
+
+  /**
    * Adjust sequence position for page up. Fires a property change event.
    */
   public void pageUp()
@@ -722,4 +813,11 @@ public class ViewportRanges extends ViewportProperties
 
     return maxScroll;
   }
+
+  @Override
+  public String toString()
+  {
+    return "[ViewportRange startRes=" + startRes + " endRes=" + endRes
+            + " startSeq=" + startSeq + " endSeq=" + endSeq + "]";
+  }
 }