/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  }