Java tutorial
/** * * 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.] * * ------------ * LineGraphDrawable.java * ------------ */ import java.awt.Color; import java.awt.Graphics2D; import java.awt.geom.Line2D; import java.awt.geom.Rectangle2D; /** * A very fast and very simple line-graph drawable. This code is based on the * LineGraph 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 LineGraphDrawable { private static final int DEFAULT_SPACING = 2; private int spacing; private Color color; private Color background; private Number[] data; /** * Creates a default bargraph drawable with some sensible default colors and * spacings. */ public LineGraphDrawable() { this.color = Color.black; this.spacing = 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 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 graphics * the graphics context on which the bargraph should be rendered. * @param drawArea * the area on which the bargraph should be drawn. */ public void draw(final Graphics2D graphics, final Rectangle2D drawArea) { if (graphics == null) { throw new NullPointerException(); } if (drawArea == null) { throw new NullPointerException(); } final int height = (int) drawArea.getHeight(); if (height <= 0) { return; } final Graphics2D g2 = (Graphics2D) graphics.create(); if (background != null) { g2.setPaint(background); g2.draw(drawArea); } if (data == null || data.length == 0) { g2.dispose(); return; } g2.translate(drawArea.getX(), drawArea.getY()); float d = getDivisor(data, height); final int spacing = getSpacing(); final int w = (((int) drawArea.getWidth()) - (spacing * (data.length - 1))) / (data.length - 1); float min = Float.MAX_VALUE; for (int index = 0; index < data.length; index++) { Number i = data[index]; if (i == null) { continue; } final float value = i.floatValue(); if (value < min) { min = value; } } int x = 0; int y = -1; if (d == 0.0) { // special case -- a horizontal straight line d = 1.0f; y = -height / 2; } final Line2D.Double line = new Line2D.Double(); for (int i = 0; i < data.length - 1; i++) { final int px1 = x; x += (w + spacing); final int px2 = x; g2.setPaint(color); final Number number = data[i]; final Number nextNumber = data[i + 1]; if (number == null && nextNumber == null) { final float delta = height - ((0 - min) / d); line.setLine(px1, y + delta, px2, y + delta); } else if (number == null) { line.setLine(px1, y + (height - ((0 - min) / d)), px2, y + (height - ((nextNumber.floatValue() - min) / d))); } else if (nextNumber == null) { line.setLine(px1, y + (height - ((number.floatValue() - min) / d)), px2, y + (height - ((0 - min) / d))); } else { line.setLine(px1, y + (height - ((number.floatValue() - min) / d)), px2, y + (height - ((nextNumber.floatValue() - min) / d))); } g2.draw(line); } g2.dispose(); } /** * 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); } }