JAL-4375 Improved trackpad user experience for wrapped format, with vertical scrollin...
[jalview.git] / src / jalview / gui / SeqPanel.java
index ff69d61..423658d 100644 (file)
@@ -44,6 +44,7 @@ import javax.swing.Timer;
 import javax.swing.ToolTipManager;
 
 import jalview.api.AlignViewportI;
+import jalview.bin.Cache;
 import jalview.bin.Console;
 import jalview.commands.EditCommand;
 import jalview.commands.EditCommand.Action;
@@ -162,6 +163,41 @@ public class SeqPanel extends JPanel
     }
   }
 
+  /**
+   * Rotation threshold for up/down trackpad/wheelmouse movement to register for
+   * an alignment in wrapped format. Up/down scrolling here results in a large
+   * jump so a larger threshold is appropriate, and reduces unintended up/down
+   * jumps when panning left/right. Should be at least 0.1 and less than 1.0
+   * since some platforms only send a value of 1.0.
+   */
+  private static double wrappedVerticalScrollRotationThreshold;
+
+  /**
+   * Property name if user needs to change rotation threshold
+   */
+  private static String WRAPPEDVERTICALSCROLLROTATIONTHRESHOLDPC = "WRAPPEDVERTICALSCROLLROTATIONTHRESHOLDPC";
+
+  /**
+   * Time threshold since last left/right trackpad/wheelmouse scroll for up/down
+   * trackpad/wheelmouse movement to register for an alignment in wrapped
+   * format. This reduces unintended up/down jumps when panning left/right. In
+   * ms.
+   */
+  private static int wrappedVerticalScrollChangeTimeThreshold;
+
+  /**
+   * Property name if user needs to change rotation threshold
+   */
+  private static String WRAPPEDVERTICALSCROLLCHANGETIMETHRESHOLD = "WRAPPEDVERTICALSCROLLCHANGETIMETHRESHOLD ";
+
+  static
+  {
+    wrappedVerticalScrollRotationThreshold = Cache.getDefault(
+            WRAPPEDVERTICALSCROLLROTATIONTHRESHOLDPC, 50) / 100.0;
+    wrappedVerticalScrollChangeTimeThreshold = Cache
+            .getDefault(WRAPPEDVERTICALSCROLLCHANGETIMETHRESHOLD, 200);
+  }
+
   private static final int MAX_TOOLTIP_LENGTH = 300;
 
   public SeqCanvas seqCanvas;
@@ -2222,6 +2258,11 @@ public class SeqPanel extends JPanel
   }
 
   /**
+   * recorded time of last left/right mousewheel/trackpad scroll in wrapped mode
+   */
+  private long lastLeftRightWrappedScrollTime = 0;
+
+  /**
    * Responds to a mouse wheel movement by scrolling the alignment
    * <ul>
    * <li>left or right, if the shift key is down, else up or down</li>
@@ -2239,7 +2280,8 @@ public class SeqPanel extends JPanel
     int wheelRotation = e.getWheelRotation();
     if (wheelRotation == 0 && Math.abs(preciseWheelRotation) > 0.1)
     {
-      wheelRotation = 1;
+      // this is one of -1, 0 ,+1 for <0, ==0, >0
+      wheelRotation = (int) Math.signum(preciseWheelRotation);
     }
 
     /*
@@ -2260,17 +2302,28 @@ public class SeqPanel extends JPanel
         {
           av.getRanges().scrollRight(true, size);
         }
+        this.lastLeftRightWrappedScrollTime = System.currentTimeMillis();
       }
       else
       {
         /*
          * scroll down
          */
-        while (size-- > 0)
+        // apply a more definite threshold for up and down scrolling in wrap
+        // format (either not a wrapped alignment, or BOTH time since last
+        // left/right scroll is above threshold AND trackpad/mousewheel movement
+        // is above threshold)
+        if (!ap.getAlignViewport().getWrapAlignment() || (Math.abs(
+                preciseWheelRotation) > wrappedVerticalScrollRotationThreshold
+                && System.currentTimeMillis()
+                        - lastLeftRightWrappedScrollTime > wrappedVerticalScrollChangeTimeThreshold))
         {
-          if (!av.getRanges().scrollUp(false))
+          while (size-- > 0)
           {
-            break;
+            if (!av.getRanges().scrollUp(false))
+            {
+              break;
+            }
           }
         }
       }
@@ -2280,20 +2333,34 @@ public class SeqPanel extends JPanel
       if (e.isShiftDown())
       {
         /*
-         * scroll left
+         * scroll left if not already at start
          */
-        av.getRanges().scrollRight(false, size);
+        if (av.getRanges().getStartRes() > 0)
+        {
+          av.getRanges().scrollRight(false, size);
+        }
+        this.lastLeftRightWrappedScrollTime = System.currentTimeMillis();
       }
       else
       {
         /*
          * scroll up
          */
-        while (size-- > 0)
+        // apply a more definite threshold for up and down scrolling in wrap
+        // format (either not a wrapped alignment, or BOTH time since last
+        // left/right scroll is above threshold AND trackpad/mousewheel movement
+        // is above threshold)
+        if (!ap.getAlignViewport().getWrapAlignment() || (Math.abs(
+                preciseWheelRotation) > wrappedVerticalScrollRotationThreshold
+                && System.currentTimeMillis()
+                        - lastLeftRightWrappedScrollTime > wrappedVerticalScrollChangeTimeThreshold))
         {
-          if (!av.getRanges().scrollUp(true))
+          while (size-- > 0)
           {
-            break;
+            if (!av.getRanges().scrollUp(true))
+            {
+              break;
+            }
           }
         }
       }