    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     * XYDotRenderer.java
    029     * ------------------
    030     * (C) Copyright 2002-2007, by Object Refinery Limited.
    031     *
    032     * Original Author:  David Gilbert (for Object Refinery Limited);
    033     * Contributor(s):   Christian W. Zuckschwerdt;
    034     *
    035     * $Id: XYDotRenderer.java,v 1.5.2.4 2007/02/06 16:29:11 mungady Exp $
    036     *
    037     * Changes (from 29-Oct-2002)
    038     * --------------------------
    039     * 29-Oct-2002 : Added standard header (DG);
    040     * 25-Mar-2003 : Implemented Serializable (DG);
    041     * 01-May-2003 : Modified drawItem() method signature (DG);
    042     * 30-Jul-2003 : Modified entity constructor (CZ);
    043     * 20-Aug-2003 : Implemented Cloneable and PublicCloneable (DG);
    044     * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
    045     * 25-Feb-2004 : Replaced CrosshairInfo with CrosshairState (DG);
    046     * 19-Jan-2005 : Now uses only primitives from dataset (DG);
    047     * ------------- JFREECHART 1.0.x ---------------------------------------------
    048     * 10-Jul-2006 : Added dotWidth and dotHeight attributes (DG);
    049     * 06-Feb-2007 : Fixed bug 1086307, crosshairs with multiple axes (DG);
    050     *
    051     */
    052
    053    package org.jfree.chart.renderer.xy;
    054
    055    import java.awt.Graphics2D;
    056    import java.awt.geom.Rectangle2D;
    057    import java.io.Serializable;
    058
    059    import org.jfree.chart.axis.ValueAxis;
    060    import org.jfree.chart.event.RendererChangeEvent;
    061    import org.jfree.chart.plot.CrosshairState;
    062    import org.jfree.chart.plot.PlotOrientation;
    063    import org.jfree.chart.plot.PlotRenderingInfo;
    064    import org.jfree.chart.plot.XYPlot;
    065    import org.jfree.data.xy.XYDataset;
    066    import org.jfree.ui.RectangleEdge;
    067    import org.jfree.util.PublicCloneable;
    068
    069    /**
    070     * A renderer that draws a small dot at each data point for an {@link XYPlot}.
    071     */
    072    public class XYDotRenderer extends AbstractXYItemRenderer
    073                               implements XYItemRenderer,
    074                                          Cloneable,
    075                                          PublicCloneable,
    076                                          Serializable {
    077
    078        /** For serialization. */
    079        private static final long serialVersionUID = -2764344339073566425L;
    080
    081        /** The dot width. */
    082        private int dotWidth;
    083
    084        /** The dot height. */
    085        private int dotHeight;
    086
    087        /**
    088         * Constructs a new renderer.
    089         */
    090        public XYDotRenderer() {
    091            super();
    092            this.dotWidth = 1;
    093            this.dotHeight = 1;
    094        }
    095
    096        /**
    097         * Returns the dot width (the default value is 1).
    098         *
    099         * @return The dot width.
    100         *
    101         * @since 1.0.2
    102         * @see #setDotWidth(int)
    103         */
    104        public int getDotWidth() {
    105            return this.dotWidth;
    106        }
    107
    108        /**
    109         * Sets the dot width and sends a {@link RendererChangeEvent} to all
    110         * registered listeners.
    111         *
    112         * @param w  the new width (must be greater than zero).
    113         *
    114         * @throws IllegalArgumentException if <code>w</code> is less than one.
    115         *
    116         * @since 1.0.2
    117         * @see #getDotWidth()
    118         */
    119        public void setDotWidth(int w) {
    120            if (w < 1) {
    121                throw new IllegalArgumentException("Requires w > 0.");
    122            }
    123            this.dotWidth = w;
    124            notifyListeners(new RendererChangeEvent(this));
    125        }
    126
    127        /**
    128         * Returns the dot height (the default value is 1).
    129         *
    130         * @return The dot height.
    131         *
    132         * @since 1.0.2
    133         * @see #setDotHeight(int)
    134         */
    135        public int getDotHeight() {
    136            return this.dotHeight;
    137        }
    138
    139        /**
    140         * Sets the dot height and sends a {@link RendererChangeEvent} to all
    141         * registered listeners.
    142         *
    143         * @param h  the new height (must be greater than zero).
    144         *
    145         * @throws IllegalArgumentException if <code>h</code> is less than one.
    146         *
    147         * @since 1.0.2
    148         * @see #getDotHeight()
    149         */
    150        public void setDotHeight(int h) {
    151            if (h < 1) {
    152                throw new IllegalArgumentException("Requires h > 0.");
    153            }
    154            this.dotHeight = h;
    155            notifyListeners(new RendererChangeEvent(this));
    156        }
    157
    158        /**
    159         * Draws the visual representation of a single data item.
    160         *
    161         * @param g2  the graphics device.
    162         * @param state  the renderer state.
    163         * @param dataArea  the area within which the data is being drawn.
    164         * @param info  collects information about the drawing.
    165         * @param plot  the plot (can be used to obtain standard color
    166         *              information etc).
    167         * @param domainAxis  the domain (horizontal) axis.
    168         * @param rangeAxis  the range (vertical) axis.
    169         * @param dataset  the dataset.
    170         * @param series  the series index (zero-based).
    171         * @param item  the item index (zero-based).
    172         * @param crosshairState  crosshair information for the plot
    173         *                        (<code>null</code> permitted).
    174         * @param pass  the pass index.
    175         */
    176        public void drawItem(Graphics2D g2,
    177                             XYItemRendererState state,
    178                             Rectangle2D dataArea,
    179                             PlotRenderingInfo info,
    180                             XYPlot plot,
    181                             ValueAxis domainAxis,
    182                             ValueAxis rangeAxis,
    183                             XYDataset dataset,
    184                             int series,
    185                             int item,
    186                             CrosshairState crosshairState,
    187                             int pass) {
    188
    189            // get the data point...
    190            double x = dataset.getXValue(series, item);
    191            double y = dataset.getYValue(series, item);
    192            double adjx = (this.dotWidth - 1) / 2.0;
    193            double adjy = (this.dotHeight - 1) / 2.0;
    194            if (!Double.isNaN(y)) {
    195                RectangleEdge xAxisLocation = plot.getDomainAxisEdge();
    196                RectangleEdge yAxisLocation = plot.getRangeAxisEdge();
    197                double transX = domainAxis.valueToJava2D(x, dataArea,
    198                        xAxisLocation) - adjx;
    199                double transY = rangeAxis.valueToJava2D(y, dataArea, yAxisLocation)
    200                        - adjy;
    201
    202                g2.setPaint(getItemPaint(series, item));
    203                PlotOrientation orientation = plot.getOrientation();
    204                if (orientation == PlotOrientation.HORIZONTAL) {
    205                    g2.fillRect((int) transY, (int) transX, this.dotHeight,
    206                            this.dotWidth);
    207                }
    208                else if (orientation == PlotOrientation.VERTICAL) {
    209                    g2.fillRect((int) transX, (int) transY, this.dotWidth,
    210                            this.dotHeight);
    211                }
    212
    213                int domainAxisIndex = plot.getDomainAxisIndex(domainAxis);
    214                int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis);
    215                updateCrosshairValues(crosshairState, x, y, domainAxisIndex,
    216                        rangeAxisIndex, transX, transY, orientation);
    217            }
    218
    219        }
    220
    221        /**
    222         * Tests this renderer for equality with an arbitrary object.  This method
    223         * returns <code>true</code> if and only if:
    224         *
    225         * <ul>
    226         * <li><code>obj</code> is not <code>null</code>;</li>
    227         * <li><code>obj</code> is an instance of <code>XYDotRenderer</code>;</li>
    228         * <li>both renderers have the same attribute values.
    229         * </ul>
    230         *
    231         * @param obj  the object (<code>null</code> permitted).
    232         *
    233         * @return A boolean.
    234         */
    235        public boolean equals(Object obj) {
    236            if (obj == this) {
    237                return true;
    238            }
    239            if (!(obj instanceof XYDotRenderer)) {
    240                return false;
    241            }
    242            XYDotRenderer that = (XYDotRenderer) obj;
    243            if (this.dotWidth != that.dotWidth) {
    244                return false;
    245            }
    246            if (this.dotHeight != that.dotHeight) {
    247                return false;
    248            }
    249            return super.equals(obj);
    250        }
    251
    252        /**
    253         * Returns a clone of the renderer.
    254         *
    255         * @return A clone.
    256         *
    257         * @throws CloneNotSupportedException  if the renderer cannot be cloned.
    258         */
    259        public Object clone() throws CloneNotSupportedException {
    260            return super.clone();
    261        }
    262
    263    }