KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jfree > chart > renderer > StandardXYItemRenderer


1 /* ======================================
2  * JFreeChart : a free Java chart library
3  * ======================================
4  *
5  * Project Info: http://www.jfree.org/jfreechart/index.html
6  * Project Lead: David Gilbert (david.gilbert@object-refinery.com);
7  *
8  * (C) Copyright 2000-2003, by Object Refinery Limited and Contributors.
9  *
10  * This library is free software; you can redistribute it and/or modify it under the terms
11  * of the GNU Lesser General Public License as published by the Free Software Foundation;
12  * either version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
15  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License along with this
19  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20  * Boston, MA 02111-1307, USA.
21  *
22  * ---------------------------
23  * StandardXYItemRenderer.java
24  * ---------------------------
25  * (C) Copyright 2001-2003, by Object Refinery Limited and Contributors.
26  *
27  * Original Author: David Gilbert (for Object Refinery Limited);
28  * Contributor(s): Mark Watson (www.markwatson.com);
29  * Jonathan Nash;
30  * Andreas Schneider;
31  * Norbert Kiesel (for TBD Networks);
32  * Christian W. Zuckschwerdt;
33  * Bill Kelemen;
34  * Nicolas Brodu (for Astrium and EADS Corporate Research Center);
35  *
36  * $Id: StandardXYItemRenderer.java,v 1.30 2003/11/03 14:21:28 mungady Exp $
37  *
38  * Changes:
39  * --------
40  * 19-Oct-2001 : Version 1, based on code by Mark Watson (DG);
41  * 22-Oct-2001 : Renamed DataSource.java --> Dataset.java etc. (DG);
42  * 21-Dec-2001 : Added working line instance to improve performance (DG);
43  * 22-Jan-2002 : Added code to lock crosshairs to data points. Based on code by Jonathan Nash (DG);
44  * 23-Jan-2002 : Added DrawInfo parameter to drawItem(...) method (DG);
45  * 28-Mar-2002 : Added a property change listener mechanism so that the renderer no longer needs to
46  * be immutable (DG);
47  * 02-Apr-2002 : Modified to handle null values (DG);
48  * 09-Apr-2002 : Modified draw method to return void. Removed the translated zero from the
49  * drawItem method. Override the initialise() method to calculate it (DG);
50  * 13-May-2002 : Added code from Andreas Schneider to allow changing shapes/colors per item (DG);
51  * 24-May-2002 : Incorporated tooltips into chart entities (DG);
52  * 25-Jun-2002 : Removed redundant code (DG);
53  * 05-Aug-2002 : Incorporated URLs for HTML image maps into chart entities (RA);
54  * 08-Aug-2002 : Added discontinuous lines option contributed by Norbert Kiesel (DG);
55  * 20-Aug-2002 : Added user definable default values to be returned by protected methods unless
56  * overridden by a subclass (DG);
57  * 23-Sep-2002 : Updated for changes in the XYItemRenderer interface (DG);
58  * 02-Oct-2002 : Fixed errors reported by Checkstyle (DG);
59  * 25-Mar-2003 : Implemented Serializable (DG);
60  * 01-May-2003 : Modified drawItem(...) method signature (DG);
61  * 15-May-2003 : Modified to take into account the plot orientation (DG);
62  * 29-Jul-2003 : Amended code that doesn't compile with JDK 1.2.2 (DG);
63  * 30-Jul-2003 : Modified entity constructor (CZ);
64  * 20-Aug-2003 : Implemented Cloneable and PublicCloneable (DG);
65  * 24-Aug-2003 : Added null/NaN checks in drawItem (BK);
66  * 08-Sep-2003 : Fixed serialization (NB);
67  * 16-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
68  *
69  */

70
71 package org.jfree.chart.renderer;
72
73 import java.awt.Graphics2D JavaDoc;
74 import java.awt.Image JavaDoc;
75 import java.awt.Paint JavaDoc;
76 import java.awt.Point JavaDoc;
77 import java.awt.Shape JavaDoc;
78 import java.awt.Stroke JavaDoc;
79 import java.awt.geom.Line2D JavaDoc;
80 import java.awt.geom.Rectangle2D JavaDoc;
81 import java.io.IOException JavaDoc;
82 import java.io.ObjectInputStream JavaDoc;
83 import java.io.Serializable JavaDoc;
84
85 import org.jfree.chart.CrosshairInfo;
86 import org.jfree.chart.axis.ValueAxis;
87 import org.jfree.chart.entity.EntityCollection;
88 import org.jfree.chart.entity.XYItemEntity;
89 import org.jfree.chart.labels.StandardXYToolTipGenerator;
90 import org.jfree.chart.labels.XYToolTipGenerator;
91 import org.jfree.chart.plot.Plot;
92 import org.jfree.chart.plot.PlotOrientation;
93 import org.jfree.chart.plot.PlotRenderingInfo;
94 import org.jfree.chart.plot.XYPlot;
95 import org.jfree.chart.urls.XYURLGenerator;
96 import org.jfree.data.XYDataset;
97 import org.jfree.ui.RectangleEdge;
98 import org.jfree.util.BooleanList;
99 import org.jfree.util.PublicCloneable;
100
101 /**
102  * Standard item renderer for an {@link XYPlot}. This class can draw (a) shapes at
103  * each point, or (b) lines between points, or (c) both shapes and lines.
104  *
105  * @author David Gilbert
106  */

107 public class StandardXYItemRenderer extends AbstractXYItemRenderer implements XYItemRenderer,
108                                                                               Cloneable JavaDoc,
109                                                                               PublicCloneable,
110                                                                               Serializable JavaDoc {
111
112     /** Constant for the type of rendering (shapes only). */
113     public static final int SHAPES = 1;
114
115     /** Constant for the type of rendering (lines only). */
116     public static final int LINES = 2;
117
118     /** Constant for the type of rendering (shapes and lines). */
119     public static final int SHAPES_AND_LINES = SHAPES | LINES;
120
121     /** Constant for the type of rendering (images only). */
122     public static final int IMAGES = 4;
123
124     /** Constant for the type of rendering (discontinuous lines). */
125     public static final int DISCONTINUOUS = 8;
126
127     /** Constant for the type of rendering (discontinuous lines). */
128     public static final int DISCONTINUOUS_LINES = LINES | DISCONTINUOUS;
129
130     /** A flag indicating whether or not shapes are drawn at each XY point. */
131     private boolean plotShapes;
132
133     /** A flag indicating whether or not lines are drawn between XY points. */
134     private boolean plotLines;
135
136     /** A flag indicating whether or not images are drawn between XY points. */
137     private boolean plotImages;
138
139     /** A flag controlling whether or not discontinuous lines are used. */
140     private boolean plotDiscontinuous;
141
142     /** Threshold for deciding when to discontinue a line. */
143     private double gapThreshold = 1.0;
144
145     /** A flag that controls whether or not shapes are filled for ALL series. */
146     private Boolean JavaDoc shapesFilled;
147
148     /** A table of flags that control (per series) whether or not shapes are filled. */
149     private BooleanList seriesShapesFilled;
150
151     /** The default value returned by the getShapeFilled(...) method. */
152     private Boolean JavaDoc defaultShapesFilled;
153
154     /** A working line (to save creating thousands of instances). */
155     private transient Line2D JavaDoc line;
156
157     /**
158      * Constructs a new renderer.
159      */

160     public StandardXYItemRenderer() {
161
162         this(LINES, new StandardXYToolTipGenerator());
163
164     }
165
166     /**
167      * Constructs a new renderer.
168      * <p>
169      * To specify the type of renderer, use one of the constants: SHAPES, LINES
170      * or SHAPES_AND_LINES.
171      *
172      * @param type the type.
173      */

174     public StandardXYItemRenderer(int type) {
175         this(type, new StandardXYToolTipGenerator());
176     }
177
178     /**
179      * Constructs a new renderer.
180      * <p>
181      * To specify the type of renderer, use one of the constants: SHAPES, LINES
182      * or SHAPES_AND_LINES.
183      *
184      * @param type the type of renderer.
185      * @param toolTipGenerator the tooltip generator.
186      */

187     public StandardXYItemRenderer(int type, XYToolTipGenerator toolTipGenerator) {
188
189         this(type, toolTipGenerator, null);
190
191     }
192
193     /**
194      * Constructs a new renderer.
195      * <p>
196      * To specify the type of renderer, use one of the constants: SHAPES, LINES or SHAPES_AND_LINES.
197      *
198      * @param type the type of renderer.
199      * @param toolTipGenerator the tooltip generator.
200      * @param urlGenerator the URL generator.
201      */

202     public StandardXYItemRenderer(int type,
203                                   XYToolTipGenerator toolTipGenerator,
204                                   XYURLGenerator urlGenerator) {
205
206         super();
207         setToolTipGenerator(toolTipGenerator);
208         setURLGenerator(urlGenerator);
209         if ((type & SHAPES) != 0) {
210             this.plotShapes = true;
211         }
212         if ((type & LINES) != 0) {
213             this.plotLines = true;
214         }
215         if ((type & IMAGES) != 0) {
216             this.plotImages = true;
217         }
218         if ((type & DISCONTINUOUS) != 0) {
219             this.plotDiscontinuous = true;
220         }
221         this.line = new Line2D.Double JavaDoc(0.0, 0.0, 0.0, 0.0);
222
223         this.shapesFilled = null;
224         this.seriesShapesFilled = new BooleanList();
225         this.defaultShapesFilled = Boolean.TRUE;
226
227     }
228
229     /**
230      * Returns true if shapes are being plotted by the renderer.
231      *
232      * @return <code>true</code> if shapes are being plotted by the renderer.
233      */

234     public boolean getPlotShapes() {
235         return this.plotShapes;
236     }
237
238     /**
239      * Sets the flag that controls whether or not a shape is plotted at each data point.
240      *
241      * @param flag the flag.
242      */

243     public void setPlotShapes(boolean flag) {
244         if (this.plotShapes != flag) {
245             Object JavaDoc oldValue = new Boolean JavaDoc (this.plotShapes);
246             this.plotShapes = flag;
247             firePropertyChanged("renderer.PlotShapes", oldValue, new Boolean JavaDoc(flag));
248         }
249     }
250
251     // SHAPES FILLED
252

253     /**
254      * Returns the flag used to control whether or not the shape for an item is filled.
255      * <p>
256      * The default implementation passes control to the <code>getSeriesShapesFilled</code> method.
257      * You can override this method if you require different behaviour.
258      *
259      * @param series the series index (zero-based).
260      * @param item the item index (zero-based).
261      *
262      * @return A boolean.
263      */

264     public boolean getItemShapeFilled(int series, int item) {
265         return getSeriesShapesFilled(series);
266     }
267
268     /**
269      * Returns the flag used to control whether or not the shapes for a series are filled.
270      *
271      * @param series the series index (zero-based).
272      *
273      * @return A boolean.
274      */

275     public boolean getSeriesShapesFilled(int series) {
276
277         // return the overall setting, if there is one...
278
if (this.shapesFilled != null) {
279             return this.shapesFilled.booleanValue();
280         }
281
282         // otherwise look up the paint table
283
Boolean JavaDoc flag = this.seriesShapesFilled.getBoolean(series);
284         if (flag != null) {
285             return flag.booleanValue();
286         }
287         else {
288             return this.defaultShapesFilled.booleanValue();
289         }
290
291     }
292
293     /**
294      * Sets the 'shapes filled' for ALL series.
295      *
296      * @param filled the flag.
297      */

298     public void setShapesFilled(boolean filled) {
299         if (filled) {
300             setShapesFilled(Boolean.TRUE);
301         }
302         else {
303             setShapesFilled(Boolean.FALSE);
304         }
305         //setShapesFilled(Boolean.valueOf(filled));
306
}
307
308     /**
309      * Sets the 'shapes filled' for ALL series.
310      *
311      * @param filled the flag (<code>null</code> permitted).
312      */

313     public void setShapesFilled(Boolean JavaDoc filled) {
314         this.shapesFilled = filled;
315     }
316
317     /**
318      * Sets the 'shapes filled' flag for a series.
319      *
320      * @param series the series index (zero-based).
321      * @param flag the flag.
322      */

323     public void setSeriesShapesFilled(int series, Boolean JavaDoc flag) {
324         this.seriesShapesFilled.setBoolean(series, flag);
325     }
326
327     /**
328      * Returns the default 'shape filled' attribute.
329      *
330      * @return The default flag.
331      */

332     public Boolean JavaDoc getDefaultShapesFilled() {
333         return this.defaultShapesFilled;
334     }
335
336     /**
337      * Sets the default 'shapes filled' flag.
338      *
339      * @param flag the flag.
340      */

341     public void setDefaultShapesFilled(Boolean JavaDoc flag) {
342         this.defaultShapesFilled = flag;
343     }
344
345     /**
346      * Returns true if lines are being plotted by the renderer.
347      *
348      * @return <code>true</code> if lines are being plotted by the renderer.
349      */

350     public boolean getPlotLines() {
351         return this.plotLines;
352     }
353
354     /**
355      * Sets the flag that controls whether or not a line is plotted between each data point.
356      *
357      * @param flag the flag.
358      */

359     public void setPlotLines(boolean flag) {
360         if (this.plotLines != flag) {
361             Object JavaDoc oldValue = new Boolean JavaDoc(this.plotLines);
362             this.plotLines = flag;
363             firePropertyChanged("renderer.PlotLines", oldValue, new Boolean JavaDoc(flag));
364         }
365     }
366
367     /**
368      * Returns the gap threshold for discontinuous lines.
369      *
370      * @return the gap threshold.
371      */

372     public double getGapThreshold() {
373         return this.gapThreshold;
374     }
375
376     /**
377      * Sets the gap threshold for discontinuous lines.
378      *
379      * @param t the threshold.
380      */

381     public void setGapThreshold(double t) {
382         Object JavaDoc oldValue = new Double JavaDoc(this.gapThreshold);
383         this.gapThreshold = t;
384         firePropertyChanged("renderer.GapThreshold", oldValue, new Double JavaDoc(t));
385     }
386
387     /**
388      * Returns true if images are being plotted by the renderer.
389      *
390      * @return <code>true</code> if images are being plotted by the renderer.
391      */

392     public boolean getPlotImages() {
393         return this.plotImages;
394     }
395
396     /**
397      * Sets the flag that controls whether or not an image is drawn at each data point.
398      *
399      * @param flag the flag.
400      */

401     public void setPlotImages(boolean flag) {
402         if (this.plotImages != flag) {
403             Object JavaDoc oldValue = new Boolean JavaDoc(this.plotImages);
404             this.plotImages = flag;
405             firePropertyChanged("renderer.PlotImages", oldValue, new Boolean JavaDoc(flag));
406         }
407     }
408
409     /**
410      * Returns true if lines should be discontinuous.
411      *
412      * @return <code>true</code> if images are being plotted by the renderer.
413      */

414     public boolean getPlotDiscontinuous() {
415         return this.plotDiscontinuous;
416     }
417
418     /**
419      * Draws the visual representation of a single data item.
420      *
421      * @param g2 the graphics device.
422      * @param state the renderer state.
423      * @param dataArea the area within which the data is being drawn.
424      * @param info collects information about the drawing.
425      * @param plot the plot (can be used to obtain standard color information etc).
426      * @param domainAxis the domain axis.
427      * @param rangeAxis the range axis.
428      * @param dataset the dataset.
429      * @param series the series index (zero-based).
430      * @param item the item index (zero-based).
431      * @param crosshairInfo information about crosshairs on a plot.
432      * @param pass the pass index.
433      */

434     public void drawItem(Graphics2D JavaDoc g2,
435                          XYItemRendererState state,
436                          Rectangle2D JavaDoc dataArea,
437                          PlotRenderingInfo info,
438                          XYPlot plot,
439                          ValueAxis domainAxis,
440                          ValueAxis rangeAxis,
441                          XYDataset dataset,
442                          int series,
443                          int item,
444                          CrosshairInfo crosshairInfo,
445                          int pass) {
446
447         // setup for collecting optional entity info...
448
Shape JavaDoc entityArea = null;
449         EntityCollection entities = null;
450         if (info != null) {
451             entities = info.getOwner().getEntityCollection();
452         }
453
454         Paint JavaDoc paint = getItemPaint(series, item);
455         Stroke JavaDoc seriesStroke = getItemStroke(series, item);
456         g2.setPaint(paint);
457         g2.setStroke(seriesStroke);
458
459         // get the data point...
460
Number JavaDoc x1n = dataset.getXValue(series, item);
461         Number JavaDoc y1n = dataset.getYValue(series, item);
462         if (y1n == null || x1n == null) {
463             return;
464         }
465
466         double x1 = x1n.doubleValue();
467         double y1 = y1n.doubleValue();
468         final RectangleEdge xAxisLocation = plot.getDomainAxisEdge();
469         final RectangleEdge yAxisLocation = plot.getRangeAxisEdge();
470         double transX1 = domainAxis.translateValueToJava2D(x1, dataArea, xAxisLocation);
471         double transY1 = rangeAxis.translateValueToJava2D(y1, dataArea, yAxisLocation);
472
473         if (this.plotLines) {
474
475             if (item > 0) {
476                 // get the previous data point...
477
Number JavaDoc x0n = dataset.getXValue(series, item - 1);
478                 Number JavaDoc y0n = dataset.getYValue(series, item - 1);
479                 if (y0n != null && x0n != null) {
480                     double x0 = x0n.doubleValue();
481                     double y0 = y0n.doubleValue();
482                     boolean drawLine = true;
483                     if (this.plotDiscontinuous) {
484                         // only draw a line if the gap between the current and previous data
485
// point is within the threshold
486
int numX = dataset.getItemCount(series);
487                         double minX = dataset.getXValue(series, 0).doubleValue();
488                         double maxX = dataset.getXValue(series, numX - 1).doubleValue();
489                         drawLine = (x1 - x0) <= ((maxX - minX) / numX * this.gapThreshold);
490                     }
491                     if (drawLine) {
492                         double transX0
493                             = domainAxis.translateValueToJava2D(x0, dataArea, xAxisLocation);
494                         double transY0
495                             = rangeAxis.translateValueToJava2D(y0, dataArea, yAxisLocation);
496
497                         // only draw if we have good values
498
if (Double.isNaN(transX0) || Double.isNaN(transY0)
499                             || Double.isNaN(transX1) || Double.isNaN(transY1)) {
500                             return;
501                         }
502
503                         PlotOrientation orientation = plot.getOrientation();
504                         if (orientation == PlotOrientation.HORIZONTAL) {
505                             line.setLine(transY0, transX0, transY1, transX1);
506                         }
507                         else if (orientation == PlotOrientation.VERTICAL) {
508                             line.setLine(transX0, transY0, transX1, transY1);
509                         }
510
511                         if (line.intersects(dataArea)) {
512                             g2.draw(line);
513                         }
514                     }
515                 }
516             }
517         }
518
519         if (this.plotShapes) {
520
521             Shape JavaDoc shape = getItemShape(series, item);
522             PlotOrientation orientation = plot.getOrientation();
523             if (orientation == PlotOrientation.HORIZONTAL) {
524                 shape = createTransformedShape(shape, transY1, transX1);
525             }
526             else if (orientation == PlotOrientation.VERTICAL) {
527                 shape = createTransformedShape(shape, transX1, transY1);
528             }
529             if (shape.intersects(dataArea)) {
530                 if (getItemShapeFilled(series, item)) {
531                     g2.fill(shape);
532                 }
533                 else {
534                     g2.draw(shape);
535                 }
536             }
537             entityArea = shape;
538
539         }
540
541         if (this.plotImages) {
542             // use shape scale with transform??
543
//double scale = getShapeScale(plot, series, item, transX1, transY1);
544
Image JavaDoc image = getImage(plot, series, item, transX1, transY1);
545             if (image != null) {
546                 Point JavaDoc hotspot = getImageHotspot(plot, series, item, transX1, transY1, image);
547                 g2.drawImage(image,
548                              (int) (transX1 - hotspot.getX()),
549                              (int) (transY1 - hotspot.getY()), null);
550                 entityArea = new Rectangle2D.Double JavaDoc(transX1 - hotspot.getX(),
551                                                     transY1 - hotspot.getY(),
552                                                     image.getWidth(null),
553                                                     image.getHeight(null));
554             }
555
556         }
557
558         // add an entity for the item...
559
if (entities != null) {
560             if (entityArea == null) {
561                 entityArea = new Rectangle2D.Double JavaDoc(transX1 - 2, transY1 - 2, 4, 4);
562             }
563             String JavaDoc tip = null;
564             if (getToolTipGenerator() != null) {
565                 tip = getToolTipGenerator().generateToolTip(dataset, series, item);
566             }
567             String JavaDoc url = null;
568             if (getURLGenerator() != null) {
569                 url = getURLGenerator().generateURL(dataset, series, item);
570             }
571             XYItemEntity entity = new XYItemEntity(entityArea, dataset, series, item, tip, url);
572             entities.addEntity(entity);
573         }
574
575         // do we need to update the crosshair values?
576
if (plot.isDomainCrosshairLockedOnData()) {
577             if (plot.isRangeCrosshairLockedOnData()) {
578                 // both axes
579
crosshairInfo.updateCrosshairPoint(x1, y1, transX1, transY1);
580             }
581             else {
582                 // just the horizontal axis...
583
crosshairInfo.updateCrosshairX(x1);
584             }
585         }
586         else {
587             if (plot.isRangeCrosshairLockedOnData()) {
588                 // just the vertical axis...
589
crosshairInfo.updateCrosshairY(y1);
590             }
591         }
592
593     }
594
595     /**
596      * Tests this renderer for equality with another object.
597      *
598      * @param obj the object.
599      *
600      * @return <code>true</code> or <code>false</code>.
601      */

602     public boolean equals(Object JavaDoc obj) {
603
604         if (obj == null) {
605             return false;
606         }
607
608         if (obj == this) {
609             return true;
610         }
611
612         if (obj instanceof StandardXYItemRenderer) {
613             StandardXYItemRenderer r = (StandardXYItemRenderer) obj;
614             if (super.equals(obj)) {
615                 boolean b0 = (this.plotShapes == r.plotShapes);
616                 boolean b1 = (this.plotLines == r.plotLines);
617                 boolean b2 = (this.plotImages == r.plotImages);
618                 boolean b3 = (this.plotDiscontinuous == r.plotDiscontinuous);
619                 boolean b4 = (this.gapThreshold == r.gapThreshold);
620                 //boolean b5 = (this.defaultShapeFilled == r.defaultShapeFilled);
621
return b0 && b1 && b2 && b3 && b4;
622             }
623         }
624
625         return false;
626
627     }
628
629     ////////////////////////////////////////////////////////////////////////////////////////////////
630
// PROTECTED METHODS
631
// These provide the opportunity to subclass the standard renderer and create custom effects.
632
////////////////////////////////////////////////////////////////////////////////////////////////
633

634     /**
635      * Returns the image used to draw a single data item.
636      *
637      * @param plot the plot (can be used to obtain standard color information etc).
638      * @param series the series index.
639      * @param item the item index.
640      * @param x the x value of the item.
641      * @param y the y value of the item.
642      *
643      * @return the image.
644      */

645     protected Image JavaDoc getImage(Plot plot, int series, int item, double x, double y) {
646         // should this be added to the plot as well ?
647
// return plot.getShape(series, item, x, y, scale);
648
// or should this be left to the user - like this:
649
return null;
650     }
651
652     /**
653      * Returns the hotspot of the image used to draw a single data item.
654      * The hotspot is the point relative to the top left of the image
655      * that should indicate the data item. The default is the center of the
656      * image.
657      *
658      * @param plot the plot (can be used to obtain standard color information etc).
659      * @param image the image (can be used to get size information about the image)
660      * @param series the series index
661      * @param item the item index
662      * @param x the x value of the item
663      * @param y the y value of the item
664      *
665      * @return the hotspot used to draw the data item.
666      */

667     protected Point JavaDoc getImageHotspot(Plot plot, int series, int item,
668                                     double x, double y, Image JavaDoc image) {
669
670         int height = image.getHeight(null);
671         int width = image.getWidth(null);
672         return new Point JavaDoc(width / 2, height / 2);
673
674     }
675
676     /**
677      * Returns a clone of the renderer.
678      *
679      * @return A clone.
680      *
681      * @throws CloneNotSupportedException if the renderer cannot be cloned.
682      */

683     public Object JavaDoc clone() throws CloneNotSupportedException JavaDoc {
684         return super.clone();
685     }
686
687     /**
688      * Restores a serialized object.
689      *
690      * @param stream the input stream.
691      *
692      * @throws IOException if there is an I/O problem.
693      * @throws ClassNotFoundException if there is a problem loading a class.
694      */

695     private void readObject(ObjectInputStream JavaDoc stream) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
696         stream.defaultReadObject();
697         this.line = new Line2D.Double JavaDoc(0.0, 0.0, 0.0, 0.0);
698     }
699
700 }
701
Popular Tags