Merge branch 'patch/JAL-4260_fix_up_select_via_ruler_in_wrapped' into develop
authorJames Procter <j.procter@dundee.ac.uk>
Wed, 1 Nov 2023 16:40:55 +0000 (16:40 +0000)
committerJames Procter <j.procter@dundee.ac.uk>
Wed, 1 Nov 2023 16:40:55 +0000 (16:40 +0000)
src/jalview/gui/AlignFrame.java
src/jalview/gui/AnnotationLabels.java
src/jalview/gui/IdCanvas.java
src/jalview/gui/ScalePanel.java
src/jalview/gui/SeqCanvas.java
src/jalview/gui/SeqPanel.java
test/jalview/gui/ScalePanelTest.java
test/jalview/gui/SeqPanelTest.java

index ac8ffb9..aca8baa 100644 (file)
@@ -5842,6 +5842,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener,
       }
     }
     alignPanel.validateAnnotationDimensions(true);
+    // TODO this triggers relayout of annotation panel - otherwise annotation label height is different to panel height
+    alignPanel.fontChanged();
     alignPanel.alignmentChanged();
   }
 
index a3f7e00..08a25ba 100755 (executable)
@@ -1246,7 +1246,7 @@ public class AnnotationLabels extends JPanel
     else
     {
       int newAnnotationIdWidth = drawLabels(g, clip, width, false, forGUI, null, false);
-      width = Math.max(newAnnotationIdWidth, givenWidth);
+      width = newAnnotationIdWidth<givenWidth ? givenWidth: Math.min(newAnnotationIdWidth, givenWidth);
     }
     drawLabels(g, clip, width, true, forGUI, null, false);
   }
@@ -1554,7 +1554,7 @@ public class AnnotationLabels extends JPanel
       }
     }
 
-    if (!resizePanel && dragEvent != null && aa != null)
+    if (!resizePanel && dragEvent != null && aa != null && selectedRow>-1 && selectedRow<aa.length)
     {
       if (actuallyDraw && g != null)
       {
index 2df84a9..0dde9b5 100755 (executable)
@@ -307,7 +307,7 @@ public class IdCanvas extends JPanel implements ViewportListenerI
 
     if (alignViewport.getWrapAlignment())
     {
-      drawIdsWrapped(g, alignViewport, startSeq, getHeight());
+      drawIdsWrapped(g, alignViewport, startSeq, getHeight(), manuallyAdjusted ? panelWidth : -1,forGUI);
       return;
     }
 
@@ -401,7 +401,7 @@ public class IdCanvas extends JPanel implements ViewportListenerI
     drawIdsWrapped(g, av2, totalHeight, totalHeight, i,false);
   }
 
-  void drawIdsWrapped(Graphics2D g, AlignViewport alignViewport,
+  public void drawIdsWrapped(Graphics2D g, AlignViewport alignViewport,
           int startSeq, int pageHeight, int idWidth, boolean forGUI)
   {
     int alignmentWidth = alignViewport.getAlignment().getWidth();
@@ -418,6 +418,8 @@ public class IdCanvas extends JPanel implements ViewportListenerI
     AnnotationLabels labels = null;
     if (alignViewport.isShowAnnotation())
     {
+      // in wrapped mode, no alignPanel reference is available
+      // FIXME: make the renderer not create a new object in wrapped mode everytime!
       labels = new AnnotationLabels(alignViewport);
     }
 
index 422601d..a186ce6 100755 (executable)
@@ -107,14 +107,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);
+    int res = ap.getSeqPanel().findAlignmentColumn(evt);
 
     min = res;
     max = res;
@@ -286,18 +279,8 @@ public class ScalePanel extends JPanel
     mouseDragging = false;
     ap.getSeqPanel().stopScrolling();
 
-    // todo res calculation should be a method on AlignViewport
-    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 res = ap.getSeqPanel().findAlignmentColumn(evt);
+    
     if (!stretchingGroup)
     {
       if (evt.isPopupTrigger()) // Windows: mouseReleased
@@ -350,16 +333,12 @@ public class ScalePanel extends JPanel
   @Override
   public void mouseDragged(MouseEvent evt)
   {
-    mouseDragging = true;
+    mouseDragging = true;  
+    int res = ap.getSeqPanel().findAlignmentColumn(evt);
+    
     ColumnSelection cs = av.getColumnSelection();
-    HiddenColumns hidden = av.getAlignment().getHiddenColumns();
-
-    int res = (evt.getX() / av.getCharWidth())
-            + av.getRanges().getStartRes();
-    res = Math.max(0, res);
-    res = hidden.visibleToAbsoluteColumn(res);
-    res = Math.min(res, av.getAlignment().getWidth() - 1);
-    min = Math.min(res, min);
+    
+    min = Math.min(res,min);
     max = Math.max(res, max);
 
     SequenceGroup sg = av.getSelectionGroup();
@@ -410,22 +389,18 @@ public class ScalePanel extends JPanel
   {
     this.setToolTipText(null);
     reveal = null;
-    if (!av.hasHiddenColumns())
-    {
-      int res = (evt.getX() / av.getCharWidth())
-              + av.getRanges().getStartRes();
-      highlightAllStructPos(res);
+    final int res = ap.getSeqPanel().findAlignmentColumn(evt);
+    
+    highlightAllStructPos(res);
+    if (!av.hasHiddenColumns()) {
       return;
     }
-
-    int res = (evt.getX() / av.getCharWidth())
-            + av.getRanges().getStartRes();
-
     reveal = av.getAlignment().getHiddenColumns()
-            .getRegionWithEdgeAtRes(res);
-
-    res = av.getAlignment().getHiddenColumns().visibleToAbsoluteColumn(res);
-    highlightAllStructPos(res);
+            .getRegionWithEdgeAtRes(av.getAlignment().getHiddenColumns().absoluteToVisibleColumn(res));
+    if (reveal==null)
+    {
+      return;
+    }
     ToolTipManager.sharedInstance().registerComponent(this);
     this.setToolTipText(
             MessageManager.getString("label.reveal_hidden_columns"));
index 537af58..a9bfbf6 100755 (executable)
@@ -323,7 +323,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
 
       if (vertical > 0) // scroll down
       {
-        startSeq = endSeq - vertical;
+        startSeq = endSeq - vertical + 1;
 
         if (startSeq < ranges.getStartSeq())
         { // ie scrolling too fast, more than a page at a time
@@ -331,12 +331,12 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
         }
         else
         {
-          transY = img.getHeight() - ((vertical + 1) * charHeight);
+          transY = img.getHeight() - (vertical * charHeight);
         }
       }
-      else if (vertical < 0)
+      else if (vertical < 0) // scroll up
       {
-        endSeq = startSeq - vertical;
+        endSeq = startSeq - vertical - 1;
 
         if (endSeq > ranges.getEndSeq())
         {
@@ -344,7 +344,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
         }
       }
 
-      // jalview.bin.Console.errPrintln(">>> FastPaint to " + transX + " " + transY + " "
+      // jalview.bin.Console.errPrintln(">>> FastPaint to " + transX + " " +
+      // transY + " "
       // + horizontal + " " + vertical + " " + startRes + " " + endRes
       // + " " + startSeq + " " + endSeq);
 
@@ -363,7 +364,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
       // Call repaint on alignment panel so that repaints from other alignment
       // panel components can be aggregated. Otherwise performance of the
       // overview window and others may be adversely affected.
-      // jalview.bin.Console.outPrintln("SeqCanvas fastPaint() repaint() request...");
+      // jalview.bin.Console.outPrintln("SeqCanvas fastPaint() repaint()
+      // request...");
       av.getAlignPanel().repaint();
     } finally
     {
@@ -456,11 +458,12 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
 
       if (av.getWrapAlignment())
       {
-        drawWrappedPanel(seqRdr, gg, getWidth(), getHeight(), ranges.getStartRes());
+        drawWrappedPanel(seqRdr, gg, getWidth(), getHeight(),
+                ranges.getStartRes());
       }
       else
       {
-        drawPanel(seqRdr,gg, startRes, endRes, startSeq, endSeq, 0);
+        drawPanel(seqRdr, gg, startRes, endRes, startSeq, endSeq, 0);
       }
 
       drawSelectionGroup(gg, startRes, endRes, startSeq, endSeq);
@@ -493,7 +496,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
           int startSeq, int endSeq)
   {
     SequenceRenderer localSeqR = new jalview.gui.SequenceRenderer(av);
-    drawPanel(localSeqR,g1, startRes, endRes, startSeq, endSeq, 0);
+    drawPanel(localSeqR, g1, startRes, endRes, startSeq, endSeq, 0);
 
     drawSelectionGroup((Graphics2D) g1, startRes, endRes, startSeq, endSeq);
   }
@@ -611,8 +614,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
    * @param startColumn
    *          the first column (0...) of the alignment to draw
    */
-  public void drawWrappedPanel(SequenceRenderer seqRdr, Graphics g, int canvasWidth,
-          int canvasHeight, final int startColumn)
+  public void drawWrappedPanel(SequenceRenderer seqRdr, Graphics g,
+          int canvasWidth, int canvasHeight, final int startColumn)
   {
     int wrappedWidthInResidues = calculateWrappedGeometry(canvasWidth,
             canvasHeight);
@@ -733,8 +736,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
    * @param endColumn
    * @param canvasHeight
    */
-  protected void drawWrappedWidth(SequenceRenderer seqRdr, Graphics g, final int ypos,
-          final int startColumn, final int endColumn,
+  protected void drawWrappedWidth(SequenceRenderer seqRdr, Graphics g,
+          final int ypos, final int startColumn, final int endColumn,
           final int canvasHeight)
   {
     ViewportRanges ranges = av.getRanges();
@@ -762,8 +765,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
     g.fillRect(0, ypos, (endx - startColumn + 1) * charWidth,
             wrappedRepeatHeightPx);
 
-    drawPanel(seqRdr, g, startColumn, endx, 0, av.getAlignment().getHeight() - 1,
-            ypos);
+    drawPanel(seqRdr, g, startColumn, endx, 0,
+            av.getAlignment().getHeight() - 1, ypos);
 
     int cHeight = av.getAlignment().getHeight() * av.getCharHeight();
 
@@ -966,7 +969,10 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
    * are hidden column markers in the visible region, then each sub-region
    * between the markers is drawn separately, followed by the hidden column
    * marker.
-   * @param localSeqR - sequence renderer implementation - when null, uses the one used for rendering interactive GUI
+   * 
+   * @param localSeqR
+   *          - sequence renderer implementation - when null, uses the one used
+   *          for rendering interactive GUI
    * 
    * @param g1
    *          the graphics context, positioned at the first residue to be drawn
@@ -981,13 +987,14 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
    * @param yOffset
    *          vertical offset at which to draw (for wrapped alignments)
    */
-  public void drawPanel(SequenceRenderer localSeqR, Graphics g1, final int startRes, final int endRes,
-          final int startSeq, final int endSeq, final int yOffset)
+  public void drawPanel(SequenceRenderer localSeqR, Graphics g1,
+          final int startRes, final int endRes, final int startSeq,
+          final int endSeq, final int yOffset)
   {
     int charHeight = av.getCharHeight();
     int charWidth = av.getCharWidth();
 
-    if (localSeqR==null)
+    if (localSeqR == null)
     {
       localSeqR = seqRdr;
     }
@@ -1017,7 +1024,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
          */
         g1.translate(screenY * charWidth, 0);
 
-        draw(localSeqR, g1, blockStart, blockEnd, startSeq, endSeq, yOffset);
+        draw(localSeqR, g1, blockStart, blockEnd, startSeq, endSeq,
+                yOffset);
 
         /*
          * draw the downline of the hidden column marker (ScalePanel draws the
@@ -1042,7 +1050,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
 
   /**
    * Draws a region of the visible alignment
-   * @param seqRdr 
+   * 
+   * @param seqRdr
    * 
    * @param g1
    * @param startRes
@@ -1056,8 +1065,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
    * @param yOffset
    *          vertical offset at which to draw (for wrapped alignments)
    */
-  private void draw(SequenceRenderer seqRdr, Graphics g, int startRes, int endRes, int startSeq,
-          int endSeq, int offset)
+  private void draw(SequenceRenderer seqRdr, Graphics g, int startRes,
+          int endRes, int startSeq, int endSeq, int offset)
   {
     int charHeight = av.getCharHeight();
     int charWidth = av.getCharWidth();
@@ -1399,7 +1408,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
         else if (inGroup)
         {
           drawVerticals(g, sx, xwidth, visWidth, oldY, bottom);
-          drawHorizontals(g, sx, xwidth, visWidth, top, bottom+1);
+          drawHorizontals(g, sx, xwidth, visWidth, top, bottom);
 
           // reset top and bottom
           top = -1;
@@ -1410,8 +1419,9 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
       if (inGroup)
       {
         sy = verticalOffset + ((i - startSeq) * charHeight);
-        drawVerticals(g, sx, xwidth, visWidth, oldY, bottom);
-        drawHorizontals(g, sx, xwidth, visWidth, top, bottom+1);
+        drawVerticals(g, sx, xwidth, visWidth, oldY,
+                bottom == -1 ? sy : bottom);
+        drawHorizontals(g, sx, xwidth, visWidth, top, bottom);
       }
     }
   }
@@ -1688,7 +1698,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
   public void propertyChange(PropertyChangeEvent evt)
   {
     String eventName = evt.getPropertyName();
-    // jalview.bin.Console.errPrintln(">>SeqCanvas propertyChange " + eventName);
+    // jalview.bin.Console.errPrintln(">>SeqCanvas propertyChange " +
+    // eventName);
     if (eventName.equals(SequenceGroup.SEQ_GROUP_CHANGED))
     {
       fastPaint = true;
@@ -1698,7 +1709,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
     else if (eventName.equals(ViewportRanges.MOVE_VIEWPORT))
     {
       fastPaint = false;
-      // jalview.bin.Console.errPrintln("!!!! fastPaint false from MOVE_VIEWPORT");
+      // jalview.bin.Console.errPrintln("!!!! fastPaint false from
+      // MOVE_VIEWPORT");
       repaint();
       return;
     }
@@ -1828,7 +1840,7 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
       if (scrollX < 0)
       {
         int startRes = ranges.getStartRes();
-        drawWrappedWidth(seqRdr,gg, wrappedSpaceAboveAlignment, startRes,
+        drawWrappedWidth(seqRdr, gg, wrappedSpaceAboveAlignment, startRes,
                 startRes - scrollX - 1, getHeight());
       }
       else
@@ -2156,8 +2168,8 @@ public class SeqCanvas extends JPanel implements ViewportListenerI
               {
                 matchFound = true;
                 gg.translate(transX, transY);
-                drawPanel(seqRdr,gg, displayColumn, displayColumn, seqNo, seqNo,
-                        yOffset);
+                drawPanel(seqRdr, gg, displayColumn, displayColumn, seqNo,
+                        seqNo, yOffset);
                 gg.translate(-transX, -transY);
               }
             }
index ce60be6..d39f937 100644 (file)
@@ -343,6 +343,14 @@ public class SeqPanel extends JPanel
   }
 
   /**
+   * @param evt
+   * @return absolute column in alignment nearest to the mouse pointer
+   */
+  int findAlignmentColumn(MouseEvent evt)
+  {
+    return findNearestColumn(evt,true);
+  }
+  /**
    * Returns the aligned sequence position (base 0) at the mouse position, or
    * the closest visible one
    * <p>
@@ -354,6 +362,15 @@ public class SeqPanel extends JPanel
    */
   int findColumn(MouseEvent evt)
   {
+    return findNearestColumn(evt, false);
+  }
+  
+  /**
+   * @param nearestColumn when false returns negative values for out of bound positions - -1 for scale left/right, <-1 if far to right
+   * @return nearest absolute column to mouse pointer
+   */
+  private int findNearestColumn(MouseEvent evt, boolean nearestColumn)
+  {
     int res = 0;
     int x = evt.getX();
 
@@ -377,7 +394,11 @@ public class SeqPanel extends JPanel
       if (x < 0)
       {
         // mouse is over left scale
-        return -1;
+        if (!nearestColumn) {
+          return -1;
+        } else {
+          x = 0;
+        }
       }
 
       int cwidth = seqCanvas.getWrappedCanvasWidth(this.getWidth());
@@ -387,8 +408,12 @@ public class SeqPanel extends JPanel
       }
       if (x >= cwidth * charWidth)
       {
-        // mouse is over right scale
-        return -1;
+        if (!nearestColumn) {
+          // mouse is over right scale
+          return -1;
+        } else {
+          x = cwidth*charWidth -1;
+        }
       }
 
       wrappedBlock = y / cHeight;
@@ -405,9 +430,16 @@ public class SeqPanel extends JPanel
        * rather than right-hand gutter
        */
       x = Math.min(x, seqCanvas.getX() + seqCanvas.getWidth());
+      if (nearestColumn)
+      {
+        x = Math.max(x, 0);
+      }
+
       res = (x / charWidth) + startRes;
       res = Math.min(res, av.getRanges().getEndRes());
+
     }
+    
 
     if (av.hasHiddenColumns())
     {
index 1523741..20e72b9 100644 (file)
@@ -64,6 +64,10 @@ public class ScalePanelTest
     ScalePanel scalePanel = alignFrame.alignPanel.getScalePanel();
 
     MouseEvent mouse = new MouseEvent(scalePanel, 0, 1, 0, 4, 0, 1, false);
+    
+    // check the bounded lookup is not returning negatives
+    assertEquals(alignFrame.alignPanel.getSeqPanel().findAlignmentColumn(mouse),0);
+    
     scalePanel.mousePressed(mouse);
     scalePanel.mouseDragged(mouse);
 
index 4e8758b..d47df46 100644 (file)
@@ -789,7 +789,7 @@ public class SeqPanelTest
   }
 
   @Test(groups = "Functional")
-  public void testFindColumn_wrapped()
+  public void testFindColumn_and_FindAlignmentColumn_wrapped()
   {
     Cache.applicationProperties.setProperty("WRAP_ALIGNMENT", "true");
     AlignFrame alignFrame = new FileLoader().LoadFileWaitTillLoaded(
@@ -811,6 +811,7 @@ public class SeqPanelTest
     MouseEvent evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0,
             x, 0, 0, 0, 0, false, 0);
     assertEquals(testee.findColumn(evt), 0);
+    assertEquals(testee.findAlignmentColumn(evt), 0);
 
     /*
      * not quite one charWidth across
@@ -819,6 +820,7 @@ public class SeqPanelTest
     evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0,
             0, false, 0);
     assertEquals(testee.findColumn(evt), 0);
+    assertEquals(testee.findAlignmentColumn(evt), 0);
 
     /*
      * one charWidth across
@@ -827,6 +829,7 @@ public class SeqPanelTest
     evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0,
             0, false, 0);
     assertEquals(testee.findColumn(evt), 1);
+    assertEquals(testee.findAlignmentColumn(evt), 1);
 
     /*
      * x over scale left (before drawn columns) results in -1
@@ -840,11 +843,15 @@ public class SeqPanelTest
     evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0,
             0, false, 0);
     assertEquals(testee.findColumn(evt), -1);
+    assertEquals(testee.findAlignmentColumn(evt), 0);
+
 
     x = labelWidth;
     evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0,
             0, false, 0);
     assertEquals(testee.findColumn(evt), 0);
+    assertEquals(testee.findAlignmentColumn(evt), 0);
+
 
     /*
      * x over right edge of last residue (including scale left)
@@ -855,6 +862,8 @@ public class SeqPanelTest
     evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0,
             0, false, 0);
     assertEquals(testee.findColumn(evt), residuesWide - 1);
+    assertEquals(testee.findAlignmentColumn(evt), residuesWide-1);
+
 
     /*
      * x over scale right (beyond drawn columns) results in -1
@@ -869,7 +878,11 @@ public class SeqPanelTest
     x += 1; // just over left edge of scale right
     evt = new MouseEvent(testee, MouseEvent.MOUSE_MOVED, 0L, 0, x, 0, 0, 0,
             0, false, 0);
+    // on scale
     assertEquals(testee.findColumn(evt), -1);
+    // return right-most column visible
+    assertEquals(testee.findAlignmentColumn(evt), residuesWide2-1);
+
 
     // todo add startRes offset, hidden columns