Merge branch 'bug/JAL-2934proportionalScrolling' into develop
authorJames Procter <j.procter@dundee.ac.uk>
Wed, 6 Dec 2023 13:48:54 +0000 (13:48 +0000)
committerJames Procter <j.procter@dundee.ac.uk>
Wed, 6 Dec 2023 13:48:54 +0000 (13:48 +0000)
src/jalview/gui/AlignmentPanel.java
src/jalview/gui/AnnotationPanel.java
src/jalview/gui/IdPanel.java
src/jalview/gui/SeqPanel.java

index d3f80ce..8e7c745 100644 (file)
@@ -42,6 +42,7 @@ import java.io.FileWriter;
 import java.io.PrintWriter;
 import java.util.List;
 
+import javax.swing.BoundedRangeModel;
 import javax.swing.SwingUtilities;
 
 import jalview.analysis.AnnotationSorter;
@@ -789,6 +790,22 @@ public class AlignmentPanel extends GAlignmentPanel implements
   }
 
   /**
+   * Answers true if the panel has no horizontal scrollbar, or the scrollbar is
+   * at its rightmost position, else false.
+   * 
+   * @return
+   */
+  boolean isScrolledFullyRight()
+  {
+    if (hscroll == null)
+    {
+      return true;
+    }
+    BoundedRangeModel model = hscroll.getModel();
+    return (model.getExtent() + model.getValue() >= model.getMaximum());
+  }
+
+  /**
    * Respond to adjustment event when horizontal or vertical scrollbar is
    * changed
    * 
index 68ceff0..ea32684 100755 (executable)
@@ -192,21 +192,27 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
     renderer = new AnnotationRenderer();
   }
 
+  /**
+   * Responds to a mouse wheel movement by scrolling the annotations up or down.
+   * Annotation labels are scrolled via method adjustmentValueChanged when the
+   * vertical scrollbar is adjusted.
+   * <p>
+   * If shift is pressed, then scrolling is left or right instead, and is
+   * delegated to AlignmentPanel, so that both sequences and annotations are
+   * scrolled together.
+   * <p>
+   * This object is a MouseWheelListener to AnnotationLabels, so mouse wheel
+   * events over the labels are delegated to this method.
+   * <p>
+   * Note that this method may also be fired by scrolling with a gesture on a
+   * trackpad.
+   */
   @Override
   public void mouseWheelMoved(MouseWheelEvent e)
   {
     if (e.isShiftDown())
     {
-      e.consume();
-      double wheelRotation = e.getPreciseWheelRotation();
-      if (wheelRotation > 0)
-      {
-        av.getRanges().scrollRight(true);
-      }
-      else if (wheelRotation < 0)
-      {
-        av.getRanges().scrollRight(false);
-      }
+      ap.getSeqPanel().mouseWheelMoved(e);
     }
     else
     {
index 7b491e4..3fff67b 100755 (executable)
@@ -26,8 +26,6 @@ import java.awt.event.ActionListener;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.awt.event.MouseMotionListener;
-import java.awt.event.MouseWheelEvent;
-import java.awt.event.MouseWheelListener;
 import java.util.List;
 
 import javax.swing.JPanel;
@@ -50,12 +48,9 @@ import jalview.viewmodel.ViewportRanges;
 /**
  * This panel hosts alignment sequence ids and responds to mouse clicks on them,
  * as well as highlighting ids matched by a search from the Find menu.
- * 
- * @author $author$
- * @version $Revision$
  */
 public class IdPanel extends JPanel
-        implements MouseListener, MouseMotionListener, MouseWheelListener
+        implements MouseListener, MouseMotionListener
 {
   private IdCanvas idCanvas;
 
@@ -90,7 +85,7 @@ public class IdPanel extends JPanel
     add(getIdCanvas(), BorderLayout.CENTER);
     addMouseListener(this);
     addMouseMotionListener(this);
-    addMouseWheelListener(this);
+    addMouseWheelListener(alignPanel.getSeqPanel());
     ToolTipManager.sharedInstance().registerComponent(this);
   }
 
@@ -171,38 +166,6 @@ public class IdPanel extends JPanel
   }
 
   /**
-   * Response to the mouse wheel by scrolling the alignment panel.
-   */
-  @Override
-  public void mouseWheelMoved(MouseWheelEvent e)
-  {
-    e.consume();
-    double wheelRotation = e.getPreciseWheelRotation();
-    if (wheelRotation > 0)
-    {
-      if (e.isShiftDown())
-      {
-        av.getRanges().scrollRight(true);
-      }
-      else
-      {
-        av.getRanges().scrollUp(false);
-      }
-    }
-    else if (wheelRotation < 0)
-    {
-      if (e.isShiftDown())
-      {
-        av.getRanges().scrollRight(false);
-      }
-      else
-      {
-        av.getRanges().scrollUp(true);
-      }
-    }
-  }
-
-  /**
    * Handle a mouse click event. Currently only responds to a double-click. The
    * action is to try to open a browser window at a URL that searches for the
    * selected sequence id. The search URL is configured in Preferences |
index 2caea17..845004b 100644 (file)
@@ -2221,32 +2221,85 @@ public class SeqPanel extends JPanel
     }
   }
 
+  /**
+   * 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>
+   * <li>right (or down) if the reported mouse movement is positive</li>
+   * <li>left (or up) if the reported mouse movement is negative</li>
+   * </ul>
+   * Note that this method may also be fired by scrolling with a gesture on a
+   * trackpad.
+   */
   @Override
   public void mouseWheelMoved(MouseWheelEvent e)
   {
     e.consume();
     double wheelRotation = e.getPreciseWheelRotation();
+
+    /*
+     * scroll more for large (fast) mouse movements
+     */
+    int size = 1 + (int) Math.abs(wheelRotation);
+
     if (wheelRotation > 0)
     {
       if (e.isShiftDown())
       {
-        av.getRanges().scrollRight(true);
-
+        /*
+         * scroll right
+         * stop trying to scroll right when limit is reached (saves
+         * expensive calls to Alignment.getWidth())
+         */
+        while (size-- > 0 && !ap.isScrolledFullyRight())
+        {
+          if (!av.getRanges().scrollRight(true))
+          {
+            break;
+          }
+        }
       }
       else
       {
-        av.getRanges().scrollUp(false);
+        /*
+         * scroll down
+         */
+        while (size-- > 0)
+        {
+          if (!av.getRanges().scrollUp(false))
+          {
+            break;
+          }
+        }
       }
     }
     else if (wheelRotation < 0)
     {
       if (e.isShiftDown())
       {
-        av.getRanges().scrollRight(false);
+        /*
+         * scroll left
+         */
+        while (size-- > 0)
+        {
+          if (!av.getRanges().scrollRight(false))
+          {
+            break;
+          }
+        }
       }
       else
       {
-        av.getRanges().scrollUp(true);
+        /*
+         * scroll up
+         */
+        while (size-- > 0)
+        {
+          if (!av.getRanges().scrollUp(true))
+          {
+            break;
+          }
+        }
       }
     }