Merge branch 'bug/JAL-2811' into bug/JAL-2831
authorkiramt <k.mourao@dundee.ac.uk>
Tue, 14 Nov 2017 11:12:55 +0000 (11:12 +0000)
committerkiramt <k.mourao@dundee.ac.uk>
Tue, 14 Nov 2017 11:12:55 +0000 (11:12 +0000)
1  2 
src/jalview/gui/SeqCanvas.java

@@@ -296,48 -296,47 +296,48 @@@ public class SeqCanvas extends JCompone
        int transX = 0;
        int transY = 0;
  
 -    gg.copyArea(horizontal * charWidth, vertical * charHeight,
 -            img.getWidth(), img.getHeight(), -horizontal * charWidth,
 -            -vertical * charHeight);
 +      gg.copyArea(horizontal * charWidth, vertical * charHeight,
 +              img.getWidth(), img.getHeight(), -horizontal * charWidth,
 +              -vertical * charHeight);
  
 -    if (horizontal > 0) // scrollbar pulled right, image to the left
 -    {
 -      transX = (endRes - startRes - horizontal) * charWidth;
 -      startRes = endRes - horizontal;
 -    }
 -    else if (horizontal < 0)
 -    {
 -      endRes = startRes - horizontal;
 -    }
 -    else if (vertical > 0) // scroll down
 -    {
 -      startSeq = endSeq - vertical;
 -
 -      if (startSeq < ranges.getStartSeq())
 -      { // ie scrolling too fast, more than a page at a time
 -        startSeq = ranges.getStartSeq();
 +      if (horizontal > 0) // scrollbar pulled right, image to the left
 +      {
 +        transX = (endRes - startRes - horizontal) * charWidth;
 +        startRes = endRes - horizontal;
        }
 -      else
 +      else if (horizontal < 0)
        {
 -        transY = img.getHeight() - ((vertical + 1) * charHeight);
 +        endRes = startRes - horizontal;
        }
 -    }
 -    else if (vertical < 0)
 -    {
 -      endSeq = startSeq - vertical;
  
 -      if (endSeq > ranges.getEndSeq())
 +      if (vertical > 0) // scroll down
        {
 -        endSeq = ranges.getEndSeq();
 +        startSeq = endSeq - vertical;
 +
 +        if (startSeq < ranges.getStartSeq())
 +        { // ie scrolling too fast, more than a page at a time
 +          startSeq = ranges.getStartSeq();
 +        }
 +        else
 +        {
 +          transY = img.getHeight() - ((vertical + 1) * charHeight);
 +        }
 +      }
 +      else if (vertical < 0)
 +      {
 +        endSeq = startSeq - vertical;
 +
 +        if (endSeq > ranges.getEndSeq())
 +        {
 +          endSeq = ranges.getEndSeq();
 +        }
        }
 -    }
  
 -    gg.translate(transX, transY);
 -    drawPanel(gg, startRes, endRes, startSeq, endSeq, 0);
 -    gg.translate(-transX, -transY);
 +      gg.translate(transX, transY);
 +      drawPanel(gg, startRes, endRes, startSeq, endSeq, 0);
 +      gg.translate(-transX, -transY);
  
 -    repaint();
 +      repaint();
      } finally
      {
        fastpainting = false;
              ranges.getStartRes(), ranges.getEndRes(),
              ranges.getStartSeq(), ranges.getEndSeq());
  
+     BufferedImage cursorImage = drawCursor(ranges.getStartRes(),
+             ranges.getEndRes(), ranges.getStartSeq(), ranges.getEndSeq());
      if ((img != null) && (fastPaint
              || (getVisibleRect().width != g.getClipBounds().width)
              || (getVisibleRect().height != g.getClipBounds().height)))
      {
-       BufferedImage lcimg = buildLocalImage(selectImage);
+       BufferedImage lcimg = buildLocalImage(selectImage, cursorImage);
        g.drawImage(lcimg, 0, 0, this);
        fastPaint = false;
      }
        }
  
        // lcimg is a local *copy* of img which we'll draw selectImage on top of
-       BufferedImage lcimg = buildLocalImage(selectImage);
+       BufferedImage lcimg = buildLocalImage(selectImage, cursorImage);
        g.drawImage(lcimg, 0, 0, this);
      }
    }
     * Make a local image by combining the cached image img
     * with any selection
     */
-   private BufferedImage buildLocalImage(BufferedImage selectImage)
+   private BufferedImage buildLocalImage(BufferedImage selectImage,
+           BufferedImage cursorImage)
    {
      // clone the cached image
      BufferedImage lcimg = new BufferedImage(img.getWidth(), img.getHeight(),
                AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
        g2d.drawImage(selectImage, 0, 0, this);
      }
+     // overlay cursor on lcimg
+     if (cursorImage != null)
+     {
+       g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
+       g2d.drawImage(cursorImage, 0, 0, this);
+     }
      g2d.dispose();
  
      return lcimg;
            int canvasWidth,
            int canvasHeight, int startRes)
    {
 -      int charHeight = av.getCharHeight();
 -      int charWidth = av.getCharWidth();
 -        
 +    int charHeight = av.getCharHeight();
 +    int charWidth = av.getCharWidth();
 +      
      // height gap above each panel
      int hgap = charHeight;
      if (av.getScaleAboveWrapped())
          }
        }
  
-       if (av.cursorMode && cursorY == i && cursorX >= startRes
+       /*      if (av.cursorMode && cursorY == i && cursorX >= startRes
                && cursorX <= endRes)
        {
          seqRdr.drawCursor(nextSeq, cursorX, (cursorX - startRes) * charWidth,
                  offset + ((i - startSeq) * charHeight));
-       }
+       }*/
      }
  
      if (av.getSelectionGroup() != null
      return selectionImage;
    }
  
+   /**
+    * Draw the cursor as a separate image and overlay
+    * 
+    * @param startRes
+    *          start residue of area to draw cursor in
+    * @param endRes
+    *          end residue of area to draw cursor in
+    * @param startSeq
+    *          start sequence of area to draw cursor in
+    * @param endSeq
+    *          end sequence of are to draw cursor in
+    * @return a transparent image of the same size as the sequence canvas, with
+    *         the cursor drawn on it, if any
+    */
+   private BufferedImage drawCursor(int startRes, int endRes, int startSeq,
+           int endSeq)
+   {
+     // define our cursor image
+     BufferedImage cursorImage = null;
+     // don't do work unless we have to
+     if (av.cursorMode && cursorY >= startSeq && cursorY <= endSeq)
+     {
+       int yoffset = 0;
+       int xoffset = 0;
+       int startx = startRes;
+       int endx = endRes;
+       if (av.getWrapAlignment())
+       {
+         // work out the correct offsets for the cursor
+         int charHeight = av.getCharHeight();
+         int charWidth = av.getCharWidth();
+         int canvasWidth = getWidth();
+         int canvasHeight = getHeight();
+         // height gap above each panel
+         int hgap = charHeight;
+         if (av.getScaleAboveWrapped())
+         {
+           hgap += charHeight;
+         }
+         int cWidth = (canvasWidth - labelWidthEast - labelWidthWest)
+                 / charWidth;
+         int cHeight = av.getAlignment().getHeight() * charHeight;
+         endx = startx + cWidth - 1;
+         int ypos = hgap; // vertical offset
+         // iterate down the wrapped panels
+         while ((ypos <= canvasHeight) && (endx < cursorX))
+         {
+           // update vertical offset
+           ypos += cHeight + getAnnotationHeight() + hgap;
+           // update horizontal offset
+           startx += cWidth;
+           endx = startx + cWidth - 1;
+         }
+         yoffset = ypos;
+         xoffset = labelWidthWest;
+       }
+       // now check if cursor is within range for x values
+       if (cursorX >= startx && cursorX <= endx)
+       {
+         // get a new image of the correct size
+         cursorImage = setupImage();
+         Graphics2D g = (Graphics2D) cursorImage.getGraphics();
+         // get the character the cursor is drawn at
+         SequenceI seq = av.getAlignment().getSequenceAt(cursorY);
+         char s = seq.getCharAt(cursorX);
+         seqRdr.drawCursor(g, s,
+                 xoffset + (cursorX - startx) * av.getCharWidth(),
+                 yoffset + (cursorY - startSeq) * av.getCharHeight());
+         g.dispose();
+       }
+     }
+     return cursorImage;
+   }
    /*
     * Set up graphics for selection group
     */
    private void drawUnwrappedSelection(Graphics2D g, SequenceGroup group,
            int startRes, int endRes, int startSeq, int endSeq, int offset)
    {
 -      int charWidth = av.getCharWidth();
 -        
 +    int charWidth = av.getCharWidth();
 +          
      if (!av.hasHiddenColumns())
      {
        drawPartialGroupOutline(g, group, startRes, endRes, startSeq, endSeq,
            int startRes, int endRes, int startSeq, int endSeq,
            int verticalOffset)
    {
 -      int charHeight = av.getCharHeight();
 -      int charWidth = av.getCharWidth();
 -        
 +        int charHeight = av.getCharHeight();
 +        int charWidth = av.getCharWidth();
 +          
      int visWidth = (endRes - startRes + 1) * charWidth;
  
      int oldY = -1;
        repaint();
        return;
      }
 +    else if (eventName.equals(ViewportRanges.MOVE_VIEWPORT))
 +    {
 +      fastPaint = false;
 +      repaint();
 +      return;
 +    }
  
      int scrollX = 0;
 -    if (eventName.equals(ViewportRanges.STARTRES))
 +    if (eventName.equals(ViewportRanges.STARTRES)
 +            || eventName.equals(ViewportRanges.STARTRESANDSEQ))
      {
        // Make sure we're not trying to draw a panel
        // larger than the visible window
 +      if (eventName.equals(ViewportRanges.STARTRES))
 +      {
 +        scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
 +      }
 +      else
 +      {
 +        scrollX = ((int[]) evt.getNewValue())[0]
 +                - ((int[]) evt.getOldValue())[0];
 +      }
        ViewportRanges vpRanges = av.getRanges();
 -      scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
 -      int range = vpRanges.getViewportWidth();
 +
 +      int range = vpRanges.getEndRes() - vpRanges.getStartRes();
        if (scrollX > range)
        {
          scrollX = range;
        {
          scrollX = -range;
        }
 -    }
 -
 -    // 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.
  
 -    // scroll - startres and endres both change
 -    if (eventName.equals(ViewportRanges.STARTRES))
 -    {
 -      if (av.getWrapAlignment())
 +      // 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 (eventName.equals(ViewportRanges.STARTRES))
        {
 -        fastPaintWrapped(scrollX);
 +        if (av.getWrapAlignment())
 +          {
 +            fastPaintWrapped(scrollX);
 +          }
 +          else
 +          {
 +            fastPaint(scrollX, 0);
 +          }
        }
 -      else
 +      else if (eventName.equals(ViewportRanges.STARTSEQ))
        {
 -        fastPaint(scrollX, 0);
 +        // scroll
 +        fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
 +      }
 +      else if (eventName.equals(ViewportRanges.STARTRESANDSEQ))
 +      {
 +        if (av.getWrapAlignment())
 +        {
 +          fastPaintWrapped(scrollX);
 +        }
 +        else
 +        {
 +          fastPaint(scrollX, 0);
 +        }
 +        // bizarrely, we only need to scroll on the x value here as fastpaint
 +        // copies the full height of the image anyway. Passing in the y value
 +        // causes nasty repaint artefacts, which only disappear on a full
 +        // repaint.
        }
 -    }
 -    else if (eventName.equals(ViewportRanges.STARTSEQ))
 -    {
 -      // scroll
 -      fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
      }
    }