JAL-3093 tweaks to code and test for 3px gap above annotations in
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 3 Oct 2018 12:53:25 +0000 (13:53 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 3 Oct 2018 12:53:25 +0000 (13:53 +0100)
wrapped mode

src/jalview/gui/SeqCanvas.java
src/jalview/gui/SeqPanel.java
test/jalview/gui/SeqCanvasTest.java
test/jalview/gui/SeqPanelTest.java

index 31c8a47..dc87eba 100755 (executable)
@@ -87,9 +87,9 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
 
   private int labelWidthWest; // label left width in pixels if shown
 
-  private int wrappedSpaceAboveAlignment; // gap between widths
+  int wrappedSpaceAboveAlignment; // gap between widths
 
-  private int wrappedRepeatHeightPx; // height in pixels of wrapped width
+  int wrappedRepeatHeightPx; // height in pixels of wrapped width
 
   private int wrappedVisibleWidths; // number of wrapped widths displayed
 
@@ -564,7 +564,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
     calculateWrappedGeometry(canvasWidth, canvasHeight);
 
     /*
-     * draw one width at a time (excluding any scales or annotation shown),
+     * draw one width at a time (excluding any scales shown),
      * until we have run out of either alignment or vertical space available
      */
     int ypos = wrappedSpaceAboveAlignment;
@@ -611,14 +611,22 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
             * (av.getScaleAboveWrapped() ? 2 : 1);
 
     /*
-     * height in pixels of the wrapped widths
+     * compute height in pixels of the wrapped widths
+     * - start with space above plus sequences
      */
     wrappedRepeatHeightPx = wrappedSpaceAboveAlignment;
-    // add sequences
     wrappedRepeatHeightPx += av.getAlignment().getHeight()
             * charHeight;
-    // add annotations panel height if shown
-    wrappedRepeatHeightPx += getAnnotationHeight();
+
+    /*
+     * add annotations panel height if shown
+     * also gap between sequences and annotations
+     */
+    if (av.isShowAnnotation())
+    {
+      wrappedRepeatHeightPx += getAnnotationHeight();
+      wrappedRepeatHeightPx += SEQS_ANNOTATION_GAP; // 3px
+    }
 
     /*
      * number of visible widths (the last one may be part height),
@@ -662,8 +670,9 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
    * @param endColumn
    * @param canvasHeight
    */
-  protected void drawWrappedWidth(Graphics g, int ypos, int startColumn,
-          int endColumn, int canvasHeight)
+  protected void drawWrappedWidth(Graphics g, final int ypos,
+          final int startColumn, final int endColumn,
+          final int canvasHeight)
   {
     ViewportRanges ranges = av.getRanges();
     int viewportWidth = ranges.getViewportWidth();
@@ -710,7 +719,8 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
 
     if (av.isShowAnnotation())
     {
-      g.translate(0, cHeight + ypos + SEQS_ANNOTATION_GAP);
+      final int yShift = cHeight + ypos + SEQS_ANNOTATION_GAP;
+      g.translate(0, yShift);
       if (annotations == null)
       {
         annotations = new AnnotationPanel(av);
@@ -718,7 +728,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI
 
       annotations.renderer.drawComponent(annotations, av, g, -1,
               startColumn, endx + 1);
-      g.translate(0, -cHeight - ypos - SEQS_ANNOTATION_GAP);
+      g.translate(0, -yShift);
     }
     g.setClip(clip);
     g.translate(-xOffset, 0);
index 0b62629..d0859b8 100644 (file)
@@ -272,29 +272,44 @@ public class SeqPanel extends JPanel
     int alignmentHeight = av.getAlignment().getHeight();
     if (av.getWrapAlignment())
     {
-      int hgap = charHeight;
-      if (av.getScaleAboveWrapped())
-      {
-        hgap += charHeight;
-      }
+      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);
+      // }
 
-      final int alignmentHeightPixels = alignmentHeight * charHeight + hgap;
-      final int annotationHeight = seqCanvas.getAnnotationHeight();
-      final int cHeight = alignmentHeightPixels + annotationHeight
-              + SeqCanvas.SEQS_ANNOTATION_GAP;
+      /*
+       * yPos modulo repeating width height
+       */
+      int yOffsetPx = y % seqCanvas.wrappedRepeatHeightPx;
 
-      int yOffsetPx = y % cHeight; // yPos below repeating width(s)
-      if (yOffsetPx >= alignmentHeightPixels
-              + SeqCanvas.SEQS_ANNOTATION_GAP)
+      /*
+       * height of sequences plus space / scale above,
+       * plus gap between sequences and annotations
+       */
+      int alignmentHeightPixels = seqCanvas.wrappedSpaceAboveAlignment
+              + alignmentHeight * charHeight
+              + SeqCanvas.SEQS_ANNOTATION_GAP;
+      if (yOffsetPx >= alignmentHeightPixels)
       {
         /*
-         * mouse is over annotations; find annotation index, also
+         * mouse is over annotations; find annotation index, also set
          * last sequence above (for backwards compatible behaviour)
          */
         AlignmentAnnotation[] anns = av.getAlignment()
                 .getAlignmentAnnotation();
-        int rowOffsetPx = yOffsetPx - alignmentHeightPixels
-                - SeqCanvas.SEQS_ANNOTATION_GAP;
+        int rowOffsetPx = yOffsetPx - alignmentHeightPixels;
         annIndex = AnnotationPanel.getRowIndex(rowOffsetPx, anns);
         seqIndex = alignmentHeight - 1;
       }
@@ -303,7 +318,7 @@ public class SeqPanel extends JPanel
         /*
          * mouse is over sequence (or the space above sequences)
          */
-        yOffsetPx -= hgap;
+        yOffsetPx -= seqCanvas.wrappedSpaceAboveAlignment;
         if (yOffsetPx >= 0)
         {
           seqIndex = Math.min(yOffsetPx / charHeight, alignmentHeight - 1);
@@ -333,7 +348,6 @@ public class SeqPanel extends JPanel
     int startRes = av.getRanges().getStartRes();
     if (av.getWrapAlignment())
     {
-
       int hgap = av.getCharHeight();
       if (av.getScaleAboveWrapped())
       {
@@ -358,7 +372,7 @@ public class SeqPanel extends JPanel
       // 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 / av.getCharWidth());
     }
     else
     {
@@ -908,6 +922,7 @@ public class SeqPanel extends JPanel
     {
       lastMousePosition = null;
       setToolTipText(null);
+      lastTooltip = null;
       ap.alignFrame.statusBar.setText("");
       return;
     }
@@ -1026,20 +1041,26 @@ public class SeqPanel extends JPanel
   @Override
   public Point getToolTipLocation(MouseEvent event)
   {
-    int x = event.getX(), w = getWidth();
-    int wdth = (w - x < 200) ? -(w / 2) : 5; // switch sides when tooltip is too
-    // close to edge
+    if (tooltipText == null || tooltipText.length() <= 6)
+    {
+      lastp = null;
+      return null;
+    }
+
+    int x = event.getX();
+    int w = getWidth();
+    // switch sides when tooltip is too close to edge
+    int wdth = (w - x < 200) ? -(w / 2) : 5;
     Point p = lastp;
     if (!event.isShiftDown() || p == null)
     {
-      p = (tooltipText != null && tooltipText.length() > 6)
-              ? new Point(event.getX() + wdth, event.getY() - 20)
-              : null;
+      p = new Point(event.getX() + wdth, event.getY() - 20);
+      lastp = p;
     }
     /*
-     * TODO: try to modify position region is not obcured by tooltip
+     * TODO: try to set position so region is not obscured by tooltip
      */
-    return lastp = p;
+    return p;
   }
 
   String lastTooltip;
index 5298680..73aeb79 100644 (file)
@@ -29,10 +29,10 @@ import jalview.io.FileLoader;
 import java.awt.Font;
 import java.awt.FontMetrics;
 
-import junit.extensions.PA;
-
 import org.testng.annotations.Test;
 
+import junit.extensions.PA;
+
 public class SeqCanvasTest
 {
   /**
@@ -97,8 +97,8 @@ public class SeqCanvasTest
     assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
 
     /*
-     * reduce canvas height by 1 pixel - should not be enough height
-     * to draw 3 widths
+     * reduce canvas height by 1 pixel 
+     * - should not be enough height to draw 3 widths
      */
     canvasHeight -= 1;
     testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
@@ -170,11 +170,11 @@ public class SeqCanvasTest
     canvasWidth += 8;
     wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
             canvasHeight);
-    assertEquals(wrappedWidth, 27);
+    assertEquals(wrappedWidth, 27); // 8px not enough
     canvasWidth += 1;
     wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
             canvasHeight);
-    assertEquals(wrappedWidth, 28);
+    assertEquals(wrappedWidth, 28); // 9px is enough
 
     /*
      * now West but not East scale - lose 39 pixels or 4 columns
@@ -190,11 +190,11 @@ public class SeqCanvasTest
     canvasWidth += 2;
     wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
             canvasHeight);
-    assertEquals(wrappedWidth, 24);
+    assertEquals(wrappedWidth, 24); // 2px not enough
     canvasWidth += 1;
     wrappedWidth = testee.calculateWrappedGeometry(canvasWidth,
             canvasHeight);
-    assertEquals(wrappedWidth, 25);
+    assertEquals(wrappedWidth, 25); // 3px is enough
 
     /*
      * turn off scales left and right, make width exactly 157 columns
@@ -256,15 +256,16 @@ public class SeqCanvasTest
             2 * charHeight);
     int repeatingHeight = (int) PA.getValue(testee, "wrappedRepeatHeightPx");
     assertEquals(repeatingHeight, charHeight * (2 + al.getHeight())
-            + annotationHeight);
+            + SeqCanvas.SEQS_ANNOTATION_GAP + annotationHeight);
     assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 1);
   
     /*
-     * repeat height is 17 * (2 + 15) = 289 + annotationHeight = 507
-     * make canvas height 2 * 289 + 3 * charHeight so just enough to
-     * draw 2 widths and the first sequence of a third
+     * repeat height is 17 * (2 + 15) = 289 + 3 + annotationHeight = 510
+     * make canvas height 2 of these plus 3 charHeights 
+     * so just enough to draw 2 widths, gap + scale + the first sequence of a third
      */
-    canvasHeight = charHeight * (17 * 2 + 3) + 2 * annotationHeight;
+    canvasHeight = charHeight * (17 * 2 + 3)
+            + 2 * (annotationHeight + SeqCanvas.SEQS_ANNOTATION_GAP);
     testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
     assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 3);
   
@@ -287,7 +288,8 @@ public class SeqCanvasTest
      * reduce height to enough for 2 widths and not quite a third
      * i.e. two repeating heights + spacer + sequence - 1 pixel
      */
-    canvasHeight = charHeight * (16 * 2 + 2) + 2 * annotationHeight - 1;
+    canvasHeight = charHeight * (16 * 2 + 2)
+            + 2 * (annotationHeight + SeqCanvas.SEQS_ANNOTATION_GAP) - 1;
     testee.calculateWrappedGeometry(canvasWidth, canvasHeight);
     assertEquals(PA.getValue(testee, "wrappedVisibleWidths"), 2);
 
index 4177acc..d5c012e 100644 (file)
@@ -138,7 +138,7 @@ public class SeqPanelTest
   }
 
   @Test(groups = "Functional")
-  public void testFindMousePosition_wrapped()
+  public void testFindMousePosition_wrapped_annotations()
   {
     Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS", "true");
     Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "true");
@@ -236,6 +236,7 @@ public class SeqPanelTest
 
     /*
      * cursor below sequences, in 3-pixel gap above annotations
+     * method reports index of nearest sequence above
      */
     y += 1;
     evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
@@ -246,7 +247,6 @@ public class SeqPanelTest
 
     /*
      * cursor still in the gap above annotations, now at the bottom of it
-     * 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,
@@ -576,6 +576,93 @@ public class SeqPanelTest
     assertEquals(pos.seqIndex, 0);
     assertEquals(pos.annotationIndex, -1);
   }
+  @Test(groups = "Functional")
+  public void testFindMousePosition_wrapped_noAnnotations()
+  {
+    Cache.applicationProperties.setProperty("SHOW_ANNOTATIONS", "false");
+    Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "true");
+    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);
+  
+    final int charHeight = av.getCharHeight();
+    final int charWidth = av.getCharWidth();
+    final int alignmentHeight = av.getAlignment().getHeight();
+    
+    // sanity checks:
+    assertTrue(charHeight > 0);
+    assertTrue(charWidth > 0);
+    assertTrue(alignFrame.alignPanel.getSeqPanel().getWidth() > 0);
+  
+    SeqPanel testee = alignFrame.alignPanel.getSeqPanel();
+    int x = 0;
+    int y = 0;
+  
+    /*
+     * 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,
+            0, 0, 0, false, 0);
+    MousePos pos = testee.findMousePosition(evt);
+    assertEquals(pos.column, 0);
+    assertEquals(pos.seqIndex, -1); // above sequences
+    assertEquals(pos.annotationIndex, -1);
+  
+    /*
+     * cursor over top of first sequence
+     */
+    y = charHeight;
+    evt = new MouseEvent(testee, Event.MOUSE_MOVE, 0L, 0, x, y, 0, 0, 0,
+            false, 0);
+    pos = testee.findMousePosition(evt);
+    assertEquals(pos.seqIndex, 0);
+    assertEquals(pos.annotationIndex, -1);
+
+    /*
+     * 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,
+            false, 0);
+    pos = testee.findMousePosition(evt);
+    assertEquals(pos.seqIndex, alignmentHeight - 1);
+    assertEquals(pos.annotationIndex, -1);
+  
+    /*
+     * 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,
+            false, 0);
+    pos = testee.findMousePosition(evt);
+    assertEquals(pos.seqIndex, -1);
+    assertEquals(pos.annotationIndex, -1);
+  
+    /*
+     * 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,
+            false, 0);
+    pos = testee.findMousePosition(evt);
+    assertEquals(pos.seqIndex, -1);
+    assertEquals(pos.annotationIndex, -1);
+  
+    /*
+     * 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,
+            false, 0);
+    pos = testee.findMousePosition(evt);
+    assertEquals(pos.seqIndex, 0);
+    assertEquals(pos.annotationIndex, -1);
+  }
   @BeforeClass(alwaysRun = true)
   public static void setUpBeforeClass() throws Exception
   {