import java.awt.Rectangle;
import java.awt.Point;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;

import java.util.Vector;
import java.util.Enumeration;

// Based on code by Philip David Meese for creating
// a bar chart component

public class BarChart extends Canvas {

    private Vector dataSet = null;
    private int margin = 5; // Margin for component
    private int separation = 2; // space between bars
    private Color barFillColor = Color.blue;
    private Color barBorderColor = Color.black;
    private Font captionFont = null;
    private int captionSeparation = 5;

    public BarChart(Vector listOfNumbers,
                    Color fill, Color border) 
    {
        dataSet = listOfNumbers;
        //reshape(0,0,w,h);
        barFillColor = fill;
        barBorderColor = border;
        captionFont = new Font("Helvetica", Font.BOLD, 12);
    }

    public BarChart(Vector listOfNumbers) {
        this(listOfNumbers, Color.blue, Color.black);
    }

    public void setBarFillColor(Color c) {
        barFillColor = c;
    } 

    public Color getBarFillColor() { return barFillColor; }

    public void setBarBorderColor(Color c) {
        barBorderColor = c;
    } 

    public Color getBarBorderColor() { return barBorderColor; }

    public void setDataSet(Vector listOfNumbers) {
        dataSet = (Vector)listOfNumbers.clone();
        repaint();
    }

    public int getMargin() { return margin; }

    public void setMargin(int m) { margin = m; }

    public int getSeparation() { return separation; }
 
    public void setSeparation(int s) { separation = s; }

    public Vector getDataSet() { return ((Vector)dataSet.clone()); }

    public void paint(Graphics g) {
        paintBackground(g, Color.white);
        if (dataSet.size() > 0) {
            paintBars(g, barFillColor, barBorderColor);
        }
    }

    private void paintBackground(Graphics g, Color c) {

        Rectangle r = bounds();
        Color cSave = g.getColor(); // we remember color for resetting
        g.setColor(c);
        g.fillRect(0,0,r.width, r.height);
        g.setColor(cSave);
    }

    private void paintBars(Graphics g, Color cFill, Color cBorder) {
        Color cSave = g.getColor(); // we remember color for resetting
        Rectangle r = bounds();

        // Get the height of the font
        FontMetrics fm = g.getFontMetrics(captionFont);
        int fontHeight = fm.getHeight();
        int fontAscent = fm.getAscent();

        // width and height of rendered area
        int renderWidth = r.width - margin * 2 - (dataSet.size() - 1)
                * separation;

        // Since we will draw the value below the bar, we need the
        // the fontHeight in there
        int renderHeight = r.height - margin * 2
               - fontAscent - captionSeparation;


        int barWidth = renderWidth/dataSet.size();

        // We need a scaling factor so values fit in a given height
        float max = 0;
        for (Enumeration e = dataSet.elements(); e.hasMoreElements();) {
            float value = ((Float)e.nextElement()).floatValue();
            if (value > max) max = value;
        }

        float scalingFactor = (float)renderHeight / max;

        // The following actually makes the bars
        Point barOrigin = new Point(margin, margin);
        for (Enumeration e = dataSet.elements(); e.hasMoreElements();) {
            float value = ((Float)e.nextElement()).floatValue();
            int barHeight = (int) (value * scalingFactor);
 
            // Remember the shapes draw relative to a top left corner... so
            // we need to readjust the origin
            barOrigin.y = margin + renderHeight - barHeight;
            g.setColor(cBorder);
            g.drawRect(barOrigin.x, barOrigin.y, barWidth - separation,
                 barHeight);

            int stringX = barOrigin.x;
            int stringY = margin + renderHeight + fontAscent +
                            captionSeparation;
            g.drawString((new Float(value)).toString(), stringX, stringY);

            g.setColor(cFill);
            g.fillRect(barOrigin.x+1, barOrigin.y+1, barWidth -
                 separation - 1, barHeight - 1);

            barOrigin.x += barWidth + separation;
        } // End of making bars

        g.setColor(cSave);
    } // end of paintBars        

} // end of BarChart class


