The Java Program: PieChart.java

  1 // PieChart.java  -- pie chart applet
  2 
  3 // Original author : Saket Kumar, saket_kumar@hotmail.com
  4 
  5 import java.applet.Applet;
  6 
  7 import java.awt.Color;
  8 import java.awt.Graphics;
  9 import java.awt.Font;
 10 import java.awt.FontMetrics;
 11 
 12 public class PieChart extends Applet {
 13 
 14    String       title;
 15    Font        font;
 16    FontMetrics fontMetrics;
 17    int          titleHeight = 15;
 18    int          columns;
 19    int          values[];
 20    Color       colors[];
 21    String      labels[];
 22    float       percent[];
 23    float       angle[];
 24    int          maxLabelWidth = 0;
 25    int         maxValueWidth = 0;
 26    int          max = 0;
 27    int         strWidth=0;
 28    boolean     showLabel=true;   // Whether to display label or not
 29    boolean     showPercent=true; // Whether to display percent or not
 30 
 31    int cx=0,cy=0;          //Center of Circle
 32    int lx=0,ly=0;
 33 
 34    private Color parseColor (String nm, Color def) {
 35       if (nm==null) return (def);
 36       if (nm.equals("red")) {
 37          return (Color.red);
 38       } else if (nm.equals("green")) {
 39          return (Color.green);
 40       } else if (nm.equals("blue")) {
 41          return (Color.decode ("#3399FF"));
 42       } else if (nm.equals("pink")) {
 43          return (Color.pink);
 44       } else if (nm.equals("orange")) {
 45          return (Color.orange);
 46       } else if (nm.equals("magenta")) {
 47          return (Color.magenta.brighter());
 48       } else if (nm.equals("cyan")) {
 49          return (Color.cyan);
 50       } else if (nm.equals("white")) {
 51          return (Color.white);
 52       } else if (nm.equals("yellow")) {
 53          return (Color.yellow);
 54       } else if (nm.equals("gray")) {
 55          return (Color.gray.brighter());
 56       } else if (nm.equals("darkGray")) {
 57          return (Color.gray);
 58       } else {
 59          return (def);
 60       }
 61    }
 62 
 63 
 64    public synchronized void init() {
 65       String temp;
 66       font = new java.awt.Font("Sanserif", Font.BOLD, 12);
 67       fontMetrics = getFontMetrics(font);
 68       setBackground (parseColor (getParameter("bgcolor"), Color.white));
 69       title = getParameter("title"); // Title of the Pie Chart
 70 
 71       temp = getParameter("columns");
 72       if (temp == null) {
 73          columns = 5;
 74       } else {
 75          columns = Integer.parseInt(temp);
 76       }
 77 
 78       temp = getParameter("showlabel");
 79       showLabel = (temp==null || temp.equalsIgnoreCase ("yes"));
 80 
 81       temp = getParameter("showpercent");
 82       showPercent = (temp==null || temp.equalsIgnoreCase ("yes"));
 83 
 84       values = new int[columns];
 85       colors = new Color[columns];
 86       labels = new String[columns];
 87       percent= new float[columns];
 88       angle  = new float[columns];
 89 
 90       float totalValue=0;
 91 
 92       for (int i=0; i < columns; i++) {
 93 
 94          temp = getParameter("Pvalue" + (i+1));
 95          if (temp != null) {
 96             try {
 97                values[i] = Integer.parseInt(temp);
 98             } catch (NumberFormatException e) {
 99                values[i] = 0;
100             }
101          }
102          totalValue +=  values[i];
103          if (values[i] > max) {
104             max = values[i];
105          }
106 
107          // parse the label for this column
108          temp = getParameter("P" + "label"+ (i+1) );
109          labels[i] = (temp == null) ? "" : temp;
110          maxLabelWidth = Math.max(fontMetrics.stringWidth((String)(labels[i])),
111                                   maxLabelWidth);
112         
113          // parse the color attribute for this column
114          colors[i] = parseColor (getParameter("P" + "color"+ (i+1)), Color.gray);
115       }
116 
117       final float multiFactor = 100 / totalValue;
118       for (int i=0; i < columns; i++) {
119          percent[i]= values[i] * multiFactor;
120          angle[i]  = (float) (percent[i] * 3.6) ;  // Calculation of Angle (360/100)
121       }
122    }
123 
124    public synchronized void paint(Graphics g) {
125       // Draw the title of the chart at the top
126       if (title!=null) {
127          final int strWidth=fontMetrics.stringWidth(title);
128          final Font fnt = new java.awt.Font("Sanserif", Font.BOLD, 16);
129          g.setFont (fnt);
130          g.setColor (Color.red);
131          g.drawString (title,((getSize().width - strWidth)/2),15);
132          g.setFont (font);
133       }
134 
135       int width  = Math.min((getSize().width - 100),(getSize().height - 100));
136       int height = width;
137       int x=50;
138       int y=x;
139 
140       if (getSize().width > width){
141          x = (getSize().width - width ) /2 ; 
142       }
143 
144       // Center of pie (cx, cy are global variables)
145       cx = x + width/2;
146       cy = y + height/2;
147       final int radius = width/2;
148 
149       int initAngle=90;
150       int sweepAngle=0;
151       int incSweepAngle=0;
152       int incLabelAngle= (int) (angle[0]/2);
153 
154       for (int i=0; i < columns; i++) {
155          sweepAngle = (int) Math.round(angle[i]);
156          g.setColor((Color)colors[i]);
157 
158          if (i==(columns-1)){
159             sweepAngle = 360 - incSweepAngle;
160             g.fillArc(x,y,width,height,initAngle,(-sweepAngle));
161             g.setColor(Color.black);
162             g.drawArc(x,y,width,height,initAngle,(-sweepAngle));
163 
164             if (showLabel){
165                lx = (int) (cx + (radius * Math.cos((incLabelAngle * 3.14f/180) - 3.14f/2)));
166                ly = (int) (cy + (radius * Math.sin((incLabelAngle * 3.14f/180) - 3.14f/2)));
167                adjustLabel(i);  // modify lx, ly
168                g.drawString((String)labels[i],lx,ly);
169             }
170             if (showPercent){
171                final int px = (int) (cx + ((radius*2/3) * Math.cos((incLabelAngle * 3.14f/180) - 3.14f/2)));
172                final int py = (int) (cy + ((radius*2/3) * Math.sin((incLabelAngle * 3.14f/180) - 3.14f/2)));
173                g.drawString(String.valueOf(Math.round(percent[i]))+"%",px,py); 
174             }
175             break;
176          }
177 
178          g.fillArc(x,y,width,height,initAngle,(-sweepAngle));
179          g.setColor(Color.black);
180          g.drawArc(x,y,width,height,initAngle,(-sweepAngle));
181          incSweepAngle +=sweepAngle;
182 
183          //  Black line from center to Peripherial
184          final int ax = (int) (cx + (radius * Math.cos((incSweepAngle * 3.14f/180) - 3.14f/2)));
185          final int ay = (int) (cy + (radius * Math.sin((incSweepAngle * 3.14f/180) - 3.14f/2)));
186          g.drawLine(cx,cy,ax,ay);
187 
188          if (showLabel){
189             lx = (int) (cx + (radius * Math.cos((incLabelAngle * 3.14f/180) - 3.14f/2)));
190             ly = (int) (cy + (radius * Math.sin((incLabelAngle * 3.14f/180) - 3.14f/2)));
191             adjustLabel(i);  // modify lx, ly
192             g.drawString((String)labels[i],lx,ly);
193          }
194          if (showPercent){
195             final int px = (int) (cx + ((radius*2/3) * Math.cos((incLabelAngle * 3.14f/180) - 3.14f/2)));
196             final int py = (int) (cy + ((radius*2/3) * Math.sin((incLabelAngle * 3.14f/180) - 3.14f/2)));
197             final int strWidth = fontMetrics.stringWidth(Math.round(percent[i])+"%");
198             g.drawString(String.valueOf(Math.round(percent[i]))+"%",(px - strWidth/2),py);
199          }
200 
201          incLabelAngle = incLabelAngle + (int) (angle[i]/2 + angle[i+1]/2);
202          initAngle += (-sweepAngle);
203       }
204       g.setColor(Color.black);
205       g.drawLine(cx,cy,cx,cy-radius);
206    }
207 
208    private void adjustLabel(int i){
209       if ( (lx > cx) && (ly < cy) ){
210          lx +=5; ly -=5;
211       }
212 
213       if ( (lx > cx) && (ly > cy) ){
214          lx +=5; ly +=10;
215       }
216 
217       if ( (lx < cx) && (ly > cy) ){
218          strWidth=fontMetrics.stringWidth(labels[i]);
219          lx -= strWidth+5;
220          if (lx < 0) lx=0;
221       }
222 
223       if ( (lx < cx) && (ly < cy) ){
224          strWidth=fontMetrics.stringWidth(labels[i]);
225          lx -= strWidth+5;
226          if (lx < 0) lx=0;
227       }
228    }
229 
230 }