Merge branch 'bug/JAL-2934proportionalScrolling' into develop
[jalview.git] / src / jalview / gui / SeqPanel.java
index 6918811..845004b 100644 (file)
@@ -137,7 +137,7 @@ public class SeqPanel extends JPanel
       MousePos o = (MousePos) obj;
       boolean b = (column == o.column && seqIndex == o.seqIndex
               && annotationIndex == o.annotationIndex);
-      // System.out.println(obj + (b ? "= " : "!= ") + this);
+      // jalview.bin.Console.outPrintln(obj + (b ? "= " : "!= ") + this);
       return b;
     }
 
@@ -343,6 +343,15 @@ public class SeqPanel extends JPanel
   }
 
   /**
+   * @param evt
+   * @return absolute column in alignment nearest to the mouse pointer
+   */
+  int findAlignmentColumn(MouseEvent evt)
+  {
+    return findNearestColumn(evt, true);
+  }
+
+  /**
    * Returns the aligned sequence position (base 0) at the mouse position, or
    * the closest visible one
    * <p>
@@ -354,6 +363,17 @@ public class SeqPanel extends JPanel
    */
   int findColumn(MouseEvent evt)
   {
+    return findNearestColumn(evt, false);
+  }
+
+  /**
+   * @param nearestColumn
+   *          when false returns negative values for out of bound positions - -1
+   *          for scale left/right, <-1 if far to right
+   * @return nearest absolute column to mouse pointer
+   */
+  private int findNearestColumn(MouseEvent evt, boolean nearestColumn)
+  {
     int res = 0;
     int x = evt.getX();
 
@@ -377,7 +397,14 @@ public class SeqPanel extends JPanel
       if (x < 0)
       {
         // mouse is over left scale
-        return -1;
+        if (!nearestColumn)
+        {
+          return -1;
+        }
+        else
+        {
+          x = 0;
+        }
       }
 
       int cwidth = seqCanvas.getWrappedCanvasWidth(this.getWidth());
@@ -387,8 +414,15 @@ public class SeqPanel extends JPanel
       }
       if (x >= cwidth * charWidth)
       {
-        // mouse is over right scale
-        return -1;
+        if (!nearestColumn)
+        {
+          // mouse is over right scale
+          return -1;
+        }
+        else
+        {
+          x = cwidth * charWidth - 1;
+        }
       }
 
       wrappedBlock = y / cHeight;
@@ -405,8 +439,14 @@ public class SeqPanel extends JPanel
        * rather than right-hand gutter
        */
       x = Math.min(x, seqCanvas.getX() + seqCanvas.getWidth());
+      if (nearestColumn)
+      {
+        x = Math.max(x, 0);
+      }
+
       res = (x / charWidth) + startRes;
       res = Math.min(res, av.getRanges().getEndRes());
+
     }
 
     if (av.hasHiddenColumns())
@@ -881,7 +921,7 @@ public class SeqPanel extends JPanel
 
     if (lastMessage == null || !lastMessage.equals(tmp))
     {
-      // System.err.println("mouseOver Sequence: "+tmp);
+      // jalview.bin.Console.errPrintln("mouseOver Sequence: "+tmp);
       ssm.mouseOverSequence(sequence, index, pos, av);
     }
     lastMessage = tmp;
@@ -1006,7 +1046,7 @@ public class SeqPanel extends JPanel
   @Override
   public void updateColours(SequenceI seq, int index)
   {
-    System.out.println("update the seqPanel colours");
+    jalview.bin.Console.outPrintln("update the seqPanel colours");
     // repaint();
   }
 
@@ -1184,7 +1224,7 @@ public class SeqPanel extends JPanel
     AlignmentAnnotation[] anns = av.getAlignment().getAlignmentAnnotation();
 
     String tooltip = AnnotationPanel.buildToolTip(anns[rowIndex], column,
-            anns, 0, av);
+            anns, 0, av, ap);
     if (tooltip == null ? tooltip != lastTooltip
             : !tooltip.equals(lastTooltip))
     {
@@ -2181,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;
+          }
+        }
       }
     }
 
@@ -2861,7 +2954,7 @@ public class SeqPanel extends JPanel
     if (copycolsel && av.hasHiddenColumns()
             && (av.getAlignment().getHiddenColumns() == null))
     {
-      System.err.println("Bad things");
+      jalview.bin.Console.errPrintln("Bad things");
     }
     if (repaint) // always true!
     {
@@ -2931,6 +3024,8 @@ public class SeqPanel extends JPanel
      * if hidden column selection has changed
      */
     ap.paintAlignment(hiddenChanged, hiddenChanged);
+    // propagate any selection changes
+    PaintRefresher.Refresh(ap, av.getSequenceSetId());
 
     return true;
   }