JAL-3093 unit tests, no mouse action over left/right wrapped scale
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Thu, 4 Oct 2018 10:38:48 +0000 (11:38 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Thu, 4 Oct 2018 10:38:48 +0000 (11:38 +0100)
src/jalview/gui/SeqPanel.java
test/jalview/gui/SeqPanelTest.java

index d0859b8..a53edb9 100644 (file)
@@ -274,23 +274,9 @@ public class SeqPanel extends JPanel
     {
       seqCanvas.calculateWrappedGeometry(seqCanvas.getWidth(),
               seqCanvas.getHeight());
-      // int gapHeight = charHeight;
-      // if (av.getScaleAboveWrapped())
-      // {
-      // gapHeight += charHeight;
-      // }
-      //
-      // final int alignmentHeightPixels = gapHeight
-      // + alignmentHeight * charHeight;
-      // int cHeight = alignmentHeightPixels;
-      // if (av.isShowAnnotation())
-      // {
-      // cHeight += (seqCanvas.getAnnotationHeight() +
-      // SeqCanvas.SEQS_ANNOTATION_GAP);
-      // }
 
       /*
-       * yPos modulo repeating width height
+       * yPos modulo height of repeating width
        */
       int yOffsetPx = y % seqCanvas.wrappedRepeatHeightPx;
 
@@ -345,7 +331,9 @@ public class SeqPanel extends JPanel
     int res = 0;
     int x = evt.getX();
 
-    int startRes = av.getRanges().getStartRes();
+    final int startRes = av.getRanges().getStartRes();
+    final int charWidth = av.getCharWidth();
+
     if (av.getWrapAlignment())
     {
       int hgap = av.getCharHeight();
@@ -359,20 +347,30 @@ public class SeqPanel extends JPanel
 
       int y = evt.getY();
       y = Math.max(0, y - hgap);
-      x = Math.max(0, x - seqCanvas.getLabelWidthWest());
+      x -= seqCanvas.getLabelWidthWest();
+      if (x < 0)
+      {
+        // mouse is over left scale
+        return -1;
+      }
 
       int cwidth = seqCanvas.getWrappedCanvasWidth(this.getWidth());
       if (cwidth < 1)
       {
         return 0;
       }
+      if (x >= cwidth * charWidth)
+      {
+        // mouse is over right scale
+        return -1;
+      }
 
       wrappedBlock = y / cHeight;
       wrappedBlock += startRes / cwidth;
       // allow for wrapped view scrolled right (possible from Overview)
       int startOffset = startRes % cwidth;
       res = wrappedBlock * cwidth + startOffset
-              + Math.min(cwidth - 1, x / av.getCharWidth());
+              + Math.min(cwidth - 1, x / charWidth);
     }
     else
     {
@@ -381,7 +379,7 @@ public class SeqPanel extends JPanel
        * rather than right-hand gutter
        */
       x = Math.min(x, seqCanvas.getX() + seqCanvas.getWidth());
-      res = (x / av.getCharWidth()) + startRes;
+      res = (x / charWidth) + startRes;
       res = Math.min(res, av.getRanges().getEndRes());
     }
 
@@ -728,9 +726,8 @@ public class SeqPanel extends JPanel
   public void mouseReleased(MouseEvent evt)
   {
     MousePos pos = findMousePosition(evt);
-    if (pos.annotationIndex != -1)
+    if (pos.isOverAnnotation() || pos.seqIndex == -1 || pos.column == -1)
     {
-      // mouse is over annotation row in wrapped mode
       return;
     }
 
@@ -765,9 +762,8 @@ public class SeqPanel extends JPanel
   {
     lastMousePress = evt.getPoint();
     MousePos pos = findMousePosition(evt);
-    if (pos.annotationIndex != -1)
+    if (pos.isOverAnnotation() || pos.seqIndex == -1 || pos.column == -1)
     {
-      // mouse is over an annotation row in wrapped mode
       return;
     }
 
@@ -795,11 +791,6 @@ public class SeqPanel extends JPanel
     int seq = pos.seqIndex;
     int res = pos.column;
 
-    if (seq < 0 || res < 0)
-    {
-      return;
-    }
-
     if ((seq < av.getAlignment().getHeight())
             && (res < av.getAlignment().getSequenceAt(seq).getLength()))
     {
@@ -923,7 +914,7 @@ public class SeqPanel extends JPanel
       lastMousePosition = null;
       setToolTipText(null);
       lastTooltip = null;
-      ap.alignFrame.statusBar.setText("");
+      ap.alignFrame.setStatus("");
       return;
     }
 
@@ -1015,7 +1006,8 @@ public class SeqPanel extends JPanel
     final int column = pos.column;
     final int rowIndex = pos.annotationIndex;
 
-    if (!av.getWrapAlignment() || !av.isShowAnnotation() || rowIndex < 0)
+    if (column < 0 || !av.getWrapAlignment() || !av.isShowAnnotation()
+            || rowIndex < 0)
     {
       return;
     }
@@ -1028,7 +1020,7 @@ public class SeqPanel extends JPanel
 
     String msg = AnnotationPanel.getStatusMessage(av.getAlignment(), column,
             anns[rowIndex]);
-    ap.alignFrame.statusBar.setText(msg);
+    ap.alignFrame.setStatus(msg);
   }
 
   private Point lastp = null;
@@ -1163,7 +1155,7 @@ public class SeqPanel extends JPanel
 
       text.append(" (").append(Integer.toString(residuePos)).append(")");
     }
-    ap.alignFrame.statusBar.setText(text.toString());
+    ap.alignFrame.setStatus(text.toString());
   }
 
   /**
@@ -1206,9 +1198,8 @@ public class SeqPanel extends JPanel
   public void mouseDragged(MouseEvent evt)
   {
     MousePos pos = findMousePosition(evt);
-    if (pos.isOverAnnotation())
+    if (pos.isOverAnnotation() || pos.column == -1)
     {
-      // mouse is over annotation row in wrapped mode
       return;
     }
 
@@ -1307,7 +1298,7 @@ public class SeqPanel extends JPanel
 
     if (!editingSeqs)
     {
-      doMouseDraggedDefineMode(evt);
+      dragStretchGroup(evt);
       return;
     }
 
@@ -1397,7 +1388,7 @@ public class SeqPanel extends JPanel
     }
 
     message.append(Math.abs(startres - lastres) + " gaps.");
-    ap.alignFrame.statusBar.setText(message.toString());
+    ap.alignFrame.setStatus(message.toString());
 
     // Are we editing within a selection group?
     if (groupEditing || (sg != null
@@ -1777,6 +1768,7 @@ public class SeqPanel extends JPanel
   @Override
   public void mouseExited(MouseEvent e)
   {
+    ap.alignFrame.setStatus(" ");
     if (av.getWrapAlignment())
     {
       return;
@@ -1798,9 +1790,8 @@ public class SeqPanel extends JPanel
   {
     SequenceGroup sg = null;
     MousePos pos = findMousePosition(evt);
-    if (pos.isOverAnnotation())
+    if (pos.isOverAnnotation() || pos.seqIndex == -1 || pos.column == -1)
     {
-      // mouse is over annotation label in wrapped mode
       return;
     }
 
@@ -1819,7 +1810,7 @@ public class SeqPanel extends JPanel
        * find features at the position (if not gapped), or straddling
        * the position (if at a gap)
        */
-      SequenceI sequence = av.getAlignment().getSequenceAt(pos.seqIndex);// findSeq(evt));
+      SequenceI sequence = av.getAlignment().getSequenceAt(pos.seqIndex);
       List<SequenceFeature> features = seqCanvas.getFeatureRenderer()
               .findFeaturesAtColumn(sequence, column + 1);
 
@@ -1891,13 +1882,8 @@ public class SeqPanel extends JPanel
    */
   protected void doMousePressedDefineMode(MouseEvent evt, MousePos pos)
   {
-    if (pos.isOverAnnotation())
+    if (pos.isOverAnnotation() || pos.seqIndex == -1 || pos.column == -1)
     {
-      // JvOptionPane.showInternalMessageDialog(Desktop.desktop,
-      // MessageManager.getString(
-      // "label.cannot_edit_annotations_in_wrapped_view"),
-      // MessageManager.getString("label.wrapped_view_no_edit"),
-      // JvOptionPane.WARNING_MESSAGE);
       return;
     }
 
@@ -1908,11 +1894,6 @@ public class SeqPanel extends JPanel
 
     startWrapBlock = wrappedBlock;
 
-    if (seq < 0 || res < 0)
-    {
-      return;
-    }
-
     SequenceI sequence = av.getAlignment().getSequenceAt(seq);
 
     if ((sequence == null) || (res > sequence.getLength()))
@@ -2035,7 +2016,8 @@ public class SeqPanel extends JPanel
    *          true if this event is happening after a mouse drag (rather than a
    *          mouse down)
    */
-  public void doMouseReleasedDefineMode(MouseEvent evt, boolean afterDrag)
+  protected void doMouseReleasedDefineMode(MouseEvent evt,
+          boolean afterDrag)
   {
     if (stretchGroup == null)
     {
@@ -2078,17 +2060,21 @@ public class SeqPanel extends JPanel
   }
 
   /**
-   * DOCUMENT ME!
+   * Resizes the borders of a selection group depending on the direction of
+   * mouse drag
    * 
    * @param evt
-   *          DOCUMENT ME!
    */
-  public void doMouseDraggedDefineMode(MouseEvent evt)
+  protected void dragStretchGroup(MouseEvent evt)
   {
+    if (stretchGroup == null)
+    {
+      return;
+    }
+
     MousePos pos = findMousePosition(evt);
-    if (pos.isOverAnnotation())
+    if (pos.isOverAnnotation() || pos.column == -1 || pos.seqIndex == -1)
     {
-      // mouse is over annotation in wrapped mode
       return;
     }
 
@@ -2100,11 +2086,6 @@ public class SeqPanel extends JPanel
       return;
     }
 
-    if (stretchGroup == null)
-    {
-      return;
-    }
-
     if (res >= av.getAlignment().getWidth())
     {
       res = av.getAlignment().getWidth() - 1;
index d5c012e..d2344cc 100644 (file)
@@ -37,10 +37,14 @@ import jalview.io.FileLoader;
 import java.awt.Event;
 import java.awt.event.MouseEvent;
 
+import javax.swing.JLabel;
+
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
+import junit.extensions.PA;
+
 public class SeqPanelTest
 {
   AlignFrame af;
@@ -65,22 +69,24 @@ public class SeqPanelTest
     assertEquals(
             alignFrame.alignPanel.getSeqPanel().setStatusMessage(
                     visAl.getSequenceAt(1), 1, 1), 2);
-    assertEquals(alignFrame.statusBar.getText(),
+    assertEquals(((JLabel) PA.getValue(alignFrame, "statusBar")).getText(),
             "Sequence 2 ID: Seq2 Residue: ALA (2)");
     assertEquals(
             alignFrame.alignPanel.getSeqPanel().setStatusMessage(
                     visAl.getSequenceAt(1), 4, 1), 3);
-    assertEquals(alignFrame.statusBar.getText(),
+    assertEquals(((JLabel) PA.getValue(alignFrame, "statusBar")).getText(),
             "Sequence 2 ID: Seq2 Residue: GLU (3)");
     // no status message at a gap, returns next residue position to the right
     assertEquals(
             alignFrame.alignPanel.getSeqPanel().setStatusMessage(
                     visAl.getSequenceAt(1), 2, 1), 3);
-    assertEquals(alignFrame.statusBar.getText(), "Sequence 2 ID: Seq2");
+    assertEquals(((JLabel) PA.getValue(alignFrame, "statusBar")).getText(),
+            "Sequence 2 ID: Seq2");
     assertEquals(
             alignFrame.alignPanel.getSeqPanel().setStatusMessage(
                     visAl.getSequenceAt(1), 3, 1), 3);
-    assertEquals(alignFrame.statusBar.getText(), "Sequence 2 ID: Seq2");
+    assertEquals(((JLabel) PA.getValue(alignFrame, "statusBar")).getText(),
+            "Sequence 2 ID: Seq2");
   }
 
   @Test(groups = "Functional")
@@ -96,7 +102,7 @@ public class SeqPanelTest
     assertEquals(
             alignFrame.alignPanel.getSeqPanel().setStatusMessage(
                     visAl.getSequenceAt(1), 1, 1), 2);
-    assertEquals(alignFrame.statusBar.getText(),
+    assertEquals(((JLabel) PA.getValue(alignFrame, "statusBar")).getText(),
             "Sequence 2 ID: Seq2 Residue: B (2)");
   }
 
@@ -149,6 +155,7 @@ public class SeqPanelTest
     av.setScaleLeftWrapped(false);
     av.setScaleRightWrapped(false);
     alignFrame.alignPanel.paintAlignment(false, false);
+    waitForSwing(); // for Swing thread
 
     final int charHeight = av.getCharHeight();
     final int charWidth = av.getCharWidth();
@@ -358,7 +365,8 @@ public class SeqPanelTest
     av.setScaleLeftWrapped(false);
     av.setScaleRightWrapped(false);
     alignFrame.alignPanel.paintAlignment(false, false);
-  
+    waitForSwing();
+
     final int charHeight = av.getCharHeight();
     final int charWidth = av.getCharWidth();
     final int alignmentHeight = av.getAlignment().getHeight();
@@ -576,6 +584,7 @@ public class SeqPanelTest
     assertEquals(pos.seqIndex, 0);
     assertEquals(pos.annotationIndex, -1);
   }
+
   @Test(groups = "Functional")
   public void testFindMousePosition_wrapped_noAnnotations()
   {
@@ -588,7 +597,8 @@ public class SeqPanelTest
     av.setScaleLeftWrapped(false);
     av.setScaleRightWrapped(false);
     alignFrame.alignPanel.paintAlignment(false, false);
-  
+    waitForSwing();
+
     final int charHeight = av.getCharHeight();
     final int charWidth = av.getCharWidth();
     final int alignmentHeight = av.getAlignment().getHeight();
@@ -663,6 +673,163 @@ public class SeqPanelTest
     assertEquals(pos.seqIndex, 0);
     assertEquals(pos.annotationIndex, -1);
   }
+
+  @Test(groups = "Functional")
+  public void testFindColumn_unwrapped()
+  {
+    Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "false");
+    AlignFrame alignFrame = new FileLoader().LoadFileWaitTillLoaded(
+            "examples/uniref50.fa", DataSourceType.FILE);
+    SeqPanel testee = alignFrame.alignPanel.getSeqPanel();
+    int x = 0;
+    final int charWidth = alignFrame.getViewport().getCharWidth();
+    assertTrue(charWidth > 0); // sanity check
+    assertEquals(alignFrame.getViewport().getRanges().getStartRes(), 0);
+
+    /*
+     * mouse at top left of unwrapped panel
+     */
+    MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0,
+            0, 0, 0, false, 0);
+    assertEquals(testee.findColumn(evt), 0);
+    
+    /*
+     * not quite one charWidth across
+     */
+    x = charWidth-1;
+    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0,
+            0, 0, 0, false, 0);
+    assertEquals(testee.findColumn(evt), 0);
+
+    /*
+     * one charWidth across
+     */
+    x = charWidth;
+    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
+            false, 0);
+    assertEquals(testee.findColumn(evt), 1);
+
+    /*
+     * two charWidths across
+     */
+    x = 2 * charWidth;
+    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
+            false, 0);
+    assertEquals(testee.findColumn(evt), 2);
+
+    /*
+     * limited to last column of seqcanvas
+     */
+    x = 20000;
+    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
+            false, 0);
+    SeqCanvas seqCanvas = alignFrame.alignPanel.getSeqPanel().seqCanvas;
+    int w = seqCanvas.getWidth();
+    // limited to number of whole columns, base 0
+    int expected = w / charWidth - 1;
+    assertEquals(testee.findColumn(evt), expected);
+
+    /*
+     * hide columns 5-10 (base 1)
+     */
+    alignFrame.getViewport().hideColumns(4, 9);
+    x = 5 * charWidth + 2;
+    // x is in 6th visible column, absolute column 12, or 11 base 0
+    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
+            false, 0);
+    assertEquals(testee.findColumn(evt), 11);
+  }
+
+  @Test(groups = "Functional")
+  public void testFindColumn_wrapped()
+  {
+    Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "true");
+    AlignFrame alignFrame = new FileLoader().LoadFileWaitTillLoaded(
+            "examples/uniref50.fa", DataSourceType.FILE);
+    AlignViewport av = alignFrame.getViewport();
+    av.setScaleAboveWrapped(false);
+    av.setScaleLeftWrapped(false);
+    av.setScaleRightWrapped(false);
+    alignFrame.alignPanel.paintAlignment(false, false);
+    // need to wait for repaint to finish!
+    waitForSwing();
+    SeqPanel testee = alignFrame.alignPanel.getSeqPanel();
+    int x = 0;
+    final int charWidth = av.getCharWidth();
+    assertTrue(charWidth > 0); // sanity check
+    assertEquals(av.getRanges().getStartRes(), 0);
+  
+    /*
+     * mouse at top left of wrapped panel, no West (left) scale
+     */
+    MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0,
+            0, 0, 0, false, 0);
+    assertEquals(testee.findColumn(evt), 0);
+    
+    /*
+     * not quite one charWidth across
+     */
+    x = charWidth-1;
+    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0,
+            0, 0, 0, false, 0);
+    assertEquals(testee.findColumn(evt), 0);
+  
+    /*
+     * one charWidth across
+     */
+    x = charWidth;
+    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
+            false, 0);
+    assertEquals(testee.findColumn(evt), 1);
+
+    /*
+     * x over scale left (before drawn columns) results in -1
+     */
+    av.setScaleLeftWrapped(true);
+    alignFrame.alignPanel.paintAlignment(false, false);
+    waitForSwing();
+    SeqCanvas seqCanvas = testee.seqCanvas;
+    int labelWidth = (int) PA.getValue(seqCanvas, "labelWidthWest");
+    assertTrue(labelWidth > 0);
+    x = labelWidth - 1;
+    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
+            false, 0);
+    assertEquals(testee.findColumn(evt), -1);
+
+    x = labelWidth;
+    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
+            false, 0);
+    assertEquals(testee.findColumn(evt), 0);
+
+    /*
+     * x over right edge of last residue (including scale left)
+     */
+    int residuesWide = av.getRanges().getViewportWidth();
+    assertTrue(residuesWide > 0);
+    x = labelWidth + charWidth * residuesWide - 1;
+    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
+            false, 0);
+    assertEquals(testee.findColumn(evt), residuesWide - 1);
+
+    /*
+     * x over scale right (beyond drawn columns) results in -1
+     */
+    av.setScaleRightWrapped(true);
+    alignFrame.alignPanel.paintAlignment(false, false);
+    waitForSwing();
+    labelWidth = (int) PA.getValue(seqCanvas, "labelWidthEast");
+    assertTrue(labelWidth > 0);
+    int residuesWide2 = av.getRanges().getViewportWidth();
+    assertTrue(residuesWide2 > 0);
+    assertTrue(residuesWide2 < residuesWide); // available width reduced
+    x += 1; // just over left edge of scale right
+    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
+            false, 0);
+    assertEquals(testee.findColumn(evt), -1);
+    
+    // todo add startRes offset, hidden columns
+
+  }
   @BeforeClass(alwaysRun = true)
   public static void setUpBeforeClass() throws Exception
   {
@@ -672,4 +839,18 @@ public class SeqPanelTest
     Cache.loadProperties("test/jalview/io/testProps.jvprops");
     Jalview.main(new String[] { "-nonews" });
   }
+
+  /**
+   * waits a few ms for Swing to do something
+   */
+  synchronized void waitForSwing()
+  {
+    try
+    {
+      super.wait(10);
+    } catch (InterruptedException e)
+    {
+      e.printStackTrace();
+    }
+  }
 }