001: /*
002: JOpenChart Java Charting Library and Toolkit
003: Copyright (C) 2001 Sebastian Müller
004: http://jopenchart.sourceforge.net
005:
006: This library is free software; you can redistribute it and/or
007: modify it under the terms of the GNU Lesser General Public
008: License as published by the Free Software Foundation; either
009: version 2.1 of the License, or (at your option) any later version.
010:
011: This library is distributed in the hope that it will be useful,
012: but WITHOUT ANY WARRANTY; without even the implied warranty of
013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: Lesser General Public License for more details.
015:
016: You should have received a copy of the GNU Lesser General Public
017: License along with this library; if not, write to the Free Software
018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019:
020: BarChartRenderer.java
021: Created on 31. October 2001, 12:32
022: */
023:
024: package de.progra.charting.render;
025:
026: import java.awt.Color;
027: import java.awt.Font;
028: import java.awt.Graphics2D;
029: import java.awt.geom.AffineTransform;
030: import java.awt.geom.Point2D;
031: import java.awt.geom.Rectangle2D;
032: import java.awt.font.LineMetrics;
033: import java.awt.font.FontRenderContext;
034: import java.text.DecimalFormat;
035: import de.progra.charting.PointToPixelTranslator;
036: import de.progra.charting.CoordSystem;
037: import de.progra.charting.model.ChartDataModel;
038: import de.progra.charting.model.ChartDataModelConstraints;
039:
040: /**
041: * This renderer creates a BarChart. This will only work on a ChartDataModel
042: * with non-numeric x-axis values, because I couldn't make any sense out of
043: * a bar chart with a numeric x-axis like in a line chart.
044: * @author mueller
045: * @version 1.0
046: */
047: public class BarChartRenderer extends AbstractChartRenderer {
048: protected DecimalFormat barTopFormat;
049: protected float boxWidth = 1.0f;
050: protected Font barTopFont;
051:
052: /** Creates new BarChartRenderer
053: * @param cs the CoordSystem used to translate into pixel space
054: * @param model the DataModel that should be rendered
055: */
056: public BarChartRenderer(CoordSystem cs, ChartDataModel model) {
057: super (cs, model);
058: }
059:
060: /** Creates new BarChartRenderer
061: * @param cs the CoordSystem used to translate into pixel space
062: * @param model the DataModel that should be rendered
063: * @param topFormat if not null, the values that each box represents will be
064: * printed at the top of the box.
065: * @param boxWidth a value between 0.0 and 1.0 representing how much of the
066: * alloted space each box should consume. If 1.0 is passed, then each box will
067: * completely fill it's allotted space, alternately I suggest you don't pass 0.0
068: */
069: public BarChartRenderer(CoordSystem cs, ChartDataModel model,
070: DecimalFormat topFormat, Font topFont, float boxWidth) {
071: super (cs, model);
072: barTopFormat = topFormat;
073: this .barTopFont = topFont;
074: this .boxWidth = boxWidth;
075: }
076:
077: /** Finally renders the Object in the Graphics object.
078: * @param g the Graphics2D object in which to render
079: */
080: public void renderChart(Graphics2D g) {
081: ChartDataModel m = getChartDataModel();
082: ChartDataModelConstraints con = m
083: .getChartDataModelConstraints(CoordSystem.FIRST_YAXIS);
084:
085: if (m.isColumnNumeric())
086: return;
087:
088: RowColorModel rcm = getRowColorModel();
089: AffineTransform yaxis1 = getTransform(CoordSystem.FIRST_YAXIS);
090: AffineTransform yaxis2 = getTransform(CoordSystem.SECOND_YAXIS);
091:
092: int datasetcount = m.getDataSetNumber();
093:
094: Point2D point1 = yaxis1.transform(new Point2D.Float((float) con
095: .getMinimumColumnValue(), con.getMaximumValue()
096: .floatValue()), null);
097: Point2D point2 = yaxis1.transform(new Point2D.Float((float) con
098: .getMaximumColumnValue(), con.getMaximumValue()
099: .floatValue()), null);
100: Point2D value = point1;
101:
102: int dataunitwidth = (int) ((point2.getX() - point1.getX()) / con
103: .getMaximumColumnValue());
104: int boxwidth = (int) (dataunitwidth * boxWidth / datasetcount);
105: float margin = (float) (dataunitwidth * ((1.0 - boxWidth) / 2f));
106:
107: Point2D pointzero;
108: if (con.getMinimumValue().floatValue() > 0)
109: pointzero = yaxis1.transform(new Point2D.Float((float) con
110: .getMinimumColumnValue(), con.getMinimumValue()
111: .floatValue()), null);
112: else if (con.getMaximumValue().floatValue() < 0)
113: pointzero = yaxis1.transform(new Point2D.Float((float) con
114: .getMinimumColumnValue(), con.getMaximumValue()
115: .floatValue()), null);
116: else
117: pointzero = yaxis1.transform(new Point2D.Float((float) con
118: .getMinimumColumnValue(), 0f), null);
119:
120: FontRenderContext columnTopfrc = null;
121: LineMetrics lm = null;
122: DecimalFormat df = null;
123: Rectangle2D fontRec = null;
124: String columnTop = null;
125: if (barTopFormat != null) {
126: g.setFont(barTopFont);
127: columnTopfrc = new FontRenderContext(null, false, false);
128: }
129: /* We paint the values starting at x-value "0".
130: * As we only render BarCharts for ChartDataModels with
131: * non-numeric x-axis values we don't have to read those
132: * values from the data model. You can look in
133: * ObjectChartDataModel to see, how the x-axis bounds
134: * are defined: the minimum value is always 0, the maximum
135: * value is the amount of non-numeric x-axis values.
136: */
137: for (int i = 0; i < datasetcount; i++) {
138: //System.out.println("** DataSet "+i);
139:
140: for (int j = 0; j < m.getDataSetLength(i); j++) {
141: yaxis1.transform(new Point2D.Float((float) j, m
142: .getValueAt(i, j).floatValue()), value);
143:
144: Rectangle2D box = new Rectangle2D.Float((float) (value
145: .getX()
146: + margin + i * boxwidth), (float) Math.min(
147: value.getY(), pointzero.getY()),
148: (float) boxwidth, (float) Math.abs(pointzero
149: .getY()
150: - value.getY()));
151:
152: g.setColor(rcm.getColor(i));
153: g.fill(box);
154: g.setColor(Color.black);
155: g.draw(box);
156:
157: if (barTopFormat != null) {
158: //get value for zero'th set, index j
159: columnTop = barTopFormat.format(model.getValueAt(i,
160: j).doubleValue());
161: fontRec = barTopFont.getStringBounds(columnTop,
162: columnTopfrc);
163: lm = barTopFont.getLineMetrics(columnTop,
164: columnTopfrc);
165: g
166: .drawString(
167: columnTop,
168: (float) (value.getX() + i
169: * boxwidth + (boxwidth - fontRec
170: .getWidth()) / 2)
171: - lm.getLeading(),
172: (float) (Math.min(value.getY(),
173: pointzero.getY()) - lm
174: .getDescent()));
175: }
176: }
177: }
178: }//end render method
179:
180: }
|