X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fjalview%2Fgui%2FSeqCanvas.java;h=7d182b2d5344ecb1ef0803f46ed67b8ab2d9c155;hb=33f8761fdb05b594fd8a3341180256003d3a91df;hp=881afe5c6c28c22f4e07fb6ce6f09793cce7e26a;hpb=e249a4950d0e7f3c5ea905f3c1c02baebd92b708;p=jalview.git diff --git a/src/jalview/gui/SeqCanvas.java b/src/jalview/gui/SeqCanvas.java index 881afe5..7d182b2 100755 --- a/src/jalview/gui/SeqCanvas.java +++ b/src/jalview/gui/SeqCanvas.java @@ -295,48 +295,52 @@ public class SeqCanvas extends JComponent implements ViewportListenerI int endSeq = ranges.getEndSeq(); 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); + + // 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. + av.getAlignPanel().repaint(); } finally { fastpainting = false; @@ -350,20 +354,20 @@ public class SeqCanvas extends JComponent implements ViewportListenerI int charHeight = av.getCharHeight(); int charWidth = av.getCharWidth(); - + ViewportRanges ranges = av.getRanges(); - + int width = getWidth(); int height = getHeight(); - + width -= (width % charWidth); height -= (height % charHeight); - + // selectImage is the selection group outline image BufferedImage selectImage = drawSelectionGroup( ranges.getStartRes(), ranges.getEndRes(), ranges.getStartSeq(), ranges.getEndSeq()); - + if ((img != null) && (fastPaint || (getVisibleRect().width != g.getClipBounds().width) || (getVisibleRect().height != g.getClipBounds().height))) @@ -387,16 +391,16 @@ public class SeqCanvas extends JComponent implements ViewportListenerI gg = (Graphics2D) img.getGraphics(); gg.setFont(av.getFont()); } - + if (av.antiAlias) { gg.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); } - + gg.setColor(Color.white); gg.fillRect(0, 0, img.getWidth(), img.getHeight()); - + if (av.getWrapAlignment()) { drawWrappedPanel(gg, getWidth(), getHeight(), ranges.getStartRes()); @@ -406,10 +410,17 @@ public class SeqCanvas extends JComponent implements ViewportListenerI drawPanel(gg, ranges.getStartRes(), ranges.getEndRes(), ranges.getStartSeq(), ranges.getEndSeq(), 0); } - + // lcimg is a local *copy* of img which we'll draw selectImage on top of 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 +507,11 @@ public class SeqCanvas extends JComponent implements ViewportListenerI private BufferedImage buildLocalImage(BufferedImage selectImage) { // clone the cached image - BufferedImage lcimg = new BufferedImage(img.getWidth(), img.getHeight(), - img.getType()); + BufferedImage lcimg = new BufferedImage(img.getWidth(), img.getHeight(), + img.getType()); + + // BufferedImage lcimg = new BufferedImage(img.getWidth(), img.getHeight(), + // img.getType()); Graphics2D g2d = lcimg.createGraphics(); g2d.drawImage(img, 0, 0, null); @@ -508,6 +522,7 @@ public class SeqCanvas extends JComponent implements ViewportListenerI AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); g2d.drawImage(selectImage, 0, 0, this); } + g2d.dispose(); return lcimg; @@ -536,8 +551,8 @@ public class SeqCanvas extends JComponent implements ViewportListenerI try { - lcimg = new BufferedImage(width, height, - BufferedImage.TYPE_INT_ARGB); // ARGB so alpha compositing works + lcimg = new BufferedImage(width, height, + BufferedImage.TYPE_INT_ARGB); // ARGB so alpha compositing works } catch (OutOfMemoryError er) { System.gc(); @@ -771,8 +786,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, @@ -912,9 +927,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()) @@ -1128,26 +1143,19 @@ public class SeqCanvas extends JComponent implements ViewportListenerI if (av.hasSearchResults()) { SearchResultsI searchResults = av.getSearchResults(); - int[] visibleResults = searchResults.getResults(nextSeq, - startRes, endRes); + int[] visibleResults = searchResults.getResults(nextSeq, startRes, + endRes); if (visibleResults != null) { for (int r = 0; r < visibleResults.length; r += 2) { seqRdr.drawHighlightedText(nextSeq, visibleResults[r], - visibleResults[r + 1], (visibleResults[r] - startRes) - * charWidth, offset - + ((i - startSeq) * charHeight)); + visibleResults[r + 1], + (visibleResults[r] - startRes) * charWidth, + offset + ((i - startSeq) * charHeight)); } } } - - if (av.cursorMode && cursorY == i && cursorX >= startRes - && cursorX <= endRes) - { - seqRdr.drawCursor(nextSeq, cursorX, (cursorX - startRes) * charWidth, - offset + ((i - startSeq) * charHeight)); - } } if (av.getSelectionGroup() != null @@ -1245,6 +1253,94 @@ public class SeqCanvas extends JComponent implements ViewportListenerI 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 void drawCursor(Graphics g, int startRes, int endRes, + int startSeq, + int endSeq) + { + // convert the cursorY into a position on the visible alignment + int cursor_ypos = cursorY; + + // don't do work unless we have to + if (cursor_ypos >= startSeq && cursor_ypos <= endSeq) + { + int yoffset = 0; + int xoffset = 0; + int startx = startRes; + int endx = endRes; + + // convert the cursorX into a position on the visible alignment + int cursor_xpos = av.getAlignment().getHiddenColumns() + .findColumnPosition(cursorX); + + if (av.getAlignment().getHiddenColumns().isVisible(cursorX)) + { + + 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 < cursor_xpos)) + { + // 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 (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()); + } + } + } + } + + /* * Set up graphics for selection group */ @@ -1276,8 +1372,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, @@ -1569,7 +1665,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; } @@ -1660,15 +1756,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; @@ -1678,17 +1790,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); } @@ -1696,11 +1821,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. } } @@ -1967,7 +2091,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; }