| PieGraph.java |
package graphics.charts;
import gui.ClosableJFrame;
import javax.swing.*;
import java.awt.*;
/**
* PieGraph implements the Paintable interface and uses the update
* method to draw a pie graphics.graph on a Canvas.
* Requires an instance of DoubleData in order
* to be constructed.<BR>
* Global variables:
* <UL>
* <LI> DoubleData: instance of DoubleData so the graphics.graph is drawn
* with the proper data
* <LI> CIRCLESIZE: 360 degrees in a circle
* <LI> startAngle: the point at which to begin drawing the pie graphics.graph
* <LI> radius: the radius of the pie graphics.graph
* <LI> centerX: the X coordinate of the center of the pie graphics.graph
* <LI> centerY: the Y coordinate of the center of the pie graphics.graph
* </UL>
*
* @author Allison McHenry
* @author Douglas Lyon, PhD
* @since JDK 1.3
*/
public class PieGraph
extends JComponent implements Paintable {
//GLOBAL VARIABLES
private static final double CIRCLESIZE = 360.0;
private double startAngle = 0;
private int centerX = 10;
private int centerY = 10;
private String labels[] = {
"Apples",
"Oranges",
"Bananas",
"Papayas"
};
private DoubleData dd;
private int radius = 0;
//CONSTRUCTORS
/**
* Default constructor, used to instantiate an instance of PieGraph by
* the testing class
* @param _dd instance of DoubleData used to draw the graphics.graph
*/
public PieGraph() {
this(400, 400);
}
/**
* Constructor used to set just the radius
*
* @param _radius The pie radius
*/
public PieGraph(int _radius) {
this(_radius * 2, _radius * 2);
}
/**
* Constructor used to set just the radius
*
* @param w the image width
* @param h the image height
*/
public PieGraph(int w, int h) {
setSize(w, h);
setBackground(Color.white);
dd = new DoubleData(w, h);
}
public Dimension getPreferredSize() {
return new Dimension(dd.getWidth(), dd.getHeight());
}
public Dimension getMinimumSize() {
return new Dimension(dd.getWidth(), dd.getHeight());
}
/**
* Draws the legend on the top canvas. The labels are passed in
* and the percentage of the pie that each slice takes up
* is calculated. The label color is determined by mapping
* the number of the label to the corresponding color value
* in the ColorUtils map. TO FIX: if the number of labels passed
* does not correspond to the number of data points, the
* labels won't match up correctly. This should throw an
* exception.
*
* @param s Array of strings which correspond to each slice
* @return p Panel with the labels drawn on it
* @see DoubleData.#calculatePercentage
* @see java.awt.Panel
* @see java.awt.Label
*/
private JPanel getLegendPanel() {
JPanel p = new JPanel();
String percentages[] = calculatePercentage();
ColorUtils cu = new ColorUtils(labels.length);
p.setBackground(Color.white);
p.setLayout(new GridLayout(0, 2));
for (int i = 0; i < labels.length; i++) {
JLabel text = new JLabel(labels[i]);
JLabel pct = new JLabel(percentages[i]);
text.setForeground(cu.getColor(i));
pct.setForeground(cu.getColor(i));
p.add(text);
p.add(pct);
}
return p;
}
/**
* Constructor used to set the data, labels and title only
*
* @param _x The data to graphics.graph
* @param _labels The labels which correspond to the data elements
* @param _title The title of the graphics.graph
*/
public PieGraph(DoubleData _dd) {
dd = _dd;
setSize(dd.getWidth(), dd.getHeight());
}
//BEGIN SETTER METHODS
/**
* Sets the center of the pie graphics.graph X and Y coordinates.
*
* @param _x X coordinate of center of pie graphics.graph
* @param _y Y coordinate of center of pie graphics.graph
*/
public void setLocation(int x, int y) {
centerX = x;
centerY = y;
}
public void setValues(double[] _x) {
dd.setXVals(_x);
}
/**
* Sets the point on the circle where the pie should begin to be drawn.
*
* @param _startAngle Pie graphics.graph start angle
*/
public void setStartAngle(double _startAngle) {
startAngle = _startAngle;
}
/**
* Sets the X coordinate of the center of the pie graphics.graph.
*
* @param _centerX X-coordinate of center of pie
*/
public void setCenterX(int _centerX) {
centerX = _centerX;
}
/**
* Sets the Y coordinate of the center of the pie graphics.graph.
*
* @param _centerY Y-coordinate of center of pie
*/
public void setCenterY(int _centerY) {
centerY = _centerY;
}
/**
* Sets pie graphics.graph labels. Each label should correspond to one data point in the X array.
*
* @param _labels Pie graphics.graph labels
*/
public void setLabels(String[] _labels) {
labels = _labels;
}
public void setRadius(int _radius) {
radius = _radius;
}
/**
* Gets the pie graphics.graph radius.
*
* @return radius Pie graphics.graph radius
*/
public int getRadius() {
if (radius == 0) {
return (Math.max(getSize().width, getSize().height)) / 2;
} else {
return radius;
}
}
/**
* Gets the point on the circle where the pie should begin to be drawn.
*
* @return _startAngle Pie graphics.graph start angle
*/
public double getStartAngle() {
return startAngle;
}
/**
* Gets the X coordinate of the center of the pie graphics.graph.
*
* @return centerX X-coordinate of center of pie
*/
public int getCenterX() {
return centerX;
}
/**
* Gets the Y coordinate of the center of the pie graphics.graph.
*
* @return centerY Y-coordinate of center of pie
*/
public int getCenterY() {
return centerY;
}
/**
* Gets pie graphics.graph labels. Each label should correspond to one data point in the X array.
*
* @return _labels Pie graphics.graph labels
*/
public String[] getLabels() {
return labels;
}
//UTILITY METHODS
/**
* Calls the update method to paint this data from DoubleData onto
* an image. It calls update instead of overriding the paint method
* directly because "paint" is a specialized method name and it
* conflicts with the "paint" method in the PieGraphCanvas class.
*
* @param g Graphics context for drawing
* @see PieGraphPanel.#update
*/
public void paint(Graphics g) {
drawGraph(g);
}
/**
* Draws the circle for the pie graphics.graph. The data to graphics.graph
* is determined by the values in the X array. The values in
* the Y array are irrelevant.StartAngle is a global variable
* from DoubleData which defaults to zero (top of the pie).
*
* @param g Graphics context for drawing
* @see PieGraph.#paint
* @see DoubleData.#getSumX
* @see ColorUtils.#getColor
* @see java.awt.Graphics.#fillArc
*/
private void drawGraph(Graphics g) {
double startAngle = getStartAngle();
ColorUtils cu = new ColorUtils(dd.getXVals().length);
double angleSize = ((CIRCLESIZE / (getSumX())));
double items[] = dd.getXVals();
for (int i = 0; i < items.length; i++) {
//360.0 * items[i] / d.getSum();
double centralAngle = (angleSize * items[i]);
g.setColor(cu.getColor(i));
g.fillArc(getCenterX(), getCenterY(),
getRadius(), getRadius(),
(int) (startAngle - 5), (int) (centralAngle + 5));
startAngle = startAngle + centralAngle;
}
}
/**
* Calculates the percentage of the pie occupied by each slice.
* Returns the value as a string so it can be written as a label on the
* pieGraph Panel.
*
*
* @return pctStrings The percentage of the pie occupied by each slice
* @see #getSumX
* @see CreatePiePanel.#getLegendPanel
*/
protected String[] calculatePercentage() {
double sum = getSumX();
double[] x = dd.getXVals();
double[] percentages = new double[x.length];
for (int i = 0; i < x.length; i++) {
percentages[i] = (x[i] / sum) * 100;
}
String[] pctStrings = new String[percentages.length];
for (int j = 0; j < pctStrings.length; j++) {
pctStrings[j] = new String(Double.toString(percentages[j]) + "%");
System.out.println("String=" + pctStrings[j]);
}
return pctStrings;
}
/**
* Computes the sum of all the data values. Used to calculate the percentage per slice
* of each data point in a pie graphics.graph.
*
* @param _x The array of data to add
* @return sum Sum of data x
* @see #getSumX
*/
private double computeSum(double x[]) {
double sum = 0;
for (int i = 0; i < x.length; i++)
sum = x[i] + sum;
return sum;
}
/**
* Default no-argument method to calculate the sum of the array xVals, which is a global
* variable
*
* @return sum Sum of data xVals
* @see #calculatePercentage
*/
private double getSumX() {
double sum = computeSum(dd.getXVals());
return sum;
}
public static void main(String args[]) {
ClosableJFrame cf = new ClosableJFrame();
Container c = cf.getContentPane();
DoubleData dd = new DoubleData(200, 200);
double[] xes = new double[]{30, 30, 30, 60};
for (int i = 0; i < dd.getXVals().length; i++) {
double[] yes = dd.getXVals();
System.out.println("value=" + yes[i]);
}
PieGraph pg = new PieGraph(200, 200);
String[] labels = new String[]{"Tiger", "Lion", "Alligator", "Mongoose"};
pg.setLabels(labels);
pg.setValues(xes);
c.add(pg);
c.add(pg.getLegendPanel());
c.setLayout(new FlowLayout());
c.setBackground(Color.white);
cf.setSize(300, 300);
cf.setVisible(true);
}
}