/*
Copyright 2006 by Sean Luke and George Mason University
Licensed under the Academic Free License version 3.0
See the file "LICENSE" for more information
*/
package sim.util.media.chart;
import java.awt.*;
import javax.swing.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.util.*;
import sim.util.gui.*;
// From JFreeChart
import org.jfree.chart.renderer.xy.*;
import org.jfree.data.general.*;
import org.jfree.chart.plot.*;
public class ScatterPlotSeriesAttributes extends SeriesAttributes
{
static Shape[] buildShapes()
{
Shape[] s = new Shape[7];
GeneralPath g = null;
// Circle
s[0] = new Ellipse2D.Double(-3, -3, 6, 6);
// Rectangle
Rectangle2D.Double r = new Rectangle2D.Double(-3, -3, 6, 6);
s[1] = r;
// Diamond
s[2] = AffineTransform.getRotateInstance(Math.PI/4.0).createTransformedShape(r);
// Cross +
g = new GeneralPath();
g.moveTo(-0.5f, -3);
g.lineTo(-0.5f, -0.5f); g.lineTo(-3, -0.5f); g.lineTo(-3, 0.5f);
g.lineTo(-0.5f, 0.5f); g.lineTo(-0.5f, 3); g.lineTo(0.5f, 3);
g.lineTo(0.5f, 0.5f); g.lineTo(3, 0.5f); g.lineTo(3, -0.5f);
g.lineTo(0.5f, -0.5f); g.lineTo(0.5f, -3); g.closePath();
s[3] = g;
// X
s[4] = g.createTransformedShape(AffineTransform.getRotateInstance(Math.PI/4.0));
// Up Triangle
g = new GeneralPath();
g.moveTo(0f, -3);
g.lineTo(-3, 3); g.lineTo(3, 3); g.closePath();
s[5] = g;
// Down Triangle
s[6] = g.createTransformedShape(AffineTransform.getRotateInstance(Math.PI));
return s;
}
final static Shape[] shapes = buildShapes();
final static String[] shapeNames = new String[]
{
"Circle", "Square", "Diamond", "Cross", "X", "Up Triangle", "Down Triangle"
};
double[][] values;
public double[][] getValues() { return values; }
public void setValues(double[][] vals)
{
if (vals != null)
{
vals = (double[][]) (vals.clone());
for(int i = 0; i < vals.length; i++)
vals[i] = (double[]) (vals[i].clone());
}
values = vals;
}
Color color;
ColorWell colorWell;
double opacity;
NumberTextField opacityField;
public void setSymbolOpacity(double value) { opacityField.setValue(opacityField.newValue(value)); }
public double getSymbolOpacity() { return opacityField.getValue(); }
public void setSymbolColor(Color value) { colorWell.setColor(color = value); }
public Color getSymbolColor() { return color; }
int shapeNum = 0;
Shape shape = shapes[shapeNum];
JComboBox shapeList;
public void setShapeNum(int value)
{
if (value >= 0 && value < shapes.length)
{
shapeList.setSelectedIndex(value);
shapeNum = value;
shape = shapes[shapeNum];
}
}
public int getShapeNum() { return shapeNum; }
public Shape getShape() { return shape; }
/** Produces a ScatterPlotSeriesAttributes object with the given generator, series name, series index,
and desire to display margin options. */
public ScatterPlotSeriesAttributes(ChartGenerator generator, String name, int index, double[][] values, SeriesChangeListener stoppable)
{
super(generator, name, index, stoppable);
setValues(values);
super.setSeriesName(name); // just set the name, don't update. Bypasses standard method below.
// increment shape counter
((ScatterPlotGenerator)generator).shapeCounter++;
if (((ScatterPlotGenerator)generator).shapeCounter >= shapes.length)
((ScatterPlotGenerator)generator).shapeCounter = 0;
// set the shape
shapeNum = ((ScatterPlotGenerator)generator).shapeCounter;
shape = shapes[shapeNum];
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer)(((XYPlot)getPlot()).getRenderer());
renderer.setSeriesShape(getSeriesIndex(), shape);
renderer.setAutoPopulateSeriesShape(false);
}
public void setSeriesName(String val)
{
super.setSeriesName(val);
((ScatterPlotGenerator)generator).update();
}
public void rebuildGraphicsDefinitions()
{
XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer)(((XYPlot)getPlot()).getRenderer());
renderer.setSeriesPaint(getSeriesIndex(), reviseColor(color, opacity));
// shape may be null at this point, that's fine
renderer.setSeriesShape(getSeriesIndex(), shape);
renderer.setAutoPopulateSeriesShape(false);
repaint();
}
public void buildAttributes()
{
// The following three variables aren't defined until AFTER construction if
// you just define them above. So we define them below here instead.
opacity = 1.0;
// NOTE:
// Paint paint = renderer.getSeriesPaint(getSeriesIndex());
// In JFreeChart 1.0.6 getSeriesPaint returns null!!!
// You need lookupSeriesPaint(), but that's not backward compatible.
// The only thing consistent in all versions is getItemPaint
// (which looks like a gross miss-use, but gets the job done)
color = (Color) ((((XYPlot)getPlot()).getRenderer()).getItemPaint(getSeriesIndex(), -1));
colorWell = new ColorWell(color)
{
public Color changeColor(Color c)
{
color = c;
rebuildGraphicsDefinitions();
return c;
}
};
addLabelled("Color", colorWell);
opacityField = new NumberTextField("Opacity ", opacity,1.0,0.125)
{
public double newValue(double newValue)
{
if (newValue < 0.0 || newValue > 1.0)
newValue = currentValue;
opacity = (float)newValue;
rebuildGraphicsDefinitions();
return newValue;
}
};
addLabelled("",opacityField);
shapeList = new JComboBox();
shapeList.setEditable(false);
shapeList.setModel(new DefaultComboBoxModel(new java.util.Vector(Arrays.asList(shapeNames))));
shapeList.setSelectedIndex(shapeNum);
shapeList.addActionListener(new ActionListener()
{
public void actionPerformed ( ActionEvent e )
{
shapeNum = shapeList.getSelectedIndex();
shape = shapes[shapeNum];
rebuildGraphicsDefinitions();
}
});
addLabelled("Shape",shapeList);
}
}