/**
* Draws the scale above a region of a wrapped alignment, consisting of a
- * column number every 10 columns.
+ * column number every major interval (10 columns).
*
* @param g
* the graphics context to draw on, positioned at the start (bottom
- * left) of the
+ * left) of the line on which to draw any scale marks
* @param startx
- * DOCUMENT ME!
+ * start alignment column (0..)
* @param endx
- * DOCUMENT ME!
+ * end alignment column (0..)
* @param ypos
- * DOCUMENT ME!
+ * y offset to draw at
*/
private void drawNorthScale(Graphics g, int startx, int endx, int ypos)
{
/*
* 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)
*/
- while ((ypos <= canvasHeight) && (startRes < maxwidth))
+ int yposMax = canvasHeight;// - hgap - charHeight + 1;
+ while ((ypos <= yposMax) && (startRes < maxwidth))
{
drawWrappedWidth(g, startRes, canvasHeight, cWidth, maxwidth, ypos);
/*
* add new columns (scale above, sequence, annotation)
- * at top left if scrollX < 0 or bottom right if scrollX > 0
+ * - 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)
{
- fastPaintWrappedTopLeft(-scrollX);
+ fastPaintWrappedAddLeft(-scrollX);
}
else
{
- // fastPaintWrappedBottomRight(scrollX);
+ fastPaintWrappedAddRight(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
+ * 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).
*
* @param columns
*/
- protected void fastPaintWrappedBottomRight(int columns)
+ protected void fastPaintWrappedAddRight(int columns)
{
if (columns == 0)
{
return;
}
+ /*
+ * how many widths are visible? we will be adding
+ * columns to the last visible width, right hand end
+ */
int repeatHeight = getRepeatHeightWrapped();
- ViewportRanges ranges = av.getRanges();
- int visibleWidths = getHeight() / repeatHeight;
- if (getHeight() % repeatHeight > 0)
+ 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
+ */
+ ViewportRanges ranges = av.getRanges();
+ int visibleAlignmentWidth = ranges.getVisibleAlignmentWidth();
int viewportWidth = ranges.getViewportWidth();
- int hgap = charHeight * (av.getScaleAboveWrapped() ? 2 : 1);
+ int maxWidths = visibleAlignmentWidth / viewportWidth;
+ if (visibleAlignmentWidth % viewportWidth > 0)
+ {
+ maxWidths++;
+ }
+ visibleWidths = Math.min(visibleWidths, maxWidths);
+ int widthInColumns = (getWidth() - labelWidthEast - labelWidthWest)
+ / charWidth;
- int startRes = av.getRanges().getStartRes();
- int endx = startRes + columns - 1;
- int ypos = charHeight * (av.getScaleAboveWrapped() ? 2 : 1);
- ypos += repeatHeight * (visibleWidths - 1);
+ /**
+ * draw full height alignment in the second last row, last columns, if the
+ * last row was not full height
+ */
+ if (lastWidthPartHeight)
+ {
+ int widthsAbove = visibleWidths - 2;
+ int ypos = repeatHeight * widthsAbove + hgap;
+ 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.setColor(Color.white);
+ gg.fillRect(labelWidthWest, ypos,
+ (endRes - startRes + 1) * charWidth, repeatHeight);
+
+ drawWrappedRegion(gg, startRes, endRes, canvasHeight, widthInColumns,
+ ypos);
+ gg.translate(-xOffset, 0);
+ }
+
+ /*
+ * y-offset for drawing is height of widths above,
+ * plus one gap row
+ */
+ int widthsAbove = visibleWidths - 1;
+ int ypos = repeatHeight * widthsAbove + hgap;
+ int endRes = ranges.getEndRes();
+ endRes += widthsAbove * viewportWidth;
+ endRes = Math.min(endRes, ranges.getVisibleAlignmentWidth());
+
+ /*
+ * draw one extra column than strictly needed - this is a (harmless)
+ * fudge to ensure scale marks get drawn (JAL-2636)
+ */
+ 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 = getWidth() - labelWidthWest - xOffset;
+ gg.fillRect(labelWidthWest, ypos - hgap, width, repeatHeight);
gg.setFont(av.getFont());
gg.setColor(Color.black);
- int cWidth = (getWidth() - labelWidthEast - labelWidthWest) / charWidth;
-
- drawWrappedRegion(gg, startRes, endx, getHeight(), cWidth, ypos);
+ 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, startRes, endx, ypos, false);
+ drawVerticalScale(gg, leftEndColumn, endRes, ypos, false);
}
}
*
* @param columns
*/
- protected void fastPaintWrappedTopLeft(int columns)
+ protected void fastPaintWrappedAddLeft(int columns)
{
int startRes = av.getRanges().getStartRes();
int repeatHeight = getRepeatHeightWrapped();
ViewportRanges ranges = av.getRanges();
+ int xMax = ranges.getVisibleAlignmentWidth();
int widthToCopy = (ranges.getViewportWidth() - Math.abs(positions))
* charWidth;
- int visibleWidths = getHeight() / repeatHeight;
- if (getHeight() % repeatHeight > 0)
+ 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++;
+ }
+
if (positions > 0)
{
/*
/*
* get y-offset of last wrapped width
*/
- int y = getHeight() / repeatHeight * repeatHeight;
+ int y = canvasHeight / 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)
int y = 0;
int copyFromRightStart = labelWidthWest - positions * charWidth;
- while (y < getHeight())
+ while (y < canvasHeight)
{
- // todo limit repeatHeight for a last part height width?
gg.copyArea(copyFromRightStart, y, widthToCopy, repeatHeight,
positions * charWidth, 0);
- if (y + repeatHeight < getHeight())
+ if (y + repeatHeight < canvasHeight - repeatHeight
+ && (xpos + viewportWidth <= xMax))
{
gg.copyArea(labelWidthWest, y + repeatHeight, -positions
* charWidth, repeatHeight, widthToCopy, -repeatHeight);
}
y += repeatHeight;
- xpos += ranges.getViewportWidth();
+ xpos += viewportWidth;
}
}
}