}
/**
- * 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);
}
}
}
g.setColor(Color.white);
int y = (ypos + (i * charHeight)) - (charHeight / 5);
- g.fillRect(xpos, y, justify, charHeight);
+ y -= charHeight; // fillRect starts from top right of rectangle
+ g.fillRect(xpos, y, justify - charWidth, charHeight + 1);
+ y += charHeight; // drawString starts from bottom right of text
g.setColor(Color.black);
g.drawString(valueAsString, xpos, y);
}
}
/**
- * 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)
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))
{
drawWrappedWidth(g, startRes, canvasHeight, cWidth, maxwidth, ypos);
drawVerticalScale(g, startRes, endx, ypos, false);
}
+ 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);
if (av.getScaleAboveWrapped())
{
- drawNorthScale(g, startRes, endx, ypos);
+ drawNorthScale(g, startRes, endRes, ypos);
}
+ // todo can we let drawPanel() handle this?
if (av.hasHiddenColumns() && av.getShowHiddenMarkers())
{
g.setColor(Color.blue);
{
int res = pos - startRes;
- if (res < 0 || res > endx - startRes)
+ if (res < 0 || res > endRes - startRes)
{
continue;
}
res * charWidth + charHeight / 4, res * charWidth }, new int[] {
ypos - (charHeight / 2), ypos - (charHeight / 2),
ypos - (charHeight / 2) + 8 }, 3);
-
}
}
(int) clip.getBounds().getHeight());
}
- drawPanel(g, startRes, endx, 0, av.getAlignment().getHeight() - 1, ypos);
+ drawPanel(g, startRes, endRes, 0, av.getAlignment().getHeight() - 1, ypos);
int cHeight = av.getAlignment().getHeight() * charHeight;
}
annotations.renderer.drawComponent(annotations, av, g, -1, startRes,
- endx + 1);
+ endRes + 1);
g.translate(0, -cHeight - ypos - 3);
}
g.setClip(clip);
* 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)
*/
{
String eventName = evt.getPropertyName();
- if (true/*!av.getWrapAlignment()*/)
+ // if (av.getWrapAlignment())
+ // {
+ // if (eventName.equals(ViewportRanges.STARTRES))
+ // {
+ // repaint();
+ // }
+ // }
+ // else
{
int scrollX = 0;
if (eventName.equals(ViewportRanges.STARTRES))
if (av.getWrapAlignment())
{
fastPaintWrapped(scrollX);
+ // fastPaintWrapped(scrollX > 0 ? 1 : -1); // to debug: 1 at a time
}
else
{
}
else if (eventName.equals(ViewportRanges.STARTSEQ))
{
- // scroll
fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
}
}
if (Math.abs(scrollX) > av.getRanges().getViewportWidth())
{
/*
- * shift of more than one view width is too much
- * to handle in this method
+ * shift of more than one view width is
+ * too complicated to handle in this method
*/
fastPaint = false;
repaint();
}
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
+ /*
+ * 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();
+ int endx = startRes + columns - 1;
+ 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.
while (y >= 0)
{
- // todo limit repeatHeight for a last part height width
+ // todo limit repeatHeight for a last part height width?
gg.copyArea(copyFromLeftStart, y, widthToCopy, repeatHeight,
positions * charWidth, 0);
if (y > 0)
while (y < getHeight())
{
- // todo limit repeatHeight for a last part height width
+ // todo limit repeatHeight for a last part height width?
gg.copyArea(copyFromRightStart, y, widthToCopy, repeatHeight,
positions * charWidth, 0);
if (y + repeatHeight < getHeight())