001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-present, by David Gilbert and Contributors.
006 *
007 * Project Info:  http://www.jfree.org/jfreechart/index.html
008 *
009 * This library is free software; you can redistribute it and/or modify it
010 * under the terms of the GNU Lesser General Public License as published by
011 * the Free Software Foundation; either version 2.1 of the License, or
012 * (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but
015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017 * License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this library; if not, write to the Free Software
021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
022 * USA.
023 *
024 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 
025 * Other names may be trademarks of their respective owners.]
026 *
027 * ------------------------
028 * IntervalBarRenderer.java
029 * ------------------------
030 * (C) Copyright 2002-present, by Jeremy Bowman and Contributors.
031 *
032 * Original Author:  Jeremy Bowman;
033 * Contributor(s):   David Gilbert;
034 *                   Christian W. Zuckschwerdt;
035 *                   Peter Kolb (patch 2497611, 2791407);
036 *
037 */
038
039package org.jfree.chart.renderer.category;
040
041import java.awt.Graphics2D;
042import java.awt.geom.Rectangle2D;
043
044import org.jfree.chart.axis.CategoryAxis;
045import org.jfree.chart.axis.ValueAxis;
046import org.jfree.chart.entity.EntityCollection;
047import org.jfree.chart.labels.CategoryItemLabelGenerator;
048import org.jfree.chart.plot.CategoryPlot;
049import org.jfree.chart.plot.PlotOrientation;
050import org.jfree.chart.ui.RectangleEdge;
051import org.jfree.data.Range;
052import org.jfree.data.category.CategoryDataset;
053import org.jfree.data.category.IntervalCategoryDataset;
054
055/**
056 * A renderer that handles the drawing of bars for a bar plot where
057 * each bar has a high and low value.  This renderer is for use with the
058 * {@link CategoryPlot} class.  The example shown here is generated by the
059 * {@code IntervalBarChartDemo1.java} program included in the JFreeChart
060 * Demo Collection:
061 * <br><br>
062 * <img src="doc-files/IntervalBarRendererSample.png"
063 * alt="IntervalBarRendererSample.png">
064 */
065public class IntervalBarRenderer extends BarRenderer {
066
067    /** For serialization. */
068    private static final long serialVersionUID = -5068857361615528725L;
069
070    /**
071     * Constructs a new renderer.
072     */
073    public IntervalBarRenderer() {
074        super();
075    }
076
077    /**
078     * Returns the range of values from the specified dataset.  For this
079     * renderer, this is equivalent to calling
080     * {@code findRangeBounds(dataset, true)}.
081     *
082     * @param dataset  the dataset ({@code null} permitted).
083     *
084     * @return The range (or {@code null} if the dataset is
085     *         {@code null} or empty).
086     */
087    @Override
088    public Range findRangeBounds(CategoryDataset dataset) {
089        return findRangeBounds(dataset, true);
090    }
091
092    /**
093     * Draws the bar for a single (series, category) data item.
094     *
095     * @param g2  the graphics device.
096     * @param state  the renderer state.
097     * @param dataArea  the data area.
098     * @param plot  the plot.
099     * @param domainAxis  the domain axis.
100     * @param rangeAxis  the range axis.
101     * @param dataset  the dataset.
102     * @param row  the row index (zero-based).
103     * @param column  the column index (zero-based).
104     * @param pass  the pass index.
105     */
106    @Override
107    public void drawItem(Graphics2D g2, CategoryItemRendererState state,
108            Rectangle2D dataArea, CategoryPlot plot, CategoryAxis domainAxis,
109            ValueAxis rangeAxis, CategoryDataset dataset, int row, int column,
110            int pass) {
111
112         if (dataset instanceof IntervalCategoryDataset) {
113             IntervalCategoryDataset d = (IntervalCategoryDataset) dataset;
114             drawInterval(g2, state, dataArea, plot, domainAxis, rangeAxis,
115                     d, row, column);
116         } else {
117             super.drawItem(g2, state, dataArea, plot, domainAxis, rangeAxis,
118                     dataset, row, column, pass);
119         }
120
121     }
122
123     /**
124      * Draws a single interval.
125      *
126      * @param g2  the graphics device.
127      * @param state  the renderer state.
128      * @param dataArea  the data plot area.
129      * @param plot  the plot.
130      * @param domainAxis  the domain axis.
131      * @param rangeAxis  the range axis.
132      * @param dataset  the data.
133      * @param row  the row index (zero-based).
134      * @param column  the column index (zero-based).
135      */
136     protected void drawInterval(Graphics2D g2, CategoryItemRendererState state,
137            Rectangle2D dataArea, CategoryPlot plot, CategoryAxis domainAxis,
138            ValueAxis rangeAxis, IntervalCategoryDataset dataset, int row,
139                                 int column) {
140
141        int visibleRow = state.getVisibleSeriesIndex(row);
142        if (visibleRow < 0) {
143            return;
144        }
145
146        PlotOrientation orientation = plot.getOrientation();
147        double rectX = 0.0;
148        double rectY = 0.0;
149
150        RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge();
151
152        // Y0
153        Number value0 = dataset.getEndValue(row, column);
154        if (value0 == null) {
155            return;
156        }
157        double java2dValue0 = rangeAxis.valueToJava2D(value0.doubleValue(),
158                dataArea, rangeAxisLocation);
159
160        // Y1
161        Number value1 = dataset.getStartValue(row, column);
162        if (value1 == null) {
163            return;
164        }
165        double java2dValue1 = rangeAxis.valueToJava2D(
166                value1.doubleValue(), dataArea, rangeAxisLocation);
167
168        if (java2dValue1 < java2dValue0) {
169            double temp = java2dValue1;
170            java2dValue1 = java2dValue0;
171            java2dValue0 = temp;
172        }
173
174        // BAR WIDTH
175        double rectWidth = state.getBarWidth();
176
177        // BAR HEIGHT
178        double rectHeight = Math.abs(java2dValue1 - java2dValue0);
179
180        RectangleEdge barBase = RectangleEdge.LEFT;
181        if (orientation == PlotOrientation.HORIZONTAL) {
182            // BAR Y
183            rectX = java2dValue0;
184            rectY = calculateBarW0(getPlot(), orientation, dataArea, 
185                    domainAxis, state, visibleRow, column);
186            rectHeight = state.getBarWidth();
187            rectWidth = Math.abs(java2dValue1 - java2dValue0);
188            barBase = RectangleEdge.LEFT;
189        } else if (orientation.isVertical()) {
190            // BAR X
191            rectX = calculateBarW0(getPlot(), orientation, dataArea, 
192                    domainAxis, state, visibleRow, column);
193            rectY = java2dValue0;
194            barBase = RectangleEdge.BOTTOM;
195        }
196        Rectangle2D bar = new Rectangle2D.Double(rectX, rectY, rectWidth,
197                rectHeight);
198        BarPainter painter = getBarPainter();
199        if (state.getElementHinting()) {
200            beginElementGroup(g2, dataset.getRowKey(row), 
201                    dataset.getColumnKey(column));
202        }
203        if (getShadowsVisible()) {
204            painter.paintBarShadow(g2, this, row, column, bar, barBase, false);
205        }
206        getBarPainter().paintBar(g2, this, row, column, bar, barBase);
207        if (state.getElementHinting()) {
208            endElementGroup(g2);
209        }
210
211        CategoryItemLabelGenerator generator = getItemLabelGenerator(row,
212                column);
213        if (generator != null && isItemLabelVisible(row, column)) {
214            drawItemLabel(g2, dataset, row, column, plot, generator, bar,
215                    false);
216        }
217
218        // add an item entity, if this information is being collected
219        EntityCollection entities = state.getEntityCollection();
220        if (entities != null) {
221            addItemEntity(entities, dataset, row, column, bar);
222        }
223
224    }
225
226    /**
227     * Tests this renderer for equality with an arbitrary object.
228     *
229     * @param obj  the object ({@code null} permitted).
230     *
231     * @return A boolean.
232     */
233    @Override
234    public boolean equals(Object obj) {
235        if (obj == this) {
236            return true;
237        }
238        if (!(obj instanceof IntervalBarRenderer)) {
239            return false;
240        }
241        // there are no fields to check
242        return super.equals(obj);
243    }
244
245}