Merge commit 'alpha/update_2_12_for_2_11_2_series_merge^2' into HEAD
[jalview.git] / test / jalview / gui / SeqPanelTest.java
index f163299..33bbeec 100644 (file)
@@ -24,6 +24,16 @@ import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 
+import java.awt.EventQueue;
+import java.awt.FontMetrics;
+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 jalview.api.AlignViewportI;
 import jalview.bin.Cache;
 import jalview.bin.Jalview;
@@ -31,22 +41,18 @@ import jalview.commands.EditCommand;
 import jalview.commands.EditCommand.Action;
 import jalview.commands.EditCommand.Edit;
 import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SearchResults;
+import jalview.datamodel.SearchResultsI;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceI;
 import jalview.gui.SeqPanel.MousePos;
 import jalview.io.DataSourceType;
 import jalview.io.FileLoader;
 import jalview.util.MessageManager;
+import jalview.viewmodel.ViewportRanges;
 
-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;
 
@@ -238,7 +244,7 @@ public class SeqPanelTest
     /*
      * mouse at top left of unwrapped panel
      */
-    MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y,
+    MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y,
             0, 0, 0, false, 0);
     MousePos pos = testee.findMousePosition(evt);
     assertEquals(pos.column, 0);
@@ -263,8 +269,8 @@ public class SeqPanelTest
     av.setScaleAboveWrapped(false);
     av.setScaleLeftWrapped(false);
     av.setScaleRightWrapped(false);
-    alignFrame.alignPanel.paintAlignment(false, false);
-    waitForSwing(); // for Swing thread
+
+    alignFrame.alignPanel.updateLayout();
 
     final int charHeight = av.getCharHeight();
     final int charWidth = av.getCharWidth();
@@ -283,7 +289,7 @@ public class SeqPanelTest
      * mouse at top left of wrapped panel; there is a gap of charHeight
      * above the alignment
      */
-    MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y,
+    MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y,
             0, 0, 0, false, 0);
     MousePos pos = testee.findMousePosition(evt);
     assertEquals(pos.column, 0);
@@ -294,7 +300,7 @@ public class SeqPanelTest
      * cursor at bottom of gap above
      */
     y = charHeight - 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, -1);
@@ -304,7 +310,7 @@ public class SeqPanelTest
      * cursor over top of first sequence
      */
     y = charHeight;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, 0);
@@ -314,7 +320,7 @@ public class SeqPanelTest
      * cursor at bottom of first sequence
      */
     y = 2 * charHeight - 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, 0);
@@ -324,7 +330,7 @@ public class SeqPanelTest
      * cursor at top of second sequence
      */
     y = 2 * charHeight;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, 1);
@@ -334,7 +340,7 @@ public class SeqPanelTest
      * cursor at bottom of second sequence
      */
     y = 3 * charHeight - 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, 1);
@@ -344,7 +350,7 @@ public class SeqPanelTest
      * cursor at bottom of last sequence
      */
     y = charHeight * (1 + alignmentHeight) - 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, alignmentHeight - 1);
@@ -355,7 +361,7 @@ public class SeqPanelTest
      * method reports index of nearest sequence above
      */
     y += 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, alignmentHeight - 1);
@@ -365,77 +371,42 @@ public class SeqPanelTest
      * cursor still in the gap above annotations, now at the bottom of it
      */
     y += SeqCanvas.SEQS_ANNOTATION_GAP - 1; // 3-1 = 2
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 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 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);
+    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, MouseEvent.MOUSE_MOVED, 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 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);
+      /*
+       * cursor at the bottom of the n'th annotation  
+       */
+      y += annotationRows[n].height - 1;
+      evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 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  
      */
     y += 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, -1);
@@ -445,7 +416,7 @@ public class SeqPanelTest
      * cursor at bottom of gap between wrapped widths  
      */
     y += charHeight - 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, -1);
@@ -455,7 +426,7 @@ public class SeqPanelTest
      * cursor at top of first sequence, second wrapped width  
      */
     y += 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, 0);
@@ -473,8 +444,7 @@ public class SeqPanelTest
     av.setScaleAboveWrapped(true);
     av.setScaleLeftWrapped(false);
     av.setScaleRightWrapped(false);
-    alignFrame.alignPanel.paintAlignment(false, false);
-    waitForSwing();
+    alignFrame.alignPanel.updateLayout();
 
     final int charHeight = av.getCharHeight();
     final int charWidth = av.getCharWidth();
@@ -493,7 +463,7 @@ public class SeqPanelTest
      * mouse at top left of wrapped panel; there is a gap of charHeight
      * above the alignment
      */
-    MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y,
+    MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y,
             0, 0, 0, false, 0);
     MousePos pos = testee.findMousePosition(evt);
     assertEquals(pos.column, 0);
@@ -505,7 +475,7 @@ public class SeqPanelTest
      * two charHeights including scale panel
      */
     y = 2 * charHeight - 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, -1);
@@ -515,7 +485,7 @@ public class SeqPanelTest
      * cursor over top of first sequence
      */
     y += 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, 0);
@@ -525,7 +495,7 @@ public class SeqPanelTest
      * cursor at bottom of first sequence
      */
     y += charHeight - 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, 0);
@@ -535,7 +505,7 @@ public class SeqPanelTest
      * cursor at top of second sequence
      */
     y += 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, 1);
@@ -545,7 +515,7 @@ public class SeqPanelTest
      * cursor at bottom of second sequence
      */
     y += charHeight - 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, 1);
@@ -556,7 +526,7 @@ public class SeqPanelTest
      * (scale + gap + sequences)
      */
     y = charHeight * (2 + alignmentHeight) - 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, alignmentHeight - 1);
@@ -566,7 +536,7 @@ public class SeqPanelTest
      * cursor below sequences, in 3-pixel gap above annotations
      */
     y += 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, alignmentHeight - 1);
@@ -577,77 +547,46 @@ public class SeqPanelTest
      * method reports index of nearest sequence above  
      */
     y += SeqCanvas.SEQS_ANNOTATION_GAP - 1; // 3-1 = 2
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 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 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, MouseEvent.MOUSE_MOVED, 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, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
+              false, 0);
+      pos = testee.findMousePosition(evt);
+      SeqCanvas sc = testee.seqCanvas;
+      assertEquals(pos.seqIndex, alignmentHeight - 1,
+              String.format("%s n=%d y=%d %d, %d, %d, %d",
+                      annotationRows[n].label, n, y, sc.getWidth(),
+                      sc.getHeight(), sc.wrappedRepeatHeightPx,
+                      sc.wrappedSpaceAboveAlignment));
+      assertEquals(pos.annotationIndex, n);
+    }
   
     /*
      * cursor in gap between wrapped widths  
      */
     y += 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, -1);
@@ -657,7 +596,7 @@ public class SeqPanelTest
      * cursor at bottom of gap between wrapped widths  
      */
     y += charHeight - 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, -1);
@@ -667,7 +606,7 @@ public class SeqPanelTest
      * cursor at top of scale, second wrapped width  
      */
     y += 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, -1);
@@ -677,7 +616,7 @@ public class SeqPanelTest
      * cursor at bottom of scale, second wrapped width  
      */
     y += charHeight - 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, -1);
@@ -687,7 +626,7 @@ public class SeqPanelTest
      * cursor at top of first sequence, second wrapped width  
      */
     y += 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, 0);
@@ -699,14 +638,14 @@ public class SeqPanelTest
   {
     Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS", "false");
     Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "true");
+    Cache.applicationProperties.setProperty("FONT_SIZE", "10");
     AlignFrame alignFrame = new FileLoader().LoadFileWaitTillLoaded(
             "examples/uniref50.fa", DataSourceType.FILE);
     AlignViewportI av = alignFrame.getViewport();
     av.setScaleAboveWrapped(false);
     av.setScaleLeftWrapped(false);
     av.setScaleRightWrapped(false);
-    alignFrame.alignPanel.paintAlignment(false, false);
-    waitForSwing();
+    alignFrame.alignPanel.updateLayout();
 
     final int charHeight = av.getCharHeight();
     final int charWidth = av.getCharWidth();
@@ -725,7 +664,7 @@ public class SeqPanelTest
      * mouse at top left of wrapped panel; there is a gap of charHeight
      * above the alignment
      */
-    MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y,
+    MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y,
             0, 0, 0, false, 0);
     MousePos pos = testee.findMousePosition(evt);
     assertEquals(pos.column, 0);
@@ -736,7 +675,7 @@ public class SeqPanelTest
      * cursor over top of first sequence
      */
     y = charHeight;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, 0);
@@ -746,7 +685,7 @@ public class SeqPanelTest
      * cursor at bottom of last sequence
      */
     y = charHeight * (1 + alignmentHeight) - 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, alignmentHeight - 1);
@@ -756,7 +695,7 @@ public class SeqPanelTest
      * cursor below sequences, at top of charHeight gap between widths
      */
     y += 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, -1);
@@ -766,7 +705,7 @@ public class SeqPanelTest
      * cursor below sequences, at top of charHeight gap between widths
      */
     y += charHeight - 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, -1);
@@ -776,7 +715,7 @@ public class SeqPanelTest
      * cursor at the top of the first sequence, second width  
      */
     y += 1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
             false, 0);
     pos = testee.findMousePosition(evt);
     assertEquals(pos.seqIndex, 0);
@@ -793,12 +732,13 @@ public class SeqPanelTest
     int x = 0;
     final int charWidth = alignFrame.getViewport().getCharWidth();
     assertTrue(charWidth > 0); // sanity check
-    assertEquals(alignFrame.getViewport().getRanges().getStartRes(), 0);
+    ViewportRanges ranges = alignFrame.getViewport().getRanges();
+    assertEquals(ranges.getStartRes(), 0);
 
     /*
      * mouse at top left of unwrapped panel
      */
-    MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0,
+    MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0,
             0, 0, 0, false, 0);
     assertEquals(testee.findColumn(evt), 0);
     
@@ -806,7 +746,7 @@ public class SeqPanelTest
      * not quite one charWidth across
      */
     x = charWidth-1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0,
             0, 0, 0, false, 0);
     assertEquals(testee.findColumn(evt), 0);
 
@@ -814,7 +754,7 @@ public class SeqPanelTest
      * one charWidth across
      */
     x = charWidth;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0, 0,
             false, 0);
     assertEquals(testee.findColumn(evt), 1);
 
@@ -822,7 +762,7 @@ public class SeqPanelTest
      * two charWidths across
      */
     x = 2 * charWidth;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0, 0,
             false, 0);
     assertEquals(testee.findColumn(evt), 2);
 
@@ -830,12 +770,14 @@ public class SeqPanelTest
      * limited to last column of seqcanvas
      */
     x = 20000;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 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;
+    // limited to number of whole columns, base 0,
+    // and to end of visible range
+    int expected = w / charWidth;
+    expected = Math.min(expected, ranges.getEndRes());
     assertEquals(testee.findColumn(evt), expected);
 
     /*
@@ -844,7 +786,7 @@ public class SeqPanelTest
     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,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0, 0,
             false, 0);
     assertEquals(testee.findColumn(evt), 11);
   }
@@ -859,9 +801,7 @@ public class SeqPanelTest
     av.setScaleAboveWrapped(false);
     av.setScaleLeftWrapped(false);
     av.setScaleRightWrapped(false);
-    alignFrame.alignPanel.paintAlignment(false, false);
-    // need to wait for repaint to finish!
-    waitForSwing();
+    alignFrame.alignPanel.updateLayout();
     SeqPanel testee = alignFrame.alignPanel.getSeqPanel();
     int x = 0;
     final int charWidth = av.getCharWidth();
@@ -871,7 +811,7 @@ public class SeqPanelTest
     /*
      * mouse at top left of wrapped panel, no West (left) scale
      */
-    MouseEvent evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0,
+    MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0,
             0, 0, 0, false, 0);
     assertEquals(testee.findColumn(evt), 0);
     
@@ -879,7 +819,7 @@ public class SeqPanelTest
      * not quite one charWidth across
      */
     x = charWidth-1;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0,
             0, 0, 0, false, 0);
     assertEquals(testee.findColumn(evt), 0);
   
@@ -887,7 +827,7 @@ public class SeqPanelTest
      * one charWidth across
      */
     x = charWidth;
-    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, 0, 0, 0, 0,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0, 0,
             false, 0);
     assertEquals(testee.findColumn(evt), 1);
 
@@ -895,18 +835,17 @@ public class SeqPanelTest
      * x over scale left (before drawn columns) results in -1
      */
     av.setScaleLeftWrapped(true);
-    alignFrame.alignPanel.paintAlignment(false, false);
-    waitForSwing();
+    alignFrame.alignPanel.updateLayout();
     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,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 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,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0, 0,
             false, 0);
     assertEquals(testee.findColumn(evt), 0);
 
@@ -916,7 +855,7 @@ public class SeqPanelTest
     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,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0, 0,
             false, 0);
     assertEquals(testee.findColumn(evt), residuesWide - 1);
 
@@ -924,15 +863,14 @@ public class SeqPanelTest
      * x over scale right (beyond drawn columns) results in -1
      */
     av.setScaleRightWrapped(true);
-    alignFrame.alignPanel.paintAlignment(false, false);
-    waitForSwing();
+    alignFrame.alignPanel.updateLayout();
     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,
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0, 0,
             false, 0);
     assertEquals(testee.findColumn(evt), -1);
     
@@ -950,16 +888,175 @@ public class SeqPanelTest
   }
 
   /**
-   * waits a few ms for Swing to do something
+   * waits for Swing event dispatch queue to empty
    */
   synchronized void waitForSwing()
   {
     try
     {
-      super.wait(10);
-    } catch (InterruptedException e)
+      EventQueue.invokeAndWait(new Runnable()
+      {
+        @Override
+        public void run()
+        {
+        }
+      });
+    } catch (InterruptedException | InvocationTargetException e)
     {
       e.printStackTrace();
     }
   }
+  @Test(groups = "Functional")
+  public void testFindMousePosition_wrapped_scales_longSequence()
+  {
+    Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS", "false");
+    Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "true");
+    Cache.applicationProperties.setProperty("FONT_SIZE", "14");
+    Cache.applicationProperties.setProperty("FONT_NAME", "SansSerif");
+    Cache.applicationProperties.setProperty("FONT_STYLE", "0");
+    // sequence of 50 bases, doubled 10 times, = 51200 bases
+    String dna = "ATGGCCATTGGGCCCAAATTTCCCAAAGGGTTTCCCTGAGGTCAGTCAGA";
+    for (int i = 0 ; i < 10 ; i++)
+    {
+      dna += dna;
+    }
+    assertEquals(dna.length(), 51200);
+    AlignFrame alignFrame = new FileLoader()
+            .LoadFileWaitTillLoaded(dna, DataSourceType.PASTE);
+    SeqPanel testee = alignFrame.alignPanel.getSeqPanel();
+    AlignViewport av = alignFrame.getViewport();
+    av.setScaleAboveWrapped(true);
+    av.setScaleLeftWrapped(true);
+    av.setScaleRightWrapped(true);
+    alignFrame.alignPanel.updateLayout();
+
+    try
+    {
+      Thread.sleep(200);
+    } catch (InterruptedException e)
+    {
+    }
+  
+    final int charHeight = av.getCharHeight();
+    final int charWidth = av.getCharWidth();
+    assertEquals(charHeight, 17);
+    assertEquals(charWidth, 12);
+    
+    FontMetrics fm = testee.getFontMetrics(av.getFont());
+    int labelWidth = fm.stringWidth("00000") + charWidth;
+    assertEquals(labelWidth, 57); // 5 x 9 + charWidth
+    assertEquals(testee.seqCanvas.getLabelWidthWest(), labelWidth);
+
+    int x = 0;
+    int y = 0;
+  
+    /*
+     * mouse at top left of wrapped panel; there is a gap of 2 * charHeight
+     * above the alignment
+     */
+    MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y,
+            0, 0, 0, false, 0);
+    MousePos pos = testee.findMousePosition(evt);
+    assertEquals(pos.column, -1); // over scale left, not an alignment column
+    assertEquals(pos.seqIndex, -1); // above sequences
+    assertEquals(pos.annotationIndex, -1);
+
+    /*
+     * cursor over scale above first sequence
+     */
+    y += charHeight;
+    x = labelWidth;
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
+            false, 0);
+    pos = testee.findMousePosition(evt);
+    assertEquals(pos.seqIndex, -1);
+    assertEquals(pos.column, 0);
+    assertEquals(pos.annotationIndex, -1);
+    
+    /*
+     * cursor over scale left of first sequence
+     */
+    y += charHeight;
+    x = 0;
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
+            false, 0);
+    pos = testee.findMousePosition(evt);
+    assertEquals(pos.seqIndex, 0);
+    assertEquals(pos.column, -1);
+    assertEquals(pos.annotationIndex, -1);
+  
+    /*
+     * cursor over start of first sequence
+     */
+    x = labelWidth;
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
+            false, 0);
+    pos = testee.findMousePosition(evt);
+    assertEquals(pos.seqIndex, 0);
+    assertEquals(pos.column, 0);
+    assertEquals(pos.annotationIndex, -1);
+  
+    /*
+     * move one character right, to bottom pixel of same row
+     */
+    x += charWidth;
+    y += charHeight - 1;
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
+            false, 0);
+    pos = testee.findMousePosition(evt);
+    assertEquals(pos.seqIndex, 0);
+    assertEquals(pos.column, 1);
+    
+    /*
+     * move down one pixel - now in the no man's land between rows
+     */
+    y += 1;
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
+            false, 0);
+    pos = testee.findMousePosition(evt);
+    assertEquals(pos.seqIndex, -1);
+    assertEquals(pos.column, 1);
+    
+    /*
+     * move down two char heights less one pixel - still in the no man's land
+     * (scale above + spacer line)
+     */
+    y += (2 * charHeight - 1);
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
+            false, 0);
+    pos = testee.findMousePosition(evt);
+    assertEquals(pos.seqIndex, -1);
+    assertEquals(pos.column, 1);
+    
+    /*
+     * move down one more pixel - now on the next row of the sequence
+     */
+    y += 1;
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
+            false, 0);
+    pos = testee.findMousePosition(evt);
+    assertEquals(pos.seqIndex, 0);
+    assertEquals(pos.column, 1 + av.getWrappedWidth());
+    
+    /*
+     * scroll to near the end of the sequence
+     */
+    SearchResultsI sr = new SearchResults();
+    int scrollTo = dna.length() - 1000;
+    sr.addResult(av.getAlignment().getSequenceAt(0), scrollTo, scrollTo); 
+    alignFrame.alignPanel.scrollToPosition(sr);
+    
+    /*
+     * place the mouse on the first column of the 6th sequence, and
+     * verify that (computed) findMousePosition matches (actual) ViewportRanges
+     */
+    x = labelWidth;
+    y = 17 * charHeight; // 17 = 6 times two header rows and 5 sequence rows
+    evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, y, 0, 0, 0,
+            false, 0);
+    pos = testee.findMousePosition(evt);
+    assertEquals(pos.seqIndex, 0);
+    int expected = av.getRanges().getStartRes() + 5 * av.getWrappedWidth();
+    assertEquals(pos.column, expected);
+  }
 }