import java.awt.*;

/**
  * PercentDial is a custom component that takes a value between 0.0 and 
  * 1.0 (inclusive) and displays the corresponding fraction of a circle
  * with a filled arc.
  */
public class PercentDial extends Canvas {
	private static	int	DEFPIXBORDER = 3;  // static val needed in constructors

	private boolean clockwise 	= true; // default to sweep in the cw direction
	private int 	zeroAngle 	= 90;   // posn on unit circle for "no angle"
	private double 	currFrac	= 0.0;  // current fraction of dial to be done

	private int		diameter	= 24;	// diameter of circle
	private int 	pixelBorder = DEFPIXBORDER; // pixels on all four borders

	private Color	usedColor	= Color.blue; // color for filled arc
	private Color	unusedColor	= Color.white;  // color for unused arc
	private Color	outlineColor= Color.black; // color for outline

	/** 
	  * Constructor which takes the width of the component (and incidentally
	  * the height) in pixels and the thickness of the border in pixels.
	  * The diameter of the circle will be: width - 2*border pixels.
	  */
	public PercentDial(int totalWidth, int pixelBorder) {
		this.pixelBorder = pixelBorder;
		diameter = totalWidth - 2 * pixelBorder;
	}

	/**
	  * Contructor which assumes the default border thickness.
	  */
	public PercentDial(int totalWidth) {
		this(totalWidth, DEFPIXBORDER);
	}

	/**
	  * The total width of the component in pixels.
	  */
	public int getWidth() {
		return (diameter + 2 * pixelBorder);
	}

	/**
	  * The total height of the component in pixels.
	  */
	public int getHeight() {
		return (diameter + 2 * pixelBorder);
	}

	/** 
	  * Overrides Component.getPreferredSize to return the preferred
	  * size of the Percent Dial.
	  */
	public Dimension getPreferredSize() {
		return (new Dimension(getWidth(), getHeight()) );
	}

	/** 
	  * Overrides Component.getMinimumSize to return the minimum
	  * size of the Percent Dial.
	  */
	public Dimension getMinimumSize() {
		return getPreferredSize();
	}

	/**
	  *  Still here for backward 1.0 compat
	  */
	public Dimension preferredSize() {  // for backward 1.0 compat
		return getPreferredSize();
	}

	/**
	  *  Still here for backward 1.0 compat
	  */
	public Dimension minimumSize() {  // for backward 1.0 compat
		return getPreferredSize();
	}

	/**
	  * Sets the fill color for the portion of the circle which shows the
	  * fraction used.
	  */
	public void setUsedColor(Color c) {
		usedColor = c;
	}

	/**
	  * Sets the fill color for the portion of the circle which shows the
	  * fraction which is not used.
	  */
	public void setUnusedColor(Color c) {
		unusedColor = c;
	}

	/**
	  * Sets the color for the outline of the circle.
	  */
	public void setOutlineColor(Color c) {
		outlineColor = c;
	}

	/**
	  * Returns the fill color for the portion of the circle which shows the
	  * fraction used.
	  */
	public Color getUsedColor() {
		return usedColor;
	}

	/**
	  * Returns the fill color for the portion of the circle which shows the
	  * fraction which is not used.
	  */
	public Color getUnusedColor() {
		return unusedColor;
	}

	/**
	  * Returns the color for the outline of the circle.
	  */
	public Color getOutlineColor() {
		return outlineColor;
	}

	/**
	  * Overrides paint() method to draw the percent dial.
	  */
	public void paint(Graphics g) {
		int degreesToFill = (int)Math.round(currFrac * 360.0);

		if ( clockwise ) {
			degreesToFill = -degreesToFill;
		}

		// color unused section as a filled circle first
		g.setColor(unusedColor);
		g.fillOval(pixelBorder, pixelBorder, diameter, diameter);

		// fill in the proper part of the arc based on currFrac
		g.setColor(usedColor);
		g.fillArc(pixelBorder, pixelBorder, diameter, diameter, 
			zeroAngle, degreesToFill);

		// provide a solid outline for circle
		g.setColor(outlineColor);
		g.drawOval(pixelBorder, pixelBorder, diameter, diameter);

	}

	/**
	  * Update the percent dial to show a new fraction of the circle.
	  * The currFrac value should be in the range 0.0 to 1.0 (inclusive).
	  */
	public void setCurrFrac(double currFrac) {
		// if currFrac is out of range, use the closest extreme
		this.currFrac = Math.min(Math.max(currFrac, 0.0), 1.0);
		repaint();
	}

}
