JAL-3093 unit test adapts to actual number of annotation rows
[jalview.git] / test / jalview / gui / SeqPanelTest.java
index d5c012e..4ce2696 100644 (file)
@@ -27,6 +27,7 @@ import jalview.api.AlignViewportI;
 import jalview.bin.Cache;
 import jalview.bin.Jalview;
 import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceI;
@@ -35,12 +36,18 @@ import jalview.io.DataSourceType;
 import jalview.io.FileLoader;
 
 import java.awt.Event;
+import java.awt.EventQueue;
 import java.awt.event.MouseEvent;
+import java.lang.reflect.InvocationTargetException;
+
+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 +72,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 +105,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 +158,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();
@@ -255,65 +265,30 @@ public class SeqPanelTest
     assertEquals(pos.seqIndex, alignmentHeight - 1);
     assertEquals(pos.annotationIndex, -1);
 
-    /*
-     * cursor at the top of the first annotation  
-     */
-    y += 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
-            false, 0);
-    pos = testee.findMousePosition(evt);
-    assertEquals(pos.seqIndex, alignmentHeight - 1);
-    assertEquals(pos.annotationIndex, 0); // over first annotation
-
-    /*
-     * cursor at the bottom of the first annotation  
-     */
-    y += av.getAlignment().getAlignmentAnnotation()[0].height - 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
-            false, 0);
-    pos = testee.findMousePosition(evt);
-    assertEquals(pos.seqIndex, alignmentHeight - 1);
-    assertEquals(pos.annotationIndex, 0);
-
-    /*
-     * cursor at the top of the second annotation  
-     */
-    y += 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
-            false, 0);
-    pos = testee.findMousePosition(evt);
-    assertEquals(pos.seqIndex, alignmentHeight - 1);
-    assertEquals(pos.annotationIndex, 1);
-
-    /*
-     * cursor at the bottom of the second annotation  
-     */
-    y += av.getAlignment().getAlignmentAnnotation()[1].height - 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
-            false, 0);
-    pos = testee.findMousePosition(evt);
-    assertEquals(pos.seqIndex, alignmentHeight - 1);
-    assertEquals(pos.annotationIndex, 1);
-
-    /*
-     * cursor at the top of the third annotation  
-     */
-    y += 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
-            false, 0);
-    pos = testee.findMousePosition(evt);
-    assertEquals(pos.seqIndex, alignmentHeight - 1);
-    assertEquals(pos.annotationIndex, 2);
-
-    /*
-     * cursor at the bottom of the third annotation  
-     */
-    y += av.getAlignment().getAlignmentAnnotation()[2].height - 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
-            false, 0);
-    pos = testee.findMousePosition(evt);
-    assertEquals(pos.seqIndex, alignmentHeight - 1);
-    assertEquals(pos.annotationIndex, 2);
+    AlignmentAnnotation[] annotationRows = av.getAlignment()
+            .getAlignmentAnnotation();
+    for (int n = 0; n < annotationRows.length; n++)
+    {
+      /*
+       * cursor at the top of the n'th annotation  
+       */
+      y += 1;
+      evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+              false, 0);
+      pos = testee.findMousePosition(evt);
+      assertEquals(pos.seqIndex, alignmentHeight - 1);
+      assertEquals(pos.annotationIndex, n); // over n'th annotation
+
+      /*
+       * cursor at the bottom of the n'th annotation  
+       */
+      y += annotationRows[n].height - 1;
+      evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+              false, 0);
+      pos = testee.findMousePosition(evt);
+      assertEquals(pos.seqIndex, alignmentHeight - 1);
+      assertEquals(pos.annotationIndex, n);
+    }
 
     /*
      * cursor in gap between wrapped widths  
@@ -358,7 +333,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();
@@ -466,65 +442,29 @@ public class SeqPanelTest
     assertEquals(pos.seqIndex, alignmentHeight - 1);
     assertEquals(pos.annotationIndex, -1);
   
-    /*
-     * cursor at the top of the first annotation  
-     */
-    y += 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
-            false, 0);
-    pos = testee.findMousePosition(evt);
-    assertEquals(pos.seqIndex, alignmentHeight - 1);
-    assertEquals(pos.annotationIndex, 0); // over first annotation
-  
-    /*
-     * cursor at the bottom of the first annotation  
-     */
-    y += av.getAlignment().getAlignmentAnnotation()[0].height - 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
-            false, 0);
-    pos = testee.findMousePosition(evt);
-    assertEquals(pos.seqIndex, alignmentHeight - 1);
-    assertEquals(pos.annotationIndex, 0);
-  
-    /*
-     * cursor at the top of the second annotation  
-     */
-    y += 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
-            false, 0);
-    pos = testee.findMousePosition(evt);
-    assertEquals(pos.seqIndex, alignmentHeight - 1);
-    assertEquals(pos.annotationIndex, 1);
-  
-    /*
-     * cursor at the bottom of the second annotation  
-     */
-    y += av.getAlignment().getAlignmentAnnotation()[1].height - 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
-            false, 0);
-    pos = testee.findMousePosition(evt);
-    assertEquals(pos.seqIndex, alignmentHeight - 1);
-    assertEquals(pos.annotationIndex, 1);
-  
-    /*
-     * cursor at the top of the third annotation  
-     */
-    y += 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
-            false, 0);
-    pos = testee.findMousePosition(evt);
-    assertEquals(pos.seqIndex, alignmentHeight - 1);
-    assertEquals(pos.annotationIndex, 2);
-  
-    /*
-     * cursor at the bottom of the third annotation  
-     */
-    y += av.getAlignment().getAlignmentAnnotation()[2].height - 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
-            false, 0);
-    pos = testee.findMousePosition(evt);
-    assertEquals(pos.seqIndex, alignmentHeight - 1);
-    assertEquals(pos.annotationIndex, 2);
+    AlignmentAnnotation[] annotationRows = av.getAlignment().getAlignmentAnnotation();
+    for (int n = 0; n < annotationRows.length; n++)
+    {
+      /*
+       * cursor at the top of the n'th annotation  
+       */
+      y += 1;
+      evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+              false, 0);
+      pos = testee.findMousePosition(evt);
+      assertEquals(pos.seqIndex, alignmentHeight - 1);
+      assertEquals(pos.annotationIndex, n); // over n'th annotation
+
+      /*
+       * cursor at the bottom of the n'th annotation  
+       */
+      y += annotationRows[n].height - 1;
+      evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+              false, 0);
+      pos = testee.findMousePosition(evt);
+      assertEquals(pos.seqIndex, alignmentHeight - 1);
+      assertEquals(pos.annotationIndex, n);
+    }
   
     /*
      * cursor in gap between wrapped widths  
@@ -576,6 +516,7 @@ public class SeqPanelTest
     assertEquals(pos.seqIndex, 0);
     assertEquals(pos.annotationIndex, -1);
   }
+
   @Test(groups = "Functional")
   public void testFindMousePosition_wrapped_noAnnotations()
   {
@@ -588,7 +529,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 +605,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 +771,24 @@ public class SeqPanelTest
     Cache.loadProperties("test/jalview/io/testProps.jvprops");
     Jalview.main(new String[] { "-nonews" });
   }
+
+  /**
+   * waits for Swing event dispatch queue to empty
+   */
+  synchronized void waitForSwing()
+  {
+    try
+    {
+      EventQueue.invokeAndWait(new Runnable()
+      {
+        @Override
+        public void run()
+        {
+        }
+      });
+    } catch (InterruptedException | InvocationTargetException e)
+    {
+      e.printStackTrace();
+    }
+  }
 }