JAL-147 don't page up above origin, repaint ids for scroll in wrapped
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Fri, 30 Jun 2017 13:49:13 +0000 (14:49 +0100)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Fri, 30 Jun 2017 13:49:13 +0000 (14:49 +0100)
mode

src/jalview/appletgui/IdCanvas.java
src/jalview/gui/IdCanvas.java
src/jalview/viewmodel/ViewportRanges.java

index 5313b41..991f3ea 100755 (executable)
@@ -199,129 +199,145 @@ public class IdCanvas extends Panel implements ViewportListenerI
 
   void drawIds(int starty, int endy)
   {
-    // hardwired italic IDs in applet currently
-    Font italic = new Font(av.getFont().getName(), Font.ITALIC, av
-            .getFont().getSize());
-    // temp variable for speed
     avcharHeight = av.getCharHeight();
 
-    gg.setFont(italic);
-
     Color currentColor = Color.white;
     Color currentTextColor = Color.black;
 
     final boolean doHiddenCheck = av.isDisplayReferenceSeq()
-            || av.hasHiddenRows(), hiddenRows = av.hasHiddenRows()
-            && av.getShowHiddenMarkers();
+            || av.hasHiddenRows();
+    boolean hiddenRows = av.hasHiddenRows() && av.getShowHiddenMarkers();
 
     if (av.getWrapAlignment())
     {
-      int maxwidth = av.getAlignment().getWidth();
-      int alheight = av.getAlignment().getHeight();
+      drawIdsWrapped(starty, doHiddenCheck, hiddenRows);
+      return;
+    }
 
-      if (av.hasHiddenColumns())
+    // Now draw the id strings
+    SequenceI seq;
+    for (int i = starty; i <= endy; i++)
+    {
+      seq = av.getAlignment().getSequenceAt(i);
+      if (seq == null)
       {
-        maxwidth = av.getAlignment().getHiddenColumns()
-                .findColumnPosition(maxwidth) - 1;
+        continue;
+      }
+      // hardwired italic IDs in applet currently
+      Font italic = new Font(av.getFont().getName(), Font.ITALIC, av
+              .getFont().getSize());
+      gg.setFont(italic);
+      // boolean isrep=false;
+      if (doHiddenCheck)
+      {
+        // isrep =
+        setHiddenFont(seq);
       }
 
-      int annotationHeight = 0;
-      AnnotationLabels labels = null;
-
-      if (av.isShowAnnotation())
+      // Selected sequence colours
+      if ((searchResults != null) && searchResults.contains(seq))
       {
-        AnnotationPanel ap = new AnnotationPanel(av);
-        annotationHeight = ap.adjustPanelHeight();
-        labels = new AnnotationLabels(av);
+        currentColor = Color.black;
+        currentTextColor = Color.white;
       }
-      int hgap = avcharHeight;
-      if (av.getScaleAboveWrapped())
+      else if ((av.getSelectionGroup() != null)
+              && av.getSelectionGroup().getSequences(null).contains(seq))
+      {
+        currentColor = Color.lightGray;
+        currentTextColor = Color.black;
+      }
+      else
       {
-        hgap += avcharHeight;
+        currentColor = av.getSequenceColour(seq);
+        currentTextColor = Color.black;
       }
 
-      int cHeight = alheight * avcharHeight + hgap + annotationHeight;
+      gg.setColor(currentColor);
+      // TODO: isrep could be used to highlight the representative in a
+      // different way
+      gg.fillRect(0, (i - starty) * avcharHeight, getSize().width,
+              avcharHeight);
+      gg.setColor(currentTextColor);
 
-      int rowSize = av.getRanges().getEndRes()
-              - av.getRanges().getStartRes();
-      // Draw the rest of the panels
-      for (int ypos = hgap, row = av.getRanges().getStartRes(); (ypos <= getSize().height)
-              && (row < maxwidth); ypos += cHeight, row += rowSize)
+      gg.drawString(seq.getDisplayId(av.getShowJVSuffix()), 0,
+              (((i - starty) * avcharHeight) + avcharHeight)
+                      - (avcharHeight / 5));
+
+      if (hiddenRows)
       {
-        for (int i = starty; i < alheight; i++)
-        {
+        drawMarker(i, starty, 0);
+      }
+    }
+  }
 
-          SequenceI s = av.getAlignment().getSequenceAt(i);
-          gg.setFont(italic);
-          if (doHiddenCheck)
-          {
-            setHiddenFont(s);
-          }
-          drawIdString(gg, hiddenRows, s, i, 0, ypos);
-        }
+  /**
+   * Draws sequence ids in wrapped mode
+   * 
+   * @param starty
+   * @param doHiddenCheck
+   * @param hiddenRows
+   */
+  protected void drawIdsWrapped(int starty, final boolean doHiddenCheck,
+          boolean hiddenRows)
+  {
+    int maxwidth = av.getAlignment().getWidth();
+    int alheight = av.getAlignment().getHeight();
 
-        if (labels != null)
-        {
-          gg.translate(0, ypos + (alheight * avcharHeight));
-          labels.drawComponent(gg, getSize().width);
-          gg.translate(0, -ypos - (alheight * avcharHeight));
-        }
+    if (av.hasHiddenColumns())
+    {
+      maxwidth = av.getAlignment().getHiddenColumns()
+              .findColumnPosition(maxwidth) - 1;
+    }
 
-      }
+    int annotationHeight = 0;
+    AnnotationLabels labels = null;
+
+    if (av.isShowAnnotation())
+    {
+      AnnotationPanel ap = new AnnotationPanel(av);
+      annotationHeight = ap.adjustPanelHeight();
+      labels = new AnnotationLabels(av);
     }
-    else
+    int hgap = avcharHeight;
+    if (av.getScaleAboveWrapped())
     {
-      // Now draw the id strings
-      SequenceI seq;
-      for (int i = starty; i <= endy; i++)
-      {
+      hgap += avcharHeight;
+    }
 
-        seq = av.getAlignment().getSequenceAt(i);
-        if (seq == null)
-        {
-          continue;
-        }
-        gg.setFont(italic);
-        // boolean isrep=false;
-        if (doHiddenCheck)
-        {
-          // isrep =
-          setHiddenFont(seq);
-        }
+    int cHeight = alheight * avcharHeight + hgap + annotationHeight;
 
-        // Selected sequence colours
-        if ((searchResults != null) && searchResults.contains(seq))
-        {
-          currentColor = Color.black;
-          currentTextColor = Color.white;
-        }
-        else if ((av.getSelectionGroup() != null)
-                && av.getSelectionGroup().getSequences(null).contains(seq))
-        {
-          currentColor = Color.lightGray;
-          currentTextColor = Color.black;
-        }
-        else
-        {
-          currentColor = av.getSequenceColour(seq);
-          currentTextColor = Color.black;
-        }
+    int rowSize = av.getRanges().getEndRes()
+            - av.getRanges().getStartRes();
 
-        gg.setColor(currentColor);
-        // TODO: isrep could be used to highlight the representative in a
-        // different way
-        gg.fillRect(0, (i - starty) * avcharHeight, getSize().width,
-                avcharHeight);
-        gg.setColor(currentTextColor);
+    // hardwired italic IDs in applet currently
+    Font italic = new Font(av.getFont().getName(), Font.ITALIC, av
+            .getFont().getSize());
+    gg.setFont(italic);
 
-        gg.drawString(seq.getDisplayId(av.getShowJVSuffix()), 0,
-                (((i - starty) * avcharHeight) + avcharHeight)
-                        - (avcharHeight / 5));
+    /*
+     * draw repeating sequence ids until out of sequence data or
+     * out of visible space, whichever comes first
+     */
+    for (int ypos = hgap, row = av.getRanges().getStartRes(); (ypos <= getSize().height)
+            && (row < maxwidth); ypos += cHeight, row += rowSize)
+    {
+      for (int i = starty; i < alheight; i++)
+      {
 
-        if (hiddenRows)
+        SequenceI s = av.getAlignment().getSequenceAt(i);
+        // gg.setFont(italic);
+        if (doHiddenCheck)
         {
-          drawMarker(i, starty, 0);
+          setHiddenFont(s);
         }
+        drawIdString(gg, hiddenRows, s, i, 0, ypos);
+      }
+
+      if (labels != null)
+      {
+        gg.translate(0, ypos + (alheight * avcharHeight));
+        labels.drawComponent(gg, getSize().width);
+        gg.translate(0, -ypos - (alheight * avcharHeight));
       }
     }
   }
@@ -398,16 +414,25 @@ public class IdCanvas extends Panel implements ViewportListenerI
     return false;
   }
 
+  /**
+   * Respond to viewport range changes (e.g. alignment panel was scrolled). Both
+   * scrolling and resizing change viewport ranges. Scrolling changes both start
+   * and end points, but resize only changes end values. Here we only want to
+   * fastpaint on a scroll, with resize using a normal paint, so scroll events
+   * are identified as changes to the horizontal or vertical start value.
+   * <p>
+   * In unwrapped mode, only responds to a vertical scroll, as horizontal scroll
+   * leaves sequence ids unchanged. In wrapped mode, only vertical scroll is
+   * provided, but it generates a change of "startres" which does require an
+   * update here.
+   */
   @Override
   public void propertyChange(PropertyChangeEvent evt)
   {
-    // Respond to viewport range changes (e.g. alignment panel was scrolled)
-    // Both scrolling and resizing change viewport ranges: scrolling changes
-    // both start and end points, but resize only changes end values.
-    // Here we only want to fastpaint on a scroll, with resize using a normal
-    // paint, so scroll events are identified as changes to the horizontal or
-    // vertical start value.
-    if (evt.getPropertyName().equals(ViewportRanges.STARTSEQ))
+    String propertyName = evt.getPropertyName();
+    if (propertyName.equals(ViewportRanges.STARTSEQ)
+            || (av.getWrapAlignment() && propertyName
+                    .equals(ViewportRanges.STARTRES)))
     {
       fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
     }
index 4642741..2ebdbba 100755 (executable)
@@ -155,7 +155,10 @@ public class IdCanvas extends JPanel implements ViewportListenerI
    */
   public void fastPaint(int vertical)
   {
-    if (gg == null)
+    /*
+     * for now, not attempting fast paint of wrapped ids...
+     */
+    if (gg == null || av.getWrapAlignment())
     {
       repaint();
 
@@ -283,143 +286,158 @@ public class IdCanvas extends JPanel implements ViewportListenerI
     Color currentColor = Color.white;
     Color currentTextColor = Color.black;
 
-    final boolean doHiddenCheck = av.isDisplayReferenceSeq()
-            || av.hasHiddenRows(), hiddenRows = av.hasHiddenRows();
+    boolean hasHiddenRows = av.hasHiddenRows();
 
     if (av.getWrapAlignment())
     {
-      int maxwidth = av.getAlignment().getWidth();
-      int alheight = av.getAlignment().getHeight();
+      drawIdsWrapped(starty, hasHiddenRows);
+      return;
+    }
 
-      if (av.hasHiddenColumns())
-      {
-        maxwidth = av.getAlignment().getHiddenColumns()
-                .findColumnPosition(maxwidth) - 1;
-      }
+    // No need to hang on to labels if we're not wrapped
+    labels = null;
 
-      int annotationHeight = 0;
+    // Now draw the id strings
+    int panelWidth = getWidth();
+    int xPos = 0;
+
+    SequenceI sequence;
+    // Now draw the id strings
+    for (int i = starty; i <= endy; i++)
+    {
+      sequence = av.getAlignment().getSequenceAt(i);
 
-      if (av.isShowAnnotation())
+      if (sequence == null)
       {
-        if (ap == null)
-        {
-          ap = new AnnotationPanel(av);
-        }
+        continue;
+      }
 
-        annotationHeight = ap.adjustPanelHeight();
-        if (labels == null)
-        {
-          labels = new AnnotationLabels(av);
-        }
+      if (hasHiddenRows || av.isDisplayReferenceSeq())
+      {
+        setHiddenFont(sequence);
       }
 
-      int hgap = av.getCharHeight();
-      if (av.getScaleAboveWrapped())
+      // Selected sequence colours
+      if ((searchResults != null) && searchResults.contains(sequence))
       {
-        hgap += av.getCharHeight();
+        currentColor = Color.black;
+        currentTextColor = Color.white;
       }
+      else if ((av.getSelectionGroup() != null)
+              && av.getSelectionGroup().getSequences(null)
+                      .contains(sequence))
+      {
+        currentColor = Color.lightGray;
+        currentTextColor = Color.black;
+      }
+      else
+      {
+        currentColor = av.getSequenceColour(sequence);
+        currentTextColor = Color.black;
+      }
+
+      gg.setColor(currentColor);
+
+      gg.fillRect(0, (i - starty) * av.getCharHeight(), getWidth(),
+              av.getCharHeight());
 
-      int cHeight = alheight * av.getCharHeight() + hgap + annotationHeight;
+      gg.setColor(currentTextColor);
 
-      int rowSize = av.getRanges().getEndRes()
-              - av.getRanges().getStartRes();
+      String string = sequence.getDisplayId(av.getShowJVSuffix());
 
-      // Draw the rest of the panels
-      for (int ypos = hgap, row = av.getRanges().getStartRes(); (ypos <= getHeight())
-              && (row < maxwidth); ypos += cHeight, row += rowSize)
+      if (av.isRightAlignIds())
       {
-        for (int i = starty; i < alheight; i++)
-        {
-          SequenceI s = av.getAlignment().getSequenceAt(i);
-          if (doHiddenCheck)
-          {
-            setHiddenFont(s);
-          }
-          else
-          {
-            gg.setFont(getIdfont());
-          }
-
-          drawIdString(gg, hiddenRows, s, i, 0, ypos);
-        }
+        xPos = panelWidth - fm.stringWidth(string) - 4;
+      }
 
-        if (labels != null && av.isShowAnnotation())
-        {
-          gg.translate(0, ypos + (alheight * av.getCharHeight()));
-          labels.drawComponent(gg, getWidth());
-          gg.translate(0, -ypos - (alheight * av.getCharHeight()));
-        }
+      gg.drawString(string, xPos,
+              (((i - starty) * av.getCharHeight()) + av.getCharHeight())
+                      - (av.getCharHeight() / 5));
+
+      if (hasHiddenRows)
+      {
+        drawMarker(i, starty, 0);
       }
     }
-    else
-    {
-      // No need to hang on to labels if we're not wrapped
-      labels = null;
+  }
 
-      // Now draw the id strings
-      int panelWidth = getWidth();
-      int xPos = 0;
+  /**
+   * Draws sequence ids in wrapped mode
+   * 
+   * @param starty
+   * @param hasHiddenRows
+   */
+  protected void drawIdsWrapped(int starty, boolean hasHiddenRows)
+  {
+    int maxwidth = av.getAlignment().getWidth();
+    int alheight = av.getAlignment().getHeight();
 
-      SequenceI sequence;
-      // Now draw the id strings
-      for (int i = starty; i <= endy; i++)
-      {
-        sequence = av.getAlignment().getSequenceAt(i);
+    if (av.hasHiddenColumns())
+    {
+      maxwidth = av.getAlignment().getHiddenColumns()
+              .findColumnPosition(maxwidth) - 1;
+    }
 
-        if (sequence == null)
-        {
-          continue;
-        }
+    int annotationHeight = 0;
 
-        if (doHiddenCheck)
-        {
-          setHiddenFont(sequence);
-        }
+    if (av.isShowAnnotation())
+    {
+      if (ap == null)
+      {
+        ap = new AnnotationPanel(av);
+      }
 
-        // Selected sequence colours
-        if ((searchResults != null) && searchResults.contains(sequence))
-        {
-          currentColor = Color.black;
-          currentTextColor = Color.white;
-        }
-        else if ((av.getSelectionGroup() != null)
-                && av.getSelectionGroup().getSequences(null)
-                        .contains(sequence))
-        {
-          currentColor = Color.lightGray;
-          currentTextColor = Color.black;
-        }
-        else
-        {
-          currentColor = av.getSequenceColour(sequence);
-          currentTextColor = Color.black;
-        }
+      annotationHeight = ap.adjustPanelHeight();
+      if (labels == null)
+      {
+        labels = new AnnotationLabels(av);
+      }
+    }
 
-        gg.setColor(currentColor);
+    int hgap = av.getCharHeight();
+    if (av.getScaleAboveWrapped())
+    {
+      hgap += av.getCharHeight();
+    }
 
-        gg.fillRect(0, (i - starty) * av.getCharHeight(), getWidth(),
-                av.getCharHeight());
+    int cHeight = alheight * av.getCharHeight() + hgap + annotationHeight;
 
-        gg.setColor(currentTextColor);
+    ViewportRanges ranges = av.getRanges();
 
-        String string = sequence.getDisplayId(av.getShowJVSuffix());
+    int rowSize = ranges.getEndRes() - ranges.getStartRes();
 
-        if (av.isRightAlignIds())
+    /*
+     * draw repeating sequence ids until out of sequence data or
+     * out of visible space, whichever comes first
+     */
+    int ypos = hgap;
+    for (int row = ranges.getStartRes(); (ypos <= getHeight())
+            && (row < maxwidth);)
+    {
+      for (int i = starty; i < alheight; i++)
+      {
+        SequenceI s = av.getAlignment().getSequenceAt(i);
+        if (hasHiddenRows || av.isDisplayReferenceSeq())
         {
-          xPos = panelWidth - fm.stringWidth(string) - 4;
+          setHiddenFont(s);
         }
-
-        gg.drawString(string, xPos,
-                (((i - starty) * av.getCharHeight()) + av.getCharHeight())
-                        - (av.getCharHeight() / 5));
-
-        if (hiddenRows)
+        else
         {
-          drawMarker(i, starty, 0);
+          gg.setFont(getIdfont());
         }
 
+        drawIdString(gg, hasHiddenRows, s, i, 0, ypos);
+      }
+
+      if (labels != null && av.isShowAnnotation())
+      {
+        gg.translate(0, ypos + (alheight * av.getCharHeight()));
+        labels.drawComponent(gg, getWidth());
+        gg.translate(0, -ypos - (alheight * av.getCharHeight()));
       }
 
+      ypos += cHeight;
+      row += rowSize;
     }
   }
 
@@ -520,16 +538,25 @@ public class IdCanvas extends JPanel implements ViewportListenerI
     this.idfont = idfont;
   }
 
+  /**
+   * Respond to viewport range changes (e.g. alignment panel was scrolled). Both
+   * scrolling and resizing change viewport ranges. Scrolling changes both start
+   * and end points, but resize only changes end values. Here we only want to
+   * fastpaint on a scroll, with resize using a normal paint, so scroll events
+   * are identified as changes to the horizontal or vertical start value.
+   * <p>
+   * In unwrapped mode, only responds to a vertical scroll, as horizontal scroll
+   * leaves sequence ids unchanged. In wrapped mode, only vertical scroll is
+   * provided, but it generates a change of "startres" which does require an
+   * update here.
+   */
   @Override
   public void propertyChange(PropertyChangeEvent evt)
   {
-    // Respond to viewport range changes (e.g. alignment panel was scrolled)
-    // Both scrolling and resizing change viewport ranges: scrolling changes
-    // both start and end points, but resize only changes end values.
-    // Here we only want to fastpaint on a scroll, with resize using a normal
-    // paint, so scroll events are identified as changes to the horizontal or
-    // vertical start value.
-    if (evt.getPropertyName().equals(ViewportRanges.STARTSEQ))
+    String propertyName = evt.getPropertyName();
+    if (propertyName.equals(ViewportRanges.STARTSEQ)
+            || (av.getWrapAlignment() && propertyName
+                    .equals(ViewportRanges.STARTRES)))
     {
       fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
     }
index 162e712..f290ae7 100644 (file)
@@ -535,7 +535,7 @@ public class ViewportRanges extends ViewportProperties
   {
     if (wrappedMode)
     {
-      setStartRes(getStartRes() - getViewportWidth());
+      setStartRes(Math.max(0, getStartRes() - getViewportWidth()));
     }
     else
     {