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();
    }

}
