X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fgui%2FSeqCanvas.java;h=1e1105f86d1a8413d931835502e8cd1a7e19ebb0;hb=f5cadfa2a55d78a08268a0df9a7c3f64d1c43e8a;hp=394a0b642d03cdb7be0ade6f7350931e71c4e861;hpb=f02e65ac3b489b25e5514d9972838af04298c148;p=jalview.git diff --git a/src/jalview/gui/SeqCanvas.java b/src/jalview/gui/SeqCanvas.java index 394a0b6..1e1105f 100755 --- a/src/jalview/gui/SeqCanvas.java +++ b/src/jalview/gui/SeqCanvas.java @@ -296,47 +296,48 @@ public class SeqCanvas extends JComponent implements ViewportListenerI 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; - gg.translate(transX, transY); - drawPanel(gg, startRes, endRes, startSeq, endSeq, 0); - gg.translate(-transX, -transY); + if (endSeq > ranges.getEndSeq()) + { + endSeq = ranges.getEndSeq(); + } + } - repaint(); + gg.translate(transX, transY); + drawPanel(gg, startRes, endRes, startSeq, endSeq, 0); + gg.translate(-transX, -transY); + + repaint(); } finally { fastpainting = false; @@ -364,14 +365,11 @@ public class SeqCanvas extends JComponent implements ViewportListenerI 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, cursorImage); + BufferedImage lcimg = buildLocalImage(selectImage); g.drawImage(lcimg, 0, 0, this); fastPaint = false; } @@ -411,8 +409,15 @@ public class SeqCanvas extends JComponent implements ViewportListenerI } // lcimg is a local *copy* of img which we'll draw selectImage on top of - BufferedImage lcimg = buildLocalImage(selectImage, cursorImage); + BufferedImage lcimg = buildLocalImage(selectImage); g.drawImage(lcimg, 0, 0, this); + + } + + if (av.cursorMode) + { + drawCursor(g, ranges.getStartRes(), ranges.getEndRes(), + ranges.getStartSeq(), ranges.getEndSeq()); } } @@ -496,8 +501,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI * Make a local image by combining the cached image img * with any selection */ - private BufferedImage buildLocalImage(BufferedImage selectImage, - BufferedImage cursorImage) + private BufferedImage buildLocalImage(BufferedImage selectImage) { // clone the cached image BufferedImage lcimg = new BufferedImage(img.getWidth(), img.getHeight(), @@ -512,12 +516,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI 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; @@ -781,8 +780,8 @@ public class SeqCanvas extends JComponent implements ViewportListenerI * white fill the region to be drawn (so incremental fast paint doesn't * scribble over an existing image) */ - gg.setColor(Color.white); - gg.fillRect(0, ypos, (endx - startColumn + 1) * charWidth, + g.setColor(Color.white); + g.fillRect(0, ypos, (endx - startColumn + 1) * charWidth, wrappedRepeatHeightPx); drawPanel(g, startColumn, endx, 0, av.getAlignment().getHeight() - 1, @@ -922,9 +921,9 @@ public class SeqCanvas extends JComponent implements ViewportListenerI 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()) @@ -1151,13 +1150,6 @@ public class SeqCanvas extends JComponent implements ViewportListenerI } } } - - /* if (av.cursorMode && cursorY == i && cursorX >= startRes - && cursorX <= endRes) - { - seqRdr.drawCursor(nextSeq, cursorX, (cursorX - startRes) * charWidth, - offset + ((i - startSeq) * charHeight)); - }*/ } if (av.getSelectionGroup() != null @@ -1269,74 +1261,77 @@ public class SeqCanvas extends JComponent implements ViewportListenerI * @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, + private void drawCursor(Graphics g, int startRes, int endRes, + int startSeq, int endSeq) { - // define our cursor image - BufferedImage cursorImage = null; + // convert the cursorY into a position on the visible alignment + int cursor_ypos = cursorY; // don't do work unless we have to - if (av.cursorMode && cursorY >= startSeq && cursorY <= endSeq) + if (cursor_ypos >= startSeq && cursor_ypos <= 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; + // convert the cursorX into a position on the visible alignment + int cursor_xpos = av.getAlignment().getHiddenColumns() + .findColumnPosition(cursorX); - endx = startx + cWidth - 1; - int ypos = hgap; // vertical offset + if (av.getAlignment().getHiddenColumns().isVisible(cursorX)) + { - // iterate down the wrapped panels - while ((ypos <= canvasHeight) && (endx < cursorX)) + if (av.getWrapAlignment()) { - // update vertical offset - ypos += cHeight + getAnnotationHeight() + hgap; + // 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; - // update horizontal offset - startx += cWidth; endx = startx + cWidth - 1; + int ypos = hgap; // vertical offset + + // iterate down the wrapped panels + while ((ypos <= canvasHeight) && (endx < cursor_xpos)) + { + // update vertical offset + ypos += cHeight + getAnnotationHeight() + hgap; + + // update horizontal offset + startx += cWidth; + endx = startx + cWidth - 1; + } + yoffset = ypos; + xoffset = labelWidthWest; } - 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(); + // now check if cursor is within range for x values + if (cursor_xpos >= startx && cursor_xpos <= endx) + { + // get the character the cursor is drawn at + SequenceI seq = av.getAlignment().getSequenceAt(cursorY); + char s = seq.getCharAt(cursorX); + + seqRdr.drawCursor(g, s, + xoffset + (cursor_xpos - startx) * av.getCharWidth(), + yoffset + (cursor_ypos - startSeq) * av.getCharHeight()); + } } } - - return cursorImage; } @@ -1371,8 +1366,8 @@ public class SeqCanvas extends JComponent implements ViewportListenerI 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, @@ -1434,9 +1429,8 @@ public class SeqCanvas extends JComponent implements ViewportListenerI 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; @@ -1444,140 +1438,141 @@ public class SeqCanvas extends JComponent implements ViewportListenerI boolean inGroup = false; int top = -1; int bottom = -1; - - int sx = -1; int sy = -1; - int xwidth = -1; - for (i = startSeq; i <= endSeq; i++) - { - // position of start residue of group relative to startRes, in pixels - sx = (group.getStartRes() - startRes) * charWidth; - - // width of group in pixels - xwidth = (((group.getEndRes() + 1) - group.getStartRes()) * charWidth) - - 1; + List seqs = group.getSequences(null); - sy = verticalOffset + (i - startSeq) * charHeight; + // position of start residue of group relative to startRes, in pixels + int sx = (group.getStartRes() - startRes) * charWidth; - if (sx + xwidth < 0 || sx > visWidth) - { - continue; - } + // width of group in pixels + int xwidth = (((group.getEndRes() + 1) - group.getStartRes()) + * charWidth) - 1; - if ((sx <= (endRes - startRes) * charWidth) - && group.getSequences(null) - .contains(av.getAlignment().getSequenceAt(i))) + if (!(sx + xwidth < 0 || sx > visWidth)) + { + for (i = startSeq; i <= endSeq; i++) { - if ((bottom == -1) && !group.getSequences(null) - .contains(av.getAlignment().getSequenceAt(i + 1))) - { - bottom = sy + charHeight; - } - - if (!inGroup) - { - if (((top == -1) && (i == 0)) || !group.getSequences(null) - .contains(av.getAlignment().getSequenceAt(i - 1))) - { - top = sy; - } + sy = verticalOffset + (i - startSeq) * charHeight; - oldY = sy; - inGroup = true; - } - } - else - { - if (inGroup) + if ((sx <= (endRes - startRes) * charWidth) + && seqs.contains(av.getAlignment().getSequenceAt(i))) { - // if start position is visible, draw vertical line to left of - // group - if (sx >= 0 && sx < visWidth) - { - g.drawLine(sx, oldY, sx, sy); - } - - // if end position is visible, draw vertical line to right of - // group - if (sx + xwidth < visWidth) - { - g.drawLine(sx + xwidth, oldY, sx + xwidth, sy); - } - - if (sx < 0) + if ((bottom == -1) + && !seqs.contains(av.getAlignment().getSequenceAt(i + 1))) { - xwidth += sx; - sx = 0; + bottom = sy + charHeight; } - // don't let width extend beyond current block, or group extent - // fixes JAL-2672 - if (sx + xwidth >= (endRes - startRes + 1) * charWidth) - { - xwidth = (endRes - startRes + 1) * charWidth - sx; - } - - // draw horizontal line at top of group - if (top != -1) + if (!inGroup) { - g.drawLine(sx, top, sx + xwidth, top); - top = -1; - } + if (((top == -1) && (i == 0)) || !seqs + .contains(av.getAlignment().getSequenceAt(i - 1))) + { + top = sy; + } - // draw horizontal line at bottom of group - if (bottom != -1) - { - g.drawLine(sx, bottom, sx + xwidth, bottom); - bottom = -1; + oldY = sy; + inGroup = true; } + } + else if (inGroup) + { + drawVerticals(g, sx, xwidth, visWidth, oldY, sy); + drawHorizontals(g, sx, xwidth, visWidth, top, bottom); + // reset top and bottom + top = -1; + bottom = -1; inGroup = false; } } - } - - if (inGroup) - { - sy = verticalOffset + ((i - startSeq) * charHeight); - if (sx >= 0 && sx < visWidth) + if (inGroup) { - g.drawLine(sx, oldY, sx, sy); + sy = verticalOffset + ((i - startSeq) * charHeight); + drawVerticals(g, sx, xwidth, visWidth, oldY, sy); + drawHorizontals(g, sx, xwidth, visWidth, top, bottom); } + } + } - if (sx + xwidth < visWidth) - { - g.drawLine(sx + xwidth, oldY, sx + xwidth, sy); - } + /** + * Draw horizontal selection group boundaries at top and bottom positions + * + * @param g + * graphics object to draw on + * @param sx + * start x position + * @param xwidth + * width of gap + * @param visWidth + * visWidth maximum available width + * @param top + * position to draw top of group at + * @param bottom + * position to draw bottom of group at + */ + private void drawHorizontals(Graphics2D g, int sx, int xwidth, + int visWidth, int top, int bottom) + { + int width = xwidth; + int startx = sx; + if (startx < 0) + { + width += startx; + startx = 0; + } - if (sx < 0) - { - xwidth += sx; - sx = 0; - } + // don't let width extend beyond current block, or group extent + // fixes JAL-2672 + if (startx + width >= visWidth) + { + width = visWidth - startx; + } - if (sx + xwidth > visWidth) - { - xwidth = visWidth; - } - else if (sx + xwidth >= (endRes - startRes + 1) * charWidth) - { - xwidth = (endRes - startRes + 1) * charWidth; - } + if (top != -1) + { + g.drawLine(startx, top, startx + width, top); + } - if (top != -1) - { - g.drawLine(sx, top, sx + xwidth, top); - top = -1; - } + if (bottom != -1) + { + g.drawLine(startx, bottom - 1, startx + width, bottom - 1); + } + } - if (bottom != -1) - { - g.drawLine(sx, bottom - 1, sx + xwidth, bottom - 1); - bottom = -1; - } + /** + * Draw vertical lines at sx and sx+xwidth providing they lie within + * [0,visWidth) + * + * @param g + * graphics object to draw on + * @param sx + * start x position + * @param xwidth + * width of gap + * @param visWidth + * visWidth maximum available width + * @param oldY + * top y value + * @param sy + * bottom y value + */ + private void drawVerticals(Graphics2D g, int sx, int xwidth, int visWidth, + int oldY, int sy) + { + // if start position is visible, draw vertical line to left of + // group + if (sx >= 0 && sx < visWidth) + { + g.drawLine(sx, oldY, sx, sy); + } - inGroup = false; + // if end position is visible, draw vertical line to right of + // group + if (sx + xwidth < visWidth) + { + g.drawLine(sx + xwidth, oldY, sx + xwidth, sy); } } @@ -1664,7 +1659,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI */ protected boolean drawMappedPositions(SearchResultsI results) { - if (results == null) + if ((results == null) || (gg == null)) // JAL-2784 check gg is not null { return false; } @@ -1755,15 +1750,31 @@ public class SeqCanvas extends JComponent implements ViewportListenerI 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; @@ -1773,17 +1784,30 @@ public class SeqCanvas extends JComponent implements ViewportListenerI 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()) + { + fastPaintWrapped(scrollX); + } + else + { + fastPaint(scrollX, 0); + } + } + else if (eventName.equals(ViewportRanges.STARTSEQ)) + { + // scroll + fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue()); + } + else if (eventName.equals(ViewportRanges.STARTRESANDSEQ)) + { + if (av.getWrapAlignment()) { fastPaintWrapped(scrollX); } @@ -1791,11 +1815,10 @@ public class SeqCanvas extends JComponent implements ViewportListenerI { fastPaint(scrollX, 0); } - } - else if (eventName.equals(ViewportRanges.STARTSEQ)) - { - // scroll - fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue()); + // 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. } } @@ -1812,7 +1835,9 @@ public class SeqCanvas extends JComponent implements ViewportListenerI { ViewportRanges ranges = av.getRanges(); - if (Math.abs(scrollX) > ranges.getViewportWidth()) + // if (Math.abs(scrollX) > ranges.getViewportWidth()) + // JAL-2836, 2836 temporarily removed wrapped fastpaint for release 2.10.3 + if (true) { /* * shift of more than one view width is @@ -2062,7 +2087,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI */ protected boolean drawMappedPositionsWrapped(SearchResultsI results) { - if (results == null) + if ((results == null) || (gg == null)) // JAL-2784 check gg is not null { return false; }