Code: Select all
/**
* ScalableDotRenderer is an XYLineAndShapeRenderer extension that produces a single circular dot per item whose size scales depending on the
* zoom factor for the plot axes. (This version also sets the base default so that only the shapes are visible, no lines.)
*/
class ScalableDotRenderer extends XYLineAndShapeRenderer {
/** Default factor by which to multiply bar width to obtain dot size */
protected static final double DEFAULT_WIDTH_FACTOR = 0.5;
/** Factor by which to multiply bar width to obtain dot size */
protected double barwidthfactor = DEFAULT_WIDTH_FACTOR;
/** The dot to use for the current pass */
protected Shape thedot = null;
/**
* Constructor that sets the dot size as a proportion of the bar width
*
* @param factor the factor by which to multiply bar width to obtain dot size
*/
public ScalableDotRenderer(double factor) {
this();
this.barwidthfactor = factor;
}
/**
* Default constructor, leave bar width factor set to default;
*/
private ScalableDotRenderer() {
super();
setBaseLinesVisible(false);
setBaseShapesVisible(true);
}
/**
* Override XYLineAndShapeRenderer.initialize() to ensure that thedot is recreated on next drawItem().
*/
@Override
public XYItemRendererState initialise(Graphics2D g2,
Rectangle2D dataArea,
XYPlot plot,
XYDataset data,
PlotRenderingInfo info) {
thedot = null;
return super.initialise(g2, dataArea, plot, data, info);
}
/**
* Override the XYLineAndShapeRenderer.drawItem() to create and cache the scaled dot.
*/
@Override
public void drawItem(Graphics2D g2, XYItemRendererState state,
Rectangle2D dataArea, PlotRenderingInfo info, XYPlot plot,
ValueAxis domainAxis, ValueAxis rangeAxis, XYDataset dataset,
int series, int item, CrosshairState crosshairState, int pass) {
if (thedot == null) {
double width = 0.0;
RectangleEdge domainEdge = plot.getDomainAxisEdge();
double widthms = source.getWidth();
double left = dataset.getXValue(series, item) - widthms;
for (int j = 0; j < 2; j++) { // check at least two bars to ensure an accurate width
double right = left + widthms;
double lpos = domainAxis.valueToJava2D(left, dataArea, domainEdge);
double rpos = domainAxis.valueToJava2D(right, dataArea, domainEdge);
width = Math.max(width, Math.abs(rpos - lpos));
left += widthms;
}
width *= barwidthfactor;
thedot = new Ellipse2D.Double(-width * 0.5, -width * 0.5, width, width);
}
super.drawItem(g2, state, dataArea, info, plot, domainAxis, rangeAxis, dataset, series, item, crosshairState, pass);
}
/**
* Override XYLineAndShapeRenderer.getItemShape() to return the properly scaled dot.
*/
@Override
public Shape getItemShape(int series, int item) {
return thedot;
}
}