/Users/lyon/j4p/src/bookExamples/ch27BusinessGraphics/charts/PieGraph.java
|
1 package bookExamples.ch27BusinessGraphics.charts;
2
3 import gui.ClosableJFrame;
4
5 import javax.swing.*;
6 import java.awt.*;
7
8 /**
9 * PieGraph implements the Paintable interface and uses the update
10 * method to draw a pie graphics.graph on a Canvas.
11 * Requires an instance of DoubleDataBean in order
12 * to be constructed.<BR>
13 * Global variables:
14 * <UL>
15 * <LI> DoubleDataBean: instance of DoubleDataBean so the graphics.graph is drawn
16 * with the proper data
17 * <LI> CIRCLESIZE: 360 degrees in a circle
18 * <LI> startAngle: the point at which to begin drawing the pie graphics.graph
19 * <LI> radius: the radius of the pie graphics.graph
20 * <LI> centerX: the X coordinate of the center of the pie graphics.graph
21 * <LI> centerY: the Y coordinate of the center of the pie graphics.graph
22 * </UL>
23 *
24 * @author Allison McHenry
25 * @author Douglas Lyon, PhD
26 * @since JDK 1.3
27 */
28
29
30 public class PieGraph
31 extends JComponent implements Paintable {
32 //GLOBAL VARIABLES
33 private static final double CIRCLESIZE = 360.0;
34 private double startAngle = 0;
35 private int centerX = 10;
36 private int centerY = 10;
37 private String labels[] = {
38 "Apples",
39 "Oranges",
40 "Bananas",
41 "Papayas"
42 };
43 private DoubleDataBean dd;
44 private int radius = 0;
45
46 //CONSTRUCTORS
47
48 /**
49 * Default constructor, used to instantiate an instance of PieGraph by
50 * the testing class
51 * @param _dd instance of DoubleDataBean used to draw the graphics.graph
52 */
53 public PieGraph() {
54 this(400, 400);
55 }
56
57 /**
58 * Constructor used to set just the radius
59 *
60 * @param _radius The pie radius
61 */
62 public PieGraph(int _radius) {
63 this(_radius * 2, _radius * 2);
64 }
65
66 /**
67 * Constructor used to set just the radius
68 *
69 * @param w the image width
70 * @param h the image height
71 */
72 public PieGraph(int w, int h) {
73 setSize(w, h);
74 setBackground(Color.white);
75 dd = new DoubleDataBean(w, h);
76 }
77
78 public Dimension getPreferredSize() {
79 return new Dimension(dd.getWidth(), dd.getHeight());
80 }
81
82 public Dimension getMinimumSize() {
83 return new Dimension(dd.getWidth(), dd.getHeight());
84 }
85
86 /**
87 * Draws the legend on the top canvas. The labels are passed in
88 * and the percentage of the pie that each slice takes up
89 * is calculated. The label color is determined by mapping
90 * the number of the label to the corresponding color value
91 * in the ColorUtils map. TO FIX: if the number of labels passed
92 * does not correspond to the number of data points, the
93 * labels won't match up correctly. This should throw an
94 * exception.
95 *
96 * @param s Array of strings which correspond to each slice
97 * @return p Panel with the labels drawn on it
98 * @see DoubleDataBean.#calculatePercentage
99 * @see java.awt.Panel
100 * @see java.awt.Label
101 */
102 private JPanel getLegendPanel() {
103 JPanel p = new JPanel();
104 String percentages[] = calculatePercentage();
105 ColorUtils cu = new ColorUtils(labels.length);
106 p.setBackground(Color.white);
107 p.setLayout(new GridLayout(0, 2));
108 for (int i = 0; i < labels.length; i++) {
109 JLabel text = new JLabel(labels[i]);
110 JLabel pct = new JLabel(percentages[i]);
111 text.setForeground(cu.getColor(i));
112 pct.setForeground(cu.getColor(i));
113 p.add(text);
114 p.add(pct);
115 }
116 return p;
117 }
118
119 /**
120 * Constructor used to set the data, labels and title only
121 *
122 * @param _x The data to graphics.graph
123 * @param _labels The labels which correspond to the data elements
124 * @param _title The title of the graphics.graph
125 */
126 public PieGraph(DoubleDataBean _dd) {
127 dd = _dd;
128 setSize(dd.getWidth(), dd.getHeight());
129 }
130
131
132 //BEGIN SETTER METHODS
133
134
135 /**
136 * Sets the center of the pie graphics.graph X and Y coordinates.
137 *
138 * @param _x X coordinate of center of pie graphics.graph
139 * @param _y Y coordinate of center of pie graphics.graph
140 */
141 public void setLocation(int x, int y) {
142 centerX = x;
143 centerY = y;
144 }
145
146 public void setValues(double[] _x) {
147 dd.setXVals(_x);
148 }
149
150
151 /**
152 * Sets the point on the circle where the pie should begin to be drawn.
153 *
154 * @param _startAngle Pie graphics.graph start angle
155 */
156 public void setStartAngle(double _startAngle) {
157 startAngle = _startAngle;
158 }
159
160 /**
161 * Sets the X coordinate of the center of the pie graphics.graph.
162 *
163 * @param _centerX X-coordinate of center of pie
164 */
165
166 public void setCenterX(int _centerX) {
167 centerX = _centerX;
168 }
169
170 /**
171 * Sets the Y coordinate of the center of the pie graphics.graph.
172 *
173 * @param _centerY Y-coordinate of center of pie
174 */
175 public void setCenterY(int _centerY) {
176 centerY = _centerY;
177 }
178
179
180 /**
181 * Sets pie graphics.graph labels. Each label should correspond to one data point in the X array.
182 *
183 * @param _labels Pie graphics.graph labels
184 */
185 public void setLabels(String[] _labels) {
186 labels = _labels;
187 }
188
189 public void setRadius(int _radius) {
190 radius = _radius;
191 }
192
193 /**
194 * Gets the pie graphics.graph radius.
195 *
196 * @return radius Pie graphics.graph radius
197 */
198 public int getRadius() {
199 if (radius == 0) {
200 return (Math.max(getSize().width, getSize().height)) / 2;
201 } else {
202 return radius;
203 }
204 }
205
206 /**
207 * Gets the point on the circle where the pie should begin to be drawn.
208 *
209 * @return _startAngle Pie graphics.graph start angle
210 */
211 public double getStartAngle() {
212 return startAngle;
213 }
214
215 /**
216 * Gets the X coordinate of the center of the pie graphics.graph.
217 *
218 * @return centerX X-coordinate of center of pie
219 */
220 public int getCenterX() {
221 return centerX;
222 }
223
224 /**
225 * Gets the Y coordinate of the center of the pie graphics.graph.
226 *
227 * @return centerY Y-coordinate of center of pie
228 */
229 public int getCenterY() {
230 return centerY;
231 }
232
233 /**
234 * Gets pie graphics.graph labels. Each label should correspond to one data point in the X array.
235 *
236 * @return _labels Pie graphics.graph labels
237 */
238 public String[] getLabels() {
239 return labels;
240 }
241
242
243 //UTILITY METHODS
244
245
246 /**
247 * Calls the update method to paint this data from DoubleDataBean onto
248 * an image. It calls update instead of overriding the paint method
249 * directly because "paint" is a specialized method name and it
250 * conflicts with the "paint" method in the PieGraphCanvas class.
251 *
252 * @param g Graphics context for drawing
253 * @see PieGraphPanel.#update
254 */
255 public void paint(Graphics g) {
256 drawGraph(g);
257 }
258
259
260 /**
261 * Draws the circle for the pie graphics.graph. The data to graphics.graph
262 * is determined by the values in the X array. The values in
263 * the Y array are irrelevant.StartAngle is a global variable
264 * from DoubleDataBean which defaults to zero (top of the pie).
265 *
266 * @param g Graphics context for drawing
267 * @see PieGraph.#paint
268 * @see DoubleDataBean.#getSumX
269 * @see ColorUtils.#getColor
270 * @see java.awt.Graphics.#fillArc
271 */
272
273 private void drawGraph(Graphics g) {
274 double startAngle = getStartAngle();
275 ColorUtils cu = new ColorUtils(dd.getXVals().length);
276 double angleSize = ((CIRCLESIZE / (getSumX())));
277 double items[] = dd.getXVals();
278 for (int i = 0; i < items.length; i++) {
279
280 //360.0 * items[i] / d.getSum();
281 double centralAngle = (angleSize * items[i]);
282
283 g.setColor(cu.getColor(i));
284 g.fillArc(getCenterX(), getCenterY(),
285 getRadius(), getRadius(),
286 (int) (startAngle - 5), (int) (centralAngle + 5));
287 startAngle = startAngle + centralAngle;
288 }
289 }
290
291 /**
292 * Calculates the percentage of the pie occupied by each slice.
293 * Returns the value as a string so it can be written as a label on the
294 * pieGraph Panel.
295 *
296 *
297 * @return pctStrings The percentage of the pie occupied by each slice
298 * @see #getSumX
299 * @see CreatePiePanel.#getLegendPanel
300 */
301 protected String[] calculatePercentage() {
302 double sum = getSumX();
303 double[] x = dd.getXVals();
304 double[] percentages = new double[x.length];
305 for (int i = 0; i < x.length; i++) {
306 percentages[i] = (x[i] / sum) * 100;
307 }
308
309 String[] pctStrings = new String[percentages.length];
310 for (int j = 0; j < pctStrings.length; j++) {
311 pctStrings[j] = new String(Double.toString(percentages[j]) + "%");
312 System.out.println("String=" + pctStrings[j]);
313 }
314 return pctStrings;
315 }
316
317
318 /**
319 * Computes the sum of all the data values. Used to calculate the percentage per slice
320 * of each data point in a pie graphics.graph.
321 *
322 * @param _x The array of data to add
323 * @return sum Sum of data x
324 * @see #getSumX
325 */
326 private double computeSum(double x[]) {
327 double sum = 0;
328 for (int i = 0; i < x.length; i++)
329 sum = x[i] + sum;
330 return sum;
331 }
332
333 /**
334 * Default no-argument method to calculate the sum of the array xVals, which is a global
335 * variable
336 *
337 * @return sum Sum of data xVals
338 * @see #calculatePercentage
339 */
340 private double getSumX() {
341 double sum = computeSum(dd.getXVals());
342 return sum;
343 }
344
345 public static void main(String args[]) {
346 ClosableJFrame cf = new ClosableJFrame();
347 Container c = cf.getContentPane();
348 DoubleDataBean dd = new DoubleDataBean(200, 200);
349 double[] xes = new double[]{30, 30, 30, 60};
350
351
352 for (int i = 0; i < dd.getXVals().length; i++) {
353 double[] yes = dd.getXVals();
354 System.out.println("value=" + yes[i]);
355 }
356 PieGraph pg = new PieGraph(200, 200);
357 String[] labels = new String[]{"Tiger", "Lion", "Alligator", "Mongoose"};
358 pg.setLabels(labels);
359 pg.setValues(xes);
360 c.add(pg);
361 c.add(pg.getLegendPanel());
362 c.setLayout(new FlowLayout());
363 c.setBackground(Color.white);
364 cf.setSize(300, 300);
365 cf.setVisible(true);
366 }
367
368 }