bar-graph drawable : Chart « Advanced Graphics « Java






bar-graph drawable

  
/**
 * 
 * LibSparkline : a free Java sparkline chart library
 * 
 *
 * Project Info:  http://reporting.pentaho.org/libsparkline/
 *
 * (C) Copyright 2008, by Larry Ogrodnek, Pentaho Corporation and Contributors.
 *
 * This library is free software; you can redistribute it and/or modify it under the terms
 * of the Apache License 2.0.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the Apache License 2.0 along with this library;
 * if not, a online version is available at http://www.apache.org/licenses/
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
 * in the United States and other countries.]
 *
 * ------------
 * BarGraphDrawable.java
 * ------------
 */


import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;



/**
 * A very fast and very simple bar-graph drawable. This code is based on the BarGraph class writen by Larry Ogrodnek
 * but instead of producing a low-resolution image, this class writes the content into a Graphics2D context.  
 *
 * @author Thomas Morgner
 */
public class BarGraphDrawable
{
  private static final int DEFAULT_SPACING = 2;

  private static final Color DEFAULT_COLOR = Color.gray;
  private static final Color DEFAULT_HIGH_COLOR = Color.black;
  private static final Color DEFAULT_LAST_COLOR = Color.red;

  private Number[] data;
  private Color color;
  private Color highColor;
  private Color lastColor;
  private Color background;
  private int spacing;

  /**
   * Creates a default bargraph drawable with some sensible default colors and spacings.
   */
  public BarGraphDrawable()
  {
    this.highColor = BarGraphDrawable.DEFAULT_HIGH_COLOR;
    this.lastColor = BarGraphDrawable.DEFAULT_LAST_COLOR;
    this.color = BarGraphDrawable.DEFAULT_COLOR;
    this.spacing = BarGraphDrawable.DEFAULT_SPACING;
  }

  /**
   * Returns the numeric data for the drawable or null, if the drawable has no data.
   *
   * @return the data.
   */
  public Number[] getData()
  {
    return data;
  }

  /**
   * Defines the numeric data for the drawable or null, if the drawable has no data.
   *
   * @param data the data (can be null).
   */
  public void setData(final Number[] data)
  {
    this.data = data;
  }

  /**
   * Returns the main color for the bars.
   *
   * @return the main color for the bars, never null.
   */
  public Color getColor()
  {
    return color;
  }

  /**
   * Defines the main color for the bars.
   *
   * @param color the main color for the bars, never null.
   */
  public void setColor(final Color color)
  {
    if (color == null)
    {
      throw new NullPointerException();
    }
    this.color = color;
  }

  /**
   * Returns the color for the highest bars. This property is optional and the high-color can be null.
   *
   * @return the color for the higest bars, or null if high bars should not be marked specially.
   */
  public Color getHighColor()
  {
    return highColor;
  }

  /**
   * Defines the color for the highest bars. This property is optional and the high-color can be null.
   *
   * @param highColor the color for the higest bars, or null if high bars should not be marked specially.
   */
  public void setHighColor(final Color highColor)
  {
    this.highColor = highColor;
  }

  /**
   * Returns the color for the last bar. This property is optional and the last-bar-color can be null.
   *
   * @return the color for the last bar in the graph, or null if last bars should not be marked specially.
   */
  public Color getLastColor()
  {
    return lastColor;
  }

  /**
   * Defines the color for the last bar. This property is optional and the last-bar-color can be null.
   *
   * @param lastColor the color for the last bar in the graph, or null if last bars should not be marked specially.
   */
  public void setLastColor(final Color lastColor)
  {
    this.lastColor = lastColor;
  }

  /**
   * Returns the color for the background of the graph. This property can be null, in which case the bar
   * will have a transparent background.
   *
   * @return color for the background or null, if the graph has a transparent background color.
   */
  public Color getBackground()
  {
    return background;
  }

  /**
   * Defines the color for the background of the graph. This property can be null, in which case the bar
   * will have a transparent background.
   *
   * @param background the background or null, if the graph has a transparent background color.
   */
  public void setBackground(final Color background)
  {
    this.background = background;
  }

  /**
   * Returns the spacing between the bars.
   *
   * @return the spacing between the bars.
   */
  public int getSpacing()
  {
    return spacing;
  }

  /**
   * Defines the spacing between the bars.
   *
   * @param spacing the spacing between the bars.
   */
  public void setSpacing(final int spacing)
  {
    this.spacing = spacing;
  }

  /**
   * Draws the bar-graph into the given Graphics2D context in the given area. This method will not draw a graph
   * if the data given is null or empty.
   *
   * @param g2 the graphics context on which the bargraph should be rendered. 
   * @param drawArea the area on which the bargraph should be drawn.
   */
  public void draw(Graphics2D g2, Rectangle2D drawArea)
  {
    if (g2 == null)
    {
      throw new NullPointerException();
    }
    if (drawArea == null)
    {
      throw new NullPointerException();
    }

    final int height = (int) drawArea.getHeight();
    if (height <= 0)
    {
      return;
    }
    
    Graphics2D g = (Graphics2D) g2.create();
    g.translate(drawArea.getX(), drawArea.getY());
    if (background != null)
    {
      g.setBackground(background);
      g.clearRect(0, 0, (int) drawArea.getWidth(), height);
    }

    if (data == null || data.length == 0)
    {
      g.dispose();
      return;
    }

    final float d = getDivisor(data, height);

    final int a = computeAverage(data);
    final int spacing1 = getSpacing();
    final int w = ((int) drawArea.getWidth() - (spacing1 * data.length)) / data.length;

    int x = 0;
    final int y = 0;

    final double vHeight = drawArea.getHeight();
    final Rectangle2D.Double bar = new Rectangle2D.Double();
    
    for (int index = 0; index < data.length; index++)
    {
      Number i = data[index];
      if (i == null)
      {
        continue;
      }
      
      final int h = (int) (i.floatValue() / d);

      final int intVal = i.intValue();
      if (index == (data.length - 1) && lastColor != null)
      {
        g.setPaint(lastColor);
      }
      else if (intVal < a || (highColor == null))
      {
        g.setPaint(color);
      }
      else
      {
        g.setPaint(highColor);
      }

      bar.setRect(x, y + (vHeight - h), w, intVal / d);
      g.fill(bar);
      x += (w + spacing1);
    }

    g.dispose();
  }

  /**
   * Computes the average for all numbers in the array.
   *
   * @param data the numbers for which the average should be computed.
   * @return the average.
   */
  private static int computeAverage(final Number[] data)
  {
    int total = 0;
    int length = 0;
    for (int index = 0; index < data.length; index++)
    {
      Number i = data[index];
      if (i == null)
      {
        continue;
      }

      total += i.intValue();
      length += 1;
    }

    return (total / length);
  }

  /**
   * Computes the scale factor to scale the given numeric data into the target
   * height.
   * 
   * @param data
   *          the numeric data.
   * @param height
   *          the target height of the graph.
   * @return the scale factor.
   */
  public static float getDivisor(final Number[] data, final int height) {
    if (data == null) {
      throw new NullPointerException("Data array must not be null.");
    }

    if (height < 1) {
      throw new IndexOutOfBoundsException("Height must be greater or equal to 1");
    }

    float max = Float.MIN_VALUE;
    float min = Float.MAX_VALUE;

    for (int index = 0; index < data.length; index++) {
      Number i = data[index];
      if (i == null) {
        continue;
      }

      final float numValue = i.floatValue();
      if (numValue < min) {
        min = numValue;
      }
      if (numValue > max) {
        max = numValue;
      }
    }

    if (max <= min) {
      return 1.0f;
    }
    if (height == 1) {
      return 0;
    }
    return (max - min) / (height - 1);
  }

}

   
    
  








Related examples in the same category

1.Chart based on Graph libraryChart based on Graph library
2.Scroll ChartScroll Chart
3.Animation Line ChartAnimation Line Chart
4.Pie ChartPie Chart
5.A rudimentary chart libraryA rudimentary chart library
6.A rudimentary bar chart classA rudimentary bar chart class