    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     * XYStepRenderer.java
    029     * -------------------
    030     * (C) Copyright 2002-2005, by Roger Studner and Contributors.
    031     *
    032     * Original Author:  Roger Studner;
    033     * Contributor(s):   David Gilbert (for Object Refinery Limited);
    034     *                   Matthias Rose;
    035     *
    036     * $Id: XYStepRenderer.java,v 1.7.2.3 2005/12/02 11:59:43 mungady Exp $
    037     *
    038     * Changes
    039     * -------
    040     * 13-May-2002 : Version 1, contributed by Roger Studner (DG);
    041     * 25-Jun-2002 : Updated import statements (DG);
    042     * 22-Jul-2002 : Added check for null data items (DG);
    043     * 25-Mar-2003 : Implemented Serializable (DG);
    044     * 01-May-2003 : Modified drawItem() method signature (DG);
    045     * 20-Aug-2003 : Implemented Cloneable and PublicCloneable (DG);
    046     * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
    047     * 28-Oct-2003 : Added tooltips, code contributed by Matthias Rose
    048     *               (RFE 824857) (DG);
    049     * 10-Feb-2004 : Removed working line (use line from state object instead) (DG);
    050     * 25-Feb-2004 : Replaced CrosshairInfo with CrosshairState.  Renamed
    051     *               XYToolTipGenerator --> XYItemLabelGenerator (DG);
    052     * 19-Jan-2005 : Now accesses only primitives from dataset (DG);
    053     * 15-Mar-2005 : Fix silly bug in drawItem() method (DG);
    054     * 19-Sep-2005 : Extend XYLineAndShapeRenderer (fixes legend shapes), added
    055     *               support for series visibility, and use getDefaultEntityRadius()
    056     *               for entity hotspot size (DG);
    057     *
    058     */
    059
    060    package org.jfree.chart.renderer.xy;
    061
    062    import java.awt.Graphics2D;
    063    import java.awt.Paint;
    064    import java.awt.Shape;
    065    import java.awt.Stroke;
    066    import java.awt.geom.Line2D;
    067    import java.awt.geom.Rectangle2D;
    068    import java.io.Serializable;
    069
    070    import org.jfree.chart.axis.ValueAxis;
    071    import org.jfree.chart.entity.EntityCollection;
    072    import org.jfree.chart.entity.XYItemEntity;
    073    import org.jfree.chart.labels.XYToolTipGenerator;
    074    import org.jfree.chart.plot.CrosshairState;
    075    import org.jfree.chart.plot.PlotOrientation;
    076    import org.jfree.chart.plot.PlotRenderingInfo;
    077    import org.jfree.chart.plot.XYPlot;
    078    import org.jfree.chart.urls.XYURLGenerator;
    079    import org.jfree.data.xy.XYDataset;
    080    import org.jfree.ui.RectangleEdge;
    081    import org.jfree.util.PublicCloneable;
    082
    083    /**
    084     * Line/Step item renderer for an {@link XYPlot}.  This class draws lines
    085     * between data points, only allowing horizontal or vertical lines (steps).
    086     *
    087     * @author Roger Studner
    088     */
    089    public class XYStepRenderer extends XYLineAndShapeRenderer
    090                                implements XYItemRenderer,
    091                                           Cloneable,
    092                                           PublicCloneable,
    093                                           Serializable {
    094
    095        /** For serialization. */
    096        private static final long serialVersionUID = -8918141928884796108L;
    097
    098        /**
    099         * Constructs a new renderer with no tooltip or URL generation.
    100         */
    101        public XYStepRenderer() {
    102            this(null, null);
    103        }
    104
    105        /**
    106         * Constructs a new renderer.
    107         *
    108         * @param toolTipGenerator  the item label generator.
    109         * @param urlGenerator  the URL generator.
    110         */
    111        public XYStepRenderer(XYToolTipGenerator toolTipGenerator,
    112                              XYURLGenerator urlGenerator) {
    113            super();
    114            setBaseToolTipGenerator(toolTipGenerator);
    115            setURLGenerator(urlGenerator);
    116            setShapesVisible(false);
    117        }
    118
    119        /**
    120         * Draws the visual representation of a single data item.
    121         *
    122         * @param g2  the graphics device.
    123         * @param state  the renderer state.
    124         * @param dataArea  the area within which the data is being drawn.
    125         * @param info  collects information about the drawing.
    126         * @param plot  the plot (can be used to obtain standard color
    127         *              information etc).
    128         * @param domainAxis  the domain axis.
    129         * @param rangeAxis  the vertical axis.
    130         * @param dataset  the dataset.
    131         * @param series  the series index (zero-based).
    132         * @param item  the item index (zero-based).
    133         * @param crosshairState  crosshair information for the plot
    134         *                        (<code>null</code> permitted).
    135         * @param pass  the pass index (ignored here).
    136         */
    137        public void drawItem(Graphics2D g2,
    138                             XYItemRendererState state,
    139                             Rectangle2D dataArea,
    140                             PlotRenderingInfo info,
    141                             XYPlot plot,
    142                             ValueAxis domainAxis,
    143                             ValueAxis rangeAxis,
    144                             XYDataset dataset,
    145                             int series,
    146                             int item,
    147                             CrosshairState crosshairState,
    148                             int pass) {
    149
    150            // do nothing if item is not visible
    151            if (!getItemVisible(series, item)) {
    152                return;
    153            }
    154
    155            PlotOrientation orientation = plot.getOrientation();
    156
    157            Paint seriesPaint = getItemPaint(series, item);
    158            Stroke seriesStroke = getItemStroke(series, item);
    159            g2.setPaint(seriesPaint);
    160            g2.setStroke(seriesStroke);
    161
    162            // get the data point...
    163            double x1 = dataset.getXValue(series, item);
    164            double y1 = dataset.getYValue(series, item);
    165            if (Double.isNaN(y1)) {
    166                return;
    167            }
    168
    169            RectangleEdge xAxisLocation = plot.getDomainAxisEdge();
    170            RectangleEdge yAxisLocation = plot.getRangeAxisEdge();
    171            double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation);
    172            double transY1 = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation);
    173
    174            if (item > 0) {
    175                // get the previous data point...
    176                double x0 = dataset.getXValue(series, item - 1);
    177                double y0 = dataset.getYValue(series, item - 1);
    178                if (!Double.isNaN(y0)) {
    179                    double transX0 = domainAxis.valueToJava2D(x0, dataArea,
    180                            xAxisLocation);
    181                    double transY0 = rangeAxis.valueToJava2D(y0, dataArea,
    182                            yAxisLocation);
    183
    184                    Line2D line = state.workingLine;
    185                    if (orientation == PlotOrientation.HORIZONTAL) {
    186                        if (transY0 == transY1) { //this represents the situation
    187                                                  // for drawing a horizontal bar.
    188                            line.setLine(transY0, transX0, transY1, transX1);
    189                            g2.draw(line);
    190                        }
    191                        else {  //this handles the need to perform a 'step'.
    192                            line.setLine(transY0, transX0, transY1, transX0);
    193                            g2.draw(line);
    194                            line.setLine(transY1, transX0, transY1, transX1);
    195                            g2.draw(line);
    196                        }
    197                    }
    198                    else if (orientation == PlotOrientation.VERTICAL) {
    199                        if (transY0 == transY1) { // this represents the situation
    200                                                  // for drawing a horizontal bar.
    201                            line.setLine(transX0, transY0, transX1, transY1);
    202                            g2.draw(line);
    203                        }
    204                        else {  //this handles the need to perform a 'step'.
    205                            line.setLine(transX0, transY0, transX1, transY0);
    206                            g2.draw(line);
    207                            line.setLine(transX1, transY0, transX1, transY1);
    208                            g2.draw(line);
    209                        }
    210                    }
    211
    212                }
    213            }
    214
    215            updateCrosshairValues(crosshairState, x1, y1, transX1, transY1,
    216                    orientation);
    217
    218            // collect entity and tool tip information...
    219            if (state.getInfo() != null) {
    220                EntityCollection entities = state.getEntityCollection();
    221                if (entities != null) {
    222                    int r = getDefaultEntityRadius();
    223                    Shape shape = orientation == PlotOrientation.VERTICAL
    224                        ? new Rectangle2D.Double(transX1 - r, transY1 - r, 2 * r,
    225                                2 * r)
    226                        : new Rectangle2D.Double(transY1 - r, transX1 - r, 2 * r,
    227                                2 * r);
    228                    if (shape != null) {
    229                        String tip = null;
    230                        XYToolTipGenerator generator
    231                            = getToolTipGenerator(series, item);
    232                        if (generator != null) {
    233                            tip = generator.generateToolTip(dataset, series, item);
    234                        }
    235                        String url = null;
    236                        if (getURLGenerator() != null) {
    237                            url = getURLGenerator().generateURL(dataset, series,
    238                                    item);
    239                        }
    240                        XYItemEntity entity = new XYItemEntity(shape, dataset,
    241                                series, item, tip, url);
    242                        entities.add(entity);
    243                    }
    244                }
    245            }
    246        }
    247
    248        /**
    249         * Returns a clone of the renderer.
    250         *
    251         * @return A clone.
    252         *
    253         * @throws CloneNotSupportedException  if the renderer cannot be cloned.
    254         */
    255        public Object clone() throws CloneNotSupportedException {
    256            return super.clone();
    257        }
    258
    259    }