/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.bio.gui.sequence; import java.awt.Graphics2D; import java.awt.Paint; import java.awt.Shape; import java.awt.Stroke; import java.awt.geom.Ellipse2D; import org.biojava.bio.seq.Feature; import org.biojava.bio.symbol.Location; import org.biojava.utils.ChangeEvent; import org.biojava.utils.ChangeSupport; import org.biojava.utils.ChangeType; import org.biojava.utils.ChangeVetoException; /** *
EllipticalBeadRenderer
renders features as simple
* ellipses. Their outline and fill Paint
,
* Stroke
, feature depth, Y-axis displacement are
* configurable. Also configurable is the minimum ratio of long axis
* to short axis of the ellipse - this prevents long features also
* becoming ever wider and obscuring neighbours.
RATIO
indicating a change to the minimum
* allowed ratio of long axis to short axis of the features.
*/
public static final ChangeType RATIO =
new ChangeType("The shape of the features has changed",
"org.biojava.bio.gui.sequence.EllipticalBeadRenderer",
"RATIO", SequenceRenderContext.LAYOUT);
protected double dimensionRatio;
/**
* Creates a new EllipticalBeadRenderer
object
* with the default settings.
*/
public EllipticalBeadRenderer()
{
super();
dimensionRatio = 2.0F;
}
/**
* Creates a new EllipticalBeadRenderer
.
*
* @param beadDepth a double
.
* @param beadDisplacement a double
.
* @param beadOutline a Paint
.
* @param beadFill a Paint
.
* @param beadStroke a Stroke
.
* @param dimensionRatio a double
.
*/
public EllipticalBeadRenderer(double beadDepth,
double beadDisplacement,
Paint beadOutline,
Paint beadFill,
Stroke beadStroke,
double dimensionRatio)
{
super(beadDepth, beadDisplacement, beadOutline, beadFill, beadStroke);
dimensionRatio = 2.0F;
}
/**
* renderBead
renders features as simple ellipse.
*
* @param g2 a Graphics2D
context.
* @param f a Feature
to render.
* @param context a SequenceRenderContext
context.
*/
public void renderBead(Graphics2D g2,
Feature f,
SequenceRenderContext context)
{
Location loc = f.getLocation();
int min = loc.getMin();
int max = loc.getMax();
int dif = max - min;
Shape shape;
if (context.getDirection() == SequenceRenderContext.HORIZONTAL)
{
double posXW = context.sequenceToGraphics(min);
double posYN = beadDisplacement;
double width = Math.max(((double) (dif + 1)) * context.getScale(), 1.0f);
double height = Math.min(beadDepth, width / dimensionRatio);
// If the bead height occupies less than the full height
// of the renderer, move it down so that it is central
if (height < beadDepth)
posYN += ((beadDepth - height) / dimensionRatio);
shape = new Ellipse2D.Double(posXW, posYN, width, height);
}
else
{
double posXW = beadDisplacement;
double posYN = context.sequenceToGraphics(min);
double height = Math.max(((double) dif + 1) * context.getScale(), 1.0f);
double width = Math.min(beadDepth, height / dimensionRatio);
if (width < beadDepth)
posXW += ((beadDepth - width) / dimensionRatio);
shape = new Ellipse2D.Double(posXW, posYN, width, height);
}
g2.setPaint(beadFill);
g2.fill(shape);
g2.setStroke(beadStroke);
g2.setPaint(beadOutline);
g2.draw(shape);
}
/**
* getDepth
calculates the depth required by this
* renderer to display its beads.
*
* @param context a SequenceRenderContext
object.
*
* @return a double
.
*/
public double getDepth(SequenceRenderContext context)
{
// Get max depth of delegates using base class method
double maxDepth = super.getDepth(context);
return Math.max(maxDepth, (beadDepth + beadDisplacement));
}
/**
* getDimensionRatio
returns the maximum ratio of
* long dimension to short dimension of the bead. This should be
* equal, or greater than 1.
*
* @return a double
.
*/
public double getDimensionRatio()
{
return dimensionRatio;
}
/**
* setDimensionRatio
sets the minimum ratio of
* long dimension to short dimension of the bead. This should be
* equal, or greater than 1.
*
* @param ratio a double
ratio of depth.
*
* @exception ChangeVetoException if an error occurs.
*/
public void setDimensionRatio(double ratio) throws ChangeVetoException
{
if (ratio < 1.0F)
throw new ChangeVetoException("The long dimension may not be less than the short dimension (ratio >= 1.0)");
if (hasListeners())
{
ChangeSupport cs = getChangeSupport(SequenceRenderContext.LAYOUT);
synchronized(cs)
{
ChangeEvent ce = new ChangeEvent(this, SequenceRenderContext.LAYOUT,
null, null,
new ChangeEvent(this, RATIO,
new Double(dimensionRatio),
new Double(ratio)));
cs.firePreChangeEvent(ce);
dimensionRatio= ratio;
cs.firePostChangeEvent(ce);
}
}
else
{
dimensionRatio = ratio;
}
}
}