/* * @(#)CPieChartUI.java 0.0.1 99/07/29 * * Copyright (c) 1999 by Willie Wheeler. All rights reserved. */ package stats.plaf.concrete; import java.awt.*; import javax.swing.*; import javax.swing.plaf.*; import stats.*; import stats.plaf.*; /** * @version 0.0.1 07/29/99 * @author Willie Wheeler */ public class CPieChartUI extends PieChartUI { protected static final int PAD = 5; protected static final double DEG_TO_RAD = Math.PI / 180.0; protected static ComponentUI ui = new CPieChartUI(); public static ComponentUI createUI(JComponent c) { return ui; } public void installUI(JComponent c) { c.setOpaque(false); } public void uninstallUI(JComponent c) { } public void paint(Graphics g, JComponent c) { PieChart chart = (PieChart)c; int numStates = chart.getNumStates(); int chartWidth = chart.getSize().width; int chartHeight = chart.getSize().height; int centerX = chartWidth / 2; int centerY = chartHeight / 2; int radius = (centerX < centerY ? chartWidth : chartHeight) / 2 - PAD; int cornerX = centerX - radius; int cornerY = centerY - radius; FontMetrics fm = g.getFontMetrics(); int fontAscent = fm.getAscent(); // Compute the sum of the values. double sum = 0.0; for (int i = 0; i < numStates; i++) { sum += chart.getStateValue(i); } // Compute the start angles and arc angles. double[] startAngles = new double[numStates]; double[] arcAngles = new double[numStates]; startAngles[0] = 0.0; arcAngles[0] = (chart.getStateValue(0) * 360.0) / sum; for (int i = 1; i < numStates; i++) { startAngles[i] = startAngles[i-1] + arcAngles[i-1]; arcAngles[i] = (chart.getStateValue(i) * 360.0) / sum; } // Paint the pie slices. for (int i = 0; i < numStates; i++) { g.setColor(chart.getStateColor(i)); g.fillArc(cornerX, cornerY, 2*radius, 2*radius, (int)Math.floor(startAngles[i]), (int)Math.ceil(arcAngles[i])); // We draw this part of the outline here because doing so makes // a better fit than drawing a circle afterwards--don't ask me // why. g.setColor(Color.black); g.drawArc(cornerX, cornerY, 2*radius, 2*radius, (int)Math.floor(startAngles[i]), (int)Math.ceil(arcAngles[i])); } // Paint the value labels. We use a separate loop so that the labels // aren't obscured by the pie slices. for (int i = 0; i < numStates; i++) { String label = chart.getStateValueAsString(i); int labelWidth = fm.stringWidth(label); double midAngle = (startAngles[i] + 0.5 * arcAngles[i]) * DEG_TO_RAD; int labelX = centerX + (int)(0.75 * radius * Math.cos(midAngle)) - labelWidth/2; int labelY = centerY - (int)(0.75 * radius * Math.sin(midAngle)) + fontAscent/2; // Clear a little background space. g.setColor(Color.white); for (int j = -2; j <= 2; j++) { for (int k = -1; k <= 1; k++) { g.drawString(label, labelX + j, labelY + k); } } // And draw the label. g.setColor(Color.black); g.drawString(label, labelX, labelY); } } }