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