001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2008, 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 * PlotRenderingInfo.java
029 * ----------------------
030 * (C) Copyright 2003-2008, by Object Refinery Limited.
031 *
032 * Original Author:  David Gilbert (for Object Refinery Limited);
033 * Contributor(s):   -;
034 *
035 * Changes
036 * -------
037 * 16-Sep-2003 : Version 1 (DG);
038 * 23-Sep-2003 : Added Javadocs (DG);
039 * 12-Nov-2004 : Added getSubplotCount() and findSubplot() methods (DG);
040 * 01-Nov-2005 : Made 'owner' non-transient to fix bug 1344048 (DG);
041 * ------------- JFREECHART 1.0.x ---------------------------------------------
042 * 01-Dec-2006 : Implemented clone() method properly (DG);
043 * 17-Apr-2007 : Fixed bug 1698965 (NPE in CombinedDomainXYPlot) (DG);
044 *
045 */
046
047package org.jfree.chart.plot;
048
049import java.awt.geom.Point2D;
050import java.awt.geom.Rectangle2D;
051import java.io.IOException;
052import java.io.ObjectInputStream;
053import java.io.ObjectOutputStream;
054import java.io.Serializable;
055import java.util.List;
056
057import org.jfree.chart.ChartRenderingInfo;
058import org.jfree.io.SerialUtilities;
059import org.jfree.util.ObjectUtilities;
060
061/**
062 * Stores information about the dimensions of a plot and its subplots.
063 */
064public class PlotRenderingInfo implements Cloneable, Serializable {
065
066    /** For serialization. */
067    private static final long serialVersionUID = 8446720134379617220L;
068
069    /** The owner of this info. */
070    private ChartRenderingInfo owner;
071
072    /** The plot area. */
073    private transient Rectangle2D plotArea;
074
075    /** The data area. */
076    private transient Rectangle2D dataArea;
077
078    /**
079     * Storage for the plot rendering info objects belonging to the subplots.
080     */
081    private List subplotInfo;
082
083    /**
084     * Creates a new instance.
085     *
086     * @param owner  the owner (<code>null</code> permitted).
087     */
088    public PlotRenderingInfo(ChartRenderingInfo owner) {
089        this.owner = owner;
090        this.dataArea = new Rectangle2D.Double();
091        this.subplotInfo = new java.util.ArrayList();
092    }
093
094    /**
095     * Returns the owner (as specified in the constructor).
096     *
097     * @return The owner (possibly <code>null</code>).
098     */
099    public ChartRenderingInfo getOwner() {
100        return this.owner;
101    }
102
103    /**
104     * Returns the plot area (in Java2D space).
105     *
106     * @return The plot area (possibly <code>null</code>).
107     *
108     * @see #setPlotArea(Rectangle2D)
109     */
110    public Rectangle2D getPlotArea() {
111        return this.plotArea;
112    }
113
114    /**
115     * Sets the plot area.
116     *
117     * @param area  the plot area (in Java2D space, <code>null</code>
118     *     permitted but discouraged)
119     *
120     * @see #getPlotArea()
121     */
122    public void setPlotArea(Rectangle2D area) {
123        this.plotArea = area;
124    }
125
126    /**
127     * Returns the plot's data area (in Java2D space).
128     *
129     * @return The data area (possibly <code>null</code>).
130     *
131     * @see #setDataArea(Rectangle2D)
132     */
133    public Rectangle2D getDataArea() {
134        return this.dataArea;
135    }
136
137    /**
138     * Sets the data area.
139     *
140     * @param area  the data area (in Java2D space, <code>null</code> permitted
141     *     but discouraged).
142     *
143     * @see #getDataArea()
144     */
145    public void setDataArea(Rectangle2D area) {
146        this.dataArea = area;
147    }
148
149    /**
150     * Returns the number of subplots (possibly zero).
151     *
152     * @return The subplot count.
153     */
154    public int getSubplotCount() {
155        return this.subplotInfo.size();
156    }
157
158    /**
159     * Adds the info for a subplot.
160     *
161     * @param info  the subplot info.
162     *
163     * @see #getSubplotInfo(int)
164     */
165    public void addSubplotInfo(PlotRenderingInfo info) {
166        this.subplotInfo.add(info);
167    }
168
169    /**
170     * Returns the info for a subplot.
171     *
172     * @param index  the subplot index.
173     *
174     * @return The info.
175     *
176     * @see #addSubplotInfo(PlotRenderingInfo)
177     */
178    public PlotRenderingInfo getSubplotInfo(int index) {
179        return (PlotRenderingInfo) this.subplotInfo.get(index);
180    }
181
182    /**
183     * Returns the index of the subplot that contains the specified
184     * (x, y) point (the "source" point).  The source point will usually
185     * come from a mouse click on a {@link org.jfree.chart.ChartPanel},
186     * and this method is then used to determine the subplot that
187     * contains the source point.
188     *
189     * @param source  the source point (in Java2D space, <code>null</code> not
190     * permitted).
191     *
192     * @return The subplot index (or -1 if no subplot contains
193     *         <code>source</code>).
194     */
195    public int getSubplotIndex(Point2D source) {
196        if (source == null) {
197            throw new IllegalArgumentException("Null 'source' argument.");
198        }
199        int subplotCount = getSubplotCount();
200        for (int i = 0; i < subplotCount; i++) {
201            PlotRenderingInfo info = getSubplotInfo(i);
202            Rectangle2D area = info.getDataArea();
203            if (area.contains(source)) {
204                return i;
205            }
206        }
207        return -1;
208    }
209
210    /**
211     * Tests this instance for equality against an arbitrary object.
212     *
213     * @param obj  the object (<code>null</code> permitted).
214     *
215     * @return A boolean.
216     */
217    public boolean equals(Object obj) {
218        if (this == obj) {
219            return true;
220        }
221        if (!(obj instanceof PlotRenderingInfo)) {
222            return false;
223        }
224        PlotRenderingInfo that = (PlotRenderingInfo) obj;
225        if (!ObjectUtilities.equal(this.dataArea, that.dataArea)) {
226            return false;
227        }
228        if (!ObjectUtilities.equal(this.plotArea, that.plotArea)) {
229            return false;
230        }
231        if (!ObjectUtilities.equal(this.subplotInfo, that.subplotInfo)) {
232            return false;
233        }
234        return true;
235    }
236
237    /**
238     * Returns a clone of this object.
239     *
240     * @return A clone.
241     *
242     * @throws CloneNotSupportedException if there is a problem cloning.
243     */
244    public Object clone() throws CloneNotSupportedException {
245        PlotRenderingInfo clone = (PlotRenderingInfo) super.clone();
246        if (this.plotArea != null) {
247            clone.plotArea = (Rectangle2D) this.plotArea.clone();
248        }
249        if (this.dataArea != null) {
250            clone.dataArea = (Rectangle2D) this.dataArea.clone();
251        }
252        clone.subplotInfo = new java.util.ArrayList(this.subplotInfo.size());
253        for (int i = 0; i < this.subplotInfo.size(); i++) {
254            PlotRenderingInfo info
255                    = (PlotRenderingInfo) this.subplotInfo.get(i);
256            clone.subplotInfo.add(info.clone());
257        }
258        return clone;
259    }
260
261    /**
262     * Provides serialization support.
263     *
264     * @param stream  the output stream.
265     *
266     * @throws IOException  if there is an I/O error.
267     */
268    private void writeObject(ObjectOutputStream stream) throws IOException {
269        stream.defaultWriteObject();
270        SerialUtilities.writeShape(this.dataArea, stream);
271        SerialUtilities.writeShape(this.plotArea, stream);
272    }
273
274    /**
275     * Provides serialization support.
276     *
277     * @param stream  the input stream.
278     *
279     * @throws IOException  if there is an I/O error.
280     * @throws ClassNotFoundException  if there is a classpath problem.
281     */
282    private void readObject(ObjectInputStream stream)
283            throws IOException, ClassNotFoundException {
284        stream.defaultReadObject();
285        this.dataArea = (Rectangle2D) SerialUtilities.readShape(stream);
286        this.plotArea = (Rectangle2D) SerialUtilities.readShape(stream);
287    }
288
289}