import jalview.datamodel.SequenceI;
import jalview.renderer.ScaleRenderer;
import jalview.renderer.ScaleRenderer.ScaleMark;
+import jalview.util.Comparison;
import jalview.viewmodel.ViewportListenerI;
import jalview.viewmodel.ViewportRanges;
boolean fastPaint = false;
+ boolean fastpainting = false;
+
int labelWidthWest;
int labelWidthEast;
}
/**
- * DOCUMENT ME!
+ * Draws the scale above a region of a wrapped alignment, consisting of a
+ * column number every 10 columns.
*
* @param g
- * DOCUMENT ME!
+ * the graphics context to draw on, positioned at the start (bottom
+ * left) of the
* @param startx
* DOCUMENT ME!
* @param endx
private void drawNorthScale(Graphics g, int startx, int endx, int ypos)
{
updateViewport();
- for (ScaleMark mark : new ScaleRenderer().calculateMarks(av, startx,
- endx))
+ List<ScaleMark> marks = new ScaleRenderer().calculateMarks(av, startx,
+ endx);
+ for (ScaleMark mark : marks)
{
int mpos = mark.column; // (i - startx - 1)
if (mpos < 0)
{
g.drawString(mstring, mpos * charWidth, ypos - (charHeight / 2));
}
- g.drawLine((mpos * charWidth) + (charWidth / 2), (ypos + 2)
- - (charHeight / 2), (mpos * charWidth) + (charWidth / 2),
- ypos - 2);
+
+ /*
+ * draw a tick mark below the column number, centred on the column;
+ * height of tick mark is 4 pixels less than half a character
+ */
+ int xpos = (mpos * charWidth) + (charWidth / 2);
+ g.drawLine(xpos, (ypos + 2) - (charHeight / 2), xpos, ypos - 2);
}
}
}
/**
- * DOCUMENT ME!
+ * Draw the scale to the left or right of a wrapped alignment
*
* @param g
- * DOCUMENT ME!
* @param startx
- * DOCUMENT ME!
+ * first column of wrapped width (0.. excluding any hidden columns)
* @param endx
- * DOCUMENT ME!
+ * last column of wrapped width (0.. excluding any hidden columns)
* @param ypos
- * DOCUMENT ME!
+ * vertical offset at which to begin the scale
+ * @param left
+ * if true, scale is left of residues, if false, scale is right
*/
- void drawWestScale(Graphics g, int startx, int endx, int ypos)
+ void drawVerticalScale(Graphics g, int startx, int endx, int ypos,
+ boolean left)
{
- FontMetrics fm = getFontMetrics(av.getFont());
ypos += charHeight;
if (av.hasHiddenColumns())
{
- startx = av.getAlignment().getHiddenColumns()
- .adjustForHiddenColumns(startx);
- endx = av.getAlignment().getHiddenColumns()
- .adjustForHiddenColumns(endx);
- }
-
- int maxwidth = av.getAlignment().getWidth();
- if (av.hasHiddenColumns())
- {
- maxwidth = av.getAlignment().getHiddenColumns()
- .findColumnPosition(maxwidth) - 1;
+ HiddenColumns hiddenColumns = av.getAlignment().getHiddenColumns();
+ startx = hiddenColumns.adjustForHiddenColumns(startx);
+ endx = hiddenColumns.adjustForHiddenColumns(endx);
}
+ FontMetrics fm = getFontMetrics(av.getFont());
- // WEST SCALE
for (int i = 0; i < av.getAlignment().getHeight(); i++)
{
SequenceI seq = av.getAlignment().getSequenceAt(i);
- int index = startx;
- int value = -1;
- while (index < endx)
+ /*
+ * find sequence position of first non-gapped position -
+ * to the right if scale left, to the left if scale right
+ */
+ int index = left ? startx : endx;
+ int value = -1;
+ while (index >= startx && index <= endx)
{
- if (jalview.util.Comparison.isGap(seq.getCharAt(index)))
+ if (!Comparison.isGap(seq.getCharAt(index)))
+ {
+ value = seq.findPosition(index);
+ break;
+ }
+ if (left)
{
index++;
-
- continue;
}
-
- value = av.getAlignment().getSequenceAt(i).findPosition(index);
-
- break;
- }
-
- if (value != -1)
- {
- int x = labelWidthWest - fm.stringWidth(String.valueOf(value))
- - charWidth / 2;
- g.drawString(value + "", x, (ypos + (i * charHeight))
- - (charHeight / 5));
- }
- }
- }
-
- /**
- * DOCUMENT ME!
- *
- * @param g
- * DOCUMENT ME!
- * @param startx
- * DOCUMENT ME!
- * @param endx
- * DOCUMENT ME!
- * @param ypos
- * DOCUMENT ME!
- */
- void drawEastScale(Graphics g, int startx, int endx, int ypos)
- {
- ypos += charHeight;
-
- if (av.hasHiddenColumns())
- {
- endx = av.getAlignment().getHiddenColumns()
- .adjustForHiddenColumns(endx);
- }
-
- SequenceI seq;
- // EAST SCALE
- for (int i = 0; i < av.getAlignment().getHeight(); i++)
- {
- seq = av.getAlignment().getSequenceAt(i);
- int index = endx;
- int value = -1;
-
- while (index > startx)
- {
- if (jalview.util.Comparison.isGap(seq.getCharAt(index)))
+ else
{
index--;
-
- continue;
}
-
- value = seq.findPosition(index);
-
- break;
}
if (value != -1)
{
- g.drawString(String.valueOf(value), 0, (ypos + (i * charHeight))
- - (charHeight / 5));
+ /*
+ * 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
+ * separation from the sequence data
+ */
+ String valueAsString = String.valueOf(value);
+ int justify = fm.stringWidth(valueAsString) + charWidth;
+ xpos = left ? labelWidthWest - justify + charWidth / 2
+ : getWidth() - justify - charWidth / 2;
+
+ g.setColor(Color.black);
+ g.drawString(valueAsString, xpos, y);
}
}
}
- boolean fastpainting = false;
-
/**
- * need to make this thread safe move alignment rendering in response to
- * slider adjustment
+ * Does a fast paint of an alignment in response to a scroll. Most of the
+ * visible region is simply copied and shifted, and then any newly visible
+ * columns or rows are drawn. The scroll may be horizontal or vertical, but
+ * not both at once. Scrolling may be the result of
+ * <ul>
+ * <li>dragging a scroll bar</li>
+ * <li>clicking in the scroll bar</li>
+ * <li>scrolling by trackpad, middle mouse button, or other device</li>
+ * <li>by moving the box in the Overview window</li>
+ * <li>programmatically to make a highlighted position visible</li>
+ * </ul>
*
* @param horizontal
- * shift along
+ * columns to shift right (positive) or left (negative)
* @param vertical
- * shift up or down in repaint
+ * rows to shift down (positive) or up (negative)
*/
public void fastPaint(int horizontal, int vertical)
{
}
/**
- * DOCUMENT ME!
+ * Draws as many widths of a wrapped alignment as can fit in the visible
+ * window
*
* @param g
- * DOCUMENT ME!
* @param canvasWidth
- * DOCUMENT ME!
+ * available width in pixels
* @param canvasHeight
- * DOCUMENT ME!
+ * available height in pixels
* @param startRes
- * DOCUMENT ME!
+ * the first visible column (0...) of the alignment to draw
*/
public void drawWrappedPanel(Graphics g, int canvasWidth,
int canvasHeight, int startRes)
{
updateViewport();
- AlignmentI al = av.getAlignment();
-
int labelWidth = 0;
if (av.getScaleRightWrapped() || av.getScaleLeftWrapped())
{
}
int cWidth = (canvasWidth - labelWidthEast - labelWidthWest) / charWidth;
- int cHeight = av.getAlignment().getHeight() * charHeight;
av.setWrappedWidth(cWidth);
- av.getRanges().setEndRes(av.getRanges().getStartRes() + cWidth - 1);
+ av.getRanges().setViewportStartAndWidth(startRes, cWidth);
- int endx;
int ypos = hgap;
- int maxwidth = av.getAlignment().getWidth() - 1;
+ int maxwidth = av.getAlignment().getWidth();
if (av.hasHiddenColumns())
{
maxwidth = av.getAlignment().getHiddenColumns()
- .findColumnPosition(maxwidth) - 1;
+ .findColumnPosition(maxwidth);
}
int annotationHeight = getAnnotationHeight();
+ int sequencesHeight = av.getAlignment().getHeight() * charHeight;
+ /*
+ * draw one width at a time (including any scales or annotation shown),
+ * until we have run out of alignment or vertical space available
+ */
while ((ypos <= canvasHeight) && (startRes < maxwidth))
{
- endx = startRes + cWidth - 1;
+ drawWrappedWidth(g, startRes, canvasHeight, cWidth, maxwidth, ypos);
- if (endx > maxwidth)
- {
- endx = maxwidth;
- }
-
- g.setFont(av.getFont());
- g.setColor(Color.black);
+ ypos += sequencesHeight + annotationHeight + hgap;
- if (av.getScaleLeftWrapped())
- {
- drawWestScale(g, startRes, endx, ypos);
- }
+ startRes += cWidth;
+ }
+ }
- if (av.getScaleRightWrapped())
- {
- g.translate(canvasWidth - labelWidthEast, 0);
- drawEastScale(g, startRes, endx, ypos);
- g.translate(-(canvasWidth - labelWidthEast), 0);
- }
+ /**
+ * Draws one width of a wrapped alignment, including scales left, right or
+ * above, and annnotations, if shown
+ *
+ * @param g
+ * @param startRes
+ * @param canvasHeight
+ * @param canvasWidth
+ * @param maxWidth
+ * @param ypos
+ */
+ protected void drawWrappedWidth(Graphics g, int startRes,
+ int canvasHeight, int canvasWidth, int maxWidth, int ypos)
+ {
+ int endx;
+ endx = startRes + canvasWidth - 1;
- g.translate(labelWidthWest, 0);
+ if (endx > maxWidth)
+ {
+ endx = maxWidth;
+ }
- if (av.getScaleAboveWrapped())
- {
- drawNorthScale(g, startRes, endx, ypos);
- }
+ g.setFont(av.getFont());
+ g.setColor(Color.black);
- if (av.hasHiddenColumns() && av.getShowHiddenMarkers())
- {
- g.setColor(Color.blue);
- int res;
- HiddenColumns hidden = av.getAlignment().getHiddenColumns();
- List<Integer> positions = hidden.findHiddenRegionPositions();
- for (int pos : positions)
- {
- res = pos - startRes;
+ if (av.getScaleLeftWrapped())
+ {
+ drawVerticalScale(g, startRes, endx, ypos, true);
+ }
- if (res < 0 || res > endx - startRes)
- {
- continue;
- }
+ if (av.getScaleRightWrapped())
+ {
+ drawVerticalScale(g, startRes, endx, ypos, false);
+ }
- 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);
+ drawWrappedRegion(g, startRes, endx, canvasHeight, canvasWidth, ypos);
+ }
- }
- }
+ /**
+ * Draws columns of a wrapped alignment from startRes to endRes, including
+ * scale above and annotations if shown, but not scale left or right.
+ *
+ * @param g
+ * @param startRes
+ * @param endRes
+ * @param canvasHeight
+ * @param canvasWidth
+ * @param ypos
+ */
+ protected void drawWrappedRegion(Graphics g, int startRes, int endRes,
+ int canvasHeight, int canvasWidth, int ypos)
+ {
+ g.translate(labelWidthWest, 0);
- // When printing we have an extra clipped region,
- // the Printable page which we need to account for here
- Shape clip = g.getClip();
+ if (av.getScaleAboveWrapped())
+ {
+ drawNorthScale(g, startRes, endRes, ypos);
+ }
- if (clip == null)
- {
- g.setClip(0, 0, cWidth * charWidth, canvasHeight);
- }
- else
+ // todo can we let drawPanel() handle this?
+ if (av.hasHiddenColumns() && av.getShowHiddenMarkers())
+ {
+ g.setColor(Color.blue);
+ HiddenColumns hidden = av.getAlignment().getHiddenColumns();
+ List<Integer> positions = hidden.findHiddenRegionPositions();
+ for (int pos : positions)
{
- g.setClip(0, (int) clip.getBounds().getY(), cWidth * charWidth,
- (int) clip.getBounds().getHeight());
- }
+ int res = pos - startRes;
- drawPanel(g, startRes, endx, 0, al.getHeight() - 1, ypos);
-
- if (av.isShowAnnotation())
- {
- g.translate(0, cHeight + ypos + 3);
- if (annotations == null)
+ if (res < 0 || res > endRes - startRes)
{
- annotations = new AnnotationPanel(av);
+ continue;
}
- annotations.renderer.drawComponent(annotations, av, g, -1,
- startRes, endx + 1);
- g.translate(0, -cHeight - ypos - 3);
+ 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);
}
- g.setClip(clip);
- g.translate(-labelWidthWest, 0);
+ }
- ypos += cHeight + annotationHeight + hgap;
+ // When printing we have an extra clipped region,
+ // the Printable page which we need to account for here
+ Shape clip = g.getClip();
- startRes += cWidth;
+ if (clip == null)
+ {
+ g.setClip(0, 0, canvasWidth * charWidth, canvasHeight);
}
+ else
+ {
+ g.setClip(0, (int) clip.getBounds().getY(), canvasWidth * charWidth,
+ (int) clip.getBounds().getHeight());
+ }
+
+ drawPanel(g, startRes, endRes, 0, av.getAlignment().getHeight() - 1, ypos);
+
+ int cHeight = av.getAlignment().getHeight() * charHeight;
+
+ if (av.isShowAnnotation())
+ {
+ g.translate(0, cHeight + ypos + 3);
+ if (annotations == null)
+ {
+ annotations = new AnnotationPanel(av);
+ }
+
+ annotations.renderer.drawComponent(annotations, av, g, -1, startRes,
+ endRes + 1);
+ g.translate(0, -cHeight - ypos - 3);
+ }
+ g.setClip(clip);
+ g.translate(-labelWidthWest, 0);
}
AnnotationPanel annotations;
* marker.
*
* @param g1
+ * the graphics context, positioned at the first residue to be drawn
* @param startRes
- * offset of the first column in the visible region (0..)
+ * offset of the first column to draw (0..)
* @param endRes
- * offset of the last column in the visible region (0..)
+ * offset of the last column to draw (0..)
* @param startSeq
- * offset of the first sequence in the visible region (0..)
+ * offset of the first sequence to draw (0..)
* @param endSeq
- * offset of the last sequence in the visible region (0..)
+ * offset of the last sequence to draw (0..)
* @param yOffset
* vertical offset at which to draw (for wrapped alignments)
*/
* on a black background. Any previous highlighting is removed. Answers true
* if any highlight was left on the visible alignment (so status bar should be
* set to match), else false.
+ * <p>
+ * Currently fastPaint is not implemented for wrapped alignments. If a wrapped
+ * alignment had to be scrolled to show the highlighted region, then it should
+ * be fully redrawn, otherwise a fast paint can be performed. This argument
+ * could be removed if fast paint of scrolled wrapped alignment is coded in
+ * future (JAL-2609).
*
* @param results
+ * @param noFastPaint
* @return
*/
- public boolean highlightSearchResults(SearchResultsI results)
+ public boolean highlightSearchResults(SearchResultsI results,
+ boolean noFastPaint)
{
- updateViewport();
-
+ if (fastpainting)
+ {
+ return false;
+ }
boolean wrapped = av.getWrapAlignment();
try
{
+ fastPaint = !noFastPaint;
+ fastpainting = fastPaint;
+
+ updateViewport();
+
/*
* to avoid redrawing the whole visible region, we instead
* redraw just the minimal regions to remove previous highlights
{
fastpainting = false;
}
-
}
/**
{
String eventName = evt.getPropertyName();
- if (!av.getWrapAlignment())
+ // if (av.getWrapAlignment())
+ // {
+ // if (eventName.equals(ViewportRanges.STARTRES))
+ // {
+ // repaint();
+ // }
+ // }
+ // else
{
int scrollX = 0;
if (eventName.equals(ViewportRanges.STARTRES))
if (eventName.equals(ViewportRanges.STARTRES))
{
// scroll - startres and endres both change
- fastPaint(scrollX, 0);
+ if (av.getWrapAlignment())
+ {
+ fastPaintWrapped(scrollX);
+ // fastPaintWrapped(scrollX > 0 ? 1 : -1); // to debug: 1 at a time
+ }
+ else
+ {
+ fastPaint(scrollX, 0);
+ }
}
else if (eventName.equals(ViewportRanges.STARTSEQ))
{
- // scroll
fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
}
}
}
/**
+ * Does a minimal update of the image for a scroll movement. This method
+ * handles scroll movements of up to one width of the wrapped alignment (one
+ * click in the vertical scrollbar). Larger movements (for example after a
+ * scroll to highlight a mapped position) trigger a full redraw instead.
+ *
+ * @param scrollX
+ * number of positions scrolled (right if positive, left if negative)
+ */
+ protected void fastPaintWrapped(int scrollX)
+ {
+ if (Math.abs(scrollX) > av.getRanges().getViewportWidth())
+ {
+ /*
+ * shift of more than one view width is
+ * too complicated to handle in this method
+ */
+ fastPaint = false;
+ repaint();
+ return;
+ }
+
+ fastPaint = true;
+
+ /*
+ * relocate the regions of the alignment that are still visible
+ */
+ shiftWrappedAlignment(-scrollX);
+
+ /*
+ * add new columns (scale above, sequence, annotation)
+ * at top left if scrollX < 0 or bottom right if scrollX > 0
+ * also West scale top left or East scale bottom right if shown
+ */
+ if (scrollX < 0)
+ {
+ fastPaintWrappedTopLeft(-scrollX);
+ }
+ else
+ {
+ // fastPaintWrappedBottomRight(scrollX);
+ }
+
+ repaint();
+ }
+
+ /**
+ * 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
+ *
+ * @param columns
+ */
+ protected void fastPaintWrappedBottomRight(int columns)
+ {
+ if (columns == 0)
+ {
+ return;
+ }
+
+ int repeatHeight = getRepeatHeightWrapped();
+ ViewportRanges ranges = av.getRanges();
+ int visibleWidths = getHeight() / repeatHeight;
+ if (getHeight() % repeatHeight > 0)
+ {
+ visibleWidths++;
+ }
+ int viewportWidth = ranges.getViewportWidth();
+ int hgap = charHeight * (av.getScaleAboveWrapped() ? 2 : 1);
+
+ int startRes = av.getRanges().getStartRes();
+ int endx = startRes + columns - 1;
+ int ypos = charHeight * (av.getScaleAboveWrapped() ? 2 : 1);
+ ypos += repeatHeight * (visibleWidths - 1);
+
+ gg.setFont(av.getFont());
+ gg.setColor(Color.black);
+
+ int cWidth = (getWidth() - labelWidthEast - labelWidthWest) / charWidth;
+
+ drawWrappedRegion(gg, startRes, endx, getHeight(), cWidth, ypos);
+
+ if (av.getScaleRightWrapped())
+ {
+ drawVerticalScale(gg, startRes, endx, ypos, false);
+ }
+ }
+
+ /**
+ * 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 fastPaintWrappedTopLeft(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.
+ *
+ * @param positions
+ */
+ protected void shiftWrappedAlignment(int positions)
+ {
+ if (positions == 0)
+ {
+ return;
+ }
+
+ int repeatHeight = getRepeatHeightWrapped();
+ ViewportRanges ranges = av.getRanges();
+ int widthToCopy = (ranges.getViewportWidth() - Math.abs(positions))
+ * charWidth;
+ int visibleWidths = getHeight() / repeatHeight;
+ if (getHeight() % repeatHeight > 0)
+ {
+ visibleWidths++;
+ }
+ int viewportWidth = ranges.getViewportWidth();
+ int hgap = charHeight * (av.getScaleAboveWrapped() ? 2 : 1);
+
+ if (positions > 0)
+ {
+ /*
+ * shift right (after scroll left)
+ * for each wrapped width (starting with the last), copy (width-positions)
+ * columns from the left margin to the right margin, and copy positions
+ * 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
+ */
+ int y = getHeight() / repeatHeight * repeatHeight;
+ int copyFromLeftStart = labelWidthWest;
+ int copyFromRightStart = copyFromLeftStart + widthToCopy;
+
+ while (y >= 0)
+ {
+ // todo limit repeatHeight for a last part height width?
+ gg.copyArea(copyFromLeftStart, y, widthToCopy, repeatHeight,
+ positions * charWidth, 0);
+ if (y > 0)
+ {
+ gg.copyArea(copyFromRightStart, y - repeatHeight, positions
+ * charWidth, repeatHeight, -widthToCopy, repeatHeight);
+ }
+
+ 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;
+ }
+ }
+ else
+ {
+ /*
+ * shift left (after scroll right)
+ * for each wrapped width (starting with the first), copy (width-positions)
+ * columns from the right margin to the left margin, and copy positions
+ * 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 copyFromRightStart = labelWidthWest - positions * charWidth;
+
+ while (y < getHeight())
+ {
+ // todo limit repeatHeight for a last part height width?
+ gg.copyArea(copyFromRightStart, y, widthToCopy, repeatHeight,
+ positions * charWidth, 0);
+ if (y + repeatHeight < getHeight())
+ {
+ 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);
+ }
+
+ y += repeatHeight;
+ xpos += ranges.getViewportWidth();
+ }
+ }
+ }
+
+ /**
* Redraws any positions in the search results in the visible region of a
* wrapped alignment. Any highlights are drawn depending on the search results
* set on the Viewport, not the <code>results</code> argument. This allows
ViewportRanges ranges = av.getRanges();
int canvasHeight = getHeight();
- int repeats = wrappedHeight / canvasHeight;
- if (wrappedHeight % canvasHeight > 0)
+ int repeats = canvasHeight / wrappedHeight;
+ if (canvasHeight / wrappedHeight > 0)
{
repeats++;
}
* transY: offset from top edge of canvas to residue position
*/
int transY = gapHeight;
- transY += (displayColumn / wrappedWidth) * wrappedHeight;
+ transY += (displayColumn - ranges.getStartRes())
+ / wrappedWidth * wrappedHeight;
transY += (seqNo - ranges.getStartSeq()) * av.getCharHeight();
/*