JAL-3072 SeqPanel.stopScrolling on mouse up in scale or annotation panel
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 25 Jul 2018 10:43:21 +0000 (11:43 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 25 Jul 2018 10:43:21 +0000 (11:43 +0100)
src/jalview/gui/IdPanel.java
src/jalview/gui/ScalePanel.java
src/jalview/gui/SeqPanel.java

index a183144..3f43008 100755 (executable)
@@ -28,6 +28,7 @@ import jalview.io.SequenceAnnotationReport;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
 import jalview.viewmodel.AlignmentViewport;
+import jalview.viewmodel.ViewportRanges;
 
 import java.awt.BorderLayout;
 import java.awt.event.MouseEvent;
@@ -224,7 +225,7 @@ public class IdPanel extends JPanel
   {
     if (scrollThread != null)
     {
-      scrollThread.running = false;
+      scrollThread.stopScrolling();
     }
   }
 
@@ -408,7 +409,7 @@ public class IdPanel extends JPanel
   {
     if (scrollThread != null)
     {
-      scrollThread.running = false;
+      scrollThread.stopScrolling();
     }
 
     mouseDragging = false;
@@ -457,24 +458,42 @@ public class IdPanel extends JPanel
     this.idCanvas = idCanvas;
   }
 
-  // this class allows scrolling off the bottom of the visible alignment
+  /**
+   * Performs scrolling of the visible alignment up or down, adding newly
+   * visible sequences to the current selection
+   */
   class ScrollThread extends Thread
   {
-    boolean running = false;
+    private boolean running = false;
 
-    boolean up = true;
+    private boolean up;
 
+    /**
+     * Constructor for a thread that scrolls either up or down
+     * 
+     * @param up
+     */
     public ScrollThread(boolean up)
     {
       this.up = up;
+      setName("IdPanel$ScrollThread$" + String.valueOf(up));
       start();
     }
 
+    /**
+     * Sets a flag to stop the scrolling
+     */
     public void stopScrolling()
     {
       running = false;
     }
 
+    /**
+     * Scrolls the alignment either up or down, one row at a time, adding newly
+     * visible sequences to the current selection. Speed is limited to a maximum
+     * of ten rows per second. The thread exits when the end of the alignment is
+     * reached or a flag is set to stop it.
+     */
     @Override
     public void run()
     {
@@ -482,29 +501,20 @@ public class IdPanel extends JPanel
 
       while (running)
       {
-        if (av.getRanges().scrollUp(up))
+        ViewportRanges ranges = IdPanel.this.av.getRanges();
+        if (ranges.scrollUp(up))
         {
-          // scroll was ok, so add new sequence to selection
-          int seq = av.getRanges().getStartSeq();
-
-          if (!up)
-          {
-            seq = av.getRanges().getEndSeq();
-          }
-
-          if (seq < lastid)
-          {
-            selectSeqs(lastid - 1, seq);
-          }
-          else if (seq > lastid)
-          {
-            selectSeqs(lastid + 1, seq);
-          }
-
-          lastid = seq;
+          int toSeq = up ? ranges.getStartSeq() : ranges.getEndSeq();
+          int fromSeq = toSeq < lastid ? lastid - 1 : lastid + 1;
+          IdPanel.this.selectSeqs(fromSeq, toSeq);
+
+          lastid = toSeq;
         }
         else
         {
+          /*
+           * scroll did nothing - reached limit of visible alignment
+           */
           running = false;
         }
 
index e6bba02..581fb7d 100755 (executable)
@@ -275,6 +275,7 @@ public class ScalePanel extends JPanel
   public void mouseReleased(MouseEvent evt)
   {
     mouseDragging = false;
+    ap.getSeqPanel().stopScrolling();
 
     int res = (evt.getX() / av.getCharWidth())
             + av.getRanges().getStartRes();
@@ -356,16 +357,20 @@ public class ScalePanel extends JPanel
   {
     if (mouseDragging)
     {
-      ap.getSeqPanel().scrollCanvas(null);
+      ap.getSeqPanel().stopScrolling();
     }
   }
 
+  /**
+   * Action on leaving the panel bounds with mouse drag in progress is to start
+   * scrolling the alignment in the direction of the mouse
+   */
   @Override
   public void mouseExited(MouseEvent evt)
   {
     if (mouseDragging)
     {
-      ap.getSeqPanel().scrollCanvas(evt);
+      ap.getSeqPanel().startScrolling(evt.getPoint());
     }
   }
 
index 8b2e7bc..134b337 100644 (file)
@@ -48,6 +48,7 @@ import jalview.util.MappingUtils;
 import jalview.util.MessageManager;
 import jalview.util.Platform;
 import jalview.viewmodel.AlignmentViewport;
+import jalview.viewmodel.ViewportRanges;
 
 import java.awt.BorderLayout;
 import java.awt.Color;
@@ -628,13 +629,14 @@ public class SeqPanel extends JPanel
       return;
     }
 
-    if (!editingSeqs)
+    if (editingSeqs)
+    {
+      endEditing();
+    }
+    else
     {
       doMouseReleasedDefineMode(evt, didDrag);
-      return;
     }
-
-    endEditing();
   }
 
   /**
@@ -1161,9 +1163,9 @@ public class SeqPanel extends JPanel
     }
 
     mouseDragging = true;
-    if ((scrollThread != null) && (scrollThread.isRunning()))
+    if (scrollThread != null)
     {
-      scrollThread.setEvent(evt);
+      scrollThread.setMousePosition(evt.getPoint());
     }
   }
 
@@ -1575,10 +1577,10 @@ public class SeqPanel extends JPanel
   }
 
   /**
-   * DOCUMENT ME!
+   * On reentering the panel, stops any scrolling that was started on dragging
+   * out of the panel
    * 
    * @param e
-   *          DOCUMENT ME!
    */
   @Override
   public void mouseEntered(MouseEvent e)
@@ -1587,29 +1589,19 @@ public class SeqPanel extends JPanel
     {
       oldSeq = 0;
     }
-
-    if ((scrollThread != null) && (scrollThread.isRunning()))
-    {
-      scrollThread.stopScrolling();
-      scrollThread = null;
-    }
+    stopScrolling();
   }
 
   /**
-   * DOCUMENT ME!
+   * On leaving the panel, if the mouse is being dragged, starts a thread to
+   * scroll it until the mouse is released (in unwrapped mode only)
    * 
    * @param e
-   *          DOCUMENT ME!
    */
   @Override
   public void mouseExited(MouseEvent e)
   {
-    if (av.getWrapAlignment())
-    {
-      return;
-    }
-
-    if (mouseDragging && scrollThread == null)
+    if (!av.getWrapAlignment() && mouseDragging && scrollThread == null)
     {
       scrollThread = new ScrollThread();
     }
@@ -2008,89 +2000,126 @@ public class SeqPanel extends JPanel
 
     mouseDragging = true;
 
-    if ((scrollThread != null) && (scrollThread.isRunning()))
+    if (scrollThread != null)
     {
-      scrollThread.setEvent(evt);
+      scrollThread.setMousePosition(evt.getPoint());
     }
   }
 
-  void scrollCanvas(MouseEvent evt)
+  /**
+   * Stops the scroll thread if it is running
+   */
+  void stopScrolling()
   {
-    if (evt == null)
+    if (scrollThread != null)
     {
-      if ((scrollThread != null) && (scrollThread.isRunning()))
-      {
-        scrollThread.stopScrolling();
-        scrollThread = null;
-      }
-      mouseDragging = false;
+      scrollThread.stopScrolling();
+      scrollThread = null;
     }
-    else
-    {
-      if (scrollThread == null)
-      {
-        scrollThread = new ScrollThread();
-      }
+    mouseDragging = false;
+  }
 
-      mouseDragging = true;
-      scrollThread.setEvent(evt);
+  /**
+   * Starts a thread to scroll the alignment, towards a given mouse position
+   * outside the panel bounds
+   * 
+   * @param mousePos
+   */
+  void startScrolling(Point mousePos)
+  {
+    if (scrollThread == null)
+    {
+      scrollThread = new ScrollThread();
     }
 
+    mouseDragging = true;
+    scrollThread.setMousePosition(mousePos);
   }
 
-  // this class allows scrolling off the bottom of the visible alignment
+  /**
+   * Performs scrolling of the visible alignment left, right, up or down
+   */
   class ScrollThread extends Thread
   {
-    MouseEvent evt;
+    private Point mousePos;
 
     private volatile boolean threadRunning = true;
 
+    /**
+     * Constructor
+     */
     public ScrollThread()
     {
+      setName("SeqPanel$ScrollThread");
       start();
     }
 
-    public void setEvent(MouseEvent e)
+    /**
+     * Sets the position of the mouse that determines the direction of the
+     * scroll to perform
+     * 
+     * @param p
+     */
+    public void setMousePosition(Point p)
     {
-      evt = e;
+      mousePos = p;
     }
 
+    /**
+     * Sets a flag that will cause the thread to exit
+     */
     public void stopScrolling()
     {
       threadRunning = false;
     }
 
-    public boolean isRunning()
-    {
-      return threadRunning;
-    }
-
+    /**
+     * Scrolls the alignment left or right, and/or up or down, depending on the
+     * last notified mouse position, until the limit of the alignment is
+     * reached, or a flag is set to stop the scroll
+     */
     @Override
     public void run()
     {
-      while (threadRunning)
+      while (threadRunning && mouseDragging)
       {
-        if (evt != null)
+        if (mousePos != null)
         {
-          if (mouseDragging && (evt.getY() < 0)
-                  && (av.getRanges().getStartSeq() > 0))
+          boolean scrolled = false;
+          ViewportRanges ranges = SeqPanel.this.av.getRanges();
+
+          /*
+           * scroll up or down
+           */
+          if (mousePos.y < 0)
           {
-            av.getRanges().scrollUp(true);
+            // mouse is above this panel - try scroll up
+            scrolled = ranges.scrollUp(true);
           }
-
-          if (mouseDragging && (evt.getY() >= getHeight()) && (av
-                  .getAlignment().getHeight() > av.getRanges().getEndSeq()))
+          else if (mousePos.y >= getHeight())
           {
-            av.getRanges().scrollUp(false);
+            // mouse is below this panel - try scroll down
+            scrolled = ranges.scrollUp(false);
           }
 
-          if (mouseDragging && (evt.getX() < 0))
+          /*
+           * scroll left or right
+           */
+          if (mousePos.x < 0)
           {
-            av.getRanges().scrollRight(false);
+            scrolled |= ranges.scrollRight(false);
           }
-          else if (mouseDragging && (evt.getX() >= getWidth()))
+          else if (mousePos.x >= getWidth())
           {
-            av.getRanges().scrollRight(true);
+            scrolled |= ranges.scrollRight(true);
+          }
+          if (!scrolled)
+          {
+            /*
+             * we have reached the limit of the visible alignment - quit
+             */
+            threadRunning = false;
+            SeqPanel.this.ap.repaint();
           }
         }