Source for org.jfree.chart.renderer.AbstractRenderer

   1: /* ===========================================================
   2:  * JFreeChart : a free chart library for the Java(tm) platform
   3:  * ===========================================================
   4:  *
   5:  * (C) Copyright 2000-2006, 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:  * AbstractRenderer.java
  29:  * ---------------------
  30:  * (C) Copyright 2002-2006, by Object Refinery Limited.
  31:  *
  32:  * Original Author:  David Gilbert (for Object Refinery Limited);
  33:  * Contributor(s):   Nicolas Brodu;
  34:  *
  35:  * $Id: AbstractRenderer.java,v 1.22.2.4 2006/08/01 16:42:14 mungady Exp $
  36:  *
  37:  * Changes:
  38:  * --------
  39:  * 22-Aug-2002 : Version 1, draws code out of AbstractXYItemRenderer to share 
  40:  *               with AbstractCategoryItemRenderer (DG);
  41:  * 01-Oct-2002 : Fixed errors reported by Checkstyle (DG);
  42:  * 06-Nov-2002 : Moved to the com.jrefinery.chart.renderer package (DG);
  43:  * 21-Nov-2002 : Added a paint table for the renderer to use (DG);
  44:  * 17-Jan-2003 : Moved plot classes into a separate package (DG);
  45:  * 25-Mar-2003 : Implemented Serializable (DG);
  46:  * 29-Apr-2003 : Added valueLabelFont and valueLabelPaint attributes, based on 
  47:  *               code from Arnaud Lelievre (DG);
  48:  * 29-Jul-2003 : Amended code that doesn't compile with JDK 1.2.2 (DG);
  49:  * 13-Aug-2003 : Implemented Cloneable (DG);
  50:  * 15-Sep-2003 : Fixed serialization (NB);
  51:  * 17-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
  52:  * 07-Oct-2003 : Moved PlotRenderingInfo into RendererState to allow for 
  53:  *               multiple threads using a single renderer (DG);
  54:  * 20-Oct-2003 : Added missing setOutlinePaint() method (DG);
  55:  * 23-Oct-2003 : Split item label attributes into 'positive' and 'negative' 
  56:  *               values (DG);
  57:  * 26-Nov-2003 : Added methods to get the positive and negative item label 
  58:  *               positions (DG);
  59:  * 01-Mar-2004 : Modified readObject() method to prevent null pointer exceptions
  60:  *               after deserialization (DG);
  61:  * 19-Jul-2004 : Fixed bug in getItemLabelFont(int, int) method (DG);
  62:  * 04-Oct-2004 : Updated equals() method, eliminated use of NumberUtils,
  63:  *               renamed BooleanUtils --> BooleanUtilities, ShapeUtils -->
  64:  *               ShapeUtilities (DG);
  65:  * 15-Mar-2005 : Fixed serialization of baseFillPaint (DG);
  66:  * 16-May-2005 : Base outline stroke should never be null (DG);
  67:  * 01-Jun-2005 : Added hasListener() method for unit testing (DG);
  68:  * 08-Jun-2005 : Fixed equals() method to handle GradientPaint (DG);
  69:  * 
  70:  */
  71: 
  72: package org.jfree.chart.renderer;
  73: 
  74: import java.awt.BasicStroke;
  75: import java.awt.Color;
  76: import java.awt.Font;
  77: import java.awt.Paint;
  78: import java.awt.Shape;
  79: import java.awt.Stroke;
  80: import java.awt.geom.Point2D;
  81: import java.awt.geom.Rectangle2D;
  82: import java.io.IOException;
  83: import java.io.ObjectInputStream;
  84: import java.io.ObjectOutputStream;
  85: import java.io.Serializable;
  86: import java.util.Arrays;
  87: import java.util.EventListener;
  88: import java.util.List;
  89: 
  90: import javax.swing.event.EventListenerList;
  91: 
  92: import org.jfree.chart.event.RendererChangeEvent;
  93: import org.jfree.chart.event.RendererChangeListener;
  94: import org.jfree.chart.labels.ItemLabelAnchor;
  95: import org.jfree.chart.labels.ItemLabelPosition;
  96: import org.jfree.chart.plot.DrawingSupplier;
  97: import org.jfree.chart.plot.PlotOrientation;
  98: import org.jfree.io.SerialUtilities;
  99: import org.jfree.ui.TextAnchor;
 100: import org.jfree.util.BooleanList;
 101: import org.jfree.util.BooleanUtilities;
 102: import org.jfree.util.ObjectList;
 103: import org.jfree.util.ObjectUtilities;
 104: import org.jfree.util.PaintList;
 105: import org.jfree.util.PaintUtilities;
 106: import org.jfree.util.ShapeList;
 107: import org.jfree.util.ShapeUtilities;
 108: import org.jfree.util.StrokeList;
 109: 
 110: /**
 111:  * Base class providing common services for renderers.  Most methods that update
 112:  * attributes of the renderer will fire a {@link RendererChangeEvent}, which 
 113:  * normally means the plot that owns the renderer will receive notification that
 114:  * the renderer has been changed (the plot will, in turn, notify the chart).
 115:  */
 116: public abstract class AbstractRenderer implements Cloneable, Serializable {
 117: 
 118:     /** For serialization. */
 119:     private static final long serialVersionUID = -828267569428206075L;
 120:     
 121:     /** A useful constant. */
 122:     public static final Double ZERO = new Double(0.0);
 123:     
 124:     /** The default paint. */
 125:     public static final Paint DEFAULT_PAINT = Color.blue;
 126: 
 127:     /** The default outline paint. */
 128:     public static final Paint DEFAULT_OUTLINE_PAINT = Color.gray;
 129: 
 130:     /** The default stroke. */
 131:     public static final Stroke DEFAULT_STROKE = new BasicStroke(1.0f);
 132: 
 133:     /** The default outline stroke. */
 134:     public static final Stroke DEFAULT_OUTLINE_STROKE = new BasicStroke(1.0f);
 135: 
 136:     /** The default shape. */
 137:     public static final Shape DEFAULT_SHAPE 
 138:         = new Rectangle2D.Double(-3.0, -3.0, 6.0, 6.0);
 139: 
 140:     /** The default value label font. */
 141:     public static final Font DEFAULT_VALUE_LABEL_FONT 
 142:         = new Font("SansSerif", Font.PLAIN, 10);
 143: 
 144:     /** The default value label paint. */
 145:     public static final Paint DEFAULT_VALUE_LABEL_PAINT = Color.black;
 146: 
 147:     /** A flag that controls the visibility of ALL series. */
 148:     private Boolean seriesVisible;
 149:     
 150:     /** A list of flags that controls whether or not each series is visible. */
 151:     private BooleanList seriesVisibleList;
 152: 
 153:     /** The default visibility for each series. */
 154:     private boolean baseSeriesVisible;
 155:     
 156:     /** A flag that controls the visibility of ALL series in the legend. */
 157:     private Boolean seriesVisibleInLegend;
 158:     
 159:     /** 
 160:      * A list of flags that controls whether or not each series is visible in 
 161:      * the legend. 
 162:      */
 163:     private BooleanList seriesVisibleInLegendList;
 164: 
 165:     /** The default visibility for each series in the legend. */
 166:     private boolean baseSeriesVisibleInLegend;
 167:         
 168:     /** The paint for ALL series (optional). */
 169:     private transient Paint paint;
 170: 
 171:     /** The paint list. */
 172:     private PaintList paintList;
 173: 
 174:     /** The base paint. */
 175:     private transient Paint basePaint;
 176: 
 177:     /** The fill paint for ALL series (optional). */
 178:     private transient Paint fillPaint;
 179: 
 180:     /** The fill paint list. */
 181:     private PaintList fillPaintList;
 182: 
 183:     /** The base fill paint. */
 184:     private transient Paint baseFillPaint;
 185: 
 186:     /** The outline paint for ALL series (optional). */
 187:     private transient Paint outlinePaint;
 188: 
 189:     /** The outline paint list. */
 190:     private PaintList outlinePaintList;
 191: 
 192:     /** The base outline paint. */
 193:     private transient Paint baseOutlinePaint;
 194: 
 195:     /** The stroke for ALL series (optional). */
 196:     private transient Stroke stroke;
 197: 
 198:     /** The stroke list. */
 199:     private StrokeList strokeList;
 200: 
 201:     /** The base stroke. */
 202:     private transient Stroke baseStroke;
 203: 
 204:     /** The outline stroke for ALL series (optional). */
 205:     private transient Stroke outlineStroke;
 206: 
 207:     /** The outline stroke list. */
 208:     private StrokeList outlineStrokeList;
 209: 
 210:     /** The base outline stroke. */
 211:     private transient Stroke baseOutlineStroke;
 212: 
 213:     /** The shape for ALL series (optional). */
 214:     private transient Shape shape;
 215: 
 216:     /** A shape list. */
 217:     private ShapeList shapeList;
 218: 
 219:     /** The base shape. */
 220:     private transient Shape baseShape;
 221: 
 222:     /** Visibility of the item labels for ALL series (optional). */
 223:     private Boolean itemLabelsVisible;
 224: 
 225:     /** Visibility of the item labels PER series. */
 226:     private BooleanList itemLabelsVisibleList;
 227: 
 228:     /** The base item labels visible. */
 229:     private Boolean baseItemLabelsVisible;
 230: 
 231:     /** The item label font for ALL series (optional). */
 232:     private Font itemLabelFont;
 233: 
 234:     /** The item label font list (one font per series). */
 235:     private ObjectList itemLabelFontList;
 236: 
 237:     /** The base item label font. */
 238:     private Font baseItemLabelFont;
 239: 
 240:     /** The item label paint for ALL series. */
 241:     private transient Paint itemLabelPaint;
 242: 
 243:     /** The item label paint list (one paint per series). */
 244:     private PaintList itemLabelPaintList;
 245: 
 246:     /** The base item label paint. */
 247:     private transient Paint baseItemLabelPaint;
 248: 
 249:     /** The positive item label position for ALL series (optional). */
 250:     private ItemLabelPosition positiveItemLabelPosition;
 251:     
 252:     /** The positive item label position (per series). */
 253:     private ObjectList positiveItemLabelPositionList;
 254:     
 255:     /** The fallback positive item label position. */
 256:     private ItemLabelPosition basePositiveItemLabelPosition;
 257:     
 258:     /** The negative item label position for ALL series (optional). */
 259:     private ItemLabelPosition negativeItemLabelPosition;
 260:     
 261:     /** The negative item label position (per series). */
 262:     private ObjectList negativeItemLabelPositionList;
 263:     
 264:     /** The fallback negative item label position. */
 265:     private ItemLabelPosition baseNegativeItemLabelPosition;
 266: 
 267:     /** The item label anchor offset. */
 268:     private double itemLabelAnchorOffset = 2.0;
 269: 
 270:     /** 
 271:      * A flag that controls whether or not entities are generated for 
 272:      * ALL series (optional). 
 273:      */
 274:     private Boolean createEntities;
 275: 
 276:     /** 
 277:      * Flags that control whether or not entities are generated for each 
 278:      * series.  This will be overridden by 'createEntities'. 
 279:      */
 280:     private BooleanList createEntitiesList;
 281: 
 282:     /**
 283:      * The default flag that controls whether or not entities are generated.
 284:      * This flag is used when both the above flags return null. 
 285:      */
 286:     private boolean baseCreateEntities;
 287:     
 288:     /** Storage for registered change listeners. */
 289:     private transient EventListenerList listenerList;
 290: 
 291:     /**
 292:      * Default constructor.
 293:      */
 294:     public AbstractRenderer() {
 295: 
 296:         this.seriesVisible = null;
 297:         this.seriesVisibleList = new BooleanList();
 298:         this.baseSeriesVisible = true;
 299:         
 300:         this.seriesVisibleInLegend = null;
 301:         this.seriesVisibleInLegendList = new BooleanList();
 302:         this.baseSeriesVisibleInLegend = true;
 303: 
 304:         this.paint = null;
 305:         this.paintList = new PaintList();
 306:         this.basePaint = DEFAULT_PAINT;
 307: 
 308:         this.fillPaint = null;
 309:         this.fillPaintList = new PaintList();
 310:         this.baseFillPaint = Color.white;
 311: 
 312:         this.outlinePaint = null;
 313:         this.outlinePaintList = new PaintList();
 314:         this.baseOutlinePaint = DEFAULT_OUTLINE_PAINT;
 315: 
 316:         this.stroke = null;
 317:         this.strokeList = new StrokeList();
 318:         this.baseStroke = DEFAULT_STROKE;
 319: 
 320:         this.outlineStroke = null;
 321:         this.outlineStrokeList = new StrokeList();
 322:         this.baseOutlineStroke = DEFAULT_OUTLINE_STROKE;
 323: 
 324:         this.shape = null;
 325:         this.shapeList = new ShapeList();
 326:         this.baseShape = DEFAULT_SHAPE;
 327: 
 328:         this.itemLabelsVisible = null;
 329:         this.itemLabelsVisibleList = new BooleanList();
 330:         this.baseItemLabelsVisible = Boolean.FALSE;
 331: 
 332:         this.itemLabelFont = null;
 333:         this.itemLabelFontList = new ObjectList();
 334:         this.baseItemLabelFont = new Font("SansSerif", Font.PLAIN, 10);
 335: 
 336:         this.itemLabelPaint = null;
 337:         this.itemLabelPaintList = new PaintList();
 338:         this.baseItemLabelPaint = Color.black;
 339: 
 340:         this.positiveItemLabelPosition = null;
 341:         this.positiveItemLabelPositionList = new ObjectList();
 342:         this.basePositiveItemLabelPosition = new ItemLabelPosition(
 343:             ItemLabelAnchor.OUTSIDE12, TextAnchor.BOTTOM_CENTER
 344:         );
 345:         
 346:         this.negativeItemLabelPosition = null;
 347:         this.negativeItemLabelPositionList = new ObjectList();
 348:         this.baseNegativeItemLabelPosition = new ItemLabelPosition(
 349:             ItemLabelAnchor.OUTSIDE6, TextAnchor.TOP_CENTER
 350:         );
 351: 
 352:         this.createEntities = null;
 353:         this.createEntitiesList = new BooleanList();
 354:         this.baseCreateEntities = true;
 355:         
 356:         this.listenerList = new EventListenerList();
 357: 
 358:     }
 359: 
 360:     /**
 361:      * Returns the drawing supplier from the plot.
 362:      * 
 363:      * @return The drawing supplier.
 364:      */
 365:     public abstract DrawingSupplier getDrawingSupplier();
 366:     
 367:     // SERIES VISIBLE (not yet respected by all renderers)
 368: 
 369:     /**
 370:      * Returns a boolean that indicates whether or not the specified item 
 371:      * should be drawn (this is typically used to hide an entire series).
 372:      * 
 373:      * @param series  the series index.
 374:      * @param item  the item index.
 375:      * 
 376:      * @return A boolean.
 377:      */
 378:     public boolean getItemVisible(int series, int item) {
 379:         return isSeriesVisible(series);
 380:     }
 381:     
 382:     /**
 383:      * Returns a boolean that indicates whether or not the specified series 
 384:      * should be drawn.
 385:      * 
 386:      * @param series  the series index.
 387:      * 
 388:      * @return A boolean.
 389:      */
 390:     public boolean isSeriesVisible(int series) {
 391:         boolean result = this.baseSeriesVisible;
 392:         if (this.seriesVisible != null) {
 393:             result = this.seriesVisible.booleanValue();   
 394:         }
 395:         else {
 396:             Boolean b = this.seriesVisibleList.getBoolean(series);
 397:             if (b != null) {
 398:                 result = b.booleanValue();   
 399:             }
 400:         }
 401:         return result;
 402:     }
 403:     
 404:     /**
 405:      * Returns the flag that controls the visibility of ALL series.  This flag 
 406:      * overrides the per series and default settings - you must set it to 
 407:      * <code>null</code> if you want the other settings to apply.
 408:      * 
 409:      * @return The flag (possibly <code>null</code>).
 410:      */
 411:     public Boolean getSeriesVisible() {
 412:         return this.seriesVisible;   
 413:     }
 414:     
 415:     /**
 416:      * Sets the flag that controls the visibility of ALL series and sends a 
 417:      * {@link RendererChangeEvent} to all registered listeners.  This flag 
 418:      * overrides the per series and default settings - you must set it to 
 419:      * <code>null</code> if you want the other settings to apply.
 420:      * 
 421:      * @param visible  the flag (<code>null</code> permitted).
 422:      */
 423:     public void setSeriesVisible(Boolean visible) {
 424:          setSeriesVisible(visible, true);
 425:     }
 426:     
 427:     /**
 428:      * Sets the flag that controls the visibility of ALL series and sends a 
 429:      * {@link RendererChangeEvent} to all registered listeners.  This flag 
 430:      * overrides the per series and default settings - you must set it to 
 431:      * <code>null</code> if you want the other settings to apply.
 432:      * 
 433:      * @param visible  the flag (<code>null</code> permitted).
 434:      * @param notify  notify listeners?
 435:      */
 436:     public void setSeriesVisible(Boolean visible, boolean notify) {
 437:         this.seriesVisible = visible;   
 438:         if (notify) {
 439:             notifyListeners(new RendererChangeEvent(this));
 440:         }
 441:     }
 442:     
 443:     /**
 444:      * Returns the flag that controls whether a series is visible.
 445:      *
 446:      * @param series  the series index (zero-based).
 447:      *
 448:      * @return The flag (possibly <code>null</code>).
 449:      */
 450:     public Boolean getSeriesVisible(int series) {
 451:         return this.seriesVisibleList.getBoolean(series);
 452:     }
 453:     
 454:     /**
 455:      * Sets the flag that controls whether a series is visible and sends a 
 456:      * {@link RendererChangeEvent} to all registered listeners.
 457:      *
 458:      * @param series  the series index (zero-based).
 459:      * @param visible  the flag (<code>null</code> permitted).
 460:      */
 461:     public void setSeriesVisible(int series, Boolean visible) {
 462:         setSeriesVisible(series, visible, true);
 463:     }
 464:     
 465:     /**
 466:      * Sets the flag that controls whether a series is visible and, if 
 467:      * requested, sends a {@link RendererChangeEvent} to all registered 
 468:      * listeners.
 469:      * 
 470:      * @param series  the series index.
 471:      * @param visible  the flag (<code>null</code> permitted).
 472:      * @param notify  notify listeners?
 473:      */
 474:     public void setSeriesVisible(int series, Boolean visible, boolean notify) {
 475:         this.seriesVisibleList.setBoolean(series, visible);       
 476:         if (notify) {
 477:             notifyListeners(new RendererChangeEvent(this));
 478:         }
 479:     }
 480: 
 481:     /**
 482:      * Returns the base visibility for all series.
 483:      *
 484:      * @return The base visibility.
 485:      */
 486:     public boolean getBaseSeriesVisible() {
 487:         return this.baseSeriesVisible;
 488:     }
 489: 
 490:     /**
 491:      * Sets the base visibility and sends a {@link RendererChangeEvent} 
 492:      * to all registered listeners.
 493:      *
 494:      * @param visible  the flag.
 495:      */
 496:     public void setBaseSeriesVisible(boolean visible) {
 497:         // defer argument checking...
 498:         setBaseSeriesVisible(visible, true);
 499:     }
 500:     
 501:     /**
 502:      * Sets the base visibility and, if requested, sends 
 503:      * a {@link RendererChangeEvent} to all registered listeners.
 504:      * 
 505:      * @param visible  the visibility.
 506:      * @param notify  notify listeners?
 507:      */
 508:     public void setBaseSeriesVisible(boolean visible, boolean notify) {
 509:         this.baseSeriesVisible = visible;
 510:         if (notify) {
 511:             notifyListeners(new RendererChangeEvent(this));
 512:         }
 513:     }
 514: 
 515:     // SERIES VISIBLE IN LEGEND (not yet respected by all renderers)
 516:     
 517:     /**
 518:      * Returns <code>true</code> if the series should be shown in the legend,
 519:      * and <code>false</code> otherwise.
 520:      * 
 521:      * @param series  the series index.
 522:      * 
 523:      * @return A boolean.
 524:      */
 525:     public boolean isSeriesVisibleInLegend(int series) {
 526:         boolean result = this.baseSeriesVisibleInLegend;
 527:         if (this.seriesVisibleInLegend != null) {
 528:             result = this.seriesVisibleInLegend.booleanValue();   
 529:         }
 530:         else {
 531:             Boolean b = this.seriesVisibleInLegendList.getBoolean(series);
 532:             if (b != null) {
 533:                 result = b.booleanValue();   
 534:             }
 535:         }
 536:         return result;
 537:     }
 538:     
 539:     /**
 540:      * Returns the flag that controls the visibility of ALL series in the 
 541:      * legend.  This flag overrides the per series and default settings - you 
 542:      * must set it to <code>null</code> if you want the other settings to 
 543:      * apply.
 544:      * 
 545:      * @return The flag (possibly <code>null</code>).
 546:      */
 547:     public Boolean getSeriesVisibleInLegend() {
 548:         return this.seriesVisibleInLegend;   
 549:     }
 550:     
 551:     /**
 552:      * Sets the flag that controls the visibility of ALL series in the legend 
 553:      * and sends a {@link RendererChangeEvent} to all registered listeners.  
 554:      * This flag overrides the per series and default settings - you must set 
 555:      * it to <code>null</code> if you want the other settings to apply.
 556:      * 
 557:      * @param visible  the flag (<code>null</code> permitted).
 558:      */
 559:     public void setSeriesVisibleInLegend(Boolean visible) {
 560:          setSeriesVisibleInLegend(visible, true);
 561:     }
 562:     
 563:     /**
 564:      * Sets the flag that controls the visibility of ALL series in the legend 
 565:      * and sends a {@link RendererChangeEvent} to all registered listeners.  
 566:      * This flag overrides the per series and default settings - you must set 
 567:      * it to <code>null</code> if you want the other settings to apply.
 568:      * 
 569:      * @param visible  the flag (<code>null</code> permitted).
 570:      * @param notify  notify listeners?
 571:      */
 572:     public void setSeriesVisibleInLegend(Boolean visible, boolean notify) {
 573:         this.seriesVisibleInLegend = visible;   
 574:         if (notify) {
 575:             notifyListeners(new RendererChangeEvent(this));
 576:         }
 577:     }
 578:     
 579:     /**
 580:      * Returns the flag that controls whether a series is visible in the 
 581:      * legend.  This method returns only the "per series" settings - to 
 582:      * incorporate the override and base settings as well, you need to use the 
 583:      * {@link #isSeriesVisibleInLegend(int)} method.
 584:      *
 585:      * @param series  the series index (zero-based).
 586:      *
 587:      * @return The flag (possibly <code>null</code>).
 588:      */
 589:     public Boolean getSeriesVisibleInLegend(int series) {
 590:         return this.seriesVisibleInLegendList.getBoolean(series);
 591:     }
 592:     
 593:     /**
 594:      * Sets the flag that controls whether a series is visible in the legend 
 595:      * and sends a {@link RendererChangeEvent} to all registered listeners.
 596:      *
 597:      * @param series  the series index (zero-based).
 598:      * @param visible  the flag (<code>null</code> permitted).
 599:      */
 600:     public void setSeriesVisibleInLegend(int series, Boolean visible) {
 601:         setSeriesVisibleInLegend(series, visible, true);
 602:     }
 603:     
 604:     /**
 605:      * Sets the flag that controls whether a series is visible in the legend
 606:      * and, if requested, sends a {@link RendererChangeEvent} to all registered 
 607:      * listeners.
 608:      * 
 609:      * @param series  the series index.
 610:      * @param visible  the flag (<code>null</code> permitted).
 611:      * @param notify  notify listeners?
 612:      */
 613:     public void setSeriesVisibleInLegend(int series, Boolean visible, 
 614:                                          boolean notify) {
 615:         this.seriesVisibleInLegendList.setBoolean(series, visible);       
 616:         if (notify) {
 617:             notifyListeners(new RendererChangeEvent(this));
 618:         }
 619:     }
 620: 
 621:     /**
 622:      * Returns the base visibility in the legend for all series.
 623:      *
 624:      * @return The base visibility.
 625:      */
 626:     public boolean getBaseSeriesVisibleInLegend() {
 627:         return this.baseSeriesVisibleInLegend;
 628:     }
 629: 
 630:     /**
 631:      * Sets the base visibility in the legend and sends a 
 632:      * {@link RendererChangeEvent} to all registered listeners.
 633:      *
 634:      * @param visible  the flag.
 635:      */
 636:     public void setBaseSeriesVisibleInLegend(boolean visible) {
 637:         // defer argument checking...
 638:         setBaseSeriesVisibleInLegend(visible, true);
 639:     }
 640:     
 641:     /**
 642:      * Sets the base visibility in the legend and, if requested, sends 
 643:      * a {@link RendererChangeEvent} to all registered listeners.
 644:      * 
 645:      * @param visible  the visibility.
 646:      * @param notify  notify listeners?
 647:      */
 648:     public void setBaseSeriesVisibleInLegend(boolean visible, boolean notify) {
 649:         this.baseSeriesVisibleInLegend = visible;
 650:         if (notify) {
 651:             notifyListeners(new RendererChangeEvent(this));
 652:         }
 653:     }
 654: 
 655:     // PAINT
 656:     
 657:     /**
 658:      * Returns the paint used to fill data items as they are drawn.
 659:      * <p>
 660:      * The default implementation passes control to the 
 661:      * <code>getSeriesPaint</code> method. You can override this method if you 
 662:      * require different behaviour.
 663:      *
 664:      * @param row  the row (or series) index (zero-based).
 665:      * @param column  the column (or category) index (zero-based).
 666:      *
 667:      * @return The paint (never <code>null</code>).
 668:      */
 669:     public Paint getItemPaint(int row, int column) {
 670:         return getSeriesPaint(row);
 671:     }
 672: 
 673:     /**
 674:      * Returns the paint used to fill an item drawn by the renderer.
 675:      *
 676:      * @param series  the series index (zero-based).
 677:      *
 678:      * @return The paint (never <code>null</code>).
 679:      */
 680:     public Paint getSeriesPaint(int series) {
 681: 
 682:         // return the override, if there is one...
 683:         if (this.paint != null) {
 684:             return this.paint;
 685:         }
 686: 
 687:         // otherwise look up the paint list
 688:         Paint seriesPaint = this.paintList.getPaint(series);
 689:         if (seriesPaint == null) {
 690:             DrawingSupplier supplier = getDrawingSupplier();
 691:             if (supplier != null) {
 692:                 seriesPaint = supplier.getNextPaint();
 693:                 this.paintList.setPaint(series, seriesPaint);
 694:             }
 695:             else {
 696:                 seriesPaint = this.basePaint;
 697:             }
 698:         }
 699:         return seriesPaint;
 700: 
 701:     }
 702: 
 703:     /**
 704:      * Sets the paint to be used for ALL series, and sends a 
 705:      * {@link RendererChangeEvent} to all registered listeners.  If this is 
 706:      * <code>null</code>, the renderer will use the paint for the series.
 707:      * 
 708:      * @param paint  the paint (<code>null</code> permitted).
 709:      */
 710:     public void setPaint(Paint paint) {
 711:         setPaint(paint, true);
 712:     }
 713:     
 714:     /**
 715:      * Sets the paint to be used for all series and, if requested, sends a 
 716:      * {@link RendererChangeEvent} to all registered listeners.
 717:      * 
 718:      * @param paint  the paint (<code>null</code> permitted).
 719:      * @param notify  notify listeners?
 720:      */
 721:     public void setPaint(Paint paint, boolean notify) {
 722:         this.paint = paint;
 723:         if (notify) {
 724:             notifyListeners(new RendererChangeEvent(this));
 725:         }
 726:     }
 727:     
 728:     /**
 729:      * Sets the paint used for a series and sends a {@link RendererChangeEvent}
 730:      * to all registered listeners.
 731:      *
 732:      * @param series  the series index (zero-based).
 733:      * @param paint  the paint (<code>null</code> permitted).
 734:      */
 735:     public void setSeriesPaint(int series, Paint paint) {
 736:         setSeriesPaint(series, paint, true);
 737:     }
 738:     
 739:     /**
 740:      * Sets the paint used for a series and, if requested, sends a 
 741:      * {@link RendererChangeEvent} to all registered listeners.
 742:      * 
 743:      * @param series  the series index.
 744:      * @param paint  the paint (<code>null</code> permitted).
 745:      * @param notify  notify listeners?
 746:      */
 747:     public void setSeriesPaint(int series, Paint paint, boolean notify) {
 748:         this.paintList.setPaint(series, paint);       
 749:         if (notify) {
 750:             notifyListeners(new RendererChangeEvent(this));
 751:         }
 752:     }
 753: 
 754:     /**
 755:      * Returns the base paint.
 756:      *
 757:      * @return The base paint (never <code>null</code>).
 758:      */
 759:     public Paint getBasePaint() {
 760:         return this.basePaint;
 761:     }
 762: 
 763:     /**
 764:      * Sets the base paint and sends a {@link RendererChangeEvent} to all 
 765:      * registered listeners.
 766:      *
 767:      * @param paint  the paint (<code>null</code> not permitted).
 768:      */
 769:     public void setBasePaint(Paint paint) {
 770:         // defer argument checking...
 771:         setBasePaint(paint, true);
 772:     }
 773:     
 774:     /**
 775:      * Sets the base paint and, if requested, sends a 
 776:      * {@link RendererChangeEvent} to all registered listeners.
 777:      * 
 778:      * @param paint  the paint (<code>null</code> not permitted).
 779:      * @param notify  notify listeners?
 780:      */
 781:     public void setBasePaint(Paint paint, boolean notify) {
 782:         this.basePaint = paint;
 783:         if (notify) {
 784:             notifyListeners(new RendererChangeEvent(this));
 785:         }
 786:     }
 787: 
 788:     //// FILL PAINT //////////////////////////////////////////////////////////
 789:     
 790:     /**
 791:      * Returns the paint used to fill data items as they are drawn.  The 
 792:      * default implementation passes control to the 
 793:      * {@link #getSeriesFillPaint(int)} method - you can override this method 
 794:      * if you require different behaviour.
 795:      *
 796:      * @param row  the row (or series) index (zero-based).
 797:      * @param column  the column (or category) index (zero-based).
 798:      *
 799:      * @return The paint (never <code>null</code>).
 800:      */
 801:     public Paint getItemFillPaint(int row, int column) {
 802:         return getSeriesFillPaint(row);
 803:     }
 804: 
 805:     /**
 806:      * Returns the paint used to fill an item drawn by the renderer.
 807:      *
 808:      * @param series  the series (zero-based index).
 809:      *
 810:      * @return The paint (never <code>null</code>).
 811:      */
 812:     public Paint getSeriesFillPaint(int series) {
 813: 
 814:         // return the override, if there is one...
 815:         if (this.fillPaint != null) {
 816:             return this.fillPaint;
 817:         }
 818: 
 819:         // otherwise look up the paint table
 820:         Paint seriesFillPaint = this.fillPaintList.getPaint(series);
 821:         if (seriesFillPaint == null) {
 822:             seriesFillPaint = this.baseFillPaint;
 823:         }
 824:         return seriesFillPaint;
 825: 
 826:     }
 827: 
 828:     /**
 829:      * Sets the paint used for a series fill and sends a 
 830:      * {@link RendererChangeEvent} to all registered listeners.
 831:      *
 832:      * @param series  the series index (zero-based).
 833:      * @param paint  the paint (<code>null</code> permitted).
 834:      */
 835:     public void setSeriesFillPaint(int series, Paint paint) {
 836:         setSeriesFillPaint(series, paint, true);
 837:     }
 838: 
 839:     /**
 840:      * Sets the paint used to fill a series and, if requested, 
 841:      * sends a {@link RendererChangeEvent} to all registered listeners.
 842:      * 
 843:      * @param series  the series index (zero-based).
 844:      * @param paint  the paint (<code>null</code> permitted).
 845:      * @param notify  notify listeners?
 846:      */    
 847:     public void setSeriesFillPaint(int series, Paint paint, boolean notify) {
 848:         this.fillPaintList.setPaint(series, paint);
 849:         if (notify) {
 850:             notifyListeners(new RendererChangeEvent(this));
 851:         }
 852:     }
 853: 
 854:     /**
 855:      * Sets the fill paint for ALL series (optional).
 856:      * 
 857:      * @param paint  the paint (<code>null</code> permitted).
 858:      */
 859:     public void setFillPaint(Paint paint) {
 860:         setFillPaint(paint, true);
 861:     }
 862: 
 863:     /**
 864:      * Sets the fill paint for ALL series and, if requested, sends a 
 865:      * {@link RendererChangeEvent} to all registered listeners.
 866:      * 
 867:      * @param paint  the paint (<code>null</code> permitted).
 868:      * @param notify  notify listeners?
 869:      */
 870:     public void setFillPaint(Paint paint, boolean notify) {
 871:         this.fillPaint = paint;
 872:         if (notify) {
 873:             notifyListeners(new RendererChangeEvent(this));
 874:         }
 875:     }
 876:     
 877:     /**
 878:      * Returns the base fill paint.
 879:      *
 880:      * @return The paint (never <code>null</code>).
 881:      */
 882:     public Paint getBaseFillPaint() {
 883:         return this.baseFillPaint;
 884:     }
 885: 
 886:     /**
 887:      * Sets the base fill paint and sends a {@link RendererChangeEvent} to 
 888:      * all registered listeners.
 889:      *
 890:      * @param paint  the paint (<code>null</code> not permitted).
 891:      */
 892:     public void setBaseFillPaint(Paint paint) {
 893:         // defer argument checking...
 894:         setBaseFillPaint(paint, true);
 895:     }
 896:     
 897:     /**
 898:      * Sets the base fill paint and, if requested, sends a 
 899:      * {@link RendererChangeEvent} to all registered listeners.
 900:      * 
 901:      * @param paint  the paint (<code>null</code> not permitted).
 902:      * @param notify  notify listeners?
 903:      */
 904:     public void setBaseFillPaint(Paint paint, boolean notify) {
 905:         if (paint == null) {
 906:             throw new IllegalArgumentException("Null 'paint' argument.");   
 907:         }
 908:         this.baseFillPaint = paint;
 909:         if (notify) {
 910:             notifyListeners(new RendererChangeEvent(this));
 911:         }
 912:     }
 913: 
 914:     // OUTLINE PAINT //////////////////////////////////////////////////////////
 915:     
 916:     /**
 917:      * Returns the paint used to outline data items as they are drawn.
 918:      * <p>
 919:      * The default implementation passes control to the getSeriesOutlinePaint 
 920:      * method.  You can override this method if you require different behaviour.
 921:      *
 922:      * @param row  the row (or series) index (zero-based).
 923:      * @param column  the column (or category) index (zero-based).
 924:      *
 925:      * @return The paint (never <code>null</code>).
 926:      */
 927:     public Paint getItemOutlinePaint(int row, int column) {
 928:         return getSeriesOutlinePaint(row);
 929:     }
 930: 
 931:     /**
 932:      * Returns the paint used to outline an item drawn by the renderer.
 933:      *
 934:      * @param series  the series (zero-based index).
 935:      *
 936:      * @return The paint (never <code>null</code>).
 937:      */
 938:     public Paint getSeriesOutlinePaint(int series) {
 939: 
 940:         // return the override, if there is one...
 941:         if (this.outlinePaint != null) {
 942:             return this.outlinePaint;
 943:         }
 944: 
 945:         // otherwise look up the paint table
 946:         Paint seriesOutlinePaint = this.outlinePaintList.getPaint(series);
 947:         if (seriesOutlinePaint == null) {
 948:             DrawingSupplier supplier = getDrawingSupplier();
 949:             if (supplier != null) {
 950:                 seriesOutlinePaint = supplier.getNextOutlinePaint();
 951:                 this.outlinePaintList.setPaint(series, seriesOutlinePaint);
 952:             }
 953:             else {
 954:                 seriesOutlinePaint = this.baseOutlinePaint;
 955:             }
 956:         }
 957:         return seriesOutlinePaint;
 958: 
 959:     }
 960: 
 961:     /**
 962:      * Sets the paint used for a series outline and sends a 
 963:      * {@link RendererChangeEvent} to all registered listeners.
 964:      *
 965:      * @param series  the series index (zero-based).
 966:      * @param paint  the paint (<code>null</code> permitted).
 967:      */
 968:     public void setSeriesOutlinePaint(int series, Paint paint) {
 969:         setSeriesOutlinePaint(series, paint, true);
 970:     }
 971: 
 972:     /**
 973:      * Sets the paint used to draw the outline for a series and, if requested, 
 974:      * sends a {@link RendererChangeEvent} to all registered listeners.
 975:      * 
 976:      * @param series  the series index (zero-based).
 977:      * @param paint  the paint (<code>null</code> permitted).
 978:      * @param notify  notify listeners?
 979:      */    
 980:     public void setSeriesOutlinePaint(int series, Paint paint, boolean notify) {
 981:         this.outlinePaintList.setPaint(series, paint);
 982:         if (notify) {
 983:             notifyListeners(new RendererChangeEvent(this));
 984:         }
 985:     }
 986: 
 987:     /**
 988:      * Sets the outline paint for ALL series (optional).
 989:      * 
 990:      * @param paint  the paint (<code>null</code> permitted).
 991:      */
 992:     public void setOutlinePaint(Paint paint) {
 993:         setOutlinePaint(paint, true);
 994:     }
 995: 
 996:     /**
 997:      * Sets the outline paint for ALL series and, if requested, sends a 
 998:      * {@link RendererChangeEvent} to all registered listeners.
 999:      * 
1000:      * @param paint  the paint (<code>null</code> permitted).
1001:      * @param notify  notify listeners?
1002:      */
1003:     public void setOutlinePaint(Paint paint, boolean notify) {
1004:         this.outlinePaint = paint;
1005:         if (notify) {
1006:             notifyListeners(new RendererChangeEvent(this));
1007:         }
1008:     }
1009:     
1010:     /**
1011:      * Returns the base outline paint.
1012:      *
1013:      * @return The paint (never <code>null</code>).
1014:      */
1015:     public Paint getBaseOutlinePaint() {
1016:         return this.baseOutlinePaint;
1017:     }
1018: 
1019:     /**
1020:      * Sets the base outline paint and sends a {@link RendererChangeEvent} to 
1021:      * all registered listeners.
1022:      *
1023:      * @param paint  the paint (<code>null</code> not permitted).
1024:      */
1025:     public void setBaseOutlinePaint(Paint paint) {
1026:         // defer argument checking...
1027:         setBaseOutlinePaint(paint, true);
1028:     }
1029:     
1030:     /**
1031:      * Sets the base outline paint and, if requested, sends a 
1032:      * {@link RendererChangeEvent} to all registered listeners.
1033:      * 
1034:      * @param paint  the paint (<code>null</code> not permitted).
1035:      * @param notify  notify listeners?
1036:      */
1037:     public void setBaseOutlinePaint(Paint paint, boolean notify) {
1038:         if (paint == null) {
1039:             throw new IllegalArgumentException("Null 'paint' argument.");   
1040:         }
1041:         this.baseOutlinePaint = paint;
1042:         if (notify) {
1043:             notifyListeners(new RendererChangeEvent(this));
1044:         }
1045:     }
1046: 
1047:     // STROKE
1048:     
1049:     /**
1050:      * Returns the stroke used to draw data items.
1051:      * <p>
1052:      * The default implementation passes control to the getSeriesStroke method.
1053:      * You can override this method if you require different behaviour.
1054:      *
1055:      * @param row  the row (or series) index (zero-based).
1056:      * @param column  the column (or category) index (zero-based).
1057:      *
1058:      * @return The stroke (never <code>null</code>).
1059:      */
1060:     public Stroke getItemStroke(int row, int column) {
1061:         return getSeriesStroke(row);
1062:     }
1063: 
1064:     /**
1065:      * Returns the stroke used to draw the items in a series.
1066:      *
1067:      * @param series  the series (zero-based index).
1068:      *
1069:      * @return The stroke (never <code>null</code>).
1070:      */
1071:     public Stroke getSeriesStroke(int series) {
1072: 
1073:         // return the override, if there is one...
1074:         if (this.stroke != null) {
1075:             return this.stroke;
1076:         }
1077: 
1078:         // otherwise look up the paint table
1079:         Stroke result = this.strokeList.getStroke(series);
1080:         if (result == null) {
1081:             DrawingSupplier supplier = getDrawingSupplier();
1082:             if (supplier != null) {
1083:                 result = supplier.getNextStroke();
1084:                 this.strokeList.setStroke(series, result);
1085:             }
1086:             else {
1087:                 result = this.baseStroke;
1088:             }
1089:         }
1090:         return result;
1091: 
1092:     }
1093:     
1094:     /**
1095:      * Sets the stroke for ALL series and sends a {@link RendererChangeEvent} 
1096:      * to all registered listeners.
1097:      * 
1098:      * @param stroke  the stroke (<code>null</code> permitted).
1099:      */
1100:     public void setStroke(Stroke stroke) {
1101:         setStroke(stroke, true);
1102:     }
1103:     
1104:     /**
1105:      * Sets the stroke for ALL series and, if requested, sends a 
1106:      * {@link RendererChangeEvent} to all registered listeners.
1107:      * 
1108:      * @param stroke  the stroke (<code>null</code> permitted).
1109:      * @param notify  notify listeners?
1110:      */
1111:     public void setStroke(Stroke stroke, boolean notify) {
1112:         this.stroke = stroke;
1113:         if (notify) {
1114:             notifyListeners(new RendererChangeEvent(this));
1115:         }
1116:     }    
1117: 
1118:     /**
1119:      * Sets the stroke used for a series and sends a {@link RendererChangeEvent}
1120:      * to all registered listeners.
1121:      *
1122:      * @param series  the series index (zero-based).
1123:      * @param stroke  the stroke (<code>null</code> permitted).
1124:      */
1125:     public void setSeriesStroke(int series, Stroke stroke) {
1126:         setSeriesStroke(series, stroke, true);
1127:     }
1128:     
1129:     /**
1130:      * Sets the stroke for a series and, if requested, sends a 
1131:      * {@link RendererChangeEvent} to all registered listeners.
1132:      * 
1133:      * @param series  the series index (zero-based).
1134:      * @param stroke  the stroke (<code>null</code> permitted).
1135:      * @param notify  notify listeners?
1136:      */
1137:     public void setSeriesStroke(int series, Stroke stroke, boolean notify) {
1138:         this.strokeList.setStroke(series, stroke);
1139:         if (notify) {
1140:             notifyListeners(new RendererChangeEvent(this));
1141:         }
1142:     }    
1143: 
1144:     /**
1145:      * Returns the base stroke.
1146:      *
1147:      * @return The base stroke (never <code>null</code>).
1148:      */
1149:     public Stroke getBaseStroke() {
1150:         return this.baseStroke;
1151:     }
1152: 
1153:     /**
1154:      * Sets the base stroke.
1155:      *
1156:      * @param stroke  the stroke (<code>null</code> not permitted).
1157:      */
1158:     public void setBaseStroke(Stroke stroke) {
1159:         // defer argument checking...
1160:         setBaseStroke(stroke, true);
1161:     }
1162: 
1163:     /**
1164:      * Sets the base stroke and, if requested, sends a 
1165:      * {@link RendererChangeEvent} to all registered listeners.
1166:      * 
1167:      * @param stroke  the stroke (<code>null</code> not permitted).
1168:      * @param notify  notify listeners?
1169:      */
1170:     public void setBaseStroke(Stroke stroke, boolean notify) {
1171:         if (stroke == null) {
1172:             throw new IllegalArgumentException("Null 'stroke' argument.");   
1173:         }
1174:         this.baseStroke = stroke;
1175:         if (notify) {
1176:             notifyListeners(new RendererChangeEvent(this));
1177:         }
1178:     }    
1179: 
1180:     // OUTLINE STROKE 
1181:     
1182:     /**
1183:      * Returns the stroke used to outline data items.  The default 
1184:      * implementation passes control to the {@link #getSeriesOutlineStroke(int)}
1185:      * method. You can override this method if you require different behaviour.
1186:      *
1187:      * @param row  the row (or series) index (zero-based).
1188:      * @param column  the column (or category) index (zero-based).
1189:      *
1190:      * @return The stroke (never <code>null</code>).
1191:      */
1192:     public Stroke getItemOutlineStroke(int row, int column) {
1193:         return getSeriesOutlineStroke(row);
1194:     }
1195: 
1196:     /**
1197:      * Returns the stroke used to outline the items in a series.
1198:      *
1199:      * @param series  the series (zero-based index).
1200:      *
1201:      * @return The stroke (never <code>null</code>).
1202:      */
1203:     public Stroke getSeriesOutlineStroke(int series) {
1204: 
1205:         // return the override, if there is one...
1206:         if (this.outlineStroke != null) {
1207:             return this.outlineStroke;
1208:         }
1209: 
1210:         // otherwise look up the stroke table
1211:         Stroke result = this.outlineStrokeList.getStroke(series);
1212:         if (result == null) {
1213:             DrawingSupplier supplier = getDrawingSupplier();
1214:             if (supplier != null) {
1215:                 result = supplier.getNextOutlineStroke();
1216:                 this.outlineStrokeList.setStroke(series, result);
1217:             }
1218:             else {
1219:                 result = this.baseOutlineStroke;
1220:             }
1221:         }
1222:         return result;
1223: 
1224:     }
1225: 
1226:     /**
1227:      * Sets the outline stroke for ALL series and sends a 
1228:      * {@link RendererChangeEvent} to all registered listeners.
1229:      *
1230:      * @param stroke  the stroke (<code>null</code> permitted).
1231:      */
1232:     public void setOutlineStroke(Stroke stroke) {
1233:         setOutlineStroke(stroke, true);
1234:     }
1235: 
1236:     /**
1237:      * Sets the outline stroke for ALL series and, if requested, sends a 
1238:      * {@link RendererChangeEvent} to all registered listeners.
1239:      * 
1240:      * @param stroke  the stroke (<code>null</code> permitted).
1241:      * @param notify  notify listeners?
1242:      */
1243:     public void setOutlineStroke(Stroke stroke, boolean notify) {
1244:         this.outlineStroke = stroke;
1245:         if (notify) {
1246:             notifyListeners(new RendererChangeEvent(this));
1247:         }
1248:     }
1249:     
1250:     /**
1251:      * Sets the outline stroke used for a series and sends a 
1252:      * {@link RendererChangeEvent} to all registered listeners.
1253:      *
1254:      * @param series  the series index (zero-based).
1255:      * @param stroke  the stroke (<code>null</code> permitted).
1256:      */
1257:     public void setSeriesOutlineStroke(int series, Stroke stroke) {
1258:         setSeriesOutlineStroke(series, stroke, true);
1259:     }
1260: 
1261:     /**
1262:      * Sets the outline stroke for a series and, if requested, sends a 
1263:      * {@link RendererChangeEvent} to all registered listeners.
1264:      * 
1265:      * @param series  the series index.
1266:      * @param stroke  the stroke (<code>null</code> permitted).
1267:      * @param notify  notify listeners?
1268:      */
1269:     public void setSeriesOutlineStroke(int series, Stroke stroke, 
1270:                                        boolean notify) {
1271:         this.outlineStrokeList.setStroke(series, stroke);
1272:         if (notify) {
1273:             notifyListeners(new RendererChangeEvent(this));
1274:         }
1275:     }
1276:     
1277:     /**
1278:      * Returns the base outline stroke.
1279:      *
1280:      * @return The stroke (never <code>null</code>).
1281:      */
1282:     public Stroke getBaseOutlineStroke() {
1283:         return this.baseOutlineStroke;
1284:     }
1285: 
1286:     /**
1287:      * Sets the base outline stroke and sends a {@link RendererChangeEvent} to 
1288:      * all registered listeners.
1289:      *
1290:      * @param stroke  the stroke (<code>null</code> not permitted).
1291:      */
1292:     public void setBaseOutlineStroke(Stroke stroke) {
1293:         setBaseOutlineStroke(stroke, true);
1294:     }
1295: 
1296:     /**
1297:      * Sets the base outline stroke and, if requested, sends a 
1298:      * {@link RendererChangeEvent} to all registered listeners.
1299:      * 
1300:      * @param stroke  the stroke (<code>null</code> not permitted).
1301:      * @param notify  a flag that controls whether or not listeners are 
1302:      *                notified.
1303:      */
1304:     public void setBaseOutlineStroke(Stroke stroke, boolean notify) {
1305:         if (stroke == null) {
1306:             throw new IllegalArgumentException("Null 'stroke' argument.");
1307:         }
1308:         this.baseOutlineStroke = stroke;
1309:         if (notify) {
1310:             notifyListeners(new RendererChangeEvent(this));
1311:         }
1312:     }
1313:     
1314:     // SHAPE
1315:     
1316:     /**
1317:      * Returns a shape used to represent a data item.
1318:      * <p>
1319:      * The default implementation passes control to the getSeriesShape method.
1320:      * You can override this method if you require different behaviour.
1321:      *
1322:      * @param row  the row (or series) index (zero-based).
1323:      * @param column  the column (or category) index (zero-based).
1324:      *
1325:      * @return The shape (never <code>null</code>).
1326:      */
1327:     public Shape getItemShape(int row, int column) {
1328:         return getSeriesShape(row);
1329:     }
1330: 
1331:     /**
1332:      * Returns a shape used to represent the items in a series.
1333:      *
1334:      * @param series  the series (zero-based index).
1335:      *
1336:      * @return The shape (never <code>null</code>).
1337:      */
1338:     public Shape getSeriesShape(int series) {
1339: 
1340:         // return the override, if there is one...
1341:         if (this.shape != null) {
1342:             return this.shape;
1343:         }
1344: 
1345:         // otherwise look up the shape list
1346:         Shape result = this.shapeList.getShape(series);
1347:         if (result == null) {
1348:             DrawingSupplier supplier = getDrawingSupplier();
1349:             if (supplier != null) {
1350:                 result = supplier.getNextShape();
1351:                 this.shapeList.setShape(series, result);
1352:             }
1353:             else {
1354:                 result = this.baseShape;
1355:             }
1356:         }
1357:         return result;
1358: 
1359:     }
1360: 
1361:     /**
1362:      * Sets the shape for ALL series (optional) and sends a 
1363:      * {@link RendererChangeEvent} to all registered listeners.
1364:      * 
1365:      * @param shape  the shape (<code>null</code> permitted).
1366:      */
1367:     public void setShape(Shape shape) {
1368:         setShape(shape, true);
1369:     }
1370:     
1371:     /**
1372:      * Sets the shape for ALL series and, if requested, sends a 
1373:      * {@link RendererChangeEvent} to all registered listeners.
1374:      * 
1375:      * @param shape  the shape (<code>null</code> permitted).
1376:      * @param notify  notify listeners?
1377:      */
1378:     public void setShape(Shape shape, boolean notify) {
1379:         this.shape = shape;
1380:         if (notify) {
1381:             notifyListeners(new RendererChangeEvent(this));
1382:         }
1383:     }
1384:     
1385:     /**
1386:      * Sets the shape used for a series and sends a {@link RendererChangeEvent} 
1387:      * to all registered listeners.
1388:      *
1389:      * @param series  the series index (zero-based).
1390:      * @param shape  the shape (<code>null</code> permitted).
1391:      */
1392:     public void setSeriesShape(int series, Shape shape) {
1393:         setSeriesShape(series, shape, true);
1394:     }
1395: 
1396:     /**
1397:      * Sets the shape for a series and, if requested, sends a 
1398:      * {@link RendererChangeEvent} to all registered listeners.
1399:      * 
1400:      * @param series  the series index (zero based).
1401:      * @param shape  the shape (<code>null</code> permitted).
1402:      * @param notify  notify listeners?
1403:      */
1404:     public void setSeriesShape(int series, Shape shape, boolean notify) {
1405:         this.shapeList.setShape(series, shape);
1406:         if (notify) {
1407:             notifyListeners(new RendererChangeEvent(this));
1408:         }
1409:     }
1410:     
1411:     /**
1412:      * Returns the base shape.
1413:      *
1414:      * @return The shape (never <code>null</code>).
1415:      */
1416:     public Shape getBaseShape() {
1417:         return this.baseShape;
1418:     }
1419: 
1420:     /**
1421:      * Sets the base shape and sends a {@link RendererChangeEvent} to all 
1422:      * registered listeners.
1423:      *
1424:      * @param shape  the shape (<code>null</code> not permitted).
1425:      */
1426:     public void setBaseShape(Shape shape) {
1427:         // defer argument checking...
1428:         setBaseShape(shape, true);
1429:     }
1430: 
1431:     /**
1432:      * Sets the base shape and, if requested, sends a 
1433:      * {@link RendererChangeEvent} to all registered listeners.
1434:      * 
1435:      * @param shape  the shape (<code>null</code> not permitted). 
1436:      * @param notify  notify listeners?
1437:      */
1438:     public void setBaseShape(Shape shape, boolean notify) {
1439:         if (shape == null) {
1440:             throw new IllegalArgumentException("Null 'shape' argument."); 
1441:         }
1442:         this.baseShape = shape;
1443:         if (notify) {
1444:             notifyListeners(new RendererChangeEvent(this));
1445:         }
1446:     }
1447:     
1448:     // ITEM LABEL VISIBILITY...
1449: 
1450:     /**
1451:      * Returns <code>true</code> if an item label is visible, and 
1452:      * <code>false</code> otherwise.
1453:      * 
1454:      * @param row  the row index (zero-based).
1455:      * @param column  the column index (zero-based).
1456:      * 
1457:      * @return A boolean.
1458:      */
1459:     public boolean isItemLabelVisible(int row, int column) {
1460:         return isSeriesItemLabelsVisible(row);
1461:     }
1462: 
1463:     /**
1464:      * Returns <code>true</code> if the item labels for a series are visible, 
1465:      * and <code>false</code> otherwise.
1466:      * 
1467:      * @param series  the series index (zero-based).
1468:      * 
1469:      * @return A boolean.
1470:      */    
1471:     public boolean isSeriesItemLabelsVisible(int series) {
1472: 
1473:         // return the override, if there is one...
1474:         if (this.itemLabelsVisible != null) {
1475:             return this.itemLabelsVisible.booleanValue();
1476:         }
1477: 
1478:         // otherwise look up the boolean table
1479:         Boolean b = this.itemLabelsVisibleList.getBoolean(series);
1480:         if (b == null) {
1481:             b = this.baseItemLabelsVisible;
1482:         }
1483:         if (b == null) {
1484:             b = Boolean.FALSE;
1485:         }
1486:         return b.booleanValue();
1487: 
1488:     }
1489:     
1490:     /**
1491:      * Sets the visibility of the item labels for ALL series.
1492:      * 
1493:      * @param visible  the flag.
1494:      */
1495:     public void setItemLabelsVisible(boolean visible) {        
1496:         setItemLabelsVisible(BooleanUtilities.valueOf(visible));
1497:         // The following alternative is only supported in JDK 1.4 - we support 
1498:         // JDK 1.2.2
1499:         // setItemLabelsVisible(Boolean.valueOf(visible));
1500:     }
1501:     
1502:     /**
1503:      * Sets the visibility of the item labels for ALL series (optional).
1504:      * 
1505:      * @param visible  the flag (<code>null</code> permitted).
1506:      */
1507:     public void setItemLabelsVisible(Boolean visible) {
1508:         setItemLabelsVisible(visible, true);
1509:     }
1510:     
1511:     /**
1512:      * Sets the visibility of item labels for ALL series and, if requested, 
1513:      * sends a {@link RendererChangeEvent} to all registered listeners.
1514:      * 
1515:      * @param visible  a flag that controls whether or not the item labels are 
1516:      *                 visible (<code>null</code> permitted).
1517:      * @param notify  a flag that controls whether or not listeners are 
1518:      *                notified.
1519:      */
1520:     public void setItemLabelsVisible(Boolean visible, boolean notify) {
1521:         this.itemLabelsVisible = visible;
1522:         if (notify) {
1523:             notifyListeners(new RendererChangeEvent(this));
1524:         }
1525:     }
1526: 
1527:     /**
1528:      * Sets a flag that controls the visibility of the item labels for a series.
1529:      * 
1530:      * @param series  the series index (zero-based).
1531:      * @param visible  the flag.
1532:      */
1533:     public void setSeriesItemLabelsVisible(int series, boolean visible) {
1534:         setSeriesItemLabelsVisible(series, BooleanUtilities.valueOf(visible));
1535:     }
1536:     
1537:     /**
1538:      * Sets the visibility of the item labels for a series.
1539:      * 
1540:      * @param series  the series index (zero-based).
1541:      * @param visible  the flag (<code>null</code> permitted).
1542:      */
1543:     public void setSeriesItemLabelsVisible(int series, Boolean visible) {
1544:         setSeriesItemLabelsVisible(series, visible, true);
1545:     }
1546: 
1547:     /**
1548:      * Sets the visibility of item labels for a series and, if requested, sends 
1549:      * a {@link RendererChangeEvent} to all registered listeners.
1550:      * 
1551:      * @param series  the series index (zero-based).
1552:      * @param visible  the visible flag.
1553:      * @param notify  a flag that controls whether or not listeners are 
1554:      *                notified.
1555:      */
1556:     public void setSeriesItemLabelsVisible(int series, Boolean visible, 
1557:                                            boolean notify) {
1558:         this.itemLabelsVisibleList.setBoolean(series, visible);
1559:         if (notify) {
1560:             notifyListeners(new RendererChangeEvent(this));
1561:         }
1562:     }
1563: 
1564:     /**
1565:      * Returns the base setting for item label visibility.  A <code>null</code>
1566:      * result should be interpreted as equivalent to <code>Boolean.FALSE</code>.
1567:      * 
1568:      * @return A flag (possibly <code>null</code>).
1569:      */
1570:     public Boolean getBaseItemLabelsVisible() {
1571:         // this should have been defined as a boolean primitive, because 
1572:         // allowing null values is a nuisance...but it is part of the final
1573:         // API now, so we'll have to support it.
1574:         return this.baseItemLabelsVisible;
1575:     }
1576: 
1577:     /**
1578:      * Sets the base flag that controls whether or not item labels are visible.
1579:      * 
1580:      * @param visible  the flag.
1581:      */
1582:     public void setBaseItemLabelsVisible(boolean visible) {
1583:         setBaseItemLabelsVisible(BooleanUtilities.valueOf(visible));
1584:     }
1585:     
1586:     /**
1587:      * Sets the base setting for item label visibility.
1588:      * 
1589:      * @param visible  the flag (<code>null</code> is permitted, and viewed
1590:      *     as equivalent to <code>Boolean.FALSE</code>).
1591:      */
1592:     public void setBaseItemLabelsVisible(Boolean visible) {
1593:         setBaseItemLabelsVisible(visible, true);
1594:     }
1595: 
1596:     /**
1597:      * Sets the base visibility for item labels and, if requested, sends a 
1598:      * {@link RendererChangeEvent} to all registered listeners.
1599:      * 
1600:      * @param visible  the flag (<code>null</code> is permitted, and viewed
1601:      *     as equivalent to <code>Boolean.FALSE</code>).
1602:      * @param notify  a flag that controls whether or not listeners are 
1603:      *                notified.
1604:      */
1605:     public void setBaseItemLabelsVisible(Boolean visible, boolean notify) {
1606:         this.baseItemLabelsVisible = visible;
1607:         if (notify) {
1608:             notifyListeners(new RendererChangeEvent(this));
1609:         }
1610:     }
1611: 
1612:     //// ITEM LABEL FONT //////////////////////////////////////////////////////
1613: 
1614:     /**
1615:      * Returns the font for an item label.
1616:      * 
1617:      * @param row  the row index (zero-based).
1618:      * @param column  the column index (zero-based).
1619:      * 
1620:      * @return The font (never <code>null</code>).
1621:      */
1622:     public Font getItemLabelFont(int row, int column) {
1623:         Font result = this.itemLabelFont;
1624:         if (result == null) {
1625:             result = getSeriesItemLabelFont(row);
1626:             if (result == null) {
1627:                 result = this.baseItemLabelFont;   
1628:             }
1629:         }
1630:         return result;
1631:     }
1632: 
1633:     /**
1634:      * Returns the font used for all item labels.  This may be 
1635:      * <code>null</code>, in which case the per series font settings will apply.
1636:      * 
1637:      * @return The font (possibly <code>null</code>).
1638:      */
1639:     public Font getItemLabelFont() {
1640:         return this.itemLabelFont;   
1641:     }
1642:     
1643:     /**
1644:      * Sets the item label font for ALL series and sends a 
1645:      * {@link RendererChangeEvent} to all registered listeners.  You can set 
1646:      * this to <code>null</code> if you prefer to set the font on a per series 
1647:      * basis.
1648:      * 
1649:      * @param font  the font (<code>null</code> permitted).
1650:      */
1651:     public void setItemLabelFont(Font font) {
1652:         setItemLabelFont(font, true);
1653:     }
1654:     
1655:     /**
1656:      * Sets the item label font for ALL series and, if requested, sends a 
1657:      * {@link RendererChangeEvent} to all registered listeners.
1658:      * 
1659:      * @param font  the font (<code>null</code> permitted).
1660:      * @param notify  a flag that controls whether or not listeners are 
1661:      *                notified.
1662:      */ 
1663:     public void setItemLabelFont(Font font, boolean notify) {
1664:         this.itemLabelFont = font;
1665:         if (notify) {
1666:             notifyListeners(new RendererChangeEvent(this));
1667:         }
1668:     }
1669: 
1670:     /**
1671:      * Returns the font for all the item labels in a series.
1672:      * 
1673:      * @param series  the series index (zero-based).
1674:      * 
1675:      * @return The font (possibly <code>null</code>).
1676:      */
1677:     public Font getSeriesItemLabelFont(int series) {
1678:         return (Font) this.itemLabelFontList.get(series);
1679:     }
1680: 
1681:     /**
1682:      * Sets the item label font for a series and sends a 
1683:      * {@link RendererChangeEvent} to all registered listeners.  
1684:      * 
1685:      * @param series  the series index (zero-based).
1686:      * @param font  the font (<code>null</code> permitted).
1687:      */
1688:     public void setSeriesItemLabelFont(int series, Font font) {
1689:         setSeriesItemLabelFont(series, font, true);
1690:     }
1691: 
1692:     /**
1693:      * Sets the item label font for a series and, if requested, sends a 
1694:      * {@link RendererChangeEvent} to all registered listeners.
1695:      * 
1696:      * @param series  the series index (zero based).
1697:      * @param font  the font (<code>null</code> permitted).
1698:      * @param notify  a flag that controls whether or not listeners are 
1699:      *                notified.
1700:      */
1701:     public void setSeriesItemLabelFont(int series, Font font, boolean notify) {
1702:         this.itemLabelFontList.set(series, font);
1703:         if (notify) {
1704:             notifyListeners(new RendererChangeEvent(this));
1705:         }
1706:     }
1707:     
1708:     /**
1709:      * Returns the base item label font (this is used when no other font 
1710:      * setting is available).
1711:      * 
1712:      * @return The font (<code>never</code> null).
1713:      */
1714:     public Font getBaseItemLabelFont() {
1715:         return this.baseItemLabelFont;
1716:     }
1717: 
1718:     /**
1719:      * Sets the base item label font and sends a {@link RendererChangeEvent} to 
1720:      * all registered listeners.  
1721:      * 
1722:      * @param font  the font (<code>null</code> not permitted).
1723:      */
1724:     public void setBaseItemLabelFont(Font font) {
1725:         if (font == null) {
1726:             throw new IllegalArgumentException("Null 'font' argument.");
1727:         }
1728:         setBaseItemLabelFont(font, true);
1729:     }
1730: 
1731:     /**
1732:      * Sets the base item label font and, if requested, sends a 
1733:      * {@link RendererChangeEvent} to all registered listeners.
1734:      * 
1735:      * @param font  the font (<code>null</code> not permitted).
1736:      * @param notify  a flag that controls whether or not listeners are 
1737:      *                notified.
1738:      */
1739:     public void setBaseItemLabelFont(Font font, boolean notify) {
1740:         this.baseItemLabelFont = font;
1741:         if (notify) {
1742:             notifyListeners(new RendererChangeEvent(this));
1743:         }
1744:     }
1745: 
1746:     //// ITEM LABEL PAINT  ////////////////////////////////////////////////////
1747: 
1748:     /**
1749:      * Returns the paint used to draw an item label.
1750:      * 
1751:      * @param row  the row index (zero based).
1752:      * @param column  the column index (zero based).
1753:      * 
1754:      * @return The paint (never <code>null</code>).
1755:      */
1756:     public Paint getItemLabelPaint(int row, int column) {
1757:         Paint result = this.itemLabelPaint;
1758:         if (result == null) {
1759:             result = getSeriesItemLabelPaint(row);
1760:             if (result == null) {
1761:                 result = this.baseItemLabelPaint;   
1762:             }
1763:         }
1764:         return result;
1765:     }
1766:     
1767:     /**
1768:      * Returns the paint used for all item labels.  This may be 
1769:      * <code>null</code>, in which case the per series paint settings will 
1770:      * apply.
1771:      * 
1772:      * @return The paint (possibly <code>null</code>).
1773:      */
1774:     public Paint getItemLabelPaint() {
1775:         return this.itemLabelPaint;   
1776:     }
1777: 
1778:     /**
1779:      * Sets the item label paint for ALL series and sends a 
1780:      * {@link RendererChangeEvent} to all registered listeners.
1781:      * 
1782:      * @param paint  the paint (<code>null</code> permitted).
1783:      */
1784:     public void setItemLabelPaint(Paint paint) {
1785:         setItemLabelPaint(paint, true);
1786:     }
1787: 
1788:     /**
1789:      * Sets the item label paint for ALL series and, if requested, sends a 
1790:      * {@link RendererChangeEvent} to all registered listeners.
1791:      * 
1792:      * @param paint  the paint.
1793:      * @param notify  a flag that controls whether or not listeners are 
1794:      *                notified.
1795:      */
1796:     public void setItemLabelPaint(Paint paint, boolean notify) {
1797:         this.itemLabelPaint = paint;
1798:         if (notify) {
1799:             notifyListeners(new RendererChangeEvent(this));
1800:         }
1801:     }
1802:     
1803:     /**
1804:      * Returns the paint used to draw the item labels for a series.
1805:      * 
1806:      * @param series  the series index (zero based).
1807:      * 
1808:      * @return The paint (possibly <code>null<code>).
1809:      */
1810:     public Paint getSeriesItemLabelPaint(int series) {
1811:         return this.itemLabelPaintList.getPaint(series);
1812:     }
1813: 
1814:     /**
1815:      * Sets the item label paint for a series and sends a 
1816:      * {@link RendererChangeEvent} to all registered listeners.
1817:      * 
1818:      * @param series  the series (zero based index).
1819:      * @param paint  the paint (<code>null</code> permitted).
1820:      */
1821:     public void setSeriesItemLabelPaint(int series, Paint paint) {
1822:         setSeriesItemLabelPaint(series, paint, true);
1823:     }
1824:     
1825:     /**
1826:      * Sets the item label paint for a series and, if requested, sends a 
1827:      * {@link RendererChangeEvent} to all registered listeners.
1828:      * 
1829:      * @param series  the series index (zero based).
1830:      * @param paint  the paint (<code>null</code> permitted).
1831:      * @param notify  a flag that controls whether or not listeners are 
1832:      *                notified.
1833:      */
1834:     public void setSeriesItemLabelPaint(int series, Paint paint, 
1835:                                         boolean notify) {
1836:         this.itemLabelPaintList.setPaint(series, paint);
1837:         if (notify) {
1838:             notifyListeners(new RendererChangeEvent(this));
1839:         }
1840:     }
1841:     
1842:     /**
1843:      * Returns the base item label paint.
1844:      * 
1845:      * @return The paint (never <code>null<code>).
1846:      */
1847:     public Paint getBaseItemLabelPaint() {
1848:         return this.baseItemLabelPaint;
1849:     }
1850: 
1851:     /**
1852:      * Sets the base item label paint and sends a {@link RendererChangeEvent} 
1853:      * to all registered listeners.
1854:      * 
1855:      * @param paint  the paint (<code>null</code> not permitted).
1856:      */
1857:     public void setBaseItemLabelPaint(Paint paint) {
1858:         // defer argument checking...
1859:         setBaseItemLabelPaint(paint, true);
1860:     }
1861: 
1862:     /**
1863:      * Sets the base item label paint and, if requested, sends a 
1864:      * {@link RendererChangeEvent} to all registered listeners..
1865:      * 
1866:      * @param paint  the paint (<code>null</code> not permitted).
1867:      * @param notify  a flag that controls whether or not listeners are 
1868:      *                notified.
1869:      */
1870:     public void setBaseItemLabelPaint(Paint paint, boolean notify) {
1871:         if (paint == null) {
1872:             throw new IllegalArgumentException("Null 'paint' argument.");   
1873:         }
1874:         this.baseItemLabelPaint = paint;
1875:         if (notify) {
1876:             notifyListeners(new RendererChangeEvent(this));
1877:         }
1878:     }
1879:     
1880:     // POSITIVE ITEM LABEL POSITION...
1881: 
1882:     /**
1883:      * Returns the item label position for positive values.
1884:      * 
1885:      * @param row  the row index (zero-based).
1886:      * @param column  the column index (zero-based).
1887:      * 
1888:      * @return The item label position (never <code>null</code>).
1889:      */
1890:     public ItemLabelPosition getPositiveItemLabelPosition(int row, int column) {
1891:         return getSeriesPositiveItemLabelPosition(row);
1892:     }
1893: 
1894:     /**
1895:      * Returns the item label position for positive values in ALL series.
1896:      * 
1897:      * @return The item label position (possibly <code>null</code>).
1898:      */
1899:     public ItemLabelPosition getPositiveItemLabelPosition() {
1900:         return this.positiveItemLabelPosition;
1901:     }
1902: 
1903:     /**
1904:      * Sets the item label position for positive values in ALL series, and 
1905:      * sends a {@link RendererChangeEvent} to all registered listeners.  You 
1906:      * need to set this to <code>null</code> to expose the settings for 
1907:      * individual series.
1908:      * 
1909:      * @param position  the position (<code>null</code> permitted).
1910:      */
1911:     public void setPositiveItemLabelPosition(ItemLabelPosition position) {
1912:         setPositiveItemLabelPosition(position, true);
1913:     }
1914:     
1915:     /**
1916:      * Sets the positive item label position for ALL series and (if requested) 
1917:      * sends a {@link RendererChangeEvent} to all registered listeners.
1918:      * 
1919:      * @param position  the position (<code>null</code> permitted).
1920:      * @param notify  notify registered listeners?
1921:      */
1922:     public void setPositiveItemLabelPosition(ItemLabelPosition position, 
1923:                                              boolean notify) {
1924:         this.positiveItemLabelPosition = position;
1925:         if (notify) {
1926:             notifyListeners(new RendererChangeEvent(this));
1927:         }
1928:     }
1929: 
1930:     /**
1931:      * Returns the item label position for all positive values in a series.
1932:      * 
1933:      * @param series  the series index (zero-based).
1934:      * 
1935:      * @return The item label position (never <code>null</code>).
1936:      */
1937:     public ItemLabelPosition getSeriesPositiveItemLabelPosition(int series) {
1938: 
1939:         // return the override, if there is one...
1940:         if (this.positiveItemLabelPosition != null) {
1941:             return this.positiveItemLabelPosition;
1942:         }
1943: 
1944:         // otherwise look up the position table
1945:         ItemLabelPosition position = (ItemLabelPosition) 
1946:             this.positiveItemLabelPositionList.get(series);
1947:         if (position == null) {
1948:             position = this.basePositiveItemLabelPosition;
1949:         }
1950:         return position;
1951: 
1952:     }
1953:     
1954:     /**
1955:      * Sets the item label position for all positive values in a series and 
1956:      * sends a {@link RendererChangeEvent} to all registered listeners.
1957:      * 
1958:      * @param series  the series index (zero-based).
1959:      * @param position  the position (<code>null</code> permitted).
1960:      */
1961:     public void setSeriesPositiveItemLabelPosition(int series, 
1962:                                                    ItemLabelPosition position) {
1963:         setSeriesPositiveItemLabelPosition(series, position, true);
1964:     }
1965: 
1966:     /**
1967:      * Sets the item label position for all positive values in a series and (if
1968:      * requested) sends a {@link RendererChangeEvent} to all registered 
1969:      * listeners.
1970:      * 
1971:      * @param series  the series index (zero-based).
1972:      * @param position  the position (<code>null</code> permitted).
1973:      * @param notify  notify registered listeners?
1974:      */
1975:     public void setSeriesPositiveItemLabelPosition(int series, 
1976:                                                    ItemLabelPosition position, 
1977:                                                    boolean notify) {
1978:         this.positiveItemLabelPositionList.set(series, position);
1979:         if (notify) {
1980:             notifyListeners(new RendererChangeEvent(this));
1981:         }
1982:     }
1983: 
1984:     /**
1985:      * Returns the base positive item label position.
1986:      * 
1987:      * @return The position (never <code>null</code>).
1988:      */
1989:     public ItemLabelPosition getBasePositiveItemLabelPosition() {
1990:         return this.basePositiveItemLabelPosition;
1991:     }
1992: 
1993:     /**
1994:      * Sets the base positive item label position.
1995:      * 
1996:      * @param position  the position (<code>null</code> not permitted).
1997:      */
1998:     public void setBasePositiveItemLabelPosition(ItemLabelPosition position) {
1999:         // defer argument checking...
2000:         setBasePositiveItemLabelPosition(position, true);
2001:     }
2002:     
2003:     /**
2004:      * Sets the base positive item label position and, if requested, sends a 
2005:      * {@link RendererChangeEvent} to all registered listeners.
2006:      * 
2007:      * @param position  the position (<code>null</code> not permitted).
2008:      * @param notify  notify registered listeners?
2009:      */
2010:     public void setBasePositiveItemLabelPosition(ItemLabelPosition position, 
2011:                                                  boolean notify) {
2012:         if (position == null) {
2013:             throw new IllegalArgumentException("Null 'position' argument.");   
2014:         }
2015:         this.basePositiveItemLabelPosition = position;
2016:         if (notify) {
2017:             notifyListeners(new RendererChangeEvent(this));
2018:         }
2019:     }
2020: 
2021:     // NEGATIVE ITEM LABEL POSITION...
2022: 
2023:     /**
2024:      * Returns the item label position for negative values.  This method can be 
2025:      * overridden to provide customisation of the item label position for 
2026:      * individual data items.
2027:      * 
2028:      * @param row  the row index (zero-based).
2029:      * @param column  the column (zero-based).
2030:      * 
2031:      * @return The item label position (never <code>null</code>).
2032:      */
2033:     public ItemLabelPosition getNegativeItemLabelPosition(int row, int column) {
2034:         return getSeriesNegativeItemLabelPosition(row);
2035:     }
2036: 
2037:     /**
2038:      * Returns the item label position for negative values in ALL series.
2039:      * 
2040:      * @return The item label position (possibly <code>null</code>).
2041:      */
2042:     public ItemLabelPosition getNegativeItemLabelPosition() {
2043:         return this.negativeItemLabelPosition;
2044:     }
2045: 
2046:     /**
2047:      * Sets the item label position for negative values in ALL series, and 
2048:      * sends a {@link RendererChangeEvent} to all registered listeners.  You 
2049:      * need to set this to <code>null</code> to expose the settings for 
2050:      * individual series.
2051:      * 
2052:      * @param position  the position (<code>null</code> permitted).
2053:      */
2054:     public void setNegativeItemLabelPosition(ItemLabelPosition position) {
2055:         setNegativeItemLabelPosition(position, true);
2056:     }
2057:     
2058:     /**
2059:      * Sets the item label position for negative values in ALL series and (if 
2060:      * requested) sends a {@link RendererChangeEvent} to all registered 
2061:      * listeners.  
2062:      * 
2063:      * @param position  the position (<code>null</code> permitted).
2064:      * @param notify  notify registered listeners?
2065:      */
2066:     public void setNegativeItemLabelPosition(ItemLabelPosition position, 
2067:                                              boolean notify) {
2068:         this.negativeItemLabelPosition = position;
2069:         if (notify) {
2070:             notifyListeners(new RendererChangeEvent(this));
2071:         }
2072:     }
2073: 
2074:     /**
2075:      * Returns the item label position for all negative values in a series.
2076:      * 
2077:      * @param series  the series index (zero-based).
2078:      * 
2079:      * @return The item label position (never <code>null</code>).
2080:      */
2081:     public ItemLabelPosition getSeriesNegativeItemLabelPosition(int series) {
2082: 
2083:         // return the override, if there is one...
2084:         if (this.negativeItemLabelPosition != null) {
2085:             return this.negativeItemLabelPosition;
2086:         }
2087: 
2088:         // otherwise look up the position list
2089:         ItemLabelPosition position = (ItemLabelPosition) 
2090:             this.negativeItemLabelPositionList.get(series);
2091:         if (position == null) {
2092:             position = this.baseNegativeItemLabelPosition;
2093:         }
2094:         return position;
2095: 
2096:     }
2097: 
2098:     /**
2099:      * Sets the item label position for negative values in a series and sends a 
2100:      * {@link RendererChangeEvent} to all registered listeners.
2101:      * 
2102:      * @param series  the series index (zero-based).
2103:      * @param position  the position (<code>null</code> permitted).
2104:      */
2105:     public void setSeriesNegativeItemLabelPosition(int series, 
2106:                                                    ItemLabelPosition position) {
2107:         setSeriesNegativeItemLabelPosition(series, position, true);
2108:     }
2109: 
2110:     /**
2111:      * Sets the item label position for negative values in a series and (if 
2112:      * requested) sends a {@link RendererChangeEvent} to all registered 
2113:      * listeners.
2114:      * 
2115:      * @param series  the series index (zero-based).
2116:      * @param position  the position (<code>null</code> permitted).
2117:      * @param notify  notify registered listeners?
2118:      */
2119:     public void setSeriesNegativeItemLabelPosition(int series, 
2120:                                                    ItemLabelPosition position, 
2121:                                                    boolean notify) {
2122:         this.negativeItemLabelPositionList.set(series, position);
2123:         if (notify) {
2124:             notifyListeners(new RendererChangeEvent(this));
2125:         }
2126:     }
2127: 
2128:     /**
2129:      * Returns the base item label position for negative values.
2130:      * 
2131:      * @return The position (never <code>null</code>).
2132:      */
2133:     public ItemLabelPosition getBaseNegativeItemLabelPosition() {
2134:         return this.baseNegativeItemLabelPosition;
2135:     }
2136: 
2137:     /**
2138:      * Sets the base item label position for negative values and sends a 
2139:      * {@link RendererChangeEvent} to all registered listeners.
2140:      * 
2141:      * @param position  the position (<code>null</code> not permitted).
2142:      */
2143:     public void setBaseNegativeItemLabelPosition(ItemLabelPosition position) {
2144:         setBaseNegativeItemLabelPosition(position, true);
2145:     }
2146:     
2147:     /**
2148:      * Sets the base negative item label position and, if requested, sends a 
2149:      * {@link RendererChangeEvent} to all registered listeners.
2150:      * 
2151:      * @param position  the position (<code>null</code> not permitted).
2152:      * @param notify  notify registered listeners?
2153:      */
2154:     public void setBaseNegativeItemLabelPosition(ItemLabelPosition position, 
2155:                                                  boolean notify) {
2156:         if (position == null) {
2157:             throw new IllegalArgumentException("Null 'position' argument.");   
2158:         }
2159:         this.baseNegativeItemLabelPosition = position;
2160:         if (notify) {
2161:             notifyListeners(new RendererChangeEvent(this));
2162:         }
2163:     }
2164: 
2165:     /**
2166:      * Returns the item label anchor offset.
2167:      *
2168:      * @return The offset.
2169:      */
2170:     public double getItemLabelAnchorOffset() {
2171:         return this.itemLabelAnchorOffset;
2172:     }
2173: 
2174:     /**
2175:      * Sets the item label anchor offset.
2176:      *
2177:      * @param offset  the offset.
2178:      */
2179:     public void setItemLabelAnchorOffset(double offset) {
2180:         this.itemLabelAnchorOffset = offset;
2181:         notifyListeners(new RendererChangeEvent(this));
2182:     }
2183: 
2184:     /**
2185:      * Returns a boolean that indicates whether or not the specified item 
2186:      * should have a chart entity created for it.
2187:      * 
2188:      * @param series  the series index.
2189:      * @param item  the item index.
2190:      * 
2191:      * @return A boolean.
2192:      */
2193:     public boolean getItemCreateEntity(int series, int item) {
2194:         if (this.createEntities != null) {
2195:             return this.createEntities.booleanValue();
2196:         }
2197:         else {
2198:             Boolean b = getSeriesCreateEntities(series);
2199:             if (b != null) {
2200:                 return b.booleanValue();
2201:             }
2202:             else {
2203:                 return this.baseCreateEntities;
2204:             }
2205:         }
2206:     }
2207:     
2208:     /**
2209:      * Returns the flag that controls whether or not chart entities are created 
2210:      * for the items in ALL series.  This flag overrides the per series and 
2211:      * default settings - you must set it to <code>null</code> if you want the
2212:      * other settings to apply.
2213:      * 
2214:      * @return The flag (possibly <code>null</code>).
2215:      */
2216:     public Boolean getCreateEntities() {
2217:         return this.createEntities;  
2218:     }
2219:     
2220:     /**
2221:      * Sets the flag that controls whether or not chart entities are created 
2222:      * for the items in ALL series, and sends a {@link RendererChangeEvent} to 
2223:      * all registered listeners.  This flag overrides the per series and 
2224:      * default settings - you must set it to <code>null</code> if you want the
2225:      * other settings to apply.
2226:      * 
2227:      * @param create  the flag (<code>null</code> permitted).
2228:      */
2229:     public void setCreateEntities(Boolean create) {
2230:          setCreateEntities(create, true);
2231:     }
2232:     
2233:     /**
2234:      * Sets the flag that controls whether or not chart entities are created 
2235:      * for the items in ALL series, and sends a {@link RendererChangeEvent} to 
2236:      * all registered listeners.  This flag overrides the per series and 
2237:      * default settings - you must set it to <code>null</code> if you want the
2238:      * other settings to apply.
2239:      * 
2240:      * @param create  the flag (<code>null</code> permitted).
2241:      * @param notify  notify listeners?
2242:      */
2243:     public void setCreateEntities(Boolean create, boolean notify) {
2244:         this.createEntities = create;   
2245:         if (notify) {
2246:             notifyListeners(new RendererChangeEvent(this));
2247:         }
2248:     }
2249:     
2250:     /**
2251:      * Returns the flag that controls whether entities are created for a
2252:      * series.
2253:      *
2254:      * @param series  the series index (zero-based).
2255:      *
2256:      * @return The flag (possibly <code>null</code>).
2257:      */
2258:     public Boolean getSeriesCreateEntities(int series) {
2259:         return this.createEntitiesList.getBoolean(series);
2260:     }
2261:     
2262:     /**
2263:      * Sets the flag that controls whether entities are created for a series,
2264:      * and sends a {@link RendererChangeEvent} to all registered listeners.
2265:      *
2266:      * @param series  the series index (zero-based).
2267:      * @param create  the flag (<code>null</code> permitted).
2268:      */
2269:     public void setSeriesCreateEntities(int series, Boolean create) {
2270:         setSeriesCreateEntities(series, create, true);
2271:     }
2272:     
2273:     /**
2274:      * Sets the flag that controls whether entities are created for a series
2275:      * and, if requested, sends a {@link RendererChangeEvent} to all registered 
2276:      * listeners.
2277:      * 
2278:      * @param series  the series index.
2279:      * @param create  the flag (<code>null</code> permitted).
2280:      * @param notify  notify listeners?
2281:      */
2282:     public void setSeriesCreateEntities(int series, Boolean create, 
2283:                                         boolean notify) {
2284:         this.createEntitiesList.setBoolean(series, create);       
2285:         if (notify) {
2286:             notifyListeners(new RendererChangeEvent(this));
2287:         }
2288:     }
2289: 
2290:     /**
2291:      * Returns the base visibility for all series.
2292:      *
2293:      * @return The base visibility.
2294:      */
2295:     public boolean getBaseCreateEntities() {
2296:         return this.baseCreateEntities;
2297:     }
2298: 
2299:     /**
2300:      * Sets the base flag that controls whether entities are created
2301:      * for a series, and sends a {@link RendererChangeEvent} 
2302:      * to all registered listeners.
2303:      *
2304:      * @param create  the flag.
2305:      */
2306:     public void setBaseCreateEntities(boolean create) {
2307:         // defer argument checking...
2308:         setBaseCreateEntities(create, true);
2309:     }
2310:     
2311:     /**
2312:      * Sets the base flag that controls whether entities are created and, 
2313:      * if requested, sends a {@link RendererChangeEvent} to all registered 
2314:      * listeners.
2315:      * 
2316:      * @param create  the visibility.
2317:      * @param notify  notify listeners?
2318:      */
2319:     public void setBaseCreateEntities(boolean create, boolean notify) {
2320:         this.baseCreateEntities = create;
2321:         if (notify) {
2322:             notifyListeners(new RendererChangeEvent(this));
2323:         }
2324:     }
2325: 
2326:     /** The adjacent offset. */
2327:     private static final double ADJ = Math.cos(Math.PI / 6.0);
2328:     
2329:     /** The opposite offset. */
2330:     private static final double OPP = Math.sin(Math.PI / 6.0);
2331:     
2332:     /**
2333:      * Calculates the item label anchor point.
2334:      *
2335:      * @param anchor  the anchor.
2336:      * @param x  the x coordinate.
2337:      * @param y  the y coordinate.
2338:      * @param orientation  the plot orientation.
2339:      *
2340:      * @return The anchor point (never <code>null</code>).
2341:      */
2342:     protected Point2D calculateLabelAnchorPoint(ItemLabelAnchor anchor,
2343:             double x, double y, PlotOrientation orientation) {
2344:         Point2D result = null;
2345:         if (anchor == ItemLabelAnchor.CENTER) {
2346:             result = new Point2D.Double(x, y);
2347:         }
2348:         else if (anchor == ItemLabelAnchor.INSIDE1) {
2349:             result = new Point2D.Double(x + OPP * this.itemLabelAnchorOffset, 
2350:                     y - ADJ * this.itemLabelAnchorOffset);
2351:         }
2352:         else if (anchor == ItemLabelAnchor.INSIDE2) {
2353:             result = new Point2D.Double(x + ADJ * this.itemLabelAnchorOffset, 
2354:                     y - OPP * this.itemLabelAnchorOffset);
2355:         }
2356:         else if (anchor == ItemLabelAnchor.INSIDE3) {
2357:             result = new Point2D.Double(x + this.itemLabelAnchorOffset, y);
2358:         }
2359:         else if (anchor == ItemLabelAnchor.INSIDE4) {
2360:             result = new Point2D.Double(x + ADJ * this.itemLabelAnchorOffset, 
2361:                     y + OPP * this.itemLabelAnchorOffset);
2362:         }
2363:         else if (anchor == ItemLabelAnchor.INSIDE5) {
2364:             result = new Point2D.Double(x + OPP * this.itemLabelAnchorOffset, 
2365:                     y + ADJ * this.itemLabelAnchorOffset);
2366:         }
2367:         else if (anchor == ItemLabelAnchor.INSIDE6) {
2368:             result = new Point2D.Double(x, y + this.itemLabelAnchorOffset);
2369:         }
2370:         else if (anchor == ItemLabelAnchor.INSIDE7) {
2371:             result = new Point2D.Double(x - OPP * this.itemLabelAnchorOffset, 
2372:                     y + ADJ * this.itemLabelAnchorOffset);
2373:         }
2374:         else if (anchor == ItemLabelAnchor.INSIDE8) {
2375:             result = new Point2D.Double(x - ADJ * this.itemLabelAnchorOffset, 
2376:                     y + OPP * this.itemLabelAnchorOffset);
2377:         }
2378:         else if (anchor == ItemLabelAnchor.INSIDE9) {
2379:             result = new Point2D.Double(x - this.itemLabelAnchorOffset, y);
2380:         }
2381:         else if (anchor == ItemLabelAnchor.INSIDE10) {
2382:             result = new Point2D.Double(x - ADJ * this.itemLabelAnchorOffset, 
2383:                     y - OPP * this.itemLabelAnchorOffset);
2384:         }
2385:         else if (anchor == ItemLabelAnchor.INSIDE11) {
2386:             result = new Point2D.Double(x - OPP * this.itemLabelAnchorOffset, 
2387:                     y - ADJ * this.itemLabelAnchorOffset);
2388:         }
2389:         else if (anchor == ItemLabelAnchor.INSIDE12) {
2390:             result = new Point2D.Double(x, y - this.itemLabelAnchorOffset);
2391:         }
2392:         else if (anchor == ItemLabelAnchor.OUTSIDE1) {
2393:             result = new Point2D.Double(
2394:                     x + 2.0 * OPP * this.itemLabelAnchorOffset, 
2395:                     y - 2.0 * ADJ * this.itemLabelAnchorOffset);
2396:         }
2397:         else if (anchor == ItemLabelAnchor.OUTSIDE2) {
2398:             result = new Point2D.Double(
2399:                     x + 2.0 * ADJ * this.itemLabelAnchorOffset, 
2400:                     y - 2.0 * OPP * this.itemLabelAnchorOffset);
2401:         }
2402:         else if (anchor == ItemLabelAnchor.OUTSIDE3) {
2403:             result = new Point2D.Double(x + 2.0 * this.itemLabelAnchorOffset, 
2404:                     y);
2405:         }
2406:         else if (anchor == ItemLabelAnchor.OUTSIDE4) {
2407:             result = new Point2D.Double(
2408:                     x + 2.0 * ADJ * this.itemLabelAnchorOffset, 
2409:                     y + 2.0 * OPP * this.itemLabelAnchorOffset);
2410:         }
2411:         else if (anchor == ItemLabelAnchor.OUTSIDE5) {
2412:             result = new Point2D.Double(
2413:                     x + 2.0 * OPP * this.itemLabelAnchorOffset, 
2414:                     y + 2.0 * ADJ * this.itemLabelAnchorOffset);
2415:         }
2416:         else if (anchor == ItemLabelAnchor.OUTSIDE6) {
2417:             result = new Point2D.Double(x, 
2418:                     y + 2.0 * this.itemLabelAnchorOffset);
2419:         }
2420:         else if (anchor == ItemLabelAnchor.OUTSIDE7) {
2421:             result = new Point2D.Double(
2422:                     x - 2.0 * OPP * this.itemLabelAnchorOffset, 
2423:                     y + 2.0 * ADJ * this.itemLabelAnchorOffset);
2424:         }
2425:         else if (anchor == ItemLabelAnchor.OUTSIDE8) {
2426:             result = new Point2D.Double(
2427:                     x - 2.0 * ADJ * this.itemLabelAnchorOffset, 
2428:                     y + 2.0 * OPP * this.itemLabelAnchorOffset);
2429:         }
2430:         else if (anchor == ItemLabelAnchor.OUTSIDE9) {
2431:             result = new Point2D.Double(x - 2.0 * this.itemLabelAnchorOffset, 
2432:                     y);
2433:         }
2434:         else if (anchor == ItemLabelAnchor.OUTSIDE10) {
2435:             result = new Point2D.Double(
2436:                     x - 2.0 * ADJ * this.itemLabelAnchorOffset, 
2437:                     y - 2.0 * OPP * this.itemLabelAnchorOffset);
2438:         }
2439:         else if (anchor == ItemLabelAnchor.OUTSIDE11) {
2440:             result = new Point2D.Double(
2441:                 x - 2.0 * OPP * this.itemLabelAnchorOffset, 
2442:                 y - 2.0 * ADJ * this.itemLabelAnchorOffset);
2443:         }
2444:         else if (anchor == ItemLabelAnchor.OUTSIDE12) {
2445:             result = new Point2D.Double(x, 
2446:                     y - 2.0 * this.itemLabelAnchorOffset);
2447:         }
2448:         return result;
2449:     }
2450:     
2451:     /**
2452:      * Registers an object to receive notification of changes to the renderer.
2453:      *
2454:      * @param listener  the listener (<code>null</code> not permitted).
2455:      */
2456:     public void addChangeListener(RendererChangeListener listener) {
2457:         if (listener == null) {
2458:             throw new IllegalArgumentException("Null 'listener' argument.");   
2459:         }
2460:         this.listenerList.add(RendererChangeListener.class, listener);
2461:     }
2462: 
2463:     /**
2464:      * Deregisters an object so that it no longer receives 
2465:      * notification of changes to the renderer.
2466:      *
2467:      * @param listener  the object (<code>null</code> not permitted).
2468:      */
2469:     public void removeChangeListener(RendererChangeListener listener) {
2470:         if (listener == null) {
2471:             throw new IllegalArgumentException("Null 'listener' argument.");   
2472:         }
2473:         this.listenerList.remove(RendererChangeListener.class, listener);
2474:     }
2475: 
2476:     /**
2477:      * Returns <code>true</code> if the specified object is registered with
2478:      * the dataset as a listener.  Most applications won't need to call this 
2479:      * method, it exists mainly for use by unit testing code.
2480:      * 
2481:      * @param listener  the listener.
2482:      * 
2483:      * @return A boolean.
2484:      */
2485:     public boolean hasListener(EventListener listener) {
2486:         List list = Arrays.asList(this.listenerList.getListenerList());
2487:         return list.contains(listener);
2488:     }
2489:     
2490:     /**
2491:      * Notifies all registered listeners that the renderer has been modified.
2492:      *
2493:      * @param event  information about the change event.
2494:      */
2495:     public void notifyListeners(RendererChangeEvent event) {
2496: 
2497:         Object[] ls = this.listenerList.getListenerList();
2498:         for (int i = ls.length - 2; i >= 0; i -= 2) {
2499:             if (ls[i] == RendererChangeListener.class) {
2500:                 ((RendererChangeListener) ls[i + 1]).rendererChanged(event);
2501:             }
2502:         }
2503: 
2504:     }
2505: 
2506:     /**
2507:      * Tests this renderer for equality with another object.
2508:      *
2509:      * @param obj  the object (<code>null</code> permitted).
2510:      *
2511:      * @return <code>true</code> or <code>false</code>.
2512:      */
2513:     public boolean equals(Object obj) {
2514:         if (obj == this) {
2515:             return true;
2516:         }
2517:         if (!(obj instanceof AbstractRenderer)) {
2518:             return false;
2519:         }
2520:         AbstractRenderer that = (AbstractRenderer) obj;
2521:         if (!ObjectUtilities.equal(this.seriesVisible, that.seriesVisible)) {
2522:             return false;   
2523:         }
2524:         if (!this.seriesVisibleList.equals(that.seriesVisibleList)) {
2525:             return false;   
2526:         }
2527:         if (this.baseSeriesVisible != that.baseSeriesVisible) {
2528:             return false;   
2529:         }
2530:         if (!ObjectUtilities.equal(this.seriesVisibleInLegend, 
2531:                 that.seriesVisibleInLegend)) {
2532:             return false;   
2533:         }
2534:         if (!this.seriesVisibleInLegendList.equals(
2535:                 that.seriesVisibleInLegendList)) {
2536:             return false;   
2537:         }
2538:         if (this.baseSeriesVisibleInLegend != that.baseSeriesVisibleInLegend) {
2539:             return false;   
2540:         }
2541:         if (!PaintUtilities.equal(this.paint, that.paint)) {
2542:             return false;
2543:         }
2544:         if (!ObjectUtilities.equal(this.paintList, that.paintList)) {
2545:             return false;
2546:         }
2547:         if (!PaintUtilities.equal(this.basePaint, that.basePaint)) {
2548:             return false;
2549:         }
2550:         if (!PaintUtilities.equal(this.fillPaint, that.fillPaint)) {
2551:             return false;
2552:         }
2553:         if (!ObjectUtilities.equal(this.fillPaintList, that.fillPaintList)) {
2554:             return false;
2555:         }
2556:         if (!PaintUtilities.equal(this.baseFillPaint, that.baseFillPaint)) {
2557:             return false;
2558:         }
2559:         if (!PaintUtilities.equal(this.outlinePaint, that.outlinePaint)) {
2560:             return false;
2561:         }
2562:         if (!ObjectUtilities.equal(this.outlinePaintList,
2563:                 that.outlinePaintList)) {
2564:             return false;
2565:         }
2566:         if (!PaintUtilities.equal(this.baseOutlinePaint, 
2567:                 that.baseOutlinePaint)) {
2568:             return false;
2569:         }
2570:         if (!ObjectUtilities.equal(this.stroke, that.stroke)) {
2571:             return false;
2572:         }
2573:         if (!ObjectUtilities.equal(this.strokeList, that.strokeList)) {
2574:             return false;
2575:         }
2576:         if (!ObjectUtilities.equal(this.baseStroke, that.baseStroke)) {
2577:             return false;
2578:         }
2579:         if (!ObjectUtilities.equal(this.outlineStroke, that.outlineStroke)) {
2580:             return false;
2581:         }
2582:         if (!ObjectUtilities.equal(
2583:             this.outlineStrokeList, that.outlineStrokeList
2584:         )) {
2585:             return false;
2586:         }
2587:         if (!ObjectUtilities.equal(
2588:             this.baseOutlineStroke, that.baseOutlineStroke)
2589:         ) {
2590:             return false;
2591:         }
2592:         if (!ObjectUtilities.equal(this.shape, that.shape)) {
2593:             return false;
2594:         }
2595:         if (!ObjectUtilities.equal(this.shapeList, that.shapeList)) {
2596:             return false;
2597:         }
2598:         if (!ObjectUtilities.equal(this.baseShape, that.baseShape)) {
2599:             return false;
2600:         }
2601:         if (!ObjectUtilities.equal(
2602:             this.itemLabelsVisible, that.itemLabelsVisible
2603:         )) {
2604:             return false;
2605:         }
2606:         if (!ObjectUtilities.equal(
2607:             this.itemLabelsVisibleList, that.itemLabelsVisibleList)
2608:         ) {
2609:             return false;
2610:         }
2611:         if (!ObjectUtilities.equal(
2612:             this.baseItemLabelsVisible, that.baseItemLabelsVisible
2613:         )) {
2614:             return false;
2615:         }
2616:         if (!ObjectUtilities.equal(this.itemLabelFont, that.itemLabelFont)) {
2617:             return false;
2618:         }
2619:         if (!ObjectUtilities.equal(
2620:             this.itemLabelFontList, that.itemLabelFontList
2621:         )) {
2622:             return false;
2623:         }
2624:         if (!ObjectUtilities.equal(
2625:             this.baseItemLabelFont, that.baseItemLabelFont
2626:         )) {
2627:             return false;
2628:         }
2629:  
2630:         if (!PaintUtilities.equal(this.itemLabelPaint, that.itemLabelPaint)) {
2631:             return false;
2632:         }
2633:         if (!ObjectUtilities.equal(
2634:             this.itemLabelPaintList, that.itemLabelPaintList
2635:         )) {
2636:             return false;
2637:         }
2638:         if (!PaintUtilities.equal(
2639:             this.baseItemLabelPaint, that.baseItemLabelPaint
2640:         )) {
2641:             return false;
2642:         }
2643: 
2644:         if (!ObjectUtilities.equal(
2645:                 this.positiveItemLabelPosition, that.positiveItemLabelPosition
2646:             )) {
2647:             return false;
2648:         }
2649:         if (!ObjectUtilities.equal(
2650:                 this.positiveItemLabelPositionList, 
2651:                 that.positiveItemLabelPositionList
2652:             )) {
2653:             return false;
2654:         }
2655:         if (!ObjectUtilities.equal(
2656:                 this.basePositiveItemLabelPosition, 
2657:                 that.basePositiveItemLabelPosition
2658:             )) {
2659:             return false;
2660:         }
2661: 
2662:         if (!ObjectUtilities.equal(
2663:                 this.negativeItemLabelPosition, that.negativeItemLabelPosition
2664:             )) {
2665:             return false;
2666:         }
2667:         if (!ObjectUtilities.equal(
2668:                 this.negativeItemLabelPositionList, 
2669:                 that.negativeItemLabelPositionList
2670:             )) {
2671:             return false;
2672:         }
2673:         if (!ObjectUtilities.equal(
2674:                 this.baseNegativeItemLabelPosition, 
2675:                 that.baseNegativeItemLabelPosition
2676:             )) {
2677:             return false;
2678:         }
2679:         if (this.itemLabelAnchorOffset != that.itemLabelAnchorOffset) {
2680:             return false;
2681:         }
2682:         if (!ObjectUtilities.equal(this.createEntities, that.createEntities)) {
2683:             return false;   
2684:         }
2685:         if (!ObjectUtilities.equal(this.createEntitiesList, 
2686:                 that.createEntitiesList)) {
2687:             return false;   
2688:         }
2689:         if (this.baseCreateEntities != that.baseCreateEntities) {
2690:             return false;   
2691:         }
2692:         return true;
2693:     }
2694:     
2695:     /**
2696:      * Returns a hashcode for the renderer.
2697:      * 
2698:      * @return The hashcode.
2699:      */
2700:     public int hashCode() {
2701:         int result = 193;   
2702:         result = 37 * result + ObjectUtilities.hashCode(this.stroke);     
2703:         result = 37 * result + ObjectUtilities.hashCode(this.baseStroke);    
2704:         result = 37 * result + ObjectUtilities.hashCode(this.outlineStroke);
2705:         result = 37 * result + ObjectUtilities.hashCode(this.baseOutlineStroke);
2706:         return result;
2707:     }
2708:     
2709:     /**
2710:      * Returns an independent copy of the renderer.
2711:      * 
2712:      * @return A clone.
2713:      * 
2714:      * @throws CloneNotSupportedException if some component of the renderer 
2715:      *         does not support cloning.
2716:      */
2717:     protected Object clone() throws CloneNotSupportedException {
2718:         AbstractRenderer clone = (AbstractRenderer) super.clone();
2719:         
2720:         // 'paint' : immutable, no need to clone reference
2721:         if (this.paintList != null) {
2722:             clone.paintList = (PaintList) this.paintList.clone();
2723:         }
2724:         // 'basePaint' : immutable, no need to clone reference
2725:         
2726:         if (this.fillPaintList != null) {
2727:             clone.fillPaintList = (PaintList) this.fillPaintList.clone();
2728:         }
2729:         // 'outlinePaint' : immutable, no need to clone reference
2730:         if (this.outlinePaintList != null) {
2731:             clone.outlinePaintList = (PaintList) this.outlinePaintList.clone();
2732:         }
2733:         // 'baseOutlinePaint' : immutable, no need to clone reference
2734:         
2735:         // 'stroke' : immutable, no need to clone reference
2736:         if (this.strokeList != null) {
2737:             clone.strokeList = (StrokeList) this.strokeList.clone();
2738:         }
2739:         // 'baseStroke' : immutable, no need to clone reference
2740:         
2741:         // 'outlineStroke' : immutable, no need to clone reference
2742:         if (this.outlineStrokeList != null) {
2743:             clone.outlineStrokeList 
2744:                 = (StrokeList) this.outlineStrokeList.clone();
2745:         }
2746:         // 'baseOutlineStroke' : immutable, no need to clone reference
2747:         
2748:         if (this.shape != null) {
2749:             clone.shape = ShapeUtilities.clone(this.shape);
2750:         }
2751:         if (this.baseShape != null) {
2752:             clone.baseShape = ShapeUtilities.clone(this.baseShape);
2753:         }
2754:         
2755:         // 'itemLabelsVisible' : immutable, no need to clone reference
2756:         if (this.itemLabelsVisibleList != null) {
2757:             clone.itemLabelsVisibleList 
2758:                 = (BooleanList) this.itemLabelsVisibleList.clone();
2759:         }
2760:         // 'basePaint' : immutable, no need to clone reference
2761:         
2762:         // 'itemLabelFont' : immutable, no need to clone reference
2763:         if (this.itemLabelFontList != null) {
2764:             clone.itemLabelFontList 
2765:                 = (ObjectList) this.itemLabelFontList.clone();
2766:         }
2767:         // 'baseItemLabelFont' : immutable, no need to clone reference
2768: 
2769:         // 'itemLabelPaint' : immutable, no need to clone reference
2770:         if (this.itemLabelPaintList != null) {
2771:             clone.itemLabelPaintList 
2772:                 = (PaintList) this.itemLabelPaintList.clone();
2773:         }
2774:         // 'baseItemLabelPaint' : immutable, no need to clone reference
2775:         
2776:         // 'postiveItemLabelAnchor' : immutable, no need to clone reference
2777:         if (this.positiveItemLabelPositionList != null) {
2778:             clone.positiveItemLabelPositionList 
2779:                 = (ObjectList) this.positiveItemLabelPositionList.clone();
2780:         }
2781:         // 'baseItemLabelAnchor' : immutable, no need to clone reference
2782: 
2783:         // 'negativeItemLabelAnchor' : immutable, no need to clone reference
2784:         if (this.negativeItemLabelPositionList != null) {
2785:             clone.negativeItemLabelPositionList 
2786:                 = (ObjectList) this.negativeItemLabelPositionList.clone();
2787:         }
2788:         // 'baseNegativeItemLabelAnchor' : immutable, no need to clone reference
2789:         
2790:         return clone;
2791:     }
2792: 
2793:     /**
2794:      * Provides serialization support.
2795:      *
2796:      * @param stream  the output stream.
2797:      *
2798:      * @throws IOException  if there is an I/O error.
2799:      */
2800:     private void writeObject(ObjectOutputStream stream) throws IOException {
2801: 
2802:         stream.defaultWriteObject();
2803:         SerialUtilities.writePaint(this.paint, stream);
2804:         SerialUtilities.writePaint(this.basePaint, stream);
2805:         SerialUtilities.writePaint(this.fillPaint, stream);
2806:         SerialUtilities.writePaint(this.baseFillPaint, stream);
2807:         SerialUtilities.writePaint(this.outlinePaint, stream);
2808:         SerialUtilities.writePaint(this.baseOutlinePaint, stream);
2809:         SerialUtilities.writeStroke(this.stroke, stream);
2810:         SerialUtilities.writeStroke(this.baseStroke, stream);
2811:         SerialUtilities.writeStroke(this.outlineStroke, stream);
2812:         SerialUtilities.writeStroke(this.baseOutlineStroke, stream);
2813:         SerialUtilities.writeShape(this.shape, stream);
2814:         SerialUtilities.writeShape(this.baseShape, stream);
2815:         SerialUtilities.writePaint(this.itemLabelPaint, stream);
2816:         SerialUtilities.writePaint(this.baseItemLabelPaint, stream);
2817: 
2818:     }
2819: 
2820:     /**
2821:      * Provides serialization support.
2822:      *
2823:      * @param stream  the input stream.
2824:      *
2825:      * @throws IOException  if there is an I/O error.
2826:      * @throws ClassNotFoundException  if there is a classpath problem.
2827:      */
2828:     private void readObject(ObjectInputStream stream) 
2829:         throws IOException, ClassNotFoundException {
2830: 
2831:         stream.defaultReadObject();
2832:         this.paint = SerialUtilities.readPaint(stream);
2833:         this.basePaint = SerialUtilities.readPaint(stream);
2834:         this.fillPaint = SerialUtilities.readPaint(stream);
2835:         this.baseFillPaint = SerialUtilities.readPaint(stream);
2836:         this.outlinePaint = SerialUtilities.readPaint(stream);
2837:         this.baseOutlinePaint = SerialUtilities.readPaint(stream);
2838:         this.stroke = SerialUtilities.readStroke(stream);
2839:         this.baseStroke = SerialUtilities.readStroke(stream);
2840:         this.outlineStroke = SerialUtilities.readStroke(stream);
2841:         this.baseOutlineStroke = SerialUtilities.readStroke(stream);
2842:         this.shape = SerialUtilities.readShape(stream);
2843:         this.baseShape = SerialUtilities.readShape(stream);
2844:         this.itemLabelPaint = SerialUtilities.readPaint(stream);
2845:         this.baseItemLabelPaint = SerialUtilities.readPaint(stream);
2846:         
2847:         // listeners are not restored automatically, but storage must be 
2848:         // provided...
2849:         this.listenerList = new EventListenerList();
2850: 
2851:     }
2852: 
2853: }