selection)
{
Font font = alignViewport.getFont();
if (alignViewport.isSeqNameItalics())
{
setIdfont(new Font(font.getName(), Font.ITALIC,
font.getSize()));
}
else
{
setIdfont(font);
}
g.setFont(getIdfont());
FontMetrics fm = g.getFontMetrics();
if (alignViewport.antiAlias)
{
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
}
Color currentColor = Color.white;
Color currentTextColor = Color.black;
boolean hasHiddenRows = alignViewport.hasHiddenRows();
if (alignViewport.getWrapAlignment())
{
drawIdsWrapped(g, alignViewport, startSeq, getHeight());
return;
}
// Now draw the id strings
int panelWidth = getWidth();
int xPos = 0;
// Now draw the id strings
for (int i = startSeq; i <= endSeq; i++)
{
SequenceI sequence = alignViewport.getAlignment().getSequenceAt(i);
if (sequence == null)
{
continue;
}
if (hasHiddenRows || alignViewport.isDisplayReferenceSeq())
{
g.setFont(getHiddenFont(sequence, alignViewport));
}
// Selected sequence colours
if (selection != null && selection.contains(sequence))
{
currentColor = Color.black;
currentTextColor = Color.white;
}
else if ((alignViewport.getSelectionGroup() != null) && alignViewport
.getSelectionGroup().getSequences(null).contains(sequence))
{
currentColor = Color.lightGray;
currentTextColor = Color.black;
}
else
{
currentColor = alignViewport.getSequenceColour(sequence);
currentTextColor = Color.black;
}
g.setColor(currentColor);
int charHeight = alignViewport.getCharHeight();
g.fillRect(0, (i - startSeq) * charHeight,
getWidth(), charHeight);
g.setColor(currentTextColor);
String string = sequence
.getDisplayId(alignViewport.getShowJVSuffix());
if (alignViewport.isRightAlignIds())
{
xPos = panelWidth - fm.stringWidth(string) - 4;
}
g.drawString(string, xPos, (((i - startSeq) * charHeight) + charHeight)
- (charHeight / 5));
if (hasHiddenRows)
{
drawMarker(g, alignViewport, i, startSeq, 0);
}
}
}
/**
* Draws sequence ids, and annotation labels if annotations are shown, in
* wrapped mode
*
* @param g
* @param alignViewport
* @param startSeq
*/
void drawIdsWrapped(Graphics2D g, AlignViewport alignViewport,
int startSeq, int pageHeight)
{
int alignmentWidth = alignViewport.getAlignment().getWidth();
final int alheight = alignViewport.getAlignment().getHeight();
if (alignViewport.hasHiddenColumns())
{
alignmentWidth = alignViewport.getAlignment().getHiddenColumns()
.absoluteToVisibleColumn(alignmentWidth) - 1;
}
int annotationHeight = 0;
AnnotationLabels labels = null;
if (alignViewport.isShowAnnotation())
{
if (ap == null)
{
ap = new AnnotationPanel(alignViewport);
}
annotationHeight = ap.adjustPanelHeight();
labels = new AnnotationLabels(alignViewport);
}
final int charHeight = alignViewport.getCharHeight();
int hgap = charHeight;
if (alignViewport.getScaleAboveWrapped())
{
hgap += charHeight;
}
/*
* height of alignment + gap + annotations (if shown)
*/
int cHeight = alheight * charHeight + hgap
+ annotationHeight;
ViewportRanges ranges = alignViewport.getRanges();
int rowSize = ranges.getViewportWidth();
/*
* draw repeating sequence ids until out of sequence data or
* out of visible space, whichever comes first
*/
boolean hasHiddenRows = alignViewport.hasHiddenRows();
int ypos = hgap;
int rowStartRes = ranges.getStartRes();
while ((ypos <= pageHeight) && (rowStartRes < alignmentWidth))
{
for (int i = startSeq; i < alheight; i++)
{
SequenceI s = alignViewport.getAlignment().getSequenceAt(i);
if (hasHiddenRows || alignViewport.isDisplayReferenceSeq())
{
g.setFont(getHiddenFont(s, alignViewport));
}
else
{
g.setFont(getIdfont());
}
drawIdString(g, hasHiddenRows, s, i, 0, ypos);
}
if (labels != null && alignViewport.isShowAnnotation())
{
g.translate(0, ypos + (alheight * charHeight));
labels.drawComponent(g, getWidth());
g.translate(0, -ypos - (alheight * charHeight));
}
ypos += cHeight;
rowStartRes += rowSize;
}
}
/**
* Draws a marker (a blue right-pointing triangle) between sequences to
* indicate hidden sequences.
*
* @param g
* @param alignViewport
* @param seqIndex
* @param starty
* @param yoffset
*/
void drawMarker(Graphics2D g, AlignViewport alignViewport, int seqIndex, int starty, int yoffset)
{
SequenceI[] hseqs = alignViewport.getAlignment()
.getHiddenSequences().hiddenSequences;
// Use this method here instead of calling hiddenSeq adjust
// 3 times.
int hSize = hseqs.length;
int hiddenIndex = seqIndex;
int lastIndex = seqIndex - 1;
int nextIndex = seqIndex + 1;
for (int j = 0; j < hSize; j++)
{
if (hseqs[j] != null)
{
if (j - 1 < hiddenIndex)
{
hiddenIndex++;
}
if (j - 1 < lastIndex)
{
lastIndex++;
}
if (j - 1 < nextIndex)
{
nextIndex++;
}
}
}
/*
* are we below or above the hidden sequences?
*/
boolean below = (hiddenIndex > lastIndex + 1);
boolean above = (nextIndex > hiddenIndex + 1);
g.setColor(Color.blue);
int charHeight = av.getCharHeight();
/*
* vertices of the triangle, below or above hidden seqs
*/
int[] xPoints = new int[]
{ getWidth() - charHeight,
getWidth() - charHeight, getWidth() };
int yShift = seqIndex - starty;
if (below)
{
int[] yPoints = new int[] { yShift * charHeight + yoffset,
yShift * charHeight + yoffset + charHeight / 4,
yShift * charHeight + yoffset };
g.fillPolygon(xPoints, yPoints, 3);
}
if (above)
{
yShift++;
int[] yPoints = new int[] { yShift * charHeight + yoffset,
yShift * charHeight + yoffset - charHeight / 4,
yShift * charHeight + yoffset };
g.fillPolygon(xPoints, yPoints, 3);
}
}
/**
* Answers the standard sequence id font, or a bold font if the sequence is
* set as reference or a hidden group representative
*
* @param seq
* @param alignViewport
* @return
*/
private Font getHiddenFont(SequenceI seq, AlignViewport alignViewport)
{
if (av.isReferenceSeq(seq) || av.isHiddenRepSequence(seq))
{
return new Font(av.getFont().getName(), Font.BOLD,
av.getFont().getSize());
}
return getIdfont();
}
public Font getIdfont()
{
return idfont;
}
public void setIdfont(Font idfont)
{
this.idfont = idfont;
}
/**
* Respond to viewport range changes (e.g. alignment panel was scrolled). 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.
*
* In unwrapped mode, only responds to a vertical scroll, as horizontal scroll
* leaves sequence ids unchanged. In wrapped mode, only vertical scroll is
* provided, but it generates a change of "startres" which does require an
* update here.
*/
@Override
public void propertyChange(PropertyChangeEvent evt)
{
String propertyName = evt.getPropertyName();
if (propertyName.equals(ViewportRanges.STARTSEQ)
|| (av.getWrapAlignment()
&& propertyName.equals(ViewportRanges.STARTRES)))
{
fastPaint((int) evt.getNewValue() - (int) evt.getOldValue());
}
else if (propertyName.equals(ViewportRanges.STARTRESANDSEQ))
{
fastPaint(((int[]) evt.getNewValue())[1]
- ((int[]) evt.getOldValue())[1]);
}
else if (propertyName.equals(ViewportRanges.MOVE_VIEWPORT))
{
repaint();
}
}
}