import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
-import java.awt.image.BufferedImage;
public class FeatureRenderer extends FeatureRendererModel
{
private static final AlphaComposite NO_TRANSPARENCY = AlphaComposite
.getInstance(AlphaComposite.SRC_OVER, 1.0f);
- protected SequenceI lastSeq;
-
- BufferedImage offscreenImage;
-
- private volatile SequenceFeature[] lastSequenceFeatures;
-
- int sfSize;
-
/**
* Constructor given a viewport
*
}
/**
- * This is used by Structure Viewers and the Overview Window to get the
- * feature colour of the rendered sequence
- *
- * @param defaultColour
- * @param seq
- * @param column
- * @return
+ * {@inheritDoc}
*/
@Override
- public Color findFeatureColour(Color defaultColour, SequenceI seq,
- int column, Graphics g)
+ public Color findFeatureColour(SequenceI seq, int column, Graphics g)
{
if (!av.isShowSequenceFeatures())
{
- return defaultColour;
+ return null;
}
SequenceFeature[] sequenceFeatures = seq.getSequenceFeatures();
- if (seq != lastSeq)
- {
- lastSeq = seq;
- lastSequenceFeatures = sequenceFeatures;
- if (lastSequenceFeatures != null)
- {
- sfSize = lastSequenceFeatures.length;
- }
- }
- else
- {
- if (lastSequenceFeatures != sequenceFeatures)
- {
- lastSequenceFeatures = sequenceFeatures;
- if (lastSequenceFeatures != null)
- {
- sfSize = lastSequenceFeatures.length;
- }
- }
- }
- if (lastSequenceFeatures == null || sfSize == 0)
+ if (sequenceFeatures == null || sequenceFeatures.length == 0)
{
- return defaultColour;
+ return null;
}
- if (Comparison.isGap(lastSeq.getCharAt(column)))
+ if (Comparison.isGap(seq.getCharAt(column)))
{
- return Color.white;
+ /*
+ * returning null allows the colour scheme to provide gap colour
+ * - normally white, but can be customised otherwise
+ */
+ return null;
}
Color renderedColour = null;
if (transparency == 1.0f)
{
+ /*
+ * simple case - just find the topmost rendered visible feature colour
+ */
renderedColour = findFeatureColour(seq, seq.findPosition(column));
}
else
{
- renderedColour = drawSequence(g, lastSeq, column, column, 0, true);
+ /*
+ * transparency case - draw all visible features in render order to
+ * build up a composite colour on the graphics context
+ */
+ renderedColour = drawSequence(g, seq, column, column, 0, true);
}
- return renderedColour == null ? defaultColour : renderedColour;
+ return renderedColour;
}
/**
* Draws the sequence features on the graphics context, or just determines the
- * colour that would be drawn (if flag offscreenrender is true).
+ * colour that would be drawn (if flag colourOnly is true). Returns the last
+ * colour drawn (which may not be the effective colour if transparency
+ * applies), or null if no feature is drawn in the range given.
*
* @param g
* the graphics context to draw on (may be null if colourOnly==true)
* @param seq
* @param start
- * start column (or sequence position in offscreenrender mode)
+ * start column
* @param end
- * end column (not used in offscreenrender mode)
+ * end column
* @param y1
* vertical offset at which to draw on the graphics
* @param colourOnly
updateFeatures();
- if (lastSeq == null || seq != lastSeq
- || sequenceFeatures != lastSequenceFeatures)
- {
- lastSeq = seq;
- lastSequenceFeatures = sequenceFeatures;
- }
-
if (transparency != 1f && g != null)
{
Graphics2D g2 = (Graphics2D) g;
transparency));
}
- int startPos = lastSeq.findPosition(start);
- int endPos = lastSeq.findPosition(end);
+ int startPos = seq.findPosition(start);
+ int endPos = seq.findPosition(end);
- sfSize = lastSequenceFeatures.length;
+ int sfSize = sequenceFeatures.length;
Color drawnColour = null;
/*
- * iterate over features in ordering of their rendering;
- * if drawing a range of columns, use render order to ensure last is on top
- * if drawing a single column (as in findFeatureColour), with no
- * transparency, work backwards to find the topmost rendered feature colour
+ * iterate over features in ordering of their rendering (last is on top)
*/
for (int renderIndex = 0; renderIndex < renderOrder.length; renderIndex++)
{
// current feature to render
for (int sfindex = 0; sfindex < sfSize; sfindex++)
{
- final SequenceFeature sequenceFeature = lastSequenceFeatures[sfindex];
+ final SequenceFeature sequenceFeature = sequenceFeatures[sfindex];
if (!sequenceFeature.type.equals(type))
{
continue;
}
+ /*
+ * a feature type may be flagged as shown but the group
+ * an instance of it belongs to may be hidden
+ */
if (featureGroupNotShown(sequenceFeature))
{
continue;
}
/*
- * check feature overlaps the visible part of the alignment,
- * unless doing offscreenRender (to the Overview window or a
- * structure viewer) which is not limited
+ * check feature overlaps the target range
+ * TODO: efficient retrieval of features overlapping a range
*/
if (sequenceFeature.getBegin() > endPos
|| sequenceFeature.getEnd() < startPos)
}
Color featureColour = getColour(sequenceFeature);
+ if (featureColour == null)
+ {
+ // score feature outwith threshold for colouring
+ continue;
+ }
+
boolean isContactFeature = sequenceFeature.isContactFeature();
if (isContactFeature)
drawnColour = featureColour;
}
}
- else if (showFeature(sequenceFeature))
+ else
{
if (av.isShowSequenceFeaturesHeight()
&& !Float.isNaN(sequenceFeature.score))
if (transparency != 1.0f && g != null)
{
/*
- * get colour as rendered including transparency
- * and reset transparency
+ * reset transparency
*/
- if (offscreenImage != null && drawnColour != null)
- {
- drawnColour = new Color(offscreenImage.getRGB(0, 0));
- }
Graphics2D g2 = (Graphics2D) g;
g2.setComposite(NO_TRANSPARENCY);
}
@Override
public void featuresAdded()
{
- lastSeq = null;
findAllFeatures();
}
return null;
}
- // updateFeatures();
+ /*
+ * check for new feature added while processing
+ */
+ updateFeatures();
/*
* inspect features in reverse renderOrder (the last in the array is
continue;
}
+ /*
+ * check the column position is within the feature range
+ * (or is one of the two contact positions for a contact feature)
+ */
boolean featureIsAtPosition = sequenceFeature.begin <= pos
&& sequenceFeature.end >= pos;
if (sequenceFeature.isContactFeature())