overlaps = seq.getFeatures().findFeatures(vp0,
vp1, type);
// colourOnly (i.e. Overview) can only be here if translucent, so
// there is no need to check for filtering
if (!colourOnly && fc.isSimpleColour())
{
filterFeaturesForDisplay(overlaps);
}
for (int i = overlaps.size(); --i >= 0;)
{
SequenceFeature sf = overlaps.get(i);
Color featureColour = getColor(sf, fc);
if (featureColour == null)
{
/*
* feature excluded by visibility settings, filters, or colour threshold
*/
continue;
}
/*
* if feature starts/ends outside the visible range,
* restrict to visible positions (or if a contact feature,
* to a single position)
*/
int sf0 = sf.getBegin();
int sf1 = sf.getEnd();
int visibleStart = sf0;
if (visibleStart < vp0)
{
visibleStart = sf.isContactFeature() ? sf1 : vp0;
}
int visibleEnd = sf1;
if (visibleEnd > vp1)
{
visibleEnd = sf.isContactFeature() ? sf0 : vp1;
}
int featureStartCol = seq.findIndex(visibleStart);
int featureEndCol = (sf.begin == sf.end ? featureStartCol
: seq.findIndex(visibleEnd));
// Color featureColour = getColour(sequenceFeature);
boolean isContactFeature = sf.isContactFeature();
if (isContactFeature)
{
boolean drawn = renderFeature(g, seq, featureStartCol - 1,
featureStartCol - 1, featureColour, start, end, y1,
colourOnly);
drawn |= renderFeature(g, seq, featureEndCol - 1,
featureEndCol - 1, featureColour, start, end, y1,
colourOnly);
if (drawn)
{
drawnColour = featureColour;
}
}
else
{
/*
* showing feature score by height of colour
* is not implemented as a selectable option
*
if (av.isShowSequenceFeaturesHeight()
&& !Float.isNaN(sequenceFeature.score))
{
boolean drawn = renderScoreFeature(g, seq,
seq.findIndex(sequenceFeature.begin) - 1,
seq.findIndex(sequenceFeature.end) - 1, featureColour,
start, end, y1, normaliseScore(sequenceFeature),
colourOnly);
if (drawn)
{
drawnColour = featureColour;
}
}
else
{
*/
boolean drawn = renderFeature(g, seq, featureStartCol - 1,
featureEndCol - 1, featureColour, start, end, y1,
colourOnly);
if (drawn)
{
drawnColour = featureColour;
}
/*}*/
}
}
}
if (transparency != 1.0f)
{
/*
* reset transparency
*/
((Graphics2D) g).setComposite(NO_TRANSPARENCY);
}
return drawnColour;
}
/**
* Called when alignment in associated view has new/modified features to
* discover and display.
*
*/
@Override
public void featuresAdded()
{
findAllFeatures();
}
/**
* Returns the sequence feature colour rendered at the given column position,
* or null if none found. The feature of highest render order (i.e. on top) is
* found, subject to both feature type and feature group being visible, and
* its colour returned. This method is suitable when no feature transparency
* applied (only the topmost visible feature colour is rendered).
*
* Note this method does not check for a gap in the column so would return the
* colour for features enclosing a gapped column. Check for gap before calling
* if different behaviour is wanted.
*
* @param seq
* @param column
* (1..)
* @return
*/
private Color findFeatureColour(SequenceI seq, int column)
{
/*
* check for new feature added while processing
*/
updateFeatures();
/*
* inspect features in reverse renderOrder (the last in the array is
* displayed on top) until we find one that is rendered at the position
*/
for (int renderIndex = renderOrder.length; --renderIndex >= 0;)
{
String type = renderOrder[renderIndex];
if (!seq.hasFeatures(type) || !showFeatureOfType(type))
{
continue;
}
/*
* field overlaps is used by JalviewJS to avoid object creation;
* not thread-safe for Java (Javascript is single-threaded)
*/
if (overlaps != null)
{
overlaps.clear();
}
List list = seq.findFeatures(column, type, overlaps);
if (list.size() > 0)
{
for (int i = 0, n = list.size(); i < n; i++)
{
SequenceFeature sf = list.get(i);
if (featureGroupNotShown(sf))
{
continue;
}
Color col = getColour(sf);
if (col != null)
{
return col;
}
}
}
}
/*
* no displayed feature found at position
*/
return null;
}
}