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