fastpainting = true;
fastPaint = true;
updateViewport();
- gg.copyArea(horizontal * charWidth, vertical * charHeight, imgWidth,
- imgHeight, -horizontal * charWidth, -vertical * charHeight);
ViewportRanges ranges = av.getRanges();
int startRes = ranges.getStartRes();
int transX = 0;
int transY = 0;
+ gg.copyArea(horizontal * charWidth, vertical * charHeight, imgWidth,
+ imgHeight, -horizontal * charWidth, -vertical * charHeight);
+
if (horizontal > 0) // scrollbar pulled right, image to the left
{
transX = (endRes - startRes - horizontal) * charWidth;
}
/**
- * 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();
* 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;
}
-
}
/**
@Override
public void propertyChange(PropertyChangeEvent evt)
{
- if (!av.getWrapAlignment())
+ String eventName = evt.getPropertyName();
+
+ if (av.getWrapAlignment())
+ {
+ if (eventName.equals(ViewportRanges.STARTRES))
+ {
+ repaint();
+ }
+ }
+ else
{
- if (evt.getPropertyName().equals("startres")
- || evt.getPropertyName().equals("endres"))
+ int scrollX = 0;
+ if (eventName.equals(ViewportRanges.STARTRES))
{
// Make sure we're not trying to draw a panel
// larger than the visible window
ViewportRanges vpRanges = av.getRanges();
- int scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
- if (scrollX > vpRanges.getEndRes() - vpRanges.getStartRes())
+ scrollX = (int) evt.getNewValue() - (int) evt.getOldValue();
+ int range = vpRanges.getEndRes() - vpRanges.getStartRes();
+ if (scrollX > range)
{
- scrollX = vpRanges.getEndRes() - vpRanges.getStartRes();
+ scrollX = range;
}
- else if (scrollX < vpRanges.getStartRes() - vpRanges.getEndRes())
+ else if (scrollX < -range)
{
- scrollX = vpRanges.getStartRes() - vpRanges.getEndRes();
+ scrollX = -range;
}
+ }
+
+ // Both scrolling and resizing change viewport ranges: scrolling changes
+ // both start and end points, but resize only changes end values.
+ // Here we only want to fastpaint on a scroll, with resize using a normal
+ // paint, so scroll events are identified as changes to the horizontal or
+ // vertical start value.
+ if (eventName.equals(ViewportRanges.STARTRES))
+ {
+ // scroll - startres and endres both change
fastPaint(scrollX, 0);
}
- else if (evt.getPropertyName().equals("startseq")
- || evt.getPropertyName().equals("endseq"))
+ else if (eventName.equals(ViewportRanges.STARTSEQ))
{
+ // scroll
fastPaint(0, (int) evt.getNewValue() - (int) evt.getOldValue());
}
}
}
/**
- * 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;
+ }
}