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