    001    /* ===========================================================
    002     * JFreeChart : a free chart library for the Java(tm) platform
    003     * ===========================================================
    004     *
    005     * (C) Copyright 2000-2005, 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-2005, 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.2 2005/12/01 20:33:26 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     *
    060     */
    061
    062    package org.jfree.chart.renderer.category;
    063
    064    import java.awt.Graphics2D;
    065    import java.awt.Paint;
    066    import java.awt.Stroke;
    067    import java.awt.geom.Rectangle2D;
    068    import java.io.Serializable;
    069
    070    import org.jfree.chart.axis.CategoryAxis;
    071    import org.jfree.chart.axis.ValueAxis;
    072    import org.jfree.chart.entity.CategoryItemEntity;
    073    import org.jfree.chart.entity.EntityCollection;
    074    import org.jfree.chart.labels.CategoryItemLabelGenerator;
    075    import org.jfree.chart.labels.CategoryToolTipGenerator;
    076    import org.jfree.chart.plot.CategoryPlot;
    077    import org.jfree.chart.plot.PlotOrientation;
    078    import org.jfree.data.category.CategoryDataset;
    079    import org.jfree.data.category.IntervalCategoryDataset;
    080    import org.jfree.ui.RectangleEdge;
    081    import org.jfree.util.PublicCloneable;
    082
    083    /**
    084     * A renderer that handles the drawing of bars for a bar plot where
    085     * each bar has a high and low value.
    086     * <p>
    087     * For use with the {@link CategoryPlot} class.
    088     *
    089     * @author Jeremy Bowman
    090     */
    091    public class IntervalBarRenderer extends BarRenderer
    092                                     implements CategoryItemRenderer,
    093                                                Cloneable,
    094                                                PublicCloneable,
    095                                                Serializable {
    096
    097        /** For serialization. */
    098        private static final long serialVersionUID = -5068857361615528725L;
    099
    100        /**
    101         * Constructs a new renderer.
    102         */
    103        public IntervalBarRenderer() {
    104            super();
    105        }
    106
    107        /**
    108         * Draws the bar for a single (series, category) data item.
    109         *
    110         * @param g2  the graphics device.
    111         * @param state  the renderer state.
    112         * @param dataArea  the data area.
    113         * @param plot  the plot.
    114         * @param domainAxis  the domain axis.
    115         * @param rangeAxis  the range axis.
    116         * @param dataset  the dataset.
    117         * @param row  the row index (zero-based).
    118         * @param column  the column index (zero-based).
    119         * @param pass  the pass index.
    120         */
    121        public void drawItem(Graphics2D g2,
    122                             CategoryItemRendererState state,
    123                             Rectangle2D dataArea,
    124                             CategoryPlot plot,
    125                             CategoryAxis domainAxis,
    126                             ValueAxis rangeAxis,
    127                             CategoryDataset dataset,
    128                             int row,
    129                             int column,
    130                             int pass) {
    131
    132             if (dataset instanceof IntervalCategoryDataset) {
    133                 IntervalCategoryDataset d = (IntervalCategoryDataset) dataset;
    134                 drawInterval(
    135                     g2, state, dataArea, plot, domainAxis, rangeAxis,
    136                     d, row, column
    137                 );
    138             }
    139             else {
    140                 super.drawItem(
    141                     g2, state, dataArea, plot, domainAxis, rangeAxis,
    142                     dataset, row, column, pass
    143                 );
    144             }
    145
    146         }
    147
    148         /**
    149          * Draws a single interval.
    150          *
    151          * @param g2  the graphics device.
    152          * @param state  the renderer state.
    153          * @param dataArea  the data plot area.
    154          * @param plot  the plot.
    155          * @param domainAxis  the domain axis.
    156          * @param rangeAxis  the range axis.
    157          * @param dataset  the data.
    158          * @param row  the row index (zero-based).
    159          * @param column  the column index (zero-based).
    160          */
    161         protected void drawInterval(Graphics2D g2,
    162                                     CategoryItemRendererState state,
    163                                     Rectangle2D dataArea,
    164                                     CategoryPlot plot,
    165                                     CategoryAxis domainAxis,
    166                                     ValueAxis rangeAxis,
    167                                     IntervalCategoryDataset dataset,
    168                                     int row,
    169                                     int column) {
    170
    171            int seriesCount = getRowCount();
    172            int categoryCount = getColumnCount();
    173
    174            PlotOrientation orientation = plot.getOrientation();
    175
    176            double rectX = 0.0;
    177            double rectY = 0.0;
    178
    179            RectangleEdge domainAxisLocation = plot.getDomainAxisEdge();
    180            RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge();
    181
    182            // Y0
    183            Number value0 = dataset.getEndValue(row, column);
    184            if (value0 == null) {
    185                return;
    186            }
    187            double java2dValue0 = rangeAxis.valueToJava2D(
    188                value0.doubleValue(), dataArea, rangeAxisLocation
    189            );
    190
    191            // Y1
    192            Number value1 = dataset.getStartValue(row, column);
    193            if (value1 == null) {
    194                return;
    195            }
    196            double java2dValue1 = rangeAxis.valueToJava2D(
    197                value1.doubleValue(), dataArea, rangeAxisLocation
    198            );
    199
    200            if (java2dValue1 < java2dValue0) {
    201                double temp = java2dValue1;
    202                java2dValue1 = java2dValue0;
    203                java2dValue0 = temp;
    204                Number tempNum = value1;
    205                value1 = value0;
    206                value0 = tempNum;
    207            }
    208
    209            // BAR WIDTH
    210            double rectWidth = state.getBarWidth();
    211
    212            // BAR HEIGHT
    213            double rectHeight = Math.abs(java2dValue1 - java2dValue0);
    214
    215            if (orientation == PlotOrientation.HORIZONTAL) {
    216                // BAR Y
    217                rectY = domainAxis.getCategoryStart(
    218                    column, getColumnCount(), dataArea, domainAxisLocation
    219                );
    220                if (seriesCount > 1) {
    221                    double seriesGap = dataArea.getHeight() * getItemMargin()
    222                                       / (categoryCount * (seriesCount - 1));
    223                    rectY = rectY + row * (state.getBarWidth() + seriesGap);
    224                }
    225                else {
    226                    rectY = rectY + row * state.getBarWidth();
    227                }
    228
    229                rectX = java2dValue0;
    230
    231                rectHeight = state.getBarWidth();
    232                rectWidth = Math.abs(java2dValue1 - java2dValue0);
    233
    234            }
    235            else if (orientation == PlotOrientation.VERTICAL) {
    236                // BAR X
    237                rectX = domainAxis.getCategoryStart(
    238                    column, getColumnCount(), dataArea, domainAxisLocation
    239                );
    240
    241                if (seriesCount > 1) {
    242                    double seriesGap = dataArea.getWidth() * getItemMargin()
    243                                       / (categoryCount * (seriesCount - 1));
    244                    rectX = rectX + row * (state.getBarWidth() + seriesGap);
    245                }
    246                else {
    247                    rectX = rectX + row * state.getBarWidth();
    248                }
    249
    250                rectY = java2dValue0;
    251
    252            }
    253            Rectangle2D bar = new Rectangle2D.Double(
    254                rectX, rectY, rectWidth, rectHeight
    255            );
    256            Paint seriesPaint = getItemPaint(row, column);
    257            g2.setPaint(seriesPaint);
    258            g2.fill(bar);
    259
    260            // draw the outline...
    261            if (state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) {
    262                Stroke stroke = getItemOutlineStroke(row, column);
    263                Paint paint = getItemOutlinePaint(row, column);
    264                if (stroke != null && paint != null) {
    265                    g2.setStroke(stroke);
    266                    g2.setPaint(paint);
    267                    g2.draw(bar);
    268                }
    269            }
    270
    271            CategoryItemLabelGenerator generator
    272                = getItemLabelGenerator(row, column);
    273            if (generator != null && isItemLabelVisible(row, column)) {
    274                drawItemLabel(
    275                    g2, dataset, row, column, plot, generator, bar, false
    276                );
    277            }
    278
    279            // collect entity and tool tip information...
    280            if (state.getInfo() != null) {
    281                EntityCollection entities = state.getEntityCollection();
    282                if (entities != null) {
    283                    String tip = null;
    284                    CategoryToolTipGenerator tipster
    285                        = getToolTipGenerator(row, column);
    286                    if (tipster != null) {
    287                        tip = tipster.generateToolTip(dataset, row, column);
    288                    }
    289                    String url = null;
    290                    if (getItemURLGenerator(row, column) != null) {
    291                        url = getItemURLGenerator(row, column).generateURL(
    292                            dataset, row, column
    293                        );
    294                    }
    295                    CategoryItemEntity entity = new CategoryItemEntity(
    296                        bar, tip, url, dataset, row,
    297                        dataset.getColumnKey(column), column
    298                    );
    299                    entities.add(entity);
    300                }
    301            }
    302
    303        }
    304
    305    }