Merge branch 'bug/JAL-3212columnSelectionWithHidden' into develop bug/JAL-3212columnSelectionWithHidden
authorJim Procter <jprocter@issues.jalview.org>
Mon, 17 Jun 2019 12:50:29 +0000 (13:50 +0100)
committerJim Procter <jprocter@issues.jalview.org>
Mon, 17 Jun 2019 12:50:29 +0000 (13:50 +0100)
src/jalview/gui/AnnotationPanel.java
src/jalview/gui/ScalePanel.java
src/jalview/gui/SeqPanel.java
src/jalview/viewmodel/AlignmentViewport.java
test/jalview/gui/AlignViewportTest.java

index 16db94c..9d64d2f 100755 (executable)
@@ -765,16 +765,7 @@ public class AnnotationPanel extends JPanel implements AwtRenderPanelI,
       this.setToolTipText(null);
       return;
     }
-
-    int column = (evt.getX() / av.getCharWidth())
-            + av.getRanges().getStartRes();
-    column = Math.min(column, av.getRanges().getEndRes());
-
-    if (av.hasHiddenColumns())
-    {
-      column = av.getAlignment().getHiddenColumns()
-              .visibleToAbsoluteColumn(column);
-    }
+    int column = av.getAbsoluteColumn(evt.getX());
 
     AlignmentAnnotation ann = aa[row];
     if (row > -1 && ann.annotations != null
index 8f49c6c..833cd54 100755 (executable)
@@ -108,14 +108,7 @@ public class ScalePanel extends JPanel
   @Override
   public void mousePressed(MouseEvent evt)
   {
-    int x = (evt.getX() / av.getCharWidth()) + av.getRanges().getStartRes();
-    final int res;
-
-    if (av.hasHiddenColumns())
-    {
-      x = av.getAlignment().getHiddenColumns().visibleToAbsoluteColumn(x);
-    }
-    res = Math.min(x, av.getAlignment().getWidth() - 1);
+    final int res = av.getAbsoluteColumn(evt.getX());
 
     min = res;
     max = res;
@@ -287,17 +280,8 @@ public class ScalePanel extends JPanel
     mouseDragging = false;
     ap.getSeqPanel().stopScrolling();
 
-    int xCords = Math.max(0, evt.getX()); // prevent negative X coordinates
-    ViewportRanges ranges = av.getRanges();
-    int res = (xCords / av.getCharWidth())
-            + ranges.getStartRes();
-    res = Math.min(res, ranges.getEndRes());
-    if (av.hasHiddenColumns())
-    {
-      res = av.getAlignment().getHiddenColumns()
-              .visibleToAbsoluteColumn(res);
-    }
-    res = Math.max(0, res);
+    int xPos = evt.getX();
+    int res = av.getAbsoluteColumn(xPos);
 
     if (!stretchingGroup)
     {
@@ -419,8 +403,6 @@ public class ScalePanel extends JPanel
     reveal = av.getAlignment().getHiddenColumns()
             .getRegionWithEdgeAtRes(res);
 
-    res = av.getAlignment().getHiddenColumns().visibleToAbsoluteColumn(res);
-
     ToolTipManager.sharedInstance().registerComponent(this);
     this.setToolTipText(
             MessageManager.getString("label.reveal_hidden_columns"));
index 1176df5..97fa19b 100644 (file)
@@ -331,61 +331,56 @@ public class SeqPanel extends JPanel
    */
   int findColumn(MouseEvent evt)
   {
-    int res = 0;
     int x = evt.getX();
 
+    if (!av.getWrapAlignment())
+    {
+      return av.getAbsoluteColumn(x);
+    }
+
+    /*
+     * wrapped mode calculation
+     */
     final int startRes = av.getRanges().getStartRes();
     final int charWidth = av.getCharWidth();
 
-    if (av.getWrapAlignment())
+    int res = 0;
+    int hgap = av.getCharHeight();
+    if (av.getScaleAboveWrapped())
     {
-      int hgap = av.getCharHeight();
-      if (av.getScaleAboveWrapped())
-      {
-        hgap += av.getCharHeight();
-      }
-
-      int cHeight = av.getAlignment().getHeight() * av.getCharHeight()
-              + hgap + seqCanvas.getAnnotationHeight();
+      hgap += av.getCharHeight();
+    }
 
-      int y = evt.getY();
-      y = Math.max(0, y - hgap);
-      x -= seqCanvas.getLabelWidthWest();
-      if (x < 0)
-      {
-        // mouse is over left scale
-        return -1;
-      }
+    int cHeight = av.getAlignment().getHeight() * av.getCharHeight() + hgap
+            + seqCanvas.getAnnotationHeight();
 
-      int cwidth = seqCanvas.getWrappedCanvasWidth(this.getWidth());
-      if (cwidth < 1)
-      {
-        return 0;
-      }
-      if (x >= cwidth * charWidth)
-      {
-        // mouse is over right scale
-        return -1;
-      }
+    int y = evt.getY();
+    y = Math.max(0, y - hgap);
+    x -= seqCanvas.getLabelWidthWest();
+    if (x < 0)
+    {
+      // mouse is over left 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 / charWidth);
+    int cwidth = seqCanvas.getWrappedCanvasWidth(this.getWidth());
+    if (cwidth < 1)
+    {
+      return 0;
     }
-    else
+    if (x >= cwidth * charWidth)
     {
-      /*
-       * make sure we calculate relative to visible alignment, 
-       * rather than right-hand gutter
-       */
-      x = Math.min(x, seqCanvas.getX() + seqCanvas.getWidth());
-      res = (x / charWidth) + startRes;
-      res = Math.min(res, av.getRanges().getEndRes());
+      // 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 / charWidth);
+
     if (av.hasHiddenColumns())
     {
       res = av.getAlignment().getHiddenColumns()
index 148ea16..e9e53e7 100644 (file)
@@ -3020,4 +3020,47 @@ public abstract class AlignmentViewport
       codingComplement.setUpdateStructures(needToUpdateStructureViews);
     }
   }
+
+  /**
+   * Answers the absolute column position (0..) (allowing for any hidden
+   * columns) for the given x position in the viewport. The position is
+   * restricted to the currently visible range, and to the width of the
+   * alignment. This method is not applicable, and throws an exception if
+   * called, if the view is in wrapped mode.<br>
+   * Example
+   * <ul>
+   * <li>alignment width 157 (uniref50.fa example)</li>
+   * <li>panel width 70</li>
+   * <li>columns 0-59 and 69-119 hidden (111 columns)</li>
+   * <li>leaves 56 columns visible, hidden columns left of and within the
+   * alignment</li>
+   * <li>getAbsoluteColumn(0) answers 60 (first visible column)</li>
+   * <li>getAbsoluteColumn(-20) answers 60</li>
+   * <li>getAbsoluteColumn(8*charWidth) answers 68 (just before hidden column
+   * marker)</li>
+   * <li>getAbsoluteColumn(9*charWidth) answers 120 (just after hidden column
+   * marker)</li>
+   * <li>getAbsoluteColumn(123456) answers 156 (last column of alignment)</li>
+   * </ul>
+   * 
+   * @param xPos
+   * @return
+   * @throw IllegalStateException
+   */
+  public int getAbsoluteColumn(int xPos)
+  {
+    if (getWrapAlignment())
+    {
+      throw new IllegalStateException("Not valid in wrapped mode");
+    }
+    int xCords = Math.max(0, xPos); // treat negative X as zero
+    int res = (xCords / getCharWidth()) + ranges.getStartRes();
+    res = Math.min(res, ranges.getEndRes());
+    if (hasHiddenColumns())
+    {
+      res = getAlignment().getHiddenColumns().visibleToAbsoluteColumn(res);
+    }
+    res = Math.max(0, res);
+    return res;
+  }
 }
index 959abb0..fc6a80d 100644 (file)
@@ -511,4 +511,71 @@ public class AlignViewportTest
     assertEquals(0, ranges.getStartSeq());
     assertEquals(2, ranges.getEndSeq());
   }
+
+  @Test(groups = { "Functional" })
+  public void testGetAbsoluteColumn()
+  {
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+            "examples/uniref50.fa", DataSourceType.FILE);
+    AlignViewport av = af.getViewport();
+    ViewportRanges ranges = av.getRanges();
+    assertEquals(0, ranges.getStartRes());
+    assertEquals(59, ranges.getEndRes()); // 60 columns wide
+
+    int cw = av.getCharWidth();
+    assertEquals(0, av.getAbsoluteColumn(0));
+    assertEquals(0, av.getAbsoluteColumn(cw - 1));
+    assertEquals(1, av.getAbsoluteColumn(cw));
+
+    // negative x is treated as zero:
+    assertEquals(0, av.getAbsoluteColumn(-20));
+
+    // x to the right of panel is restricted to panel width:
+    assertEquals(59, av.getAbsoluteColumn(100 * cw));
+
+    // scroll right by 10 columns
+    af.alignPanel.setScrollValues(10, 0);
+    assertEquals(10, av.getAbsoluteColumn(0));
+    assertEquals(10, av.getAbsoluteColumn(cw - 1));
+    assertEquals(11, av.getAbsoluteColumn(cw));
+    assertEquals(10, av.getAbsoluteColumn(-20));
+    assertEquals(69, av.getAbsoluteColumn(100 * cw));
+  }
+
+  @Test(
+    groups =
+    { "Functional" },
+    expectedExceptions =
+    { IllegalStateException.class })
+  public void testGetAbsoluteColumn_wrapped()
+  {
+    testee.setWrapAlignment(true);
+    testee.getAbsoluteColumn(0);
+  }
+
+  @Test(groups = { "Functional" })
+  public void testGetAbsoluteColumn_hiddenColumns()
+  {
+    AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(
+            "examples/uniref50.fa", DataSourceType.FILE);
+    AlignViewport av = af.getViewport();
+    ViewportRanges ranges = av.getRanges();
+    assertEquals(0, ranges.getStartRes());
+    assertEquals(59, ranges.getEndRes()); // 60 columns wide
+  
+    av.hideColumns(11, 40); // 30 columns hidden, cols 0-10 visible
+    int cw = av.getCharWidth();
+    assertEquals(0, av.getAbsoluteColumn(0));
+    assertEquals(10, av.getAbsoluteColumn(10 * cw)); // left of hidden cols
+    assertEquals(41, av.getAbsoluteColumn(11 * cw)); // skipped 30 hidden
+  
+    // scroll right by 11 columns - to just past hidden columns marker
+    af.alignPanel.setScrollValues(11, 0);
+    assertEquals(41, av.getAbsoluteColumn(0));
+
+    // hide absolute columns 60-70 (visible columns 19-29)
+    av.hideColumns(60, 70);
+    assertEquals(59, av.getAbsoluteColumn(18 * cw));
+    assertEquals(71, av.getAbsoluteColumn(19 * cw)); // skipped 11 hidden
+  }
 }