int cursorY = 0;
- int charHeight = 0;
-
- int charWidth = 0;
-
private AnnotationPanel annotations;
/*
public SeqCanvas(AlignmentPanel ap)
{
this.av = ap.av;
- updateViewport();
fr = new FeatureRenderer(ap);
sr = new SequenceRenderer(av);
setLayout(new BorderLayout());
return fr;
}
- private void updateViewport()
- {
- charHeight = av.getCharHeight();
- charWidth = av.getCharWidth();
- }
-
/**
* Draws the scale above a region of a wrapped alignment, consisting of a
* column number every major interval (10 columns).
*/
private void drawNorthScale(Graphics g, int startx, int endx, int ypos)
{
- updateViewport();
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
/*
* white fill the scale space (for the fastPaint case)
* Draw the scale to the left or right of a wrapped alignment
*
* @param g
+ * graphics context, positioned at the start of the scale to be drawn
* @param startx
* first column of wrapped width (0.. excluding any hidden columns)
* @param endx
void drawVerticalScale(Graphics g, int startx, int endx, int ypos,
boolean left)
{
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
ypos += charHeight;
if (av.hasHiddenColumns())
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,
+ g.fillRect(0, y, left ? labelWidthWest : labelWidthEast,
charHeight + 1);
y += charHeight; // drawString: origin is bottom left of text
*/
String valueAsString = String.valueOf(value);
int justify = fm.stringWidth(valueAsString) + charWidth;
- xpos = left ? labelWidthWest - justify + charWidth / 2
- : getWidth() - justify - charWidth / 2;
-
+ int xpos = left ? labelWidthWest - justify + charWidth / 2
+ : labelWidthEast - justify + charWidth / 2;
g.setColor(Color.black);
g.drawString(valueAsString, xpos, y);
}
try
{
- updateViewport();
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
ViewportRanges ranges = av.getRanges();
int startRes = ranges.getStartRes();
@Override
public void paintComponent(Graphics g)
{
- updateViewport();
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
BufferedImage lcimg = img; // take reference since other threads may null
// img and call later.
super.paintComponent(g);
- if (lcimg != null
- && (fastPaint
- || (getVisibleRect().width != g.getClipBounds().width) || (getVisibleRect().height != g
- .getClipBounds().height)))
+ if (lcimg != null && (fastPaint
+ || (getVisibleRect().width != g.getClipBounds().width)
+ || (getVisibleRect().height != g.getClipBounds().height)))
{
g.drawImage(lcimg, 0, 0, this);
fastPaint = false;
*/
public int getWrappedCanvasWidth(int canvasWidth)
{
+ int charWidth = av.getCharWidth();
+
FontMetrics fm = getFontMetrics(av.getFont());
labelWidthEast = 0;
public void drawWrappedPanel(Graphics g, int canvasWidth,
int canvasHeight, final int startColumn)
{
- updateViewport();
-
int wrappedWidthInResidues = calculateWrappedGeometry(canvasWidth,
canvasHeight);
* draw one width at a time (including any scales or annotation shown),
* until we have run out of either alignment or vertical space available
*/
- int yposMax = canvasHeight;
- // ensure room for at least one sequence
- yposMax -= wrappedSpaceAboveAlignment - charHeight;
int ypos = wrappedSpaceAboveAlignment;
int maxWidth = ranges.getVisibleAlignmentWidth();
int start = startColumn;
- while ((ypos <= yposMax) && (start < maxWidth))
+ int currentWidth = 0;
+ while ((currentWidth < wrappedVisibleWidths) && (start < maxWidth))
{
int endColumn = Math
.min(maxWidth, start + wrappedWidthInResidues - 1);
drawWrappedWidth(g, ypos, start, endColumn, canvasHeight);
ypos += wrappedRepeatHeightPx;
start += wrappedWidthInResidues;
+ currentWidth++;
}
- drawWrappedDecorators(g, canvasHeight, startColumn);
+ drawWrappedDecorators(g, startColumn);
}
/**
*/
protected int calculateWrappedGeometry(int canvasWidth, int canvasHeight)
{
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
/*
* width of labels in pixels left and right (if shown)
*/
/*
* vertical space in pixels between wrapped widths of alignment
+ * - one character height, or two if scale above is drawn
*/
wrappedSpaceAboveAlignment = charHeight
* (av.getScaleAboveWrapped() ? 2 : 1);
wrappedRepeatHeightPx += getAnnotationHeight();
/*
- * number of visible widths (the last one may be part height)
+ * number of residue columns we can show in each row;
+ * this is just canvas width less scale left and right (if shown),
+ * as a whole multiple of character widths
+ */
+ int wrappedWidthInResidues = (canvasWidth - labelWidthEast - labelWidthWest)
+ / charWidth;
+
+ /*
+ * number of visible widths (the last one may be part height),
+ * ensuring a part height includes at least one sequence
*/
ViewportRanges ranges = av.getRanges();
int xMax = ranges.getVisibleAlignmentWidth();
/*
* limit visibleWidths to not exceed width of alignment
*/
- int viewportWidth = ranges.getViewportWidth();
- int maxWidths = (xMax - ranges.getStartRes()) / viewportWidth;
- if (xMax % viewportWidth > 0)
+ int maxWidths = (xMax - ranges.getStartRes()) / wrappedWidthInResidues;
+ if (xMax % wrappedWidthInResidues > 0)
{
maxWidths++;
}
wrappedVisibleWidths = Math.min(wrappedVisibleWidths, maxWidths);
- /*
- * number of whole width residue columns we can show in each row
- */
- int wrappedWidthInResidues = (canvasWidth - labelWidthEast - labelWidthWest)
- / charWidth;
return wrappedWidthInResidues;
}
protected void drawWrappedWidth(Graphics g, int ypos,
int startColumn, int endColumn, int canvasHeight)
{
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
ViewportRanges ranges = av.getRanges();
int viewportWidth = ranges.getViewportWidth();
/*
* 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)
+ * plus column offset from left margin (usually zero, but may be non-zero
+ * when fast painting is drawing just a few columns)
*/
int xOffset = labelWidthWest
+ ((startColumn - ranges.getStartRes()) % viewportWidth)
viewportWidth * charWidth, (int) clip.getBounds().getHeight());
}
+ /*
+ * 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,
+ wrappedRepeatHeightPx);
+
drawPanel(g, startColumn, endx, 0, av.getAlignment().getHeight() - 1,
ypos);
/**
* Draws scales left, right and above (if shown), and any hidden column
- * markers, on the wrapped alignment
+ * markers, on all widths of the wrapped alignment
*
* @param g
- * @param ypos
* @param startColumn
- * @param endColumn
*/
- protected void drawWrappedDecorators(Graphics g, int canvasHeight,
- int startColumn)
+ protected void drawWrappedDecorators(Graphics g, int startColumn)
{
+ int charWidth = av.getCharWidth();
+
g.setFont(av.getFont());
g.setColor(Color.black);
if (av.getScaleRightWrapped())
{
+ int x = labelWidthWest + viewportWidth * charWidth;
+ g.translate(x, 0);
drawVerticalScale(g, startColumn, endColumn, ypos, false);
+ g.translate(-x, 0);
}
+ /*
+ * white fill region of scale above and hidden column markers
+ * (to support incremental fast paint of image)
+ */
+ g.setColor(Color.white);
+ g.fillRect(0, ypos - wrappedSpaceAboveAlignment, viewportWidth
+ * charWidth + labelWidthWest, wrappedSpaceAboveAlignment);
+ g.setColor(Color.black);
+
g.translate(labelWidthWest, 0);
if (av.getScaleAboveWrapped())
protected void drawHiddenColumnMarkers(Graphics g, int ypos,
int startColumn, int endColumn)
{
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
g.setColor(Color.blue);
HiddenColumns hidden = av.getAlignment().getHiddenColumns();
List<Integer> positions = hidden.findHiddenRegionPositions();
xMiddle + charHeight / 4, xMiddle };
int yTop = ypos - (charHeight / 2);
int[] yPoints = new int[] { yTop, yTop, yTop + 8 };
- gg.fillPolygon(xPoints, yPoints, 3);
+ g.fillPolygon(xPoints, yPoints, 3);
}
}
public void drawPanel(Graphics g1, final int startRes, final int endRes,
final int startSeq, final int endSeq, final int yOffset)
{
- updateViewport();
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
if (!av.hasHiddenColumns())
{
draw(g1, startRes, endRes, startSeq, endSeq, yOffset);
private void draw(Graphics g, int startRes, int endRes, int startSeq,
int endSeq, int offset)
{
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
g.setFont(av.getFont());
sr.prepare(g, av.isRenderGaps());
if (av.isShowSequenceFeatures())
{
- fr.drawSequence(g, nextSeq, startRes, endRes, offset
- + ((i - startSeq) * charHeight), false);
+ fr.drawSequence(g, nextSeq, startRes, endRes,
+ offset + ((i - startSeq) * charHeight), false);
}
/*
for (int r = 0; r < visibleResults.length; r += 2)
{
sr.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));
}
}
}
void drawGroupsBoundaries(Graphics g1, int startRes, int endRes,
int startSeq, int endSeq, int offset)
{
+ int charHeight = av.getCharHeight();
+ int charWidth = av.getCharWidth();
+
Graphics2D g = (Graphics2D) g1;
//
// ///////////////////////////////////
{
sx = (group.getStartRes() - startRes) * charWidth;
sy = offset + ((i - startSeq) * charHeight);
- ex = (((group.getEndRes() + 1) - group.getStartRes()) * charWidth) - 1;
+ ex = (((group.getEndRes() + 1) - group.getStartRes()) * charWidth)
+ - 1;
if (sx + ex < 0 || sx > visWidth)
{
}
if ((sx <= (endRes - startRes) * charWidth)
- && group.getSequences(null).contains(
- av.getAlignment().getSequenceAt(i)))
+ && group.getSequences(null)
+ .contains(av.getAlignment().getSequenceAt(i)))
{
- if ((bottom == -1)
- && !group.getSequences(null).contains(
- av.getAlignment().getSequenceAt(i + 1)))
+ if ((bottom == -1) && !group.getSequences(null)
+ .contains(av.getAlignment().getSequenceAt(i + 1)))
{
bottom = sy + charHeight;
}
if (!inGroup)
{
- if (((top == -1) && (i == 0))
- || !group.getSequences(null).contains(
- av.getAlignment().getSequenceAt(i - 1)))
+ if (((top == -1) && (i == 0)) || !group.getSequences(null)
+ .contains(av.getAlignment().getSequenceAt(i - 1)))
{
top = sy;
}
if (group == av.getSelectionGroup())
{
g.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT,
- BasicStroke.JOIN_ROUND, 3f, new float[] { 5f, 3f },
- 0f));
+ BasicStroke.JOIN_ROUND, 3f, new float[]
+ { 5f, 3f }, 0f));
g.setColor(Color.RED);
}
else
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
/*
* draw all scales (if shown) and hidden column markers
*/
- drawWrappedDecorators(gg, getHeight(), ranges.getStartRes());
+ drawWrappedDecorators(gg, ranges.getStartRes());
repaint();
} finally
ViewportRanges ranges = av.getRanges();
int viewportWidth = ranges.getViewportWidth();
+ int charWidth = av.getCharWidth();
/**
* draw full height alignment in the second last row, last columns, if the
if (lastWidthPartHeight)
{
- int widthsAbove = visibleWidths - 2;
+ int widthsAbove = Math.max(0, visibleWidths - 2);
int ypos = wrappedRepeatHeightPx * widthsAbove
+ wrappedSpaceAboveAlignment;
int endRes = ranges.getEndRes();
}
/*
+ * draw newly visible columns in last wrapped width (none if we
+ * have reached the end of the alignment)
* y-offset for drawing last width is height of widths above,
* plus one gap row
*/
+ wrappedSpaceAboveAlignment;
int endRes = ranges.getEndRes();
endRes += widthsAbove * viewportWidth;
- endRes = Math.min(endRes, ranges.getVisibleAlignmentWidth());
int startRes = endRes - columns + 1;
/*
gg.setFont(av.getFont());
gg.setColor(Color.black);
- drawWrappedWidth(gg, ypos, startRes, endRes, canvasHeight);
+ if (startRes < ranges.getVisibleAlignmentWidth())
+ {
+ drawWrappedWidth(gg, ypos, startRes, endRes, canvasHeight);
+ }
/*
* and finally, white fill any space below the visible alignment
{
return;
}
+ int charWidth = av.getCharWidth();
int canvasHeight = getHeight();
ViewportRanges ranges = av.getRanges();
{
return false;
}
-
+ int charHeight = av.getCharHeight();
+
boolean matchFound = false;
+ calculateWrappedGeometry(getWidth(), getHeight());
int wrappedWidth = av.getWrappedWidth();
- int wrappedHeight = getRepeatHeightWrapped();
+ int wrappedHeight = wrappedRepeatHeightPx;
ViewportRanges ranges = av.getRanges();
int canvasHeight = getHeight();
return matchFound;
}
-
- /**
- * Answers the height in pixels of a repeating section of the wrapped
- * alignment, including space above, scale above if shown, sequences, and
- * annotation panel if shown
- *
- * @return
- */
- protected int getRepeatHeightWrapped()
- {
- // gap (and maybe scale) above
- int repeatHeight = charHeight * (av.getScaleAboveWrapped() ? 2 : 1);
-
- // add sequences
- repeatHeight += av.getRanges().getViewportHeight() * charHeight;
-
- // add annotations panel height if shown
- repeatHeight += getAnnotationHeight();
-
- return repeatHeight;
- }
}