From 27f919983bfa01f41164bfc1c847617961b95e18 Mon Sep 17 00:00:00 2001 From: gmungoc Date: Mon, 7 Aug 2017 15:52:05 +0200 Subject: [PATCH] JAL-2609 revised design (always draw all scales, fast paint relocates sequences/annotations) --- src/jalview/gui/SeqCanvas.java | 601 ++++++++++++++++++++-------------------- 1 file changed, 297 insertions(+), 304 deletions(-) diff --git a/src/jalview/gui/SeqCanvas.java b/src/jalview/gui/SeqCanvas.java index 576d6ca..efc6910 100755 --- a/src/jalview/gui/SeqCanvas.java +++ b/src/jalview/gui/SeqCanvas.java @@ -73,14 +73,29 @@ public class SeqCanvas extends JComponent implements ViewportListenerI boolean fastpainting = false; - int labelWidthWest; - - int labelWidthEast; - int cursorX = 0; int cursorY = 0; + int charHeight = 0; + + int charWidth = 0; + + private AnnotationPanel annotations; + + /* + * measurements for drawing a wrapped alignment + */ + int labelWidthWest; // label left width in pixels if shown + + private int labelWidthEast; // label right width in pixels if shown + + private int wrappedSpaceAboveAlignment; // gap between widths + + private int wrappedRepeatHeightPx; // height in pixels of wrapped width + + private int wrappedVisibleWidths; // number of wrapped widths displayed + /** * Creates a new SeqCanvas object. * @@ -110,8 +125,6 @@ public class SeqCanvas extends JComponent implements ViewportListenerI return fr; } - int charHeight = 0, charWidth = 0; - private void updateViewport() { charHeight = av.getCharHeight(); @@ -135,6 +148,15 @@ public class SeqCanvas extends JComponent implements ViewportListenerI private void drawNorthScale(Graphics g, int startx, int endx, int ypos) { updateViewport(); + + /* + * white fill the scale space (for the fastPaint case) + */ + g.setColor(Color.white); + g.fillRect(0, ypos - charHeight - charHeight / 2, getWidth(), + charHeight * 3 / 2 + 2); + g.setColor(Color.black); + List marks = new ScaleRenderer().calculateMarks(av, startx, endx); for (ScaleMark mark : marks) @@ -216,18 +238,20 @@ public class SeqCanvas extends JComponent implements ViewportListenerI } } + /* + * white fill the space for the scale + */ + g.setColor(Color.white); + int y = (ypos + (i * charHeight)) - (charHeight / 5); + y -= charHeight; // fillRect: origin is top left of rectangle + int xpos = left ? 0 : labelWidthWest + charWidth + * av.getRanges().getViewportWidth(); + g.fillRect(xpos, y, left ? labelWidthWest : labelWidthEast, + charHeight + 1); + y += charHeight; // drawString: origin is bottom left of text + if (value != -1) { - /* - * white fill the space for the scale - */ - g.setColor(Color.white); - int y = (ypos + (i * charHeight)) - (charHeight / 5); - y -= charHeight; // fillRect: origin is top left of rectangle - int xpos = left ? 0 : getWidth() - labelWidthEast; - g.fillRect(xpos, y, left ? labelWidthWest : labelWidthEast, - charHeight + 1); - y += charHeight; // drawString: origin is bottom left of text /* * draw scale value, right justified, with half a character width @@ -471,143 +495,146 @@ public class SeqCanvas extends JComponent implements ViewportListenerI * available width in pixels * @param canvasHeight * available height in pixels - * @param startRes - * the first visible column (0...) of the alignment to draw + * @param startColumn + * the first column (0...) of the alignment to draw */ public void drawWrappedPanel(Graphics g, int canvasWidth, - int canvasHeight, int startRes) + int canvasHeight, final int startColumn) { updateViewport(); - int labelWidth = 0; - if (av.getScaleRightWrapped() || av.getScaleLeftWrapped()) - { - FontMetrics fm = getFontMetrics(av.getFont()); - labelWidth = getLabelWidth(fm); - } - - labelWidthEast = av.getScaleRightWrapped() ? labelWidth : 0; - labelWidthWest = av.getScaleLeftWrapped() ? labelWidth : 0; - - int hgap = charHeight; - if (av.getScaleAboveWrapped()) - { - hgap += charHeight; - } - int cWidth = (canvasWidth - labelWidthEast - labelWidthWest) / charWidth; + int wrappedWidthInResidues = calculateWrappedGeometry(canvasWidth, + canvasHeight); - av.setWrappedWidth(cWidth); - - av.getRanges().setViewportStartAndWidth(startRes, cWidth); - - int ypos = hgap; - int maxwidth = av.getAlignment().getWidth(); - - if (av.hasHiddenColumns()) - { - maxwidth = av.getAlignment().getHiddenColumns() - .findColumnPosition(maxwidth); - } + av.setWrappedWidth(wrappedWidthInResidues); - int annotationHeight = getAnnotationHeight(); - int sequencesHeight = av.getAlignment().getHeight() * charHeight; + ViewportRanges ranges = av.getRanges(); + ranges.setViewportStartAndWidth(startColumn, wrappedWidthInResidues); /* * draw one width at a time (including any scales or annotation shown), - * until we have run out of alignment or vertical space available - * (stop if not enough room left for at least one sequence) + * until we have run out of either alignment or vertical space available */ - int yposMax = canvasHeight;// - hgap - charHeight + 1; - while ((ypos <= yposMax) && (startRes < maxwidth)) - { - drawWrappedWidth(g, startRes, canvasHeight, cWidth, maxwidth, ypos); + int yposMax = canvasHeight; + // ensure room for at least one sequence + yposMax -= wrappedSpaceAboveAlignment - charHeight; + int ypos = wrappedSpaceAboveAlignment; + int maxWidth = ranges.getVisibleAlignmentWidth(); - ypos += sequencesHeight + annotationHeight + hgap; - - startRes += cWidth; + int start = startColumn; + while ((ypos <= yposMax) && (start < maxWidth)) + { + int endColumn = Math + .min(maxWidth, start + wrappedWidthInResidues - 1); + drawWrappedWidth(g, ypos, start, endColumn, canvasHeight); + ypos += wrappedRepeatHeightPx; + start += wrappedWidthInResidues; } + + drawWrappedDecorators(g, canvasHeight, startColumn); } /** - * Draws one width of a wrapped alignment, including scales left, right or - * above, and annnotations, if shown + * Calculates and saves values needed when rendering a wrapped alignment. + * These depend on many factors, including + * * - * @param g - * @param startRes - * @param canvasHeight * @param canvasWidth - * @param maxWidth - * @param ypos + * @param canvasHeight + * @return the number of residue columns in each width */ - protected void drawWrappedWidth(Graphics g, int startRes, - int canvasHeight, int canvasWidth, int maxWidth, int ypos) + protected int calculateWrappedGeometry(int canvasWidth, int canvasHeight) { - int endx; - endx = startRes + canvasWidth - 1; - - if (endx > maxWidth) + /* + * width of labels in pixels left and right (if shown) + */ + int labelWidth = 0; + if (av.getScaleRightWrapped() || av.getScaleLeftWrapped()) { - endx = maxWidth; + FontMetrics fm = getFontMetrics(av.getFont()); + labelWidth = getLabelWidth(fm); } + labelWidthEast = av.getScaleRightWrapped() ? labelWidth : 0; + labelWidthWest = av.getScaleLeftWrapped() ? labelWidth : 0; - g.setFont(av.getFont()); - g.setColor(Color.black); + /* + * vertical space in pixels between wrapped widths of alignment + */ + wrappedSpaceAboveAlignment = charHeight + * (av.getScaleAboveWrapped() ? 2 : 1); - if (av.getScaleLeftWrapped()) + /* + * height in pixels of the wrapped widths + */ + wrappedRepeatHeightPx = wrappedSpaceAboveAlignment; + // add sequences + wrappedRepeatHeightPx += av.getRanges().getViewportHeight() * charHeight; + // add annotations panel height if shown + wrappedRepeatHeightPx += getAnnotationHeight(); + + /* + * number of visible widths (the last one may be part height) + */ + ViewportRanges ranges = av.getRanges(); + int xMax = ranges.getVisibleAlignmentWidth(); + wrappedVisibleWidths = canvasHeight / wrappedRepeatHeightPx; + int remainder = canvasHeight % wrappedRepeatHeightPx; + if (remainder >= (wrappedSpaceAboveAlignment + charHeight)) { - drawVerticalScale(g, startRes, endx, ypos, true); + wrappedVisibleWidths++; } - if (av.getScaleRightWrapped()) + /* + * limit visibleWidths to not exceed width of alignment + */ + int viewportWidth = ranges.getViewportWidth(); + int maxWidths = (xMax - ranges.getStartRes()) / viewportWidth; + if (xMax % viewportWidth > 0) { - drawVerticalScale(g, startRes, endx, ypos, false); + maxWidths++; } + wrappedVisibleWidths = Math.min(wrappedVisibleWidths, maxWidths); - drawWrappedRegion(g, startRes, endx, canvasHeight, canvasWidth, ypos); + /* + * number of whole width residue columns we can show in each row + */ + int wrappedWidthInResidues = (canvasWidth - labelWidthEast - labelWidthWest) + / charWidth; + return wrappedWidthInResidues; } /** - * Draws columns of a wrapped alignment from startRes to endRes, including - * scale above and annotations if shown, but not scale left or right. + * Draws one width of a wrapped alignment, including sequences and + * annnotations, if shown, but not scales or hidden column markers * * @param g - * @param startRes - * @param endRes - * @param canvasHeight - * @param canvasWidth * @param ypos + * @param startColumn + * @param endColumn + * @param canvasHeight */ - protected void drawWrappedRegion(Graphics g, int startRes, int endRes, - int canvasHeight, int canvasWidth, int ypos) + protected void drawWrappedWidth(Graphics g, int ypos, + int startColumn, int endColumn, int canvasHeight) { - g.translate(labelWidthWest, 0); - - if (av.getScaleAboveWrapped()) - { - drawNorthScale(g, startRes, endRes, ypos); - } + ViewportRanges ranges = av.getRanges(); + int viewportWidth = ranges.getViewportWidth(); - // todo can we let drawPanel() handle this? - if (av.hasHiddenColumns() && av.getShowHiddenMarkers()) - { - g.setColor(Color.blue); - HiddenColumns hidden = av.getAlignment().getHiddenColumns(); - List positions = hidden.findHiddenRegionPositions(); - for (int pos : positions) - { - int res = pos - startRes; + int endx = Math.min(startColumn + viewportWidth - 1, endColumn); - if (res < 0 || res > endRes - startRes) - { - continue; - } - - gg.fillPolygon(new int[] { res * charWidth - charHeight / 4, - res * charWidth + charHeight / 4, res * charWidth }, new int[] { - ypos - (charHeight / 2), ypos - (charHeight / 2), - ypos - (charHeight / 2) + 8 }, 3); - } - } + /* + * move right before drawing by the width of the scale left (if any) + * plus column offset from left margin (usually zero, but may not be + * when fast painting draws just a few columns) + */ + int xOffset = labelWidthWest + + ((startColumn - ranges.getStartRes()) % viewportWidth) + * charWidth; + g.translate(xOffset, 0); // When printing we have an extra clipped region, // the Printable page which we need to account for here @@ -615,15 +642,16 @@ public class SeqCanvas extends JComponent implements ViewportListenerI if (clip == null) { - g.setClip(0, 0, canvasWidth * charWidth, canvasHeight); + g.setClip(0, 0, viewportWidth * charWidth, canvasHeight); } else { - g.setClip(0, (int) clip.getBounds().getY(), canvasWidth * charWidth, - (int) clip.getBounds().getHeight()); + g.setClip(0, (int) clip.getBounds().getY(), + viewportWidth * charWidth, (int) clip.getBounds().getHeight()); } - drawPanel(g, startRes, endRes, 0, av.getAlignment().getHeight() - 1, ypos); + drawPanel(g, startColumn, endx, 0, av.getAlignment().getHeight() - 1, + ypos); int cHeight = av.getAlignment().getHeight() * charHeight; @@ -635,15 +663,101 @@ public class SeqCanvas extends JComponent implements ViewportListenerI annotations = new AnnotationPanel(av); } - annotations.renderer.drawComponent(annotations, av, g, -1, startRes, - endRes + 1); + annotations.renderer.drawComponent(annotations, av, g, -1, + startColumn, endx + 1); g.translate(0, -cHeight - ypos - 3); } g.setClip(clip); - g.translate(-labelWidthWest, 0); + g.translate(-xOffset, 0); + } + + /** + * Draws scales left, right and above (if shown), and any hidden column + * markers, on the wrapped alignment + * + * @param g + * @param ypos + * @param startColumn + * @param endColumn + */ + protected void drawWrappedDecorators(Graphics g, int canvasHeight, + int startColumn) + { + g.setFont(av.getFont()); + g.setColor(Color.black); + + int ypos = wrappedSpaceAboveAlignment; + ViewportRanges ranges = av.getRanges(); + int viewportWidth = ranges.getViewportWidth(); + int maxWidth = ranges.getVisibleAlignmentWidth(); + int widthsDrawn = 0; + while (widthsDrawn < wrappedVisibleWidths) + { + int endColumn = Math.min(maxWidth, startColumn + viewportWidth - 1); + + if (av.getScaleLeftWrapped()) + { + drawVerticalScale(g, startColumn, endColumn - 1, ypos, true); + } + + if (av.getScaleRightWrapped()) + { + drawVerticalScale(g, startColumn, endColumn, ypos, false); + } + + g.translate(labelWidthWest, 0); + + if (av.getScaleAboveWrapped()) + { + drawNorthScale(g, startColumn, endColumn, ypos); + } + + if (av.hasHiddenColumns() && av.getShowHiddenMarkers()) + { + drawHiddenColumnMarkers(g, ypos, startColumn, endColumn); + } + + g.translate(-labelWidthWest, 0); + + ypos += wrappedRepeatHeightPx; + startColumn += viewportWidth; + widthsDrawn++; + } } - AnnotationPanel annotations; + /** + * @param g + * @param ypos + * @param startColumn + * @param endColumn + */ + protected void drawHiddenColumnMarkers(Graphics g, int ypos, + int startColumn, int endColumn) + { + g.setColor(Color.blue); + HiddenColumns hidden = av.getAlignment().getHiddenColumns(); + List positions = hidden.findHiddenRegionPositions(); + for (int pos : positions) + { + int res = pos - startColumn; + + if (res < 0 || res > endColumn - startColumn) + { + continue; + } + + /* + * draw a downward-pointing triangle at the hidden columns location + * (before the following visible column) + */ + int xMiddle = res * charWidth; + int[] xPoints = new int[] { xMiddle - charHeight / 4, + xMiddle + charHeight / 4, xMiddle }; + int yTop = ypos - (charHeight / 2); + int[] yPoints = new int[] { yTop, yTop, yTop + 8 }; + gg.fillPolygon(xPoints, yPoints, 3); + } + } int getAnnotationHeight() { @@ -1243,7 +1357,9 @@ public class SeqCanvas extends JComponent implements ViewportListenerI */ protected void fastPaintWrapped(int scrollX) { - if (Math.abs(scrollX) > av.getRanges().getViewportWidth()) + ViewportRanges ranges = av.getRanges(); + + if (Math.abs(scrollX) > ranges.getViewportWidth()) { /* * shift of more than one view width is @@ -1264,26 +1380,34 @@ public class SeqCanvas extends JComponent implements ViewportListenerI try { + calculateWrappedGeometry(getWidth(), getHeight()); + /* * relocate the regions of the alignment that are still visible */ shiftWrappedAlignment(-scrollX); /* - * add new columns (scale above, sequence, annotation) + * add new columns (sequence, annotation) * - at top left if scrollX < 0 * - at right of last two widths if scrollX > 0 - * also West scale top left or East scale bottom right if shown */ if (scrollX < 0) { - fastPaintWrappedAddLeft(-scrollX); + int startRes = ranges.getStartRes(); + drawWrappedWidth(gg, wrappedSpaceAboveAlignment, startRes, startRes + - scrollX - 1, getHeight()); } else { fastPaintWrappedAddRight(scrollX); } + /* + * draw all scales (if shown) and hidden column markers + */ + drawWrappedDecorators(gg, getHeight(), ranges.getStartRes()); + repaint(); } finally { @@ -1293,10 +1417,10 @@ public class SeqCanvas extends JComponent implements ViewportListenerI /** * Draws the specified number of columns at the 'end' (bottom right) of a - * wrapped alignment view, including scale above and right and annotations if - * shown. Also draws the same number of columns at the right hand end of the - * second last width shown, if the last width is not full height (so cannot - * simply be copied from the graphics image). + * wrapped alignment view, including sequences and annotations if shown, but + * not scales. Also draws the same number of columns at the right hand end of + * the second last width shown, if the last width is not full height (so + * cannot simply be copied from the graphics image). * * @param columns */ @@ -1307,175 +1431,84 @@ public class SeqCanvas extends JComponent implements ViewportListenerI return; } - /* - * how many widths are visible? we will be adding - * columns to the last visible width, right hand end - */ - int repeatHeight = getRepeatHeightWrapped(); - int canvasHeight = getHeight(); - int visibleWidths = canvasHeight / repeatHeight; - int remainder = canvasHeight % repeatHeight; - int hgap = charHeight * (av.getScaleAboveWrapped() ? 2 : 1); - boolean lastWidthPartHeight = false; - if (remainder >= (hgap + charHeight)) - { - visibleWidths++; - lastWidthPartHeight = true; - } - - /* - * limit visible widths to max widths of alignment, from the - * current start residue (we may be scrolled down) - */ ViewportRanges ranges = av.getRanges(); - int availableAlignmentWidth = ranges.getVisibleAlignmentWidth() - - ranges.getStartRes(); int viewportWidth = ranges.getViewportWidth(); - int maxWidths = availableAlignmentWidth / viewportWidth; - if (availableAlignmentWidth % viewportWidth > 0) - { - maxWidths++; - } - visibleWidths = Math.min(visibleWidths, maxWidths); - int canvasWidth = getWidth(); - int widthInColumns = (canvasWidth - labelWidthEast - labelWidthWest) - / charWidth; /** * draw full height alignment in the second last row, last columns, if the * last row was not full height */ + int visibleWidths = wrappedVisibleWidths; + int canvasHeight = getHeight(); + boolean lastWidthPartHeight = (wrappedVisibleWidths * wrappedRepeatHeightPx) > canvasHeight; + if (lastWidthPartHeight) { int widthsAbove = visibleWidths - 2; - int ypos = repeatHeight * widthsAbove + hgap; + int ypos = wrappedRepeatHeightPx * widthsAbove + + wrappedSpaceAboveAlignment; int endRes = ranges.getEndRes(); endRes += widthsAbove * viewportWidth; int startRes = endRes - columns; int xOffset = ((startRes - ranges.getStartRes()) % viewportWidth) * charWidth; - gg.translate(xOffset, 0); /* * white fill first to erase annotations */ + gg.translate(xOffset, 0); gg.setColor(Color.white); gg.fillRect(labelWidthWest, ypos, - (endRes - startRes + 1) * charWidth, repeatHeight); - - drawWrappedRegion(gg, startRes, endRes, canvasHeight, widthInColumns, - ypos); + (endRes - startRes + 1) * charWidth, wrappedRepeatHeightPx); gg.translate(-xOffset, 0); + + drawWrappedWidth(gg, ypos, startRes, endRes, canvasHeight); } /* - * y-offset for drawing is height of widths above, + * y-offset for drawing last width is height of widths above, * plus one gap row */ int widthsAbove = visibleWidths - 1; - int ypos = repeatHeight * widthsAbove + hgap; + int ypos = wrappedRepeatHeightPx * widthsAbove + + wrappedSpaceAboveAlignment; int endRes = ranges.getEndRes(); endRes += widthsAbove * viewportWidth; endRes = Math.min(endRes, ranges.getVisibleAlignmentWidth()); + int startRes = endRes - columns + 1; /* - * draw one extra column than strictly needed - this is a (harmless) - * fudge to ensure scale marks get drawn (JAL-2636) + * white fill first to erase annotations */ - int startRes = endRes - columns; - - /* - * x-offset is x-start modulo viewport start residue; - * doesn't include label West (offset is applied in drawWrappedRegion) - */ - - int leftEndColumn = ranges.getStartRes() + widthsAbove - * ranges.getViewportWidth(); - // startRes = Math.max(startRes - 0, leftEndColumn); int xOffset = ((startRes - ranges.getStartRes()) % viewportWidth) * charWidth; gg.translate(xOffset, 0); - - /* - * white fill the region to be drawn including scale left or above; - * extend to right hand margin so as to erase scale above when - * scrolling right beyond end of alignment - */ gg.setColor(Color.white); - int width = canvasWidth - labelWidthWest - xOffset; - gg.fillRect(labelWidthWest, ypos - hgap, width, repeatHeight); + int width = viewportWidth * charWidth - xOffset; + gg.fillRect(labelWidthWest, ypos, width, wrappedRepeatHeightPx); + gg.translate(-xOffset, 0); gg.setFont(av.getFont()); gg.setColor(Color.black); - drawWrappedRegion(gg, startRes, endRes, canvasHeight, widthInColumns, - ypos); - gg.translate(-xOffset, 0); - - /* - * draw scale right if shown, passing in the start/end columns - * for the whole line, not just the last few columns - */ - if (av.getScaleRightWrapped()) - { - drawVerticalScale(gg, leftEndColumn, endRes, ypos, false); - } + drawWrappedWidth(gg, ypos, startRes, endRes, canvasHeight); /* * and finally, white fill any space below the visible alignment - * (in case it has wrapped to just the top part of the panel) */ - int heightBelow = canvasHeight - visibleWidths * repeatHeight; + int heightBelow = canvasHeight - visibleWidths * wrappedRepeatHeightPx; if (heightBelow > 0) { gg.setColor(Color.white); - gg.fillRect(0, canvasHeight - heightBelow, canvasWidth, heightBelow); + gg.fillRect(0, canvasHeight - heightBelow, getWidth(), heightBelow); } } /** - * Draws the specified number of columns at the 'start' (top left) of a - * wrapped alignment view, including scale above and left and annotations if - * shown - * - * @param columns - */ - protected void fastPaintWrappedAddLeft(int columns) - { - int startRes = av.getRanges().getStartRes(); - - /* - * draw one extra column than strictly needed - this is a (harmless) - * fudge to ensure scale marks get drawn (JAL-2636) - */ - int endx = startRes + columns; - int ypos = 0; - - /* - * white fill the region to be drawn including scale left or above - */ - gg.setColor(Color.white); - int height = getRepeatHeightWrapped(); - gg.fillRect(0, ypos, labelWidthWest + columns * charWidth, height); - ypos += charHeight * (av.getScaleAboveWrapped() ? 2 : 1); - - gg.setFont(av.getFont()); - gg.setColor(Color.black); - - if (av.getScaleLeftWrapped()) - { - drawVerticalScale(gg, startRes, endx, ypos, true); - } - - int cWidth = (getWidth() - labelWidthEast - labelWidthWest) / charWidth; - - drawWrappedRegion(gg, startRes, endx, getHeight(), cWidth, ypos); - } - - /** * Shifts the visible alignment by the specified number of columns - left if - * negative, right if positive. Includes scale above, left or right and - * annotations (if shown). Does not draw newly visible columns. + * negative, right if positive. Copies and moves sequences and annotations (if + * shown). Scales, hidden column markers and any newly visible columns must be + * drawn separately. * * @param positions */ @@ -1486,34 +1519,13 @@ public class SeqCanvas extends JComponent implements ViewportListenerI return; } - int repeatHeight = getRepeatHeightWrapped(); + int canvasHeight = getHeight(); ViewportRanges ranges = av.getRanges(); - int xMax = ranges.getVisibleAlignmentWidth(); + int viewportWidth = ranges.getViewportWidth(); int widthToCopy = (ranges.getViewportWidth() - Math.abs(positions)) * charWidth; - int canvasHeight = getHeight(); - int visibleWidths = canvasHeight / repeatHeight; - if (canvasHeight % repeatHeight > 0) - { - visibleWidths++; - } - int viewportWidth = ranges.getViewportWidth(); - int hgap = charHeight * (av.getScaleAboveWrapped() ? 2 : 1); - - int remainder = canvasHeight % repeatHeight; - if (remainder >= (hgap + charHeight)) - { - visibleWidths++; - } - /* - * limit visibleWidths to not exceed width of alignment - */ - int maxWidths = (xMax - ranges.getStartRes()) / viewportWidth; - if (xMax % viewportWidth > 0) - { - maxWidths++; - } - visibleWidths = Math.min(visibleWidths, maxWidths); + int heightToCopy = wrappedRepeatHeightPx - wrappedSpaceAboveAlignment; + int xMax = ranges.getVisibleAlignmentWidth(); if (positions > 0) { @@ -1524,38 +1536,27 @@ public class SeqCanvas extends JComponent implements ViewportListenerI * columns from the right margin of the row above (if any) to the * left margin of the current row */ - int xpos = ranges.getStartRes() + (visibleWidths - 1) * viewportWidth; /* - * get y-offset of last wrapped width + * get y-offset of last wrapped width, first row of sequences */ - int y = canvasHeight / repeatHeight * repeatHeight; + int y = canvasHeight / wrappedRepeatHeightPx * wrappedRepeatHeightPx; + y += wrappedSpaceAboveAlignment; int copyFromLeftStart = labelWidthWest; int copyFromRightStart = copyFromLeftStart + widthToCopy; while (y >= 0) { - gg.copyArea(copyFromLeftStart, y, widthToCopy, repeatHeight, + gg.copyArea(copyFromLeftStart, y, widthToCopy, heightToCopy, positions * charWidth, 0); if (y > 0) { - gg.copyArea(copyFromRightStart, y - repeatHeight, positions - * charWidth, repeatHeight, -widthToCopy, repeatHeight); + gg.copyArea(copyFromRightStart, y - wrappedRepeatHeightPx, + positions * charWidth, heightToCopy, -widthToCopy, + wrappedRepeatHeightPx); } - if (av.getScaleLeftWrapped()) - { - drawVerticalScale(gg, xpos, xpos + viewportWidth - 1, y + hgap, - true); - } - if (av.getScaleRightWrapped()) - { - drawVerticalScale(gg, xpos, xpos + viewportWidth - 1, y + hgap, - false); - } - - y -= repeatHeight; - xpos -= viewportWidth; + y -= wrappedRepeatHeightPx; } } else @@ -1567,31 +1568,23 @@ public class SeqCanvas extends JComponent implements ViewportListenerI * columns from the left margin of the row below (if any) to the * right margin of the current row */ - int xpos = ranges.getStartRes(); - int y = 0; + int xpos = av.getRanges().getStartRes(); + int y = wrappedSpaceAboveAlignment; int copyFromRightStart = labelWidthWest - positions * charWidth; while (y < canvasHeight) { - gg.copyArea(copyFromRightStart, y, widthToCopy, repeatHeight, + gg.copyArea(copyFromRightStart, y, widthToCopy, heightToCopy, positions * charWidth, 0); - if (y + repeatHeight < canvasHeight - repeatHeight + if (y + wrappedRepeatHeightPx < canvasHeight - wrappedRepeatHeightPx && (xpos + viewportWidth <= xMax)) { - gg.copyArea(labelWidthWest, y + repeatHeight, -positions - * charWidth, repeatHeight, widthToCopy, -repeatHeight); - } - - if (av.getScaleLeftWrapped()) - { - drawVerticalScale(gg, xpos, xpos + viewportWidth, y + hgap, true); - } - if (av.getScaleRightWrapped()) - { - drawVerticalScale(gg, xpos, xpos + viewportWidth, y + hgap, false); + gg.copyArea(labelWidthWest, y + wrappedRepeatHeightPx, -positions + * charWidth, heightToCopy, widthToCopy, + -wrappedRepeatHeightPx); } - y += repeatHeight; + y += wrappedRepeatHeightPx; xpos += viewportWidth; } } -- 1.7.10.2