Source for org.jfree.chart.plot.Marker

   1: /* ===========================================================
   2:  * JFreeChart : a free chart library for the Java(tm) platform
   3:  * ===========================================================
   4:  *
   5:  * (C) Copyright 2000-2007, by Object Refinery Limited and Contributors.
   6:  *
   7:  * Project Info:  http://www.jfree.org/jfreechart/index.html
   8:  *
   9:  * This library is free software; you can redistribute it and/or modify it 
  10:  * under the terms of the GNU Lesser General Public License as published by 
  11:  * the Free Software Foundation; either version 2.1 of the License, or 
  12:  * (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but 
  15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  16:  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
  17:  * License for more details.
  18:  *
  19:  * You should have received a copy of the GNU Lesser General Public
  20:  * License along with this library; if not, write to the Free Software
  21:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
  22:  * USA.  
  23:  *
  24:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
  25:  * in the United States and other countries.]
  26:  *
  27:  * -----------
  28:  * Marker.java
  29:  * -----------
  30:  * (C) Copyright 2002-2007, by Object Refinery Limited.
  31:  *
  32:  * Original Author:  David Gilbert (for Object Refinery Limited);
  33:  * Contributor(s):   Nicolas Brodu;
  34:  *
  35:  * Changes
  36:  * -------
  37:  * 02-Jul-2002 : Added extra constructor, standard header and Javadoc 
  38:  *               comments (DG);
  39:  * 20-Aug-2002 : Added the outline stroke attribute (DG);
  40:  * 02-Oct-2002 : Fixed errors reported by Checkstyle (DG);
  41:  * 16-Oct-2002 : Added new constructor (DG);
  42:  * 26-Mar-2003 : Implemented Serializable (DG);
  43:  * 21-May-2003 : Added labels (DG);
  44:  * 11-Sep-2003 : Implemented Cloneable (NB);
  45:  * 05-Nov-2003 : Added checks to ensure some attributes are never null (DG);
  46:  * 11-Feb-2003 : Moved to org.jfree.chart.plot package, plus significant API 
  47:  *               changes to support IntervalMarker in plots (DG);
  48:  * 14-Jun-2004 : Updated equals() method (DG);
  49:  * 21-Jan-2005 : Added settings to control direction of horizontal and 
  50:  *               vertical label offsets (DG);
  51:  * 01-Jun-2005 : Modified to use only one label offset type - this will be 
  52:  *               applied to the domain or range axis as appropriate (DG);
  53:  * 06-Jun-2005 : Fix equals() method to handle GradientPaint (DG);
  54:  * 19-Aug-2005 : Changed constructor from public --> protected (DG);
  55:  * ------------- JFREECHART 1.0.x ---------------------------------------------
  56:  * 05-Sep-2006 : Added MarkerChangeListener support (DG);
  57:  * 26-Sep-2007 : Fix for serialization bug 1802195 (DG);
  58:  *
  59:  */
  60: 
  61: package org.jfree.chart.plot;
  62: 
  63: import java.awt.BasicStroke;
  64: import java.awt.Color;
  65: import java.awt.Font;
  66: import java.awt.Paint;
  67: import java.awt.Stroke;
  68: import java.io.IOException;
  69: import java.io.ObjectInputStream;
  70: import java.io.ObjectOutputStream;
  71: import java.io.Serializable;
  72: import java.util.EventListener;
  73: 
  74: import javax.swing.event.EventListenerList;
  75: 
  76: import org.jfree.chart.event.MarkerChangeEvent;
  77: import org.jfree.chart.event.MarkerChangeListener;
  78: import org.jfree.io.SerialUtilities;
  79: import org.jfree.ui.LengthAdjustmentType;
  80: import org.jfree.ui.RectangleAnchor;
  81: import org.jfree.ui.RectangleInsets;
  82: import org.jfree.ui.TextAnchor;
  83: import org.jfree.util.ObjectUtilities;
  84: import org.jfree.util.PaintUtilities;
  85: 
  86: /**
  87:  * The base class for markers that can be added to plots to highlight a value 
  88:  * or range of values.
  89:  * <br><br>
  90:  * An event notification mechanism was added to this class in JFreeChart 
  91:  * version 1.0.3.
  92:  */
  93: public abstract class Marker implements Cloneable, Serializable {
  94: 
  95:     /** For serialization. */
  96:     private static final long serialVersionUID = -734389651405327166L;
  97: 
  98:     /** The paint. */
  99:     private transient Paint paint;
 100: 
 101:     /** The stroke. */
 102:     private transient Stroke stroke;
 103:     
 104:     /** The outline paint. */
 105:     private transient Paint outlinePaint;
 106: 
 107:     /** The outline stroke. */
 108:     private transient Stroke outlineStroke;
 109: 
 110:     /** The alpha transparency. */
 111:     private float alpha;
 112: 
 113:     /** The label. */
 114:     private String label = null;
 115: 
 116:     /** The label font. */
 117:     private Font labelFont;
 118: 
 119:     /** The label paint. */
 120:     private transient Paint labelPaint;
 121: 
 122:     /** The label position. */
 123:     private RectangleAnchor labelAnchor;
 124:     
 125:     /** The text anchor for the label. */
 126:     private TextAnchor labelTextAnchor;
 127: 
 128:     /** The label offset from the marker rectangle. */
 129:     private RectangleInsets labelOffset;
 130:     
 131:     /** 
 132:      * The offset type for the domain or range axis (never <code>null</code>). 
 133:      */
 134:     private LengthAdjustmentType labelOffsetType;
 135:     
 136:     /** Storage for registered change listeners. */
 137:     private transient EventListenerList listenerList;
 138: 
 139:     /**
 140:      * Creates a new marker with default attributes.
 141:      */
 142:     protected Marker() {
 143:         this(Color.gray);
 144:     }
 145: 
 146:     /**
 147:      * Constructs a new marker.
 148:      *
 149:      * @param paint  the paint (<code>null</code> not permitted).
 150:      */
 151:     protected Marker(Paint paint) {
 152:         this(paint, new BasicStroke(0.5f), Color.gray, new BasicStroke(0.5f), 
 153:                 0.80f);
 154:     }
 155: 
 156:     /**
 157:      * Constructs a new marker.
 158:      *
 159:      * @param paint  the paint (<code>null</code> not permitted).
 160:      * @param stroke  the stroke (<code>null</code> not permitted).
 161:      * @param outlinePaint  the outline paint (<code>null</code> permitted).
 162:      * @param outlineStroke  the outline stroke (<code>null</code> permitted).
 163:      * @param alpha  the alpha transparency (must be in the range 0.0f to 
 164:      *     1.0f).
 165:      *     
 166:      * @throws IllegalArgumentException if <code>paint</code> or 
 167:      *     <code>stroke</code> is <code>null</code>, or <code>alpha</code> is 
 168:      *     not in the specified range.
 169:      */
 170:     protected Marker(Paint paint, Stroke stroke, 
 171:                      Paint outlinePaint, Stroke outlineStroke, 
 172:                      float alpha) {
 173: 
 174:         if (paint == null) {
 175:             throw new IllegalArgumentException("Null 'paint' argument.");
 176:         }
 177:         if (stroke == null) {
 178:             throw new IllegalArgumentException("Null 'stroke' argument.");
 179:         }
 180:         if (alpha < 0.0f || alpha > 1.0f)
 181:             throw new IllegalArgumentException(
 182:                     "The 'alpha' value must be in the range 0.0f to 1.0f");
 183:         
 184:         this.paint = paint;
 185:         this.stroke = stroke;
 186:         this.outlinePaint = outlinePaint;
 187:         this.outlineStroke = outlineStroke;
 188:         this.alpha = alpha;
 189:         
 190:         this.labelFont = new Font("SansSerif", Font.PLAIN, 9);
 191:         this.labelPaint = Color.black;
 192:         this.labelAnchor = RectangleAnchor.TOP_LEFT;
 193:         this.labelOffset = new RectangleInsets(3.0, 3.0, 3.0, 3.0);
 194:         this.labelOffsetType = LengthAdjustmentType.CONTRACT;
 195:         this.labelTextAnchor = TextAnchor.CENTER;
 196:         
 197:         this.listenerList = new EventListenerList();
 198:     }
 199: 
 200:     /**
 201:      * Returns the paint.
 202:      *
 203:      * @return The paint (never <code>null</code>).
 204:      * 
 205:      * @see #setPaint(Paint)
 206:      */
 207:     public Paint getPaint() {
 208:         return this.paint;
 209:     }
 210:     
 211:     /**
 212:      * Sets the paint and sends a {@link MarkerChangeEvent} to all registered
 213:      * listeners.
 214:      * 
 215:      * @param paint  the paint (<code>null</code> not permitted).
 216:      * 
 217:      * @see #getPaint()
 218:      */
 219:     public void setPaint(Paint paint) {
 220:         if (paint == null) {
 221:             throw new IllegalArgumentException("Null 'paint' argument.");
 222:         }
 223:         this.paint = paint;
 224:         notifyListeners(new MarkerChangeEvent(this));
 225:     }
 226: 
 227:     /**
 228:      * Returns the stroke.
 229:      *
 230:      * @return The stroke (never <code>null</code>).
 231:      * 
 232:      * @see #setStroke(Stroke)
 233:      */
 234:     public Stroke getStroke() {
 235:         return this.stroke;
 236:     }
 237:     
 238:     /**
 239:      * Sets the stroke and sends a {@link MarkerChangeEvent} to all registered
 240:      * listeners.
 241:      * 
 242:      * @param stroke  the stroke (<code>null</code> not permitted).
 243:      * 
 244:      * @see #getStroke()
 245:      */
 246:     public void setStroke(Stroke stroke) {
 247:         if (stroke == null) {
 248:             throw new IllegalArgumentException("Null 'stroke' argument.");
 249:         }
 250:         this.stroke = stroke;
 251:         notifyListeners(new MarkerChangeEvent(this));
 252:     }
 253: 
 254:     /**
 255:      * Returns the outline paint.
 256:      *
 257:      * @return The outline paint (possibly <code>null</code>).
 258:      * 
 259:      * @see #setOutlinePaint(Paint)
 260:      */
 261:     public Paint getOutlinePaint() {
 262:         return this.outlinePaint;
 263:     }
 264:     
 265:     /**
 266:      * Sets the outline paint and sends a {@link MarkerChangeEvent} to all 
 267:      * registered listeners.
 268:      * 
 269:      * @param paint  the paint (<code>null</code> permitted).
 270:      * 
 271:      * @see #getOutlinePaint()
 272:      */
 273:     public void setOutlinePaint(Paint paint) {
 274:         this.outlinePaint = paint;
 275:         notifyListeners(new MarkerChangeEvent(this));
 276:     }
 277: 
 278:     /**
 279:      * Returns the outline stroke.
 280:      *
 281:      * @return The outline stroke (possibly <code>null</code>).
 282:      * 
 283:      * @see #setOutlineStroke(Stroke)
 284:      */
 285:     public Stroke getOutlineStroke() {
 286:         return this.outlineStroke;
 287:     }
 288:     
 289:     /**
 290:      * Sets the outline stroke and sends a {@link MarkerChangeEvent} to all 
 291:      * registered listeners.
 292:      * 
 293:      * @param stroke  the stroke (<code>null</code> permitted).
 294:      * 
 295:      * @see #getOutlineStroke()
 296:      */
 297:     public void setOutlineStroke(Stroke stroke) {
 298:         this.outlineStroke = stroke;
 299:         notifyListeners(new MarkerChangeEvent(this));
 300:     }
 301: 
 302:     /**
 303:      * Returns the alpha transparency.
 304:      *
 305:      * @return The alpha transparency.
 306:      * 
 307:      * @see #setAlpha(float)
 308:      */
 309:     public float getAlpha() {
 310:         return this.alpha;
 311:     }
 312:     
 313:     /**
 314:      * Sets the alpha transparency that should be used when drawing the 
 315:      * marker, and sends a {@link MarkerChangeEvent} to all registered 
 316:      * listeners.  The alpha transparency is a value in the range 0.0f 
 317:      * (completely transparent) to 1.0f (completely opaque).
 318:      * 
 319:      * @param alpha  the alpha transparency (must be in the range 0.0f to 
 320:      *     1.0f).
 321:      *     
 322:      * @throws IllegalArgumentException if <code>alpha</code> is not in the
 323:      *     specified range.
 324:      *     
 325:      * @see #getAlpha()
 326:      */
 327:     public void setAlpha(float alpha) {
 328:         if (alpha < 0.0f || alpha > 1.0f)
 329:             throw new IllegalArgumentException(
 330:                     "The 'alpha' value must be in the range 0.0f to 1.0f");
 331:         this.alpha = alpha;
 332:         notifyListeners(new MarkerChangeEvent(this));
 333:     }
 334: 
 335:     /**
 336:      * Returns the label (if <code>null</code> no label is displayed).
 337:      *
 338:      * @return The label (possibly <code>null</code>).
 339:      * 
 340:      * @see #setLabel(String)
 341:      */
 342:     public String getLabel() {
 343:         return this.label;
 344:     }
 345: 
 346:     /**
 347:      * Sets the label (if <code>null</code> no label is displayed) and sends a
 348:      * {@link MarkerChangeEvent} to all registered listeners.
 349:      *
 350:      * @param label  the label (<code>null</code> permitted).
 351:      * 
 352:      * @see #getLabel()
 353:      */
 354:     public void setLabel(String label) {
 355:         this.label = label;
 356:         notifyListeners(new MarkerChangeEvent(this));
 357:     }
 358: 
 359:     /**
 360:      * Returns the label font.
 361:      *
 362:      * @return The label font (never <code>null</code>).
 363:      * 
 364:      * @see #setLabelFont(Font)
 365:      */
 366:     public Font getLabelFont() {
 367:         return this.labelFont;
 368:     }
 369: 
 370:     /**
 371:      * Sets the label font and sends a {@link MarkerChangeEvent} to all 
 372:      * registered listeners.
 373:      *
 374:      * @param font  the font (<code>null</code> not permitted).
 375:      * 
 376:      * @see #getLabelFont()
 377:      */
 378:     public void setLabelFont(Font font) {
 379:         if (font == null) {
 380:             throw new IllegalArgumentException("Null 'font' argument.");
 381:         }
 382:         this.labelFont = font;
 383:         notifyListeners(new MarkerChangeEvent(this));
 384:     }
 385: 
 386:     /**
 387:      * Returns the label paint.
 388:      *
 389:      * @return The label paint (never </code>null</code>).
 390:      * 
 391:      * @see #setLabelPaint(Paint)
 392:      */
 393:     public Paint getLabelPaint() {
 394:         return this.labelPaint;
 395:     }
 396: 
 397:     /**
 398:      * Sets the label paint and sends a {@link MarkerChangeEvent} to all
 399:      * registered listeners.
 400:      *
 401:      * @param paint  the paint (<code>null</code> not permitted).
 402:      * 
 403:      * @see #getLabelPaint()
 404:      */
 405:     public void setLabelPaint(Paint paint) {
 406:         if (paint == null) {
 407:             throw new IllegalArgumentException("Null 'paint' argument.");
 408:         }
 409:         this.labelPaint = paint;
 410:         notifyListeners(new MarkerChangeEvent(this));
 411:     }
 412: 
 413:     /**
 414:      * Returns the label anchor.  This defines the position of the label 
 415:      * anchor, relative to the bounds of the marker.
 416:      *
 417:      * @return The label anchor (never <code>null</code>).
 418:      * 
 419:      * @see #setLabelAnchor(RectangleAnchor)
 420:      */
 421:     public RectangleAnchor getLabelAnchor() {
 422:         return this.labelAnchor;
 423:     }
 424: 
 425:     /**
 426:      * Sets the label anchor and sends a {@link MarkerChangeEvent} to all 
 427:      * registered listeners.  The anchor defines the position of the label 
 428:      * anchor, relative to the bounds of the marker.
 429:      *
 430:      * @param anchor  the anchor (<code>null</code> not permitted).
 431:      * 
 432:      * @see #getLabelAnchor()
 433:      */
 434:     public void setLabelAnchor(RectangleAnchor anchor) {
 435:         if (anchor == null) {
 436:             throw new IllegalArgumentException("Null 'anchor' argument.");
 437:         }
 438:         this.labelAnchor = anchor;
 439:         notifyListeners(new MarkerChangeEvent(this));
 440:     }
 441: 
 442:     /**
 443:      * Returns the label offset.
 444:      * 
 445:      * @return The label offset (never <code>null</code>).
 446:      * 
 447:      * @see #setLabelOffset(RectangleInsets)
 448:      */
 449:     public RectangleInsets getLabelOffset() {
 450:         return this.labelOffset;
 451:     }
 452:     
 453:     /**
 454:      * Sets the label offset and sends a {@link MarkerChangeEvent} to all
 455:      * registered listeners.
 456:      * 
 457:      * @param offset  the label offset (<code>null</code> not permitted).
 458:      * 
 459:      * @see #getLabelOffset()
 460:      */
 461:     public void setLabelOffset(RectangleInsets offset) {
 462:         if (offset == null) {
 463:             throw new IllegalArgumentException("Null 'offset' argument.");
 464:         }
 465:         this.labelOffset = offset;
 466:         notifyListeners(new MarkerChangeEvent(this));
 467:     }
 468:     
 469:     /**
 470:      * Returns the label offset type.
 471:      * 
 472:      * @return The type (never <code>null</code>).
 473:      * 
 474:      * @see #setLabelOffsetType(LengthAdjustmentType)
 475:      */
 476:     public LengthAdjustmentType getLabelOffsetType() {
 477:         return this.labelOffsetType;   
 478:     }
 479:     
 480:     /**
 481:      * Sets the label offset type and sends a {@link MarkerChangeEvent} to all
 482:      * registered listeners.
 483:      * 
 484:      * @param adj  the type (<code>null</code> not permitted).
 485:      * 
 486:      * @see #getLabelOffsetType()
 487:      */
 488:     public void setLabelOffsetType(LengthAdjustmentType adj) {
 489:         if (adj == null) {
 490:             throw new IllegalArgumentException("Null 'adj' argument.");
 491:         }
 492:         this.labelOffsetType = adj;    
 493:         notifyListeners(new MarkerChangeEvent(this));
 494:     }
 495:         
 496:     /**
 497:      * Returns the label text anchor.
 498:      * 
 499:      * @return The label text anchor (never <code>null</code>).
 500:      * 
 501:      * @see #setLabelTextAnchor(TextAnchor)
 502:      */
 503:     public TextAnchor getLabelTextAnchor() {
 504:         return this.labelTextAnchor;
 505:     }
 506:     
 507:     /**
 508:      * Sets the label text anchor and sends a {@link MarkerChangeEvent} to 
 509:      * all registered listeners.
 510:      * 
 511:      * @param anchor  the label text anchor (<code>null</code> not permitted).
 512:      * 
 513:      * @see #getLabelTextAnchor()
 514:      */
 515:     public void setLabelTextAnchor(TextAnchor anchor) {
 516:         if (anchor == null) { 
 517:             throw new IllegalArgumentException("Null 'anchor' argument.");
 518:         }
 519:         this.labelTextAnchor = anchor;
 520:         notifyListeners(new MarkerChangeEvent(this));
 521:     }
 522:     
 523:     /**
 524:      * Registers an object for notification of changes to the marker.
 525:      *
 526:      * @param listener  the object to be registered.
 527:      * 
 528:      * @see #removeChangeListener(MarkerChangeListener)
 529:      * 
 530:      * @since 1.0.3
 531:      */
 532:     public void addChangeListener(MarkerChangeListener listener) {
 533:         this.listenerList.add(MarkerChangeListener.class, listener);
 534:     }
 535: 
 536:     /**
 537:      * Unregisters an object for notification of changes to the marker.
 538:      *
 539:      * @param listener  the object to be unregistered.
 540:      * 
 541:      * @see #addChangeListener(MarkerChangeListener)
 542:      * 
 543:      * @since 1.0.3
 544:      */
 545:     public void removeChangeListener(MarkerChangeListener listener) {
 546:         this.listenerList.remove(MarkerChangeListener.class, listener);
 547:     }
 548: 
 549:     /**
 550:      * Notifies all registered listeners that the marker has been modified.
 551:      *
 552:      * @param event  information about the change event.
 553:      * 
 554:      * @since 1.0.3
 555:      */
 556:     public void notifyListeners(MarkerChangeEvent event) {
 557: 
 558:         Object[] listeners = this.listenerList.getListenerList();
 559:         for (int i = listeners.length - 2; i >= 0; i -= 2) {
 560:             if (listeners[i] == MarkerChangeListener.class) {
 561:                 ((MarkerChangeListener) listeners[i + 1]).markerChanged(event);
 562:             }
 563:         }
 564: 
 565:     }
 566: 
 567:     /**
 568:      * Returns an array containing all the listeners of the specified type.
 569:      * 
 570:      * @param listenerType  the listener type.
 571:      * 
 572:      * @return The array of listeners.
 573:      * 
 574:      * @since 1.0.3
 575:      */
 576:     public EventListener[] getListeners(Class listenerType) {
 577:         return this.listenerList.getListeners(listenerType);    
 578:     }
 579:     
 580:     /**
 581:      * Tests the marker for equality with an arbitrary object.
 582:      * 
 583:      * @param obj  the object (<code>null</code> permitted).
 584:      * 
 585:      * @return A boolean.
 586:      */
 587:     public boolean equals(Object obj) {
 588:         if (obj == this) {
 589:             return true;
 590:         }
 591:         if (!(obj instanceof Marker)) {
 592:             return false;
 593:         }
 594:         Marker that = (Marker) obj;
 595:         if (!PaintUtilities.equal(this.paint, that.paint)) {
 596:             return false;   
 597:         }
 598:         if (!ObjectUtilities.equal(this.stroke, that.stroke)) {
 599:             return false;
 600:         }
 601:         if (!PaintUtilities.equal(this.outlinePaint, that.outlinePaint)) {
 602:             return false;   
 603:         }
 604:         if (!ObjectUtilities.equal(this.outlineStroke, that.outlineStroke)) {
 605:             return false;
 606:         }
 607:         if (this.alpha != that.alpha) {
 608:             return false;
 609:         }
 610:         if (!ObjectUtilities.equal(this.label, that.label)) {
 611:             return false;
 612:         }
 613:         if (!ObjectUtilities.equal(this.labelFont, that.labelFont)) {
 614:             return false;
 615:         }
 616:         if (!PaintUtilities.equal(this.labelPaint, that.labelPaint)) {
 617:             return false;
 618:         }
 619:         if (this.labelAnchor != that.labelAnchor) {
 620:             return false;
 621:         }
 622:         if (this.labelTextAnchor != that.labelTextAnchor) {
 623:             return false;   
 624:         }
 625:         if (!ObjectUtilities.equal(this.labelOffset, that.labelOffset)) {
 626:             return false;
 627:         }
 628:         if (!this.labelOffsetType.equals(that.labelOffsetType)) {
 629:             return false;
 630:         }
 631:         return true;
 632:     }
 633:     
 634:     /**
 635:      * Creates a clone of the marker.
 636:      * 
 637:      * @return A clone.
 638:      * 
 639:      * @throws CloneNotSupportedException never.
 640:      */
 641:     public Object clone() throws CloneNotSupportedException {
 642:         return super.clone();
 643:     }
 644:     
 645:     /**
 646:      * Provides serialization support.
 647:      *
 648:      * @param stream  the output stream.
 649:      *
 650:      * @throws IOException  if there is an I/O error.
 651:      */
 652:     private void writeObject(ObjectOutputStream stream) throws IOException {
 653:         stream.defaultWriteObject();
 654:         SerialUtilities.writePaint(this.paint, stream);
 655:         SerialUtilities.writeStroke(this.stroke, stream);
 656:         SerialUtilities.writePaint(this.outlinePaint, stream);
 657:         SerialUtilities.writeStroke(this.outlineStroke, stream);
 658:         SerialUtilities.writePaint(this.labelPaint, stream);
 659:     }
 660: 
 661:     /**
 662:      * Provides serialization support.
 663:      *
 664:      * @param stream  the input stream.
 665:      *
 666:      * @throws IOException  if there is an I/O error.
 667:      * @throws ClassNotFoundException  if there is a classpath problem.
 668:      */
 669:     private void readObject(ObjectInputStream stream) 
 670:         throws IOException, ClassNotFoundException {
 671:         stream.defaultReadObject();
 672:         this.paint = SerialUtilities.readPaint(stream);
 673:         this.stroke = SerialUtilities.readStroke(stream);
 674:         this.outlinePaint = SerialUtilities.readPaint(stream);
 675:         this.outlineStroke = SerialUtilities.readStroke(stream);
 676:         this.labelPaint = SerialUtilities.readPaint(stream);
 677:         this.listenerList = new EventListenerList();
 678:     }
 679: 
 680: }