{
g.drawString(mstring, mpos * charWidth, ypos - (charHeight / 2));
}
- g.drawLine((mpos * charWidth) + (charWidth / 2), (ypos + 2)
- - (charHeight / 2), (mpos * charWidth) + (charWidth / 2),
- ypos - 2);
+ g.drawLine((mpos * charWidth) + (charWidth / 2),
+ (ypos + 2) - (charHeight / 2),
+ (mpos * charWidth) + (charWidth / 2), ypos - 2);
}
}
}
{
int x = labelWidthWest - fm.stringWidth(String.valueOf(value))
- charWidth / 2;
- g.drawString(value + "", x, (ypos + (i * charHeight))
- - (charHeight / 5));
+ g.drawString(value + "", x,
+ (ypos + (i * charHeight)) - (charHeight / 5));
}
}
}
if (value != -1)
{
- g.drawString(String.valueOf(value), 0, (ypos + (i * charHeight))
- - (charHeight / 5));
+ g.drawString(String.valueOf(value), 0,
+ (ypos + (i * charHeight)) - (charHeight / 5));
}
}
}
// 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;
}
/**
- * DOCUMENT ME!
+ * Returns the visible width of the canvas in residues, after allowing for
+ * East or West scales (if shown)
*
- * @param cwidth
- * DOCUMENT ME!
+ * @param canvasWidth
+ * the width in pixels (possibly including scales)
*
- * @return DOCUMENT ME!
+ * @return
*/
- public int getWrappedCanvasWidth(int cwidth)
+ public int getWrappedCanvasWidth(int canvasWidth)
{
FontMetrics fm = getFontMetrics(av.getFont());
if (av.getScaleLeftWrapped())
{
- labelWidthWest = getLabelWidth(fm);
+ labelWidthWest = labelWidthEast > 0 ? labelWidthEast
+ : getLabelWidth(fm);
}
- return (cwidth - labelWidthEast - labelWidthWest) / charWidth;
+ return (canvasWidth - labelWidthEast - labelWidthWest) / charWidth;
}
/**
*/
protected int getLabelWidth(FontMetrics fm)
{
+ /*
+ * find the biggest sequence end position we need to show
+ * (note this is not necessarily the sequence length)
+ */
int maxWidth = 0;
- for (int i = 0; i < av.getAlignment().getHeight(); i++)
+ AlignmentI alignment = av.getAlignment();
+ for (int i = 0; i < alignment.getHeight(); i++)
{
- maxWidth = Math.max(maxWidth, av.getAlignment().getSequenceAt(i)
- .getEnd());
+ maxWidth = Math.max(maxWidth, alignment.getSequenceAt(i).getEnd());
}
int length = 2;
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();
}
gg.fillPolygon(
- new int[] { res * charWidth - charHeight / 4,
+ new int[]
+ { res * charWidth - charHeight / 4,
res * charWidth + charHeight / 4, res * charWidth },
- new int[] { ypos - (charHeight / 2),
- ypos - (charHeight / 2), ypos - (charHeight / 2) + 8 },
+ new int[]
+ { ypos - (charHeight / 2), ypos - (charHeight / 2),
+ ypos - (charHeight / 2) + 8 },
3);
}
annotations = new AnnotationPanel(av);
}
- annotations.renderer.drawComponent(annotations, av, g, -1,
- startRes, endx + 1);
+ annotations.renderer.drawComponent(annotations, av, g, -1, startRes,
+ endx + 1);
g.translate(0, -cHeight - ypos - 3);
}
g.setClip(clip);
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));
}
}
}
{
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
* 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();
-
- /*
- * for now, don't attempt fastpaint if wrapped format
- */
- boolean wrapped = av.getWrapAlignment();
- if (wrapped)
+ if (fastpainting)
{
- // drawWrappedMappedPositions(results);
- // img = null;
- // av.setSearchResults(results);
- // repaint();
- // return;
+ return false;
}
-
- fastpainting = true;
- fastPaint = true;
+ 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
boolean drawn = false;
if (wrapped)
{
- redrawn = drawWrappedMappedPositions(previous);
- drawn = drawWrappedMappedPositions(results);
+ redrawn = drawMappedPositionsWrapped(previous);
+ drawn = drawMappedPositionsWrapped(results);
redrawn |= drawn;
}
else
{
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))
}
/**
- * Redraws any positions in the search results in the visible region. Any
- * highlights are drawn depending on the search results set on the Viewport,
- * not the results parameter. This allows this method to be called to either
- * clear highlighting (passing the previous search results), or set new
- * highlighting.
+ * 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
+ * this method to be called either to clear highlights (passing the previous
+ * search results), or to draw new highlights.
*
* @param results
* @return
*/
- protected boolean drawWrappedMappedPositions(SearchResultsI results)
+ protected boolean drawMappedPositionsWrapped(SearchResultsI results)
{
if (results == null)
{
}
boolean matchFound = false;
-
- /*
- * Viewport ranges are set for the 'row' of the wrapped alignment
- * the cursor is in, not the whole visible region; really we want
- * the latter; +-6 a temporary fudge for codons wrapping across lines
- */
+
+ int wrappedWidth = av.getWrappedWidth();
+ int wrappedHeight = getRepeatHeightWrapped();
+
ViewportRanges ranges = av.getRanges();
- int firstVisibleColumn = ranges.getStartRes() - 6;
- int lastVisibleColumn = ranges.getEndRes() + 6;
+ int canvasHeight = getHeight();
+ int repeats = canvasHeight / wrappedHeight;
+ if (canvasHeight / wrappedHeight > 0)
+ {
+ repeats++;
+ }
+
+ int firstVisibleColumn = ranges.getStartRes();
+ int lastVisibleColumn = ranges.getStartRes() + repeats
+ * ranges.getViewportWidth() - 1;
+
AlignmentI alignment = av.getAlignment();
if (av.hasHiddenColumns())
{
lastVisibleColumn = alignment.getHiddenColumns()
.adjustForHiddenColumns(lastVisibleColumn);
}
-
- /*
- * find width of alignment in residues, and height of alignment,
- * so we can calculate where to render each matched position
- */
- int wrappedWidth = av.getWrappedWidth();
- int wrappedHeight = av.getAlignment().getHeight() * av.getCharHeight();
- int gapHeight = av.getCharHeight()
- * (av.getScaleAboveWrapped() ? 2 : 1);
- wrappedHeight += gapHeight;
- wrappedHeight += getAnnotationHeight();
+
+ int gapHeight = charHeight * (av.getScaleAboveWrapped() ? 2 : 1);
for (int seqNo = ranges.getStartSeq(); seqNo <= ranges
.getEndSeq(); seqNo++)
* 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();
/*
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;
+ }
}