    001    /* ===========================================================
    002     * JFreeChart : a free chart library for the Java(tm) platform
    003     * ===========================================================
    004     *
    005     * (C) Copyright 2000-2009, by Object Refinery Limited 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     * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
    025     * in the United States and other countries.]
    026     *
    027     * ------------------------
    028     * IntervalBarRenderer.java
    029     * ------------------------
    030     * (C) Copyright 2002-2009, by Jeremy Bowman.
    031     *
    032     * Original Author:  Jeremy Bowman;
    033     * Contributor(s):   David Gilbert (for Object Refinery Limited);
    034     *                   Christian W. Zuckschwerdt;
    035     *                   Peter Kolb (patch 2497611);
    036     *
    037     * Changes
    038     * -------
    039     * 29-Apr-2002 : Version 1, contributed by Jeremy Bowman (DG);
    040     * 11-May-2002 : Use CategoryPlot.getLabelsVisible() (JB);
    041     * 29-May-2002 : Added constructors (DG);
    042     * 26-Jun-2002 : Added axis to initialise method (DG);
    043     * 20-Sep-2002 : Added basic support for chart entities (DG);
    044     * 24-Oct-2002 : Amendments for changes in CategoryDataset interface and
    045     *               CategoryToolTipGenerator interface (DG);
    046     * 05-Nov-2002 : Base dataset is now TableDataset not CategoryDataset (DG);
    047     * 25-Mar-2003 : Implemented Serializable (DG);
    048     * 30-Jul-2003 : Modified entity constructor (CZ);
    049     * 19-Aug-2003 : Implemented Cloneable and PublicCloneable (DG);
    050     * 08-Sep-2003 : Added checks for null values (DG);
    051     * 07-Oct-2003 : Added renderer state (DG);
    052     * 21-Oct-2003 : Bar width moved into renderer state (DG);
    053     * 23-Dec-2003 : Removed the deprecated MultiIntervalCategoryDataset
    054     *               interface (DG);
    055     * 05-Nov-2004 : Modified drawItem() signature (DG);
    056     * 20-Apr-2005 : Renamed CategoryLabelGenerator
    057     *               --> CategoryItemLabelGenerator (DG);
    058     * 02-Feb-2007 : Removed author tags all over JFreeChart sources (DG);
    059     * 24-Jun-2008 : Added new barPainter mechanism (DG);
    060     * 07-Oct-2008 : Override equals() method to fix minor bug (DG);
    061     * 14-Jan-2009 : Added support for seriesVisible flags (PK);
    062     *
    063     */
    064
    065    package org.jfree.chart.renderer.category;
    066
    067    import java.awt.Graphics2D;
    068    import java.awt.geom.Rectangle2D;
    069
    070    import org.jfree.chart.axis.CategoryAxis;
    071    import org.jfree.chart.axis.ValueAxis;
    072    import org.jfree.chart.entity.EntityCollection;
    073    import org.jfree.chart.labels.CategoryItemLabelGenerator;
    074    import org.jfree.chart.plot.CategoryPlot;
    075    import org.jfree.chart.plot.PlotOrientation;
    076    import org.jfree.data.category.CategoryDataset;
    077    import org.jfree.data.category.IntervalCategoryDataset;
    078    import org.jfree.ui.RectangleEdge;
    079
    080    /**
    081     * A renderer that handles the drawing of bars for a bar plot where
    082     * each bar has a high and low value.  This renderer is for use with the
    083     * {@link CategoryPlot} class.  The example shown here is generated by the
    084     * <code>IntervalBarChartDemo1.java</code> program included in the JFreeChart
    085     * Demo Collection:
    086     * <br><br>
    087     * <img src="../../../../../images/IntervalBarRendererSample.png"
    088     * alt="IntervalBarRendererSample.png" />
    089     */
    090    public class IntervalBarRenderer extends BarRenderer {
    091
    092        /** For serialization. */
    093        private static final long serialVersionUID = -5068857361615528725L;
    094
    095        /**
    096         * Constructs a new renderer.
    097         */
    098        public IntervalBarRenderer() {
    099            super();
    100        }
    101
    102        /**
    103         * Draws the bar for a single (series, category) data item.
    104         *
    105         * @param g2  the graphics device.
    106         * @param state  the renderer state.
    107         * @param dataArea  the data area.
    108         * @param plot  the plot.
    109         * @param domainAxis  the domain axis.
    110         * @param rangeAxis  the range axis.
    111         * @param dataset  the dataset.
    112         * @param row  the row index (zero-based).
    113         * @param column  the column index (zero-based).
    114         * @param pass  the pass index.
    115         */
    116        public void drawItem(Graphics2D g2,
    117                             CategoryItemRendererState state,
    118                             Rectangle2D dataArea,
    119                             CategoryPlot plot,
    120                             CategoryAxis domainAxis,
    121                             ValueAxis rangeAxis,
    122                             CategoryDataset dataset,
    123                             int row,
    124                             int column,
    125                             int pass) {
    126
    127             if (dataset instanceof IntervalCategoryDataset) {
    128                 IntervalCategoryDataset d = (IntervalCategoryDataset) dataset;
    129                 drawInterval(g2, state, dataArea, plot, domainAxis, rangeAxis,
    130                         d, row, column);
    131             }
    132             else {
    133                 super.drawItem(g2, state, dataArea, plot, domainAxis, rangeAxis,
    134                         dataset, row, column, pass);
    135             }
    136
    137         }
    138
    139         /**
    140          * Draws a single interval.
    141          *
    142          * @param g2  the graphics device.
    143          * @param state  the renderer state.
    144          * @param dataArea  the data plot area.
    145          * @param plot  the plot.
    146          * @param domainAxis  the domain axis.
    147          * @param rangeAxis  the range axis.
    148          * @param dataset  the data.
    149          * @param row  the row index (zero-based).
    150          * @param column  the column index (zero-based).
    151          */
    152         protected void drawInterval(Graphics2D g2,
    153                                     CategoryItemRendererState state,
    154                                     Rectangle2D dataArea,
    155                                     CategoryPlot plot,
    156                                     CategoryAxis domainAxis,
    157                                     ValueAxis rangeAxis,
    158                                     IntervalCategoryDataset dataset,
    159                                     int row,
    160                                     int column) {
    161
    162            int visibleRow = state.getVisibleSeriesIndex(row);
    163            if (visibleRow < 0) {
    164                return;
    165            }
    166            int seriesCount = state.getVisibleSeriesCount() >= 0
    167                    ? state.getVisibleSeriesCount() : getRowCount();
    168
    169            int categoryCount = getColumnCount();
    170
    171            PlotOrientation orientation = plot.getOrientation();
    172
    173            double rectX = 0.0;
    174            double rectY = 0.0;
    175
    176            RectangleEdge domainAxisLocation = plot.getDomainAxisEdge();
    177            RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge();
    178
    179            // Y0
    180            Number value0 = dataset.getEndValue(row, column);
    181            if (value0 == null) {
    182                return;
    183            }
    184            double java2dValue0 = rangeAxis.valueToJava2D(value0.doubleValue(),
    185                    dataArea, rangeAxisLocation);
    186
    187            // Y1
    188            Number value1 = dataset.getStartValue(row, column);
    189            if (value1 == null) {
    190                return;
    191            }
    192            double java2dValue1 = rangeAxis.valueToJava2D(
    193                    value1.doubleValue(), dataArea, rangeAxisLocation);
    194
    195            if (java2dValue1 < java2dValue0) {
    196                double temp = java2dValue1;
    197                java2dValue1 = java2dValue0;
    198                java2dValue0 = temp;
    199                Number tempNum = value1;
    200                value1 = value0;
    201                value0 = tempNum;
    202            }
    203
    204            // BAR WIDTH
    205            double rectWidth = state.getBarWidth();
    206
    207            // BAR HEIGHT
    208            double rectHeight = Math.abs(java2dValue1 - java2dValue0);
    209
    210            RectangleEdge barBase = RectangleEdge.LEFT;
    211            if (orientation == PlotOrientation.HORIZONTAL) {
    212                // BAR Y
    213                rectY = domainAxis.getCategoryStart(column, getColumnCount(),
    214                        dataArea, domainAxisLocation);
    215                if (seriesCount > 1) {
    216                    double seriesGap = dataArea.getHeight() * getItemMargin()
    217                                       / (categoryCount * (seriesCount - 1));
    218                    rectY = rectY + visibleRow * (state.getBarWidth() + seriesGap);
    219                }
    220                else {
    221                    rectY = rectY + visibleRow * state.getBarWidth();
    222                }
    223
    224                rectX = java2dValue0;
    225
    226                rectHeight = state.getBarWidth();
    227                rectWidth = Math.abs(java2dValue1 - java2dValue0);
    228                barBase = RectangleEdge.LEFT;
    229            }
    230            else if (orientation == PlotOrientation.VERTICAL) {
    231                // BAR X
    232                rectX = domainAxis.getCategoryStart(column, getColumnCount(),
    233                        dataArea, domainAxisLocation);
    234
    235                if (seriesCount > 1) {
    236                    double seriesGap = dataArea.getWidth() * getItemMargin()
    237                                       / (categoryCount * (seriesCount - 1));
    238                    rectX = rectX + visibleRow * (state.getBarWidth() + seriesGap);
    239                }
    240                else {
    241                    rectX = rectX + visibleRow * state.getBarWidth();
    242                }
    243
    244                rectY = java2dValue0;
    245                barBase = RectangleEdge.BOTTOM;
    246            }
    247            Rectangle2D bar = new Rectangle2D.Double(rectX, rectY, rectWidth,
    248                    rectHeight);
    249            BarPainter painter = getBarPainter();
    250            if (getShadowsVisible()) {
    251                painter.paintBarShadow(g2, this, row, column, bar, barBase, false);
    252            }
    253            getBarPainter().paintBar(g2, this, row, column, bar, barBase);
    254
    255            CategoryItemLabelGenerator generator = getItemLabelGenerator(row,
    256                    column);
    257            if (generator != null && isItemLabelVisible(row, column)) {
    258                drawItemLabel(g2, dataset, row, column, plot, generator, bar,
    259                        false);
    260            }
    261
    262            // add an item entity, if this information is being collected
    263            EntityCollection entities = state.getEntityCollection();
    264            if (entities != null) {
    265                addItemEntity(entities, dataset, row, column, bar);
    266            }
    267
    268        }
    269
    270        /**
    271         * Tests this renderer for equality with an arbitrary object.
    272         *
    273         * @param obj  the object (<code>null</code> permitted).
    274         *
    275         * @return A boolean.
    276         */
    277        public boolean equals(Object obj) {
    278            if (obj == this) {
    279                return true;
    280            }
    281            if (!(obj instanceof IntervalBarRenderer)) {
    282                return false;
    283            }
    284            // there are no fields to check
    285            return super.equals(obj);
    286        }
    287
    288    }