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-2007, by Object Refinery Limited and Contributors.
   6:  *
   7:  * Project Info:  http://www.jfree.org/jfreechart/index.html
   8:  *
   9:  * This library is free software; you can redistribute it and/or modify it 
  10:  * under the terms of the GNU Lesser General Public License as published by 
  11:  * the Free Software Foundation; either version 2.1 of the License, or 
  12:  * (at your option) any later version.
  13:  *
  14:  * This library is distributed in the hope that it will be useful, but 
  15:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  16:  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
  17:  * License for more details.
  18:  *
  19:  * You should have received a copy of the GNU Lesser General Public
  20:  * License along with this library; if not, write to the Free Software
  21:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
  22:  * USA.  
  23:  *
  24:  * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
  25:  * in the United States and other countries.]
  26:  *
  27:  * ---------------------
  28:  * AbstractRenderer.java
  29:  * ---------------------
  30:  * (C) Copyright 2002-2007, by Object Refinery Limited.
  31:  *
  32:  * Original Author:  David Gilbert (for Object Refinery Limited);
  33:  * Contributor(s):   Nicolas Brodu;
  34:  *
  35:  * Changes:
  36:  * --------
  37:  * 22-Aug-2002 : Version 1, draws code out of AbstractXYItemRenderer to share 
  38:  *               with AbstractCategoryItemRenderer (DG);
  39:  * 01-Oct-2002 : Fixed errors reported by Checkstyle (DG);
  40:  * 06-Nov-2002 : Moved to the com.jrefinery.chart.renderer package (DG);
  41:  * 21-Nov-2002 : Added a paint table for the renderer to use (DG);
  42:  * 17-Jan-2003 : Moved plot classes into a separate package (DG);
  43:  * 25-Mar-2003 : Implemented Serializable (DG);
  44:  * 29-Apr-2003 : Added valueLabelFont and valueLabelPaint attributes, based on 
  45:  *               code from Arnaud Lelievre (DG);
  46:  * 29-Jul-2003 : Amended code that doesn't compile with JDK 1.2.2 (DG);
  47:  * 13-Aug-2003 : Implemented Cloneable (DG);
  48:  * 15-Sep-2003 : Fixed serialization (NB);
  49:  * 17-Sep-2003 : Changed ChartRenderingInfo --> PlotRenderingInfo (DG);
  50:  * 07-Oct-2003 : Moved PlotRenderingInfo into RendererState to allow for 
  51:  *               multiple threads using a single renderer (DG);
  52:  * 20-Oct-2003 : Added missing setOutlinePaint() method (DG);
  53:  * 23-Oct-2003 : Split item label attributes into 'positive' and 'negative' 
  54:  *               values (DG);
  55:  * 26-Nov-2003 : Added methods to get the positive and negative item label 
  56:  *               positions (DG);
  57:  * 01-Mar-2004 : Modified readObject() method to prevent null pointer exceptions
  58:  *               after deserialization (DG);
  59:  * 19-Jul-2004 : Fixed bug in getItemLabelFont(int, int) method (DG);
  60:  * 04-Oct-2004 : Updated equals() method, eliminated use of NumberUtils,
  61:  *               renamed BooleanUtils --> BooleanUtilities, ShapeUtils -->
  62:  *               ShapeUtilities (DG);
  63:  * 15-Mar-2005 : Fixed serialization of baseFillPaint (DG);
  64:  * 16-May-2005 : Base outline stroke should never be null (DG);
  65:  * 01-Jun-2005 : Added hasListener() method for unit testing (DG);
  66:  * 08-Jun-2005 : Fixed equals() method to handle GradientPaint (DG);
  67:  * ------------- JFREECHART 1.0.x ---------------------------------------------
  68:  * 02-Feb-2007 : Minor API doc update (DG);
  69:  * 19-Feb-2007 : Fixes for clone() method (DG);
  70:  * 28-Feb-2007 : Use cached event to signal changes (DG);
  71:  * 19-Apr-2007 : Deprecated seriesVisible and seriesVisibleInLegend flags (DG);
  72:  * 20-Apr-2007 : Deprecated paint, fillPaint, outlinePaint, stroke, 
  73:  *               outlineStroke, shape, itemLabelsVisible, itemLabelFont, 
  74:  *               itemLabelPaint, positiveItemLabelPosition, 
  75:  *               negativeItemLabelPosition and createEntities override 
  76:  *               fields (DG);
  77:  * 13-Jun-2007 : Added new autoPopulate flags for core series attributes (DG);
  78:  * 23-Oct-2007 : Updated lookup methods to better handle overridden 
  79:  *               methods (DG);
  80:  * 
  81:  */
  82: 
  83: package org.jfree.chart.renderer;
  84: 
  85: import java.awt.BasicStroke;
  86: import java.awt.Color;
  87: import java.awt.Font;
  88: import java.awt.Paint;
  89: import java.awt.Shape;
  90: import java.awt.Stroke;
  91: import java.awt.geom.Point2D;
  92: import java.awt.geom.Rectangle2D;
  93: import java.io.IOException;
  94: import java.io.ObjectInputStream;
  95: import java.io.ObjectOutputStream;
  96: import java.io.Serializable;
  97: import java.util.Arrays;
  98: import java.util.EventListener;
  99: import java.util.List;
 100: 
 101: import javax.swing.event.EventListenerList;
 102: 
 103: import org.jfree.chart.event.RendererChangeEvent;
 104: import org.jfree.chart.event.RendererChangeListener;
 105: import org.jfree.chart.labels.ItemLabelAnchor;
 106: import org.jfree.chart.labels.ItemLabelPosition;
 107: import org.jfree.chart.plot.DrawingSupplier;
 108: import org.jfree.chart.plot.PlotOrientation;
 109: import org.jfree.io.SerialUtilities;
 110: import org.jfree.ui.TextAnchor;
 111: import org.jfree.util.BooleanList;
 112: import org.jfree.util.BooleanUtilities;
 113: import org.jfree.util.ObjectList;
 114: import org.jfree.util.ObjectUtilities;
 115: import org.jfree.util.PaintList;
 116: import org.jfree.util.PaintUtilities;
 117: import org.jfree.util.ShapeList;
 118: import org.jfree.util.ShapeUtilities;
 119: import org.jfree.util.StrokeList;
 120: 
 121: /**
 122:  * Base class providing common services for renderers.  Most methods that update
 123:  * attributes of the renderer will fire a {@link RendererChangeEvent}, which 
 124:  * normally means the plot that owns the renderer will receive notification that
 125:  * the renderer has been changed (the plot will, in turn, notify the chart).
 126:  */
 127: public abstract class AbstractRenderer implements Cloneable, Serializable {
 128: 
 129:     /** For serialization. */
 130:     private static final long serialVersionUID = -828267569428206075L;
 131:     
 132:     /** Zero represented as a <code>Double</code>. */
 133:     public static final Double ZERO = new Double(0.0);
 134:     
 135:     /** The default paint. */
 136:     public static final Paint DEFAULT_PAINT = Color.blue;
 137: 
 138:     /** The default outline paint. */
 139:     public static final Paint DEFAULT_OUTLINE_PAINT = Color.gray;
 140: 
 141:     /** The default stroke. */
 142:     public static final Stroke DEFAULT_STROKE = new BasicStroke(1.0f);
 143: 
 144:     /** The default outline stroke. */
 145:     public static final Stroke DEFAULT_OUTLINE_STROKE = new BasicStroke(1.0f);
 146: 
 147:     /** The default shape. */
 148:     public static final Shape DEFAULT_SHAPE 
 149:             = new Rectangle2D.Double(-3.0, -3.0, 6.0, 6.0);
 150: 
 151:     /** The default value label font. */
 152:     public static final Font DEFAULT_VALUE_LABEL_FONT 
 153:             = new Font("SansSerif", Font.PLAIN, 10);
 154: 
 155:     /** The default value label paint. */
 156:     public static final Paint DEFAULT_VALUE_LABEL_PAINT = Color.black;
 157: 
 158:     /** 
 159:      * A flag that controls the visibility of ALL series.
 160:      * 
 161:      * @deprecated This field is redundant, you can rely on seriesVisibleList
 162:      *     and baseSeriesVisible.  Deprecated from version 1.0.6 onwards.
 163:      */
 164:     private Boolean seriesVisible;
 165:     
 166:     /** A list of flags that controls whether or not each series is visible. */
 167:     private BooleanList seriesVisibleList;
 168: 
 169:     /** The default visibility for each series. */
 170:     private boolean baseSeriesVisible;
 171:     
 172:     /** 
 173:      * A flag that controls the visibility of ALL series in the legend. 
 174:      * 
 175:      * @deprecated This field is redundant, you can rely on 
 176:      *     seriesVisibleInLegendList and baseSeriesVisibleInLegend.  
 177:      *     Deprecated from version 1.0.6 onwards.
 178:      */
 179:     private Boolean seriesVisibleInLegend;
 180:     
 181:     /** 
 182:      * A list of flags that controls whether or not each series is visible in 
 183:      * the legend. 
 184:      */
 185:     private BooleanList seriesVisibleInLegendList;
 186: 
 187:     /** The default visibility for each series in the legend. */
 188:     private boolean baseSeriesVisibleInLegend;
 189:         
 190:     /** 
 191:      * The paint for ALL series (optional). 
 192:      *
 193:      * @deprecated This field is redundant, you can rely on paintList and 
 194:      *     basePaint.  Deprecated from version 1.0.6 onwards.
 195:      */
 196:     private transient Paint paint;
 197: 
 198:     /** The paint list. */
 199:     private PaintList paintList;
 200: 
 201:     /**
 202:      * A flag that controls whether or not the paintList is auto-populated
 203:      * in the {@link #lookupSeriesPaint(int)} method.
 204:      * 
 205:      * @since 1.0.6
 206:      */
 207:     private boolean autoPopulateSeriesPaint;
 208:     
 209:     /** The base paint. */
 210:     private transient Paint basePaint;
 211: 
 212:     /** 
 213:      * The fill paint for ALL series (optional). 
 214:      *
 215:      * @deprecated This field is redundant, you can rely on fillPaintList and 
 216:      *     baseFillPaint.  Deprecated from version 1.0.6 onwards.
 217:      */
 218:     private transient Paint fillPaint;
 219: 
 220:     /** The fill paint list. */
 221:     private PaintList fillPaintList;
 222:     
 223:     /**
 224:      * A flag that controls whether or not the fillPaintList is auto-populated
 225:      * in the {@link #lookupSeriesFillPaint(int)} method.
 226:      * 
 227:      * @since 1.0.6
 228:      */
 229:     private boolean autoPopulateSeriesFillPaint;
 230: 
 231:     /** The base fill paint. */
 232:     private transient Paint baseFillPaint;
 233: 
 234:     /** 
 235:      * The outline paint for ALL series (optional). 
 236:      *
 237:      * @deprecated This field is redundant, you can rely on outlinePaintList 
 238:      *         and baseOutlinePaint.  Deprecated from version 1.0.6 onwards.
 239:      */
 240:     private transient Paint outlinePaint;
 241: 
 242:     /** The outline paint list. */
 243:     private PaintList outlinePaintList;
 244: 
 245:     /**
 246:      * A flag that controls whether or not the outlinePaintList is 
 247:      * auto-populated in the {@link #lookupSeriesOutlinePaint(int)} method.
 248:      * 
 249:      * @since 1.0.6
 250:      */
 251:     private boolean autoPopulateSeriesOutlinePaint;
 252:     
 253:     /** The base outline paint. */
 254:     private transient Paint baseOutlinePaint;
 255: 
 256:     /** 
 257:      * The stroke for ALL series (optional). 
 258:      *
 259:      * @deprecated This field is redundant, you can rely on strokeList and 
 260:      *     baseStroke.  Deprecated from version 1.0.6 onwards.
 261:      */
 262:     private transient Stroke stroke;
 263: 
 264:     /** The stroke list. */
 265:     private StrokeList strokeList;
 266: 
 267:     /**
 268:      * A flag that controls whether or not the strokeList is auto-populated
 269:      * in the {@link #lookupSeriesStroke(int)} method.
 270:      * 
 271:      * @since 1.0.6
 272:      */
 273:     private boolean autoPopulateSeriesStroke;
 274: 
 275:     /** The base stroke. */
 276:     private transient Stroke baseStroke;
 277: 
 278:     /** 
 279:      * The outline stroke for ALL series (optional). 
 280:      *
 281:      * @deprecated This field is redundant, you can rely on strokeList and 
 282:      *     baseStroke.  Deprecated from version 1.0.6 onwards.
 283:      */
 284:     private transient Stroke outlineStroke;
 285: 
 286:     /** The outline stroke list. */
 287:     private StrokeList outlineStrokeList;
 288: 
 289:     /** The base outline stroke. */
 290:     private transient Stroke baseOutlineStroke;
 291: 
 292:     /**
 293:      * A flag that controls whether or not the outlineStrokeList is 
 294:      * auto-populated in the {@link #lookupSeriesOutlineStroke(int)} method.
 295:      * 
 296:      * @since 1.0.6
 297:      */
 298:     private boolean autoPopulateSeriesOutlineStroke;
 299: 
 300:     /** 
 301:      * The shape for ALL series (optional). 
 302:      *
 303:      * @deprecated This field is redundant, you can rely on shapeList and 
 304:      *     baseShape.  Deprecated from version 1.0.6 onwards.
 305:      */
 306:     private transient Shape shape;
 307: 
 308:     /** A shape list. */
 309:     private ShapeList shapeList;
 310:     
 311:     /**
 312:      * A flag that controls whether or not the shapeList is auto-populated
 313:      * in the {@link #lookupSeriesShape(int)} method.
 314:      * 
 315:      * @since 1.0.6
 316:      */
 317:     private boolean autoPopulateSeriesShape;
 318: 
 319:     /** The base shape. */
 320:     private transient Shape baseShape;
 321: 
 322:     /** 
 323:      * Visibility of the item labels for ALL series (optional). 
 324:      * 
 325:      * @deprecated This field is redundant, you can rely on 
 326:      *     itemLabelsVisibleList and baseItemLabelsVisible.  Deprecated from 
 327:      *     version 1.0.6 onwards.
 328:      */
 329:     private Boolean itemLabelsVisible;
 330: 
 331:     /** Visibility of the item labels PER series. */
 332:     private BooleanList itemLabelsVisibleList;
 333: 
 334:     /** The base item labels visible. */
 335:     private Boolean baseItemLabelsVisible;
 336: 
 337:     /** 
 338:      * The item label font for ALL series (optional). 
 339:      * 
 340:      * @deprecated This field is redundant, you can rely on itemLabelFontList 
 341:      *     and baseItemLabelFont.  Deprecated from version 1.0.6 onwards.
 342:      */
 343:     private Font itemLabelFont;
 344: 
 345:     /** The item label font list (one font per series). */
 346:     private ObjectList itemLabelFontList;
 347: 
 348:     /** The base item label font. */
 349:     private Font baseItemLabelFont;
 350: 
 351:     /** 
 352:      * The item label paint for ALL series. 
 353:      * 
 354:      * @deprecated This field is redundant, you can rely on itemLabelPaintList 
 355:      *     and baseItemLabelPaint.  Deprecated from version 1.0.6 onwards.
 356:      */
 357:     private transient Paint itemLabelPaint;
 358: 
 359:     /** The item label paint list (one paint per series). */
 360:     private PaintList itemLabelPaintList;
 361: 
 362:     /** The base item label paint. */
 363:     private transient Paint baseItemLabelPaint;
 364: 
 365:     /** 
 366:      * The positive item label position for ALL series (optional). 
 367:      * 
 368:      * @deprecated This field is redundant, you can rely on the 
 369:      *     positiveItemLabelPositionList and basePositiveItemLabelPosition
 370:      *     fields.  Deprecated from version 1.0.6 onwards.
 371:      */
 372:     private ItemLabelPosition positiveItemLabelPosition;
 373:     
 374:     /** The positive item label position (per series). */
 375:     private ObjectList positiveItemLabelPositionList;
 376:     
 377:     /** The fallback positive item label position. */
 378:     private ItemLabelPosition basePositiveItemLabelPosition;
 379:     
 380:     /** 
 381:      * The negative item label position for ALL series (optional). 
 382:      * 
 383:      * @deprecated This field is redundant, you can rely on the 
 384:      *     negativeItemLabelPositionList and baseNegativeItemLabelPosition
 385:      *     fields.  Deprecated from version 1.0.6 onwards.
 386:      */
 387:     private ItemLabelPosition negativeItemLabelPosition;
 388:     
 389:     /** The negative item label position (per series). */
 390:     private ObjectList negativeItemLabelPositionList;
 391:     
 392:     /** The fallback negative item label position. */
 393:     private ItemLabelPosition baseNegativeItemLabelPosition;
 394: 
 395:     /** The item label anchor offset. */
 396:     private double itemLabelAnchorOffset = 2.0;
 397: 
 398:     /** 
 399:      * A flag that controls whether or not entities are generated for 
 400:      * ALL series (optional). 
 401:      * 
 402:      * @deprecated This field is redundant, you can rely on the 
 403:      *     createEntitiesList and baseCreateEntities fields.  Deprecated from 
 404:      *     version 1.0.6 onwards.
 405:      */
 406:     private Boolean createEntities;
 407: 
 408:     /** 
 409:      * Flags that control whether or not entities are generated for each 
 410:      * series.  This will be overridden by 'createEntities'. 
 411:      */
 412:     private BooleanList createEntitiesList;
 413: 
 414:     /**
 415:      * The default flag that controls whether or not entities are generated.
 416:      * This flag is used when both the above flags return null. 
 417:      */
 418:     private boolean baseCreateEntities;
 419:     
 420:     /** Storage for registered change listeners. */
 421:     private transient EventListenerList listenerList;
 422: 
 423:     /** An event for re-use. */
 424:     private transient RendererChangeEvent event;
 425:     
 426:     /**
 427:      * Default constructor.
 428:      */
 429:     public AbstractRenderer() {
 430: 
 431:         this.seriesVisible = null;
 432:         this.seriesVisibleList = new BooleanList();
 433:         this.baseSeriesVisible = true;
 434:         
 435:         this.seriesVisibleInLegend = null;
 436:         this.seriesVisibleInLegendList = new BooleanList();
 437:         this.baseSeriesVisibleInLegend = true;
 438: 
 439:         this.paint = null;
 440:         this.paintList = new PaintList();
 441:         this.basePaint = DEFAULT_PAINT;
 442:         this.autoPopulateSeriesPaint = true;
 443: 
 444:         this.fillPaint = null;
 445:         this.fillPaintList = new PaintList();
 446:         this.baseFillPaint = Color.white;
 447:         this.autoPopulateSeriesFillPaint = false;
 448: 
 449:         this.outlinePaint = null;
 450:         this.outlinePaintList = new PaintList();
 451:         this.baseOutlinePaint = DEFAULT_OUTLINE_PAINT;
 452:         this.autoPopulateSeriesOutlinePaint = false;
 453: 
 454:         this.stroke = null;
 455:         this.strokeList = new StrokeList();
 456:         this.baseStroke = DEFAULT_STROKE;
 457:         this.autoPopulateSeriesStroke = false;
 458: 
 459:         this.outlineStroke = null;
 460:         this.outlineStrokeList = new StrokeList();
 461:         this.baseOutlineStroke = DEFAULT_OUTLINE_STROKE;
 462:         this.autoPopulateSeriesOutlineStroke = false;
 463: 
 464:         this.shape = null;
 465:         this.shapeList = new ShapeList();
 466:         this.baseShape = DEFAULT_SHAPE;
 467:         this.autoPopulateSeriesShape = true;
 468: 
 469:         this.itemLabelsVisible = null;
 470:         this.itemLabelsVisibleList = new BooleanList();
 471:         this.baseItemLabelsVisible = Boolean.FALSE;
 472: 
 473:         this.itemLabelFont = null;
 474:         this.itemLabelFontList = new ObjectList();
 475:         this.baseItemLabelFont = new Font("SansSerif", Font.PLAIN, 10);
 476: 
 477:         this.itemLabelPaint = null;
 478:         this.itemLabelPaintList = new PaintList();
 479:         this.baseItemLabelPaint = Color.black;
 480: 
 481:         this.positiveItemLabelPosition = null;
 482:         this.positiveItemLabelPositionList = new ObjectList();
 483:         this.basePositiveItemLabelPosition = new ItemLabelPosition(
 484:                 ItemLabelAnchor.OUTSIDE12, TextAnchor.BOTTOM_CENTER);
 485:         
 486:         this.negativeItemLabelPosition = null;
 487:         this.negativeItemLabelPositionList = new ObjectList();
 488:         this.baseNegativeItemLabelPosition = new ItemLabelPosition(
 489:                 ItemLabelAnchor.OUTSIDE6, TextAnchor.TOP_CENTER);
 490: 
 491:         this.createEntities = null;
 492:         this.createEntitiesList = new BooleanList();
 493:         this.baseCreateEntities = true;
 494:         
 495:         this.listenerList = new EventListenerList();
 496: 
 497:     }
 498: 
 499:     /**
 500:      * Returns the drawing supplier from the plot.
 501:      * 
 502:      * @return The drawing supplier.
 503:      */
 504:     public abstract DrawingSupplier getDrawingSupplier();
 505:     
 506:     // SERIES VISIBLE (not yet respected by all renderers)
 507: 
 508:     /**
 509:      * Returns a boolean that indicates whether or not the specified item 
 510:      * should be drawn (this is typically used to hide an entire series).
 511:      * 
 512:      * @param series  the series index.
 513:      * @param item  the item index.
 514:      * 
 515:      * @return A boolean.
 516:      */
 517:     public boolean getItemVisible(int series, int item) {
 518:         return isSeriesVisible(series);
 519:     }
 520:     
 521:     /**
 522:      * Returns a boolean that indicates whether or not the specified series 
 523:      * should be drawn.
 524:      * 
 525:      * @param series  the series index.
 526:      * 
 527:      * @return A boolean.
 528:      */
 529:     public boolean isSeriesVisible(int series) {
 530:         boolean result = this.baseSeriesVisible;
 531:         if (this.seriesVisible != null) {
 532:             result = this.seriesVisible.booleanValue();   
 533:         }
 534:         else {
 535:             Boolean b = this.seriesVisibleList.getBoolean(series);
 536:             if (b != null) {
 537:                 result = b.booleanValue();   
 538:             }
 539:         }
 540:         return result;
 541:     }
 542:     
 543:     /**
 544:      * Returns the flag that controls the visibility of ALL series.  This flag 
 545:      * overrides the per series and default settings - you must set it to 
 546:      * <code>null</code> if you want the other settings to apply.
 547:      * 
 548:      * @return The flag (possibly <code>null</code>).
 549:      * 
 550:      * @see #setSeriesVisible(Boolean)
 551:      * 
 552:      * @deprecated This method should no longer be used (as of version 1.0.6). 
 553:      *     It is sufficient to rely on {@link #getSeriesVisible(int)} and
 554:      *     {@link #getBaseSeriesVisible()}.
 555:      */
 556:     public Boolean getSeriesVisible() {
 557:         return this.seriesVisible;   
 558:     }
 559:     
 560:     /**
 561:      * Sets the flag that controls the visibility of ALL series and sends a 
 562:      * {@link RendererChangeEvent} to all registered listeners.  This flag 
 563:      * overrides the per series and default settings - you must set it to 
 564:      * <code>null</code> if you want the other settings to apply.
 565:      * 
 566:      * @param visible  the flag (<code>null</code> permitted).
 567:      * 
 568:      * @see #getSeriesVisible()
 569:      * 
 570:      * @deprecated This method should no longer be used (as of version 1.0.6). 
 571:      *     It is sufficient to rely on {@link #setSeriesVisible(int, Boolean)} 
 572:      *     and {@link #setBaseSeriesVisible(boolean)}.
 573:      */
 574:     public void setSeriesVisible(Boolean visible) {
 575:          setSeriesVisible(visible, true);
 576:     }
 577:     
 578:     /**
 579:      * Sets the flag that controls the visibility of ALL series and sends a 
 580:      * {@link RendererChangeEvent} to all registered listeners.  This flag 
 581:      * overrides the per series and default settings - you must set it to 
 582:      * <code>null</code> if you want the other settings to apply.
 583:      * 
 584:      * @param visible  the flag (<code>null</code> permitted).
 585:      * @param notify  notify listeners?
 586:      * 
 587:      * @see #getSeriesVisible()
 588:      * 
 589:      * @deprecated This method should no longer be used (as of version 1.0.6). 
 590:      *     It is sufficient to rely on {@link #setSeriesVisible(int, Boolean)} 
 591:      *     and {@link #setBaseSeriesVisible(boolean)}.
 592:      */
 593:     public void setSeriesVisible(Boolean visible, boolean notify) {
 594:         this.seriesVisible = visible;   
 595:         if (notify) {
 596:             fireChangeEvent();
 597:         }
 598:     }
 599:     
 600:     /**
 601:      * Returns the flag that controls whether a series is visible.
 602:      *
 603:      * @param series  the series index (zero-based).
 604:      *
 605:      * @return The flag (possibly <code>null</code>).
 606:      * 
 607:      * @see #setSeriesVisible(int, Boolean)
 608:      */
 609:     public Boolean getSeriesVisible(int series) {
 610:         return this.seriesVisibleList.getBoolean(series);
 611:     }
 612:     
 613:     /**
 614:      * Sets the flag that controls whether a series is visible and sends a 
 615:      * {@link RendererChangeEvent} to all registered listeners.
 616:      *
 617:      * @param series  the series index (zero-based).
 618:      * @param visible  the flag (<code>null</code> permitted).
 619:      * 
 620:      * @see #getSeriesVisible(int)
 621:      */
 622:     public void setSeriesVisible(int series, Boolean visible) {
 623:         setSeriesVisible(series, visible, true);
 624:     }
 625:     
 626:     /**
 627:      * Sets the flag that controls whether a series is visible and, if 
 628:      * requested, sends a {@link RendererChangeEvent} to all registered 
 629:      * listeners.
 630:      * 
 631:      * @param series  the series index.
 632:      * @param visible  the flag (<code>null</code> permitted).
 633:      * @param notify  notify listeners?
 634:      * 
 635:      * @see #getSeriesVisible(int)
 636:      */
 637:     public void setSeriesVisible(int series, Boolean visible, boolean notify) {
 638:         this.seriesVisibleList.setBoolean(series, visible);       
 639:         if (notify) {
 640:             fireChangeEvent();
 641:         }
 642:     }
 643: 
 644:     /**
 645:      * Returns the base visibility for all series.
 646:      *
 647:      * @return The base visibility.
 648:      * 
 649:      * @see #setBaseSeriesVisible(boolean)
 650:      */
 651:     public boolean getBaseSeriesVisible() {
 652:         return this.baseSeriesVisible;
 653:     }
 654: 
 655:     /**
 656:      * Sets the base visibility and sends a {@link RendererChangeEvent} 
 657:      * to all registered listeners.
 658:      *
 659:      * @param visible  the flag.
 660:      * 
 661:      * @see #getBaseSeriesVisible()
 662:      */
 663:     public void setBaseSeriesVisible(boolean visible) {
 664:         // defer argument checking...
 665:         setBaseSeriesVisible(visible, true);
 666:     }
 667:     
 668:     /**
 669:      * Sets the base visibility and, if requested, sends 
 670:      * a {@link RendererChangeEvent} to all registered listeners.
 671:      * 
 672:      * @param visible  the visibility.
 673:      * @param notify  notify listeners?
 674:      * 
 675:      * @see #getBaseSeriesVisible()
 676:      */
 677:     public void setBaseSeriesVisible(boolean visible, boolean notify) {
 678:         this.baseSeriesVisible = visible;
 679:         if (notify) {
 680:             fireChangeEvent();
 681:         }
 682:     }
 683: 
 684:     // SERIES VISIBLE IN LEGEND (not yet respected by all renderers)
 685:     
 686:     /**
 687:      * Returns <code>true</code> if the series should be shown in the legend,
 688:      * and <code>false</code> otherwise.
 689:      * 
 690:      * @param series  the series index.
 691:      * 
 692:      * @return A boolean.
 693:      */
 694:     public boolean isSeriesVisibleInLegend(int series) {
 695:         boolean result = this.baseSeriesVisibleInLegend;
 696:         if (this.seriesVisibleInLegend != null) {
 697:             result = this.seriesVisibleInLegend.booleanValue();   
 698:         }
 699:         else {
 700:             Boolean b = this.seriesVisibleInLegendList.getBoolean(series);
 701:             if (b != null) {
 702:                 result = b.booleanValue();   
 703:             }
 704:         }
 705:         return result;
 706:     }
 707:     
 708:     /**
 709:      * Returns the flag that controls the visibility of ALL series in the 
 710:      * legend.  This flag overrides the per series and default settings - you 
 711:      * must set it to <code>null</code> if you want the other settings to 
 712:      * apply.
 713:      * 
 714:      * @return The flag (possibly <code>null</code>).
 715:      * 
 716:      * @see #setSeriesVisibleInLegend(Boolean)
 717:      * 
 718:      * @deprecated This method should no longer be used (as of version 1.0.6). 
 719:      *     It is sufficient to rely on {@link #getSeriesVisibleInLegend(int)} 
 720:      *     and {@link #getBaseSeriesVisibleInLegend()}.
 721:      */
 722:     public Boolean getSeriesVisibleInLegend() {
 723:         return this.seriesVisibleInLegend;   
 724:     }
 725:     
 726:     /**
 727:      * Sets the flag that controls the visibility of ALL series in the legend 
 728:      * and sends a {@link RendererChangeEvent} to all registered listeners.  
 729:      * This flag overrides the per series and default settings - you must set 
 730:      * it to <code>null</code> if you want the other settings to apply.
 731:      * 
 732:      * @param visible  the flag (<code>null</code> permitted).
 733:      * 
 734:      * @see #getSeriesVisibleInLegend()
 735:      * 
 736:      * @deprecated This method should no longer be used (as of version 1.0.6). 
 737:      *     It is sufficient to rely on {@link #setSeriesVisibleInLegend(int, 
 738:      *     Boolean)} and {@link #setBaseSeriesVisibleInLegend(boolean)}.
 739:      */
 740:     public void setSeriesVisibleInLegend(Boolean visible) {
 741:          setSeriesVisibleInLegend(visible, true);
 742:     }
 743:     
 744:     /**
 745:      * Sets the flag that controls the visibility of ALL series in the legend 
 746:      * and sends a {@link RendererChangeEvent} to all registered listeners.  
 747:      * This flag overrides the per series and default settings - you must set 
 748:      * it to <code>null</code> if you want the other settings to apply.
 749:      * 
 750:      * @param visible  the flag (<code>null</code> permitted).
 751:      * @param notify  notify listeners?
 752:      * 
 753:      * @see #getSeriesVisibleInLegend()
 754:      * 
 755:      * @deprecated This method should no longer be used (as of version 1.0.6). 
 756:      *     It is sufficient to rely on {@link #setSeriesVisibleInLegend(int, 
 757:      *     Boolean, boolean)} and {@link #setBaseSeriesVisibleInLegend(boolean,
 758:      *     boolean)}.
 759:      */
 760:     public void setSeriesVisibleInLegend(Boolean visible, boolean notify) {
 761:         this.seriesVisibleInLegend = visible;   
 762:         if (notify) {
 763:             fireChangeEvent();
 764:         }
 765:     }
 766:     
 767:     /**
 768:      * Returns the flag that controls whether a series is visible in the 
 769:      * legend.  This method returns only the "per series" settings - to 
 770:      * incorporate the override and base settings as well, you need to use the 
 771:      * {@link #isSeriesVisibleInLegend(int)} method.
 772:      *
 773:      * @param series  the series index (zero-based).
 774:      *
 775:      * @return The flag (possibly <code>null</code>).
 776:      * 
 777:      * @see #setSeriesVisibleInLegend(int, Boolean)
 778:      */
 779:     public Boolean getSeriesVisibleInLegend(int series) {
 780:         return this.seriesVisibleInLegendList.getBoolean(series);
 781:     }
 782:     
 783:     /**
 784:      * Sets the flag that controls whether a series is visible in the legend 
 785:      * and sends a {@link RendererChangeEvent} to all registered listeners.
 786:      *
 787:      * @param series  the series index (zero-based).
 788:      * @param visible  the flag (<code>null</code> permitted).
 789:      * 
 790:      * @see #getSeriesVisibleInLegend(int)
 791:      */
 792:     public void setSeriesVisibleInLegend(int series, Boolean visible) {
 793:         setSeriesVisibleInLegend(series, visible, true);
 794:     }
 795:     
 796:     /**
 797:      * Sets the flag that controls whether a series is visible in the legend
 798:      * and, if requested, sends a {@link RendererChangeEvent} to all registered 
 799:      * listeners.
 800:      * 
 801:      * @param series  the series index.
 802:      * @param visible  the flag (<code>null</code> permitted).
 803:      * @param notify  notify listeners?
 804:      * 
 805:      * @see #getSeriesVisibleInLegend(int)
 806:      */
 807:     public void setSeriesVisibleInLegend(int series, Boolean visible, 
 808:                                          boolean notify) {
 809:         this.seriesVisibleInLegendList.setBoolean(series, visible);       
 810:         if (notify) {
 811:             fireChangeEvent();
 812:         }
 813:     }
 814: 
 815:     /**
 816:      * Returns the base visibility in the legend for all series.
 817:      *
 818:      * @return The base visibility.
 819:      * 
 820:      * @see #setBaseSeriesVisibleInLegend(boolean)
 821:      */
 822:     public boolean getBaseSeriesVisibleInLegend() {
 823:         return this.baseSeriesVisibleInLegend;
 824:     }
 825: 
 826:     /**
 827:      * Sets the base visibility in the legend and sends a 
 828:      * {@link RendererChangeEvent} to all registered listeners.
 829:      *
 830:      * @param visible  the flag.
 831:      * 
 832:      * @see #getBaseSeriesVisibleInLegend()
 833:      */
 834:     public void setBaseSeriesVisibleInLegend(boolean visible) {
 835:         // defer argument checking...
 836:         setBaseSeriesVisibleInLegend(visible, true);
 837:     }
 838:     
 839:     /**
 840:      * Sets the base visibility in the legend and, if requested, sends 
 841:      * a {@link RendererChangeEvent} to all registered listeners.
 842:      * 
 843:      * @param visible  the visibility.
 844:      * @param notify  notify listeners?
 845:      * 
 846:      * @see #getBaseSeriesVisibleInLegend()
 847:      */
 848:     public void setBaseSeriesVisibleInLegend(boolean visible, boolean notify) {
 849:         this.baseSeriesVisibleInLegend = visible;
 850:         if (notify) {
 851:             fireChangeEvent();
 852:         }
 853:     }
 854: 
 855:     // PAINT
 856:     
 857:     /**
 858:      * Returns the paint used to fill data items as they are drawn.
 859:      * <p>
 860:      * The default implementation passes control to the 
 861:      * <code>getSeriesPaint</code> method. You can override this method if you 
 862:      * require different behaviour.
 863:      *
 864:      * @param row  the row (or series) index (zero-based).
 865:      * @param column  the column (or category) index (zero-based).
 866:      *
 867:      * @return The paint (never <code>null</code>).
 868:      */
 869:     public Paint getItemPaint(int row, int column) {
 870:         return lookupSeriesPaint(row);
 871:     }
 872: 
 873:     /**
 874:      * Returns the paint used to fill an item drawn by the renderer.
 875:      *
 876:      * @param series  the series index (zero-based).
 877:      *
 878:      * @return The paint (never <code>null</code>).
 879:      * 
 880:      * @since 1.0.6
 881:      */
 882:     public Paint lookupSeriesPaint(int series) {
 883: 
 884:         // return the override, if there is one...
 885:         if (this.paint != null) {
 886:             return this.paint;
 887:         }
 888: 
 889:         // otherwise look up the paint list
 890:         Paint seriesPaint = getSeriesPaint(series);
 891:         if (seriesPaint == null && this.autoPopulateSeriesPaint) {
 892:             DrawingSupplier supplier = getDrawingSupplier();
 893:             if (supplier != null) {
 894:                 seriesPaint = supplier.getNextPaint();
 895:                 setSeriesPaint(series, seriesPaint, false);
 896:             }
 897:         }
 898:         if (seriesPaint == null) {
 899:             seriesPaint = this.basePaint;
 900:         }
 901:         return seriesPaint;
 902: 
 903:     }
 904: 
 905:     /**
 906:      * Sets the paint to be used for ALL series, and sends a 
 907:      * {@link RendererChangeEvent} to all registered listeners.  If this is 
 908:      * <code>null</code>, the renderer will use the paint for the series.
 909:      * 
 910:      * @param paint  the paint (<code>null</code> permitted).
 911:      * 
 912:      * @deprecated This method should no longer be used (as of version 1.0.6). 
 913:      *     It is sufficient to rely on {@link #setSeriesPaint(int, Paint)} and 
 914:      *     {@link #setBasePaint(Paint)}.
 915:      */
 916:     public void setPaint(Paint paint) {
 917:         setPaint(paint, true);
 918:     }
 919:     
 920:     /**
 921:      * Sets the paint to be used for all series and, if requested, sends a 
 922:      * {@link RendererChangeEvent} to all registered listeners.
 923:      * 
 924:      * @param paint  the paint (<code>null</code> permitted).
 925:      * @param notify  notify listeners?
 926:      * 
 927:      * @deprecated This method should no longer be used (as of version 1.0.6). 
 928:      *     It is sufficient to rely on {@link #setSeriesPaint(int, Paint, 
 929:      *     boolean)} and {@link #setBasePaint(Paint, boolean)}.
 930:      */
 931:     public void setPaint(Paint paint, boolean notify) {
 932:         this.paint = paint;
 933:         if (notify) {
 934:             fireChangeEvent();
 935:         }
 936:     }
 937:     
 938:     /**
 939:      * Returns the paint used to fill an item drawn by the renderer.
 940:      *
 941:      * @param series  the series index (zero-based).
 942:      *
 943:      * @return The paint (possibly <code>null</code>).
 944:      * 
 945:      * @see #setSeriesPaint(int, Paint)
 946:      */
 947:     public Paint getSeriesPaint(int series) {
 948:         return this.paintList.getPaint(series);
 949:     }
 950:     
 951:     /**
 952:      * Sets the paint used for a series and sends a {@link RendererChangeEvent}
 953:      * to all registered listeners.
 954:      *
 955:      * @param series  the series index (zero-based).
 956:      * @param paint  the paint (<code>null</code> permitted).
 957:      * 
 958:      * @see #getSeriesPaint(int)
 959:      */
 960:     public void setSeriesPaint(int series, Paint paint) {
 961:         setSeriesPaint(series, paint, true);
 962:     }
 963:     
 964:     /**
 965:      * Sets the paint used for a series and, if requested, sends a 
 966:      * {@link RendererChangeEvent} to all registered listeners.
 967:      * 
 968:      * @param series  the series index.
 969:      * @param paint  the paint (<code>null</code> permitted).
 970:      * @param notify  notify listeners?
 971:      * 
 972:      * @see #getSeriesPaint(int)
 973:      */
 974:     public void setSeriesPaint(int series, Paint paint, boolean notify) {
 975:         this.paintList.setPaint(series, paint);       
 976:         if (notify) {
 977:             fireChangeEvent();
 978:         }
 979:     }
 980: 
 981:     /**
 982:      * Returns the base paint.
 983:      *
 984:      * @return The base paint (never <code>null</code>).
 985:      * 
 986:      * @see #setBasePaint(Paint)
 987:      */
 988:     public Paint getBasePaint() {
 989:         return this.basePaint;
 990:     }
 991: 
 992:     /**
 993:      * Sets the base paint and sends a {@link RendererChangeEvent} to all 
 994:      * registered listeners.
 995:      *
 996:      * @param paint  the paint (<code>null</code> not permitted).
 997:      * 
 998:      * @see #getBasePaint()
 999:      */
1000:     public void setBasePaint(Paint paint) {
1001:         // defer argument checking...
1002:         setBasePaint(paint, true);
1003:     }
1004:     
1005:     /**
1006:      * Sets the base paint and, if requested, sends a 
1007:      * {@link RendererChangeEvent} to all registered listeners.
1008:      * 
1009:      * @param paint  the paint (<code>null</code> not permitted).
1010:      * @param notify  notify listeners?
1011:      * 
1012:      * @see #getBasePaint()
1013:      */
1014:     public void setBasePaint(Paint paint, boolean notify) {
1015:         this.basePaint = paint;
1016:         if (notify) {
1017:             fireChangeEvent();
1018:         }
1019:     }
1020:     
1021:     /**
1022:      * Returns the flag that controls whether or not the series paint list is
1023:      * automatically populated when {@link #lookupSeriesPaint(int)} is called.
1024:      * 
1025:      * @return A boolean.
1026:      * 
1027:      * @since 1.0.6
1028:      * 
1029:      * @see #setAutoPopulateSeriesPaint(boolean)
1030:      */
1031:     public boolean getAutoPopulateSeriesPaint() {
1032:         return this.autoPopulateSeriesPaint;
1033:     }
1034:     
1035:     /**
1036:      * Sets the flag that controls whether or not the series paint list is
1037:      * automatically populated when {@link #lookupSeriesPaint(int)} is called.
1038:      * 
1039:      * @param auto  the new flag value.
1040:      * 
1041:      * @since 1.0.6
1042:      * 
1043:      * @see #getAutoPopulateSeriesPaint()
1044:      */
1045:     public void setAutoPopulateSeriesPaint(boolean auto) {
1046:         this.autoPopulateSeriesPaint = auto;
1047:     }
1048: 
1049:     //// FILL PAINT //////////////////////////////////////////////////////////
1050:     
1051:     /**
1052:      * Returns the paint used to fill data items as they are drawn.  The 
1053:      * default implementation passes control to the 
1054:      * {@link #lookupSeriesFillPaint(int)} method - you can override this 
1055:      * method if you require different behaviour.
1056:      *
1057:      * @param row  the row (or series) index (zero-based).
1058:      * @param column  the column (or category) index (zero-based).
1059:      *
1060:      * @return The paint (never <code>null</code>).
1061:      */
1062:     public Paint getItemFillPaint(int row, int column) {
1063:         return lookupSeriesFillPaint(row);
1064:     }
1065: 
1066:     /**
1067:      * Returns the paint used to fill an item drawn by the renderer.
1068:      *
1069:      * @param series  the series (zero-based index).
1070:      *
1071:      * @return The paint (never <code>null</code>).
1072:      * 
1073:      * @since 1.0.6
1074:      */
1075:     public Paint lookupSeriesFillPaint(int series) {
1076: 
1077:         // return the override, if there is one...
1078:         if (this.fillPaint != null) {
1079:             return this.fillPaint;
1080:         }
1081: 
1082:         // otherwise look up the paint table
1083:         Paint seriesFillPaint = getSeriesFillPaint(series);
1084:         if (seriesFillPaint == null && this.autoPopulateSeriesFillPaint) {
1085:             DrawingSupplier supplier = getDrawingSupplier();
1086:             if (supplier != null) {
1087:                 seriesFillPaint = supplier.getNextFillPaint();
1088:                 setSeriesFillPaint(series, seriesFillPaint, false);
1089:             }
1090:         }
1091:         if (seriesFillPaint == null) {
1092:             seriesFillPaint = this.baseFillPaint;
1093:         }
1094:         return seriesFillPaint;
1095: 
1096:     }
1097: 
1098:     /**
1099:      * Returns the paint used to fill an item drawn by the renderer.
1100:      *
1101:      * @param series  the series (zero-based index).
1102:      *
1103:      * @return The paint (never <code>null</code>).
1104:      * 
1105:      * @see #setSeriesFillPaint(int, Paint)
1106:      */
1107:     public Paint getSeriesFillPaint(int series) {
1108:         return this.fillPaintList.getPaint(series);    
1109:     }
1110:     
1111:     /**
1112:      * Sets the paint used for a series fill and sends a 
1113:      * {@link RendererChangeEvent} to all registered listeners.
1114:      *
1115:      * @param series  the series index (zero-based).
1116:      * @param paint  the paint (<code>null</code> permitted).
1117:      * 
1118:      * @see #getSeriesFillPaint(int)
1119:      */
1120:     public void setSeriesFillPaint(int series, Paint paint) {
1121:         setSeriesFillPaint(series, paint, true);
1122:     }
1123: 
1124:     /**
1125:      * Sets the paint used to fill a series and, if requested, 
1126:      * sends a {@link RendererChangeEvent} to all registered listeners.
1127:      * 
1128:      * @param series  the series index (zero-based).
1129:      * @param paint  the paint (<code>null</code> permitted).
1130:      * @param notify  notify listeners?
1131:      * 
1132:      * @see #getSeriesFillPaint(int)
1133:      */    
1134:     public void setSeriesFillPaint(int series, Paint paint, boolean notify) {
1135:         this.fillPaintList.setPaint(series, paint);
1136:         if (notify) {
1137:             fireChangeEvent();
1138:         }
1139:     }
1140: 
1141:     /**
1142:      * Sets the fill paint for ALL series (optional).
1143:      * 
1144:      * @param paint  the paint (<code>null</code> permitted).
1145:      * 
1146:      * @deprecated This method should no longer be used (as of version 1.0.6). 
1147:      *     It is sufficient to rely on {@link #setSeriesFillPaint(int, Paint)} 
1148:      *     and {@link #setBaseFillPaint(Paint)}.
1149:      */
1150:     public void setFillPaint(Paint paint) {
1151:         setFillPaint(paint, true);
1152:     }
1153: 
1154:     /**
1155:      * Sets the fill paint for ALL series and, if requested, sends a 
1156:      * {@link RendererChangeEvent} to all registered listeners.
1157:      * 
1158:      * @param paint  the paint (<code>null</code> permitted).
1159:      * @param notify  notify listeners?
1160:      * 
1161:      * @deprecated This method should no longer be used (as of version 1.0.6). 
1162:      *     It is sufficient to rely on {@link #setSeriesFillPaint(int, Paint,
1163:      *     boolean)} and {@link #setBaseFillPaint(Paint, boolean)}.
1164:      */
1165:     public void setFillPaint(Paint paint, boolean notify) {
1166:         this.fillPaint = paint;
1167:         if (notify) {
1168:             fireChangeEvent();
1169:         }
1170:     }
1171:     
1172:     /**
1173:      * Returns the base fill paint.
1174:      *
1175:      * @return The paint (never <code>null</code>).
1176:      * 
1177:      * @see #setBaseFillPaint(Paint)
1178:      */
1179:     public Paint getBaseFillPaint() {
1180:         return this.baseFillPaint;
1181:     }
1182: 
1183:     /**
1184:      * Sets the base fill paint and sends a {@link RendererChangeEvent} to 
1185:      * all registered listeners.
1186:      *
1187:      * @param paint  the paint (<code>null</code> not permitted).
1188:      * 
1189:      * @see #getBaseFillPaint()
1190:      */
1191:     public void setBaseFillPaint(Paint paint) {
1192:         // defer argument checking...
1193:         setBaseFillPaint(paint, true);
1194:     }
1195:     
1196:     /**
1197:      * Sets the base fill paint and, if requested, sends a 
1198:      * {@link RendererChangeEvent} to all registered listeners.
1199:      * 
1200:      * @param paint  the paint (<code>null</code> not permitted).
1201:      * @param notify  notify listeners?
1202:      * 
1203:      * @see #getBaseFillPaint()
1204:      */
1205:     public void setBaseFillPaint(Paint paint, boolean notify) {
1206:         if (paint == null) {
1207:             throw new IllegalArgumentException("Null 'paint' argument.");   
1208:         }
1209:         this.baseFillPaint = paint;
1210:         if (notify) {
1211:             fireChangeEvent();
1212:         }
1213:     }
1214: 
1215:     /**
1216:      * Returns the flag that controls whether or not the series fill paint list
1217:      * is automatically populated when {@link #lookupSeriesFillPaint(int)} is 
1218:      * called.
1219:      * 
1220:      * @return A boolean.
1221:      * 
1222:      * @since 1.0.6
1223:      * 
1224:      * @see #setAutoPopulateSeriesFillPaint(boolean)
1225:      */
1226:     public boolean getAutoPopulateSeriesFillPaint() {
1227:         return this.autoPopulateSeriesFillPaint;
1228:     }
1229:     
1230:     /**
1231:      * Sets the flag that controls whether or not the series fill paint list is
1232:      * automatically populated when {@link #lookupSeriesFillPaint(int)} is 
1233:      * called.
1234:      * 
1235:      * @param auto  the new flag value.
1236:      * 
1237:      * @since 1.0.6
1238:      * 
1239:      * @see #getAutoPopulateSeriesFillPaint()
1240:      */
1241:     public void setAutoPopulateSeriesFillPaint(boolean auto) {
1242:         this.autoPopulateSeriesFillPaint = auto;
1243:     }
1244: 
1245:     // OUTLINE PAINT //////////////////////////////////////////////////////////
1246:     
1247:     /**
1248:      * Returns the paint used to outline data items as they are drawn.
1249:      * <p>
1250:      * The default implementation passes control to the 
1251:      * {@link #lookupSeriesOutlinePaint} method.  You can override this method 
1252:      * if you require different behaviour.
1253:      *
1254:      * @param row  the row (or series) index (zero-based).
1255:      * @param column  the column (or category) index (zero-based).
1256:      *
1257:      * @return The paint (never <code>null</code>).
1258:      */
1259:     public Paint getItemOutlinePaint(int row, int column) {
1260:         return lookupSeriesOutlinePaint(row);
1261:     }
1262: 
1263:     /**
1264:      * Returns the paint used to outline an item drawn by the renderer.
1265:      *
1266:      * @param series  the series (zero-based index).
1267:      *
1268:      * @return The paint (never <code>null</code>).
1269:      * 
1270:      * @since 1.0.6
1271:      */
1272:     public Paint lookupSeriesOutlinePaint(int series) {
1273: 
1274:         // return the override, if there is one...
1275:         if (this.outlinePaint != null) {
1276:             return this.outlinePaint;
1277:         }
1278: 
1279:         // otherwise look up the paint table
1280:         Paint seriesOutlinePaint = getSeriesOutlinePaint(series);
1281:         if (seriesOutlinePaint == null && this.autoPopulateSeriesOutlinePaint) {
1282:             DrawingSupplier supplier = getDrawingSupplier();
1283:             if (supplier != null) {
1284:                 seriesOutlinePaint = supplier.getNextOutlinePaint();
1285:                 setSeriesOutlinePaint(series, seriesOutlinePaint, false);
1286:             }
1287:         }
1288:         if (seriesOutlinePaint == null) {
1289:             seriesOutlinePaint = this.baseOutlinePaint;
1290:         }
1291:         return seriesOutlinePaint;
1292: 
1293:     }
1294: 
1295:     /**
1296:      * Returns the paint used to outline an item drawn by the renderer.
1297:      *
1298:      * @param series  the series (zero-based index).
1299:      *
1300:      * @return The paint (possibly <code>null</code>).
1301:      * 
1302:      * @see #setSeriesOutlinePaint(int, Paint)
1303:      */
1304:     public Paint getSeriesOutlinePaint(int series) {
1305:         return this.outlinePaintList.getPaint(series);    
1306:     }
1307:     
1308:     /**
1309:      * Sets the paint used for a series outline and sends a 
1310:      * {@link RendererChangeEvent} to all registered listeners.
1311:      *
1312:      * @param series  the series index (zero-based).
1313:      * @param paint  the paint (<code>null</code> permitted).
1314:      * 
1315:      * @see #getSeriesOutlinePaint(int)
1316:      */
1317:     public void setSeriesOutlinePaint(int series, Paint paint) {
1318:         setSeriesOutlinePaint(series, paint, true);
1319:     }
1320: 
1321:     /**
1322:      * Sets the paint used to draw the outline for a series and, if requested, 
1323:      * sends a {@link RendererChangeEvent} to all registered listeners.
1324:      * 
1325:      * @param series  the series index (zero-based).
1326:      * @param paint  the paint (<code>null</code> permitted).
1327:      * @param notify  notify listeners?
1328:      * 
1329:      * @see #getSeriesOutlinePaint(int)
1330:      */    
1331:     public void setSeriesOutlinePaint(int series, Paint paint, boolean notify) {
1332:         this.outlinePaintList.setPaint(series, paint);
1333:         if (notify) {
1334:             fireChangeEvent();
1335:         }
1336:     }
1337: 
1338:     /**
1339:      * Sets the outline paint for ALL series (optional) and sends a 
1340:      * {@link RendererChangeEvent} to all registered listeners.
1341:      * 
1342:      * @param paint  the paint (<code>null</code> permitted).
1343:      * 
1344:      * @deprecated This method should no longer be used (as of version 1.0.6). 
1345:      *     It is sufficient to rely on {@link #setSeriesOutlinePaint(int, 
1346:      *     Paint)} and {@link #setBaseOutlinePaint(Paint)}.
1347:      */
1348:     public void setOutlinePaint(Paint paint) {
1349:         setOutlinePaint(paint, true);
1350:     }
1351: 
1352:     /**
1353:      * Sets the outline paint for ALL series and, if requested, sends a 
1354:      * {@link RendererChangeEvent} to all registered listeners.
1355:      * 
1356:      * @param paint  the paint (<code>null</code> permitted).
1357:      * @param notify  notify listeners?
1358:      * 
1359:      * @deprecated This method should no longer be used (as of version 1.0.6). 
1360:      *     It is sufficient to rely on {@link #setSeriesOutlinePaint(int, 
1361:      *     Paint, boolean)} and {@link #setBaseOutlinePaint(Paint, boolean)}.
1362:      */
1363:     public void setOutlinePaint(Paint paint, boolean notify) {
1364:         this.outlinePaint = paint;
1365:         if (notify) {
1366:             fireChangeEvent();
1367:         }
1368:     }
1369:     
1370:     /**
1371:      * Returns the base outline paint.
1372:      *
1373:      * @return The paint (never <code>null</code>).
1374:      * 
1375:      * @see #setBaseOutlinePaint(Paint)
1376:      */
1377:     public Paint getBaseOutlinePaint() {
1378:         return this.baseOutlinePaint;
1379:     }
1380: 
1381:     /**
1382:      * Sets the base outline paint and sends a {@link RendererChangeEvent} to 
1383:      * all registered listeners.
1384:      *
1385:      * @param paint  the paint (<code>null</code> not permitted).
1386:      * 
1387:      * @see #getBaseOutlinePaint()
1388:      */
1389:     public void setBaseOutlinePaint(Paint paint) {
1390:         // defer argument checking...
1391:         setBaseOutlinePaint(paint, true);
1392:     }
1393:     
1394:     /**
1395:      * Sets the base outline paint and, if requested, sends a 
1396:      * {@link RendererChangeEvent} to all registered listeners.
1397:      * 
1398:      * @param paint  the paint (<code>null</code> not permitted).
1399:      * @param notify  notify listeners?
1400:      * 
1401:      * @see #getBaseOutlinePaint()
1402:      */
1403:     public void setBaseOutlinePaint(Paint paint, boolean notify) {
1404:         if (paint == null) {
1405:             throw new IllegalArgumentException("Null 'paint' argument.");   
1406:         }
1407:         this.baseOutlinePaint = paint;
1408:         if (notify) {
1409:             fireChangeEvent();
1410:         }
1411:     }
1412: 
1413:     /**
1414:      * Returns the flag that controls whether or not the series outline paint 
1415:      * list is automatically populated when 
1416:      * {@link #lookupSeriesOutlinePaint(int)} is called.
1417:      * 
1418:      * @return A boolean.
1419:      * 
1420:      * @since 1.0.6
1421:      * 
1422:      * @see #setAutoPopulateSeriesOutlinePaint(boolean)
1423:      */
1424:     public boolean getAutoPopulateSeriesOutlinePaint() {
1425:         return this.autoPopulateSeriesOutlinePaint;
1426:     }
1427:     
1428:     /**
1429:      * Sets the flag that controls whether or not the series outline paint list
1430:      * is automatically populated when {@link #lookupSeriesOutlinePaint(int)} 
1431:      * is called.
1432:      * 
1433:      * @param auto  the new flag value.
1434:      * 
1435:      * @since 1.0.6
1436:      * 
1437:      * @see #getAutoPopulateSeriesOutlinePaint()
1438:      */
1439:     public void setAutoPopulateSeriesOutlinePaint(boolean auto) {
1440:         this.autoPopulateSeriesOutlinePaint = auto;
1441:     }
1442: 
1443:     // STROKE
1444:     
1445:     /**
1446:      * Returns the stroke used to draw data items.
1447:      * <p>
1448:      * The default implementation passes control to the getSeriesStroke method.
1449:      * You can override this method if you require different behaviour.
1450:      *
1451:      * @param row  the row (or series) index (zero-based).
1452:      * @param column  the column (or category) index (zero-based).
1453:      *
1454:      * @return The stroke (never <code>null</code>).
1455:      */
1456:     public Stroke getItemStroke(int row, int column) {
1457:         return lookupSeriesStroke(row);
1458:     }
1459: 
1460:     /**
1461:      * Returns the stroke used to draw the items in a series.
1462:      *
1463:      * @param series  the series (zero-based index).
1464:      *
1465:      * @return The stroke (never <code>null</code>).
1466:      * 
1467:      * @since 1.0.6
1468:      */
1469:     public Stroke lookupSeriesStroke(int series) {
1470: 
1471:         // return the override, if there is one...
1472:         if (this.stroke != null) {
1473:             return this.stroke;
1474:         }
1475: 
1476:         // otherwise look up the paint table
1477:         Stroke result = getSeriesStroke(series);
1478:         if (result == null && this.autoPopulateSeriesStroke) {
1479:             DrawingSupplier supplier = getDrawingSupplier();
1480:             if (supplier != null) {
1481:                 result = supplier.getNextStroke();
1482:                 setSeriesStroke(series, result, false);
1483:             }
1484:         }
1485:         if (result == null) {
1486:             result = this.baseStroke;
1487:         }
1488:         return result;
1489: 
1490:     }
1491:     
1492:     /**
1493:      * Sets the stroke for ALL series and sends a {@link RendererChangeEvent} 
1494:      * to all registered listeners.
1495:      * 
1496:      * @param stroke  the stroke (<code>null</code> permitted).
1497:      * 
1498:      * @deprecated This method should no longer be used (as of version 1.0.6). 
1499:      *     It is sufficient to rely on {@link #setSeriesStroke(int, Stroke)} 
1500:      *     and {@link #setBaseStroke(Stroke)}.
1501:      */
1502:     public void setStroke(Stroke stroke) {
1503:         setStroke(stroke, true);
1504:     }
1505:     
1506:     /**
1507:      * Sets the stroke for ALL series and, if requested, sends a 
1508:      * {@link RendererChangeEvent} to all registered listeners.
1509:      * 
1510:      * @param stroke  the stroke (<code>null</code> permitted).
1511:      * @param notify  notify listeners?
1512:      * 
1513:      * @deprecated This method should no longer be used (as of version 1.0.6). 
1514:      *     It is sufficient to rely on {@link #setSeriesStroke(int, Stroke, 
1515:      *     boolean)} and {@link #setBaseStroke(Stroke, boolean)}.
1516:      */
1517:     public void setStroke(Stroke stroke, boolean notify) {
1518:         this.stroke = stroke;
1519:         if (notify) {
1520:             fireChangeEvent();
1521:         }
1522:     }    
1523: 
1524:     /**
1525:      * Returns the stroke used to draw the items in a series.
1526:      *
1527:      * @param series  the series (zero-based index).
1528:      *
1529:      * @return The stroke (possibly <code>null</code>).
1530:      * 
1531:      * @see #setSeriesStroke(int, Stroke)
1532:      */
1533:     public Stroke getSeriesStroke(int series) {
1534:         return this.strokeList.getStroke(series);
1535:     }
1536:     
1537:     /**
1538:      * Sets the stroke used for a series and sends a {@link RendererChangeEvent}
1539:      * to all registered listeners.
1540:      *
1541:      * @param series  the series index (zero-based).
1542:      * @param stroke  the stroke (<code>null</code> permitted).
1543:      * 
1544:      * @see #getSeriesStroke(int)
1545:      */
1546:     public void setSeriesStroke(int series, Stroke stroke) {
1547:         setSeriesStroke(series, stroke, true);
1548:     }
1549:     
1550:     /**
1551:      * Sets the stroke for a series and, if requested, sends a 
1552:      * {@link RendererChangeEvent} to all registered listeners.
1553:      * 
1554:      * @param series  the series index (zero-based).
1555:      * @param stroke  the stroke (<code>null</code> permitted).
1556:      * @param notify  notify listeners?
1557:      * 
1558:      * @see #getSeriesStroke(int)
1559:      */
1560:     public void setSeriesStroke(int series, Stroke stroke, boolean notify) {
1561:         this.strokeList.setStroke(series, stroke);
1562:         if (notify) {
1563:             fireChangeEvent();
1564:         }
1565:     }    
1566: 
1567:     /**
1568:      * Returns the base stroke.
1569:      *
1570:      * @return The base stroke (never <code>null</code>).
1571:      * 
1572:      * @see #setBaseStroke(Stroke)
1573:      */
1574:     public Stroke getBaseStroke() {
1575:         return this.baseStroke;
1576:     }
1577: 
1578:     /**
1579:      * Sets the base stroke and sends a {@link RendererChangeEvent} to all
1580:      * registered listeners.
1581:      *
1582:      * @param stroke  the stroke (<code>null</code> not permitted).
1583:      * 
1584:      * @see #getBaseStroke()
1585:      */
1586:     public void setBaseStroke(Stroke stroke) {
1587:         // defer argument checking...
1588:         setBaseStroke(stroke, true);
1589:     }
1590: 
1591:     /**
1592:      * Sets the base stroke and, if requested, sends a 
1593:      * {@link RendererChangeEvent} to all registered listeners.
1594:      * 
1595:      * @param stroke  the stroke (<code>null</code> not permitted).
1596:      * @param notify  notify listeners?
1597:      * 
1598:      * @see #getBaseStroke()
1599:      */
1600:     public void setBaseStroke(Stroke stroke, boolean notify) {
1601:         if (stroke == null) {
1602:             throw new IllegalArgumentException("Null 'stroke' argument.");   
1603:         }
1604:         this.baseStroke = stroke;
1605:         if (notify) {
1606:             fireChangeEvent();
1607:         }
1608:     }    
1609: 
1610:     /**
1611:      * Returns the flag that controls whether or not the series stroke list is
1612:      * automatically populated when {@link #lookupSeriesStroke(int)} is called.
1613:      * 
1614:      * @return A boolean.
1615:      * 
1616:      * @since 1.0.6
1617:      * 
1618:      * @see #setAutoPopulateSeriesStroke(boolean)
1619:      */
1620:     public boolean getAutoPopulateSeriesStroke() {
1621:         return this.autoPopulateSeriesStroke;
1622:     }
1623:     
1624:     /**
1625:      * Sets the flag that controls whether or not the series stroke list is
1626:      * automatically populated when {@link #lookupSeriesStroke(int)} is called.
1627:      * 
1628:      * @param auto  the new flag value.
1629:      * 
1630:      * @since 1.0.6
1631:      * 
1632:      * @see #getAutoPopulateSeriesStroke()
1633:      */
1634:     public void setAutoPopulateSeriesStroke(boolean auto) {
1635:         this.autoPopulateSeriesStroke = auto;
1636:     }
1637: 
1638:     // OUTLINE STROKE 
1639:     
1640:     /**
1641:      * Returns the stroke used to outline data items.  The default 
1642:      * implementation passes control to the 
1643:      * {@link #lookupSeriesOutlineStroke(int)} method. You can override this 
1644:      * method if you require different behaviour.
1645:      *
1646:      * @param row  the row (or series) index (zero-based).
1647:      * @param column  the column (or category) index (zero-based).
1648:      *
1649:      * @return The stroke (never <code>null</code>).
1650:      */
1651:     public Stroke getItemOutlineStroke(int row, int column) {
1652:         return lookupSeriesOutlineStroke(row);
1653:     }
1654: 
1655:     /**
1656:      * Returns the stroke used to outline the items in a series.
1657:      *
1658:      * @param series  the series (zero-based index).
1659:      *
1660:      * @return The stroke (never <code>null</code>).
1661:      * 
1662:      * @since 1.0.6
1663:      */
1664:     public Stroke lookupSeriesOutlineStroke(int series) {
1665: 
1666:         // return the override, if there is one...
1667:         if (this.outlineStroke != null) {
1668:             return this.outlineStroke;
1669:         }
1670: 
1671:         // otherwise look up the stroke table
1672:         Stroke result = getSeriesOutlineStroke(series);
1673:         if (result == null && this.autoPopulateSeriesOutlineStroke) {
1674:             DrawingSupplier supplier = getDrawingSupplier();
1675:             if (supplier != null) {
1676:                 result = supplier.getNextOutlineStroke();
1677:                 setSeriesOutlineStroke(series, result, false);
1678:             }
1679:         }
1680:         if (result == null) {
1681:             result = this.baseOutlineStroke;
1682:         }
1683:         return result;
1684: 
1685:     }
1686: 
1687:     /**
1688:      * Sets the outline stroke for ALL series and sends a 
1689:      * {@link RendererChangeEvent} to all registered listeners.
1690:      *
1691:      * @param stroke  the stroke (<code>null</code> permitted).
1692:      * 
1693:      * @deprecated This method should no longer be used (as of version 1.0.6). 
1694:      *     It is sufficient to rely on {@link #setSeriesOutlineStroke(int, 
1695:      *     Stroke)} and {@link #setBaseOutlineStroke(Stroke)}.
1696:      */
1697:     public void setOutlineStroke(Stroke stroke) {
1698:         setOutlineStroke(stroke, true);
1699:     }
1700: 
1701:     /**
1702:      * Sets the outline stroke for ALL series and, if requested, sends a 
1703:      * {@link RendererChangeEvent} to all registered listeners.
1704:      * 
1705:      * @param stroke  the stroke (<code>null</code> permitted).
1706:      * @param notify  notify listeners?
1707:      * 
1708:      * @deprecated This method should no longer be used (as of version 1.0.6). 
1709:      *     It is sufficient to rely on {@link #setSeriesOutlineStroke(int, 
1710:      *     Stroke, boolean)} and {@link #setBaseOutlineStroke(Stroke, boolean)}.
1711:      */
1712:     public void setOutlineStroke(Stroke stroke, boolean notify) {
1713:         this.outlineStroke = stroke;
1714:         if (notify) {
1715:             fireChangeEvent();
1716:         }
1717:     }
1718:     
1719:     /**
1720:      * Returns the stroke used to outline the items in a series.
1721:      *
1722:      * @param series  the series (zero-based index).
1723:      *
1724:      * @return The stroke (possibly <code>null</code>).
1725:      * 
1726:      * @see #setSeriesOutlineStroke(int, Stroke)
1727:      */
1728:     public Stroke getSeriesOutlineStroke(int series) {
1729:         return this.outlineStrokeList.getStroke(series);
1730:     }
1731:     
1732:     /**
1733:      * Sets the outline stroke used for a series and sends a 
1734:      * {@link RendererChangeEvent} to all registered listeners.
1735:      *
1736:      * @param series  the series index (zero-based).
1737:      * @param stroke  the stroke (<code>null</code> permitted).
1738:      * 
1739:      * @see #getSeriesOutlineStroke(int)
1740:      */
1741:     public void setSeriesOutlineStroke(int series, Stroke stroke) {
1742:         setSeriesOutlineStroke(series, stroke, true);
1743:     }
1744: 
1745:     /**
1746:      * Sets the outline stroke for a series and, if requested, sends a 
1747:      * {@link RendererChangeEvent} to all registered listeners.
1748:      * 
1749:      * @param series  the series index.
1750:      * @param stroke  the stroke (<code>null</code> permitted).
1751:      * @param notify  notify listeners?
1752:      * 
1753:      * @see #getSeriesOutlineStroke(int)
1754:      */
1755:     public void setSeriesOutlineStroke(int series, Stroke stroke, 
1756:                                        boolean notify) {
1757:         this.outlineStrokeList.setStroke(series, stroke);
1758:         if (notify) {
1759:             fireChangeEvent();
1760:         }
1761:     }
1762:     
1763:     /**
1764:      * Returns the base outline stroke.
1765:      *
1766:      * @return The stroke (never <code>null</code>).
1767:      * 
1768:      * @see #setBaseOutlineStroke(Stroke)
1769:      */
1770:     public Stroke getBaseOutlineStroke() {
1771:         return this.baseOutlineStroke;
1772:     }
1773: 
1774:     /**
1775:      * Sets the base outline stroke and sends a {@link RendererChangeEvent} to 
1776:      * all registered listeners.
1777:      *
1778:      * @param stroke  the stroke (<code>null</code> not permitted).
1779:      * 
1780:      * @see #getBaseOutlineStroke()
1781:      */
1782:     public void setBaseOutlineStroke(Stroke stroke) {
1783:         setBaseOutlineStroke(stroke, true);
1784:     }
1785: 
1786:     /**
1787:      * Sets the base outline stroke and, if requested, sends a 
1788:      * {@link RendererChangeEvent} to all registered listeners.
1789:      * 
1790:      * @param stroke  the stroke (<code>null</code> not permitted).
1791:      * @param notify  a flag that controls whether or not listeners are 
1792:      *                notified.
1793:      *                
1794:      * @see #getBaseOutlineStroke()
1795:      */
1796:     public void setBaseOutlineStroke(Stroke stroke, boolean notify) {
1797:         if (stroke == null) {
1798:             throw new IllegalArgumentException("Null 'stroke' argument.");
1799:         }
1800:         this.baseOutlineStroke = stroke;
1801:         if (notify) {
1802:             fireChangeEvent();
1803:         }
1804:     }
1805:     
1806:     /**
1807:      * Returns the flag that controls whether or not the series outline stroke 
1808:      * list is automatically populated when 
1809:      * {@link #lookupSeriesOutlineStroke(int)} is called.
1810:      * 
1811:      * @return A boolean.
1812:      * 
1813:      * @since 1.0.6
1814:      * 
1815:      * @see #setAutoPopulateSeriesOutlineStroke(boolean)
1816:      */
1817:     public boolean getAutoPopulateSeriesOutlineStroke() {
1818:         return this.autoPopulateSeriesOutlineStroke;
1819:     }
1820:     
1821:     /**
1822:      * Sets the flag that controls whether or not the series outline stroke list
1823:      * is automatically populated when {@link #lookupSeriesOutlineStroke(int)} 
1824:      * is called.
1825:      * 
1826:      * @param auto  the new flag value.
1827:      * 
1828:      * @since 1.0.6
1829:      * 
1830:      * @see #getAutoPopulateSeriesOutlineStroke()
1831:      */
1832:     public void setAutoPopulateSeriesOutlineStroke(boolean auto) {
1833:         this.autoPopulateSeriesOutlineStroke = auto;
1834:     }
1835: 
1836:     // SHAPE
1837:     
1838:     /**
1839:      * Returns a shape used to represent a data item.
1840:      * <p>
1841:      * The default implementation passes control to the getSeriesShape method.
1842:      * You can override this method if you require different behaviour.
1843:      *
1844:      * @param row  the row (or series) index (zero-based).
1845:      * @param column  the column (or category) index (zero-based).
1846:      *
1847:      * @return The shape (never <code>null</code>).
1848:      */
1849:     public Shape getItemShape(int row, int column) {
1850:         return lookupSeriesShape(row);
1851:     }
1852: 
1853:     /**
1854:      * Returns a shape used to represent the items in a series.
1855:      *
1856:      * @param series  the series (zero-based index).
1857:      *
1858:      * @return The shape (never <code>null</code>).
1859:      * 
1860:      * @since 1.0.6
1861:      */
1862:     public Shape lookupSeriesShape(int series) {
1863: 
1864:         // return the override, if there is one...
1865:         if (this.shape != null) {
1866:             return this.shape;
1867:         }
1868: 
1869:         // otherwise look up the shape list
1870:         Shape result = getSeriesShape(series);
1871:         if (result == null && this.autoPopulateSeriesShape) {
1872:             DrawingSupplier supplier = getDrawingSupplier();
1873:             if (supplier != null) {
1874:                 result = supplier.getNextShape();
1875:                 setSeriesShape(series, result, false);
1876:             }
1877:         }
1878:         if (result == null) {
1879:             result = this.baseShape;
1880:         }
1881:         return result;
1882: 
1883:     }
1884: 
1885:     /**
1886:      * Sets the shape for ALL series (optional) and sends a 
1887:      * {@link RendererChangeEvent} to all registered listeners.
1888:      * 
1889:      * @param shape  the shape (<code>null</code> permitted).
1890:      * 
1891:      * @deprecated This method should no longer be used (as of version 1.0.6). 
1892:      *     It is sufficient to rely on {@link #setSeriesShape(int, Shape)} 
1893:      *     and {@link #setBaseShape(Shape)}.
1894:      */
1895:     public void setShape(Shape shape) {
1896:         setShape(shape, true);
1897:     }
1898:     
1899:     /**
1900:      * Sets the shape for ALL series and, if requested, sends a 
1901:      * {@link RendererChangeEvent} to all registered listeners.
1902:      * 
1903:      * @param shape  the shape (<code>null</code> permitted).
1904:      * @param notify  notify listeners?
1905:      * 
1906:      * @deprecated This method should no longer be used (as of version 1.0.6). 
1907:      *     It is sufficient to rely on {@link #setSeriesShape(int, Shape, 
1908:      *     boolean)} and {@link #setBaseShape(Shape, boolean)}.
1909:      */
1910:     public void setShape(Shape shape, boolean notify) {
1911:         this.shape = shape;
1912:         if (notify) {
1913:             fireChangeEvent();
1914:         }
1915:     }
1916:     
1917:     /**
1918:      * Returns a shape used to represent the items in a series.
1919:      *
1920:      * @param series  the series (zero-based index).
1921:      *
1922:      * @return The shape (possibly <code>null</code>).
1923:      * 
1924:      * @see #setSeriesShape(int, Shape)
1925:      */
1926:     public Shape getSeriesShape(int series) {
1927:         return this.shapeList.getShape(series);
1928:     }
1929: 
1930:     /**
1931:      * Sets the shape used for a series and sends a {@link RendererChangeEvent} 
1932:      * to all registered listeners.
1933:      *
1934:      * @param series  the series index (zero-based).
1935:      * @param shape  the shape (<code>null</code> permitted).
1936:      * 
1937:      * @see #getSeriesShape(int)
1938:      */
1939:     public void setSeriesShape(int series, Shape shape) {
1940:         setSeriesShape(series, shape, true);
1941:     }
1942: 
1943:     /**
1944:      * Sets the shape for a series and, if requested, sends a 
1945:      * {@link RendererChangeEvent} to all registered listeners.
1946:      * 
1947:      * @param series  the series index (zero based).
1948:      * @param shape  the shape (<code>null</code> permitted).
1949:      * @param notify  notify listeners?
1950:      * 
1951:      * @see #getSeriesShape(int)
1952:      */
1953:     public void setSeriesShape(int series, Shape shape, boolean notify) {
1954:         this.shapeList.setShape(series, shape);
1955:         if (notify) {
1956:             fireChangeEvent();
1957:         }
1958:     }
1959:     
1960:     /**
1961:      * Returns the base shape.
1962:      *
1963:      * @return The shape (never <code>null</code>).
1964:      * 
1965:      * @see #setBaseShape(Shape)
1966:      */
1967:     public Shape getBaseShape() {
1968:         return this.baseShape;
1969:     }
1970: 
1971:     /**
1972:      * Sets the base shape and sends a {@link RendererChangeEvent} to all 
1973:      * registered listeners.
1974:      *
1975:      * @param shape  the shape (<code>null</code> not permitted).
1976:      * 
1977:      * @see #getBaseShape()
1978:      */
1979:     public void setBaseShape(Shape shape) {
1980:         // defer argument checking...
1981:         setBaseShape(shape, true);
1982:     }
1983: 
1984:     /**
1985:      * Sets the base shape and, if requested, sends a 
1986:      * {@link RendererChangeEvent} to all registered listeners.
1987:      * 
1988:      * @param shape  the shape (<code>null</code> not permitted). 
1989:      * @param notify  notify listeners?
1990:      * 
1991:      * @see #getBaseShape()
1992:      */
1993:     public void setBaseShape(Shape shape, boolean notify) {
1994:         if (shape == null) {
1995:             throw new IllegalArgumentException("Null 'shape' argument."); 
1996:         }
1997:         this.baseShape = shape;
1998:         if (notify) {
1999:             fireChangeEvent();
2000:         }
2001:     }
2002:     
2003:     /**
2004:      * Returns the flag that controls whether or not the series shape list is
2005:      * automatically populated when {@link #lookupSeriesShape(int)} is called.
2006:      * 
2007:      * @return A boolean.
2008:      * 
2009:      * @since 1.0.6
2010:      * 
2011:      * @see #setAutoPopulateSeriesShape(boolean)
2012:      */
2013:     public boolean getAutoPopulateSeriesShape() {
2014:         return this.autoPopulateSeriesShape;
2015:     }
2016:     
2017:     /**
2018:      * Sets the flag that controls whether or not the series shape list is
2019:      * automatically populated when {@link #lookupSeriesShape(int)} is called.
2020:      * 
2021:      * @param auto  the new flag value.
2022:      * 
2023:      * @since 1.0.6
2024:      * 
2025:      * @see #getAutoPopulateSeriesShape()
2026:      */
2027:     public void setAutoPopulateSeriesShape(boolean auto) {
2028:         this.autoPopulateSeriesShape = auto;
2029:     }
2030: 
2031:     // ITEM LABEL VISIBILITY...
2032: 
2033:     /**
2034:      * Returns <code>true</code> if an item label is visible, and 
2035:      * <code>false</code> otherwise.
2036:      * 
2037:      * @param row  the row index (zero-based).
2038:      * @param column  the column index (zero-based).
2039:      * 
2040:      * @return A boolean.
2041:      */
2042:     public boolean isItemLabelVisible(int row, int column) {
2043:         return isSeriesItemLabelsVisible(row);
2044:     }
2045: 
2046:     /**
2047:      * Returns <code>true</code> if the item labels for a series are visible, 
2048:      * and <code>false</code> otherwise.
2049:      * 
2050:      * @param series  the series index (zero-based).
2051:      * 
2052:      * @return A boolean.
2053:      */    
2054:     public boolean isSeriesItemLabelsVisible(int series) {
2055: 
2056:         // return the override, if there is one...
2057:         if (this.itemLabelsVisible != null) {
2058:             return this.itemLabelsVisible.booleanValue();
2059:         }
2060: 
2061:         // otherwise look up the boolean table
2062:         Boolean b = this.itemLabelsVisibleList.getBoolean(series);
2063:         if (b == null) {
2064:             b = this.baseItemLabelsVisible;
2065:         }
2066:         if (b == null) {
2067:             b = Boolean.FALSE;
2068:         }
2069:         return b.booleanValue();
2070: 
2071:     }
2072:     
2073:     /**
2074:      * Sets the visibility of the item labels for ALL series.
2075:      * 
2076:      * @param visible  the flag.
2077:      * 
2078:      * @deprecated This method should no longer be used (as of version 1.0.6). 
2079:      *     It is sufficient to rely on {@link #setSeriesItemLabelsVisible(int, 
2080:      *     Boolean)} and {@link #setBaseItemLabelsVisible(boolean)}.
2081:      */
2082:     public void setItemLabelsVisible(boolean visible) {        
2083:         setItemLabelsVisible(BooleanUtilities.valueOf(visible));
2084:         // The following alternative is only supported in JDK 1.4 - we support 
2085:         // JDK 1.3.1 onwards
2086:         // setItemLabelsVisible(Boolean.valueOf(visible));
2087:     }
2088:     
2089:     /**
2090:      * Sets the visibility of the item labels for ALL series (optional).
2091:      * 
2092:      * @param visible  the flag (<code>null</code> permitted).
2093:      * 
2094:      * @deprecated This method should no longer be used (as of version 1.0.6). 
2095:      *     It is sufficient to rely on {@link #setSeriesItemLabelsVisible(int, 
2096:      *     Boolean)} and {@link #setBaseItemLabelsVisible(boolean)}.
2097:      */
2098:     public void setItemLabelsVisible(Boolean visible) {
2099:         setItemLabelsVisible(visible, true);
2100:     }
2101:     
2102:     /**
2103:      * Sets the visibility of item labels for ALL series and, if requested, 
2104:      * sends a {@link RendererChangeEvent} to all registered listeners.
2105:      * 
2106:      * @param visible  a flag that controls whether or not the item labels are 
2107:      *                 visible (<code>null</code> permitted).
2108:      * @param notify  a flag that controls whether or not listeners are 
2109:      *                notified.
2110:      *                
2111:      * @deprecated This method should no longer be used (as of version 1.0.6). 
2112:      *     It is sufficient to rely on {@link #setSeriesItemLabelsVisible(int, 
2113:      *     Boolean, boolean)} and {@link #setBaseItemLabelsVisible(Boolean, 
2114:      *     boolean)}.
2115:      */
2116:     public void setItemLabelsVisible(Boolean visible, boolean notify) {
2117:         this.itemLabelsVisible = visible;
2118:         if (notify) {
2119:             fireChangeEvent();
2120:         }
2121:     }
2122: 
2123:     /**
2124:      * Sets a flag that controls the visibility of the item labels for a series,
2125:      * and sends a {@link RendererChangeEvent} to all registered listeners.
2126:      * 
2127:      * @param series  the series index (zero-based).
2128:      * @param visible  the flag.
2129:      */
2130:     public void setSeriesItemLabelsVisible(int series, boolean visible) {
2131:         setSeriesItemLabelsVisible(series, BooleanUtilities.valueOf(visible));
2132:     }
2133:     
2134:     /**
2135:      * Sets the visibility of the item labels for a series and sends a 
2136:      * {@link RendererChangeEvent} to all registered listeners.
2137:      * 
2138:      * @param series  the series index (zero-based).
2139:      * @param visible  the flag (<code>null</code> permitted).
2140:      */
2141:     public void setSeriesItemLabelsVisible(int series, Boolean visible) {
2142:         setSeriesItemLabelsVisible(series, visible, true);
2143:     }
2144: 
2145:     /**
2146:      * Sets the visibility of item labels for a series and, if requested, sends 
2147:      * a {@link RendererChangeEvent} to all registered listeners.
2148:      * 
2149:      * @param series  the series index (zero-based).
2150:      * @param visible  the visible flag.
2151:      * @param notify  a flag that controls whether or not listeners are 
2152:      *                notified.
2153:      */
2154:     public void setSeriesItemLabelsVisible(int series, Boolean visible, 
2155:                                            boolean notify) {
2156:         this.itemLabelsVisibleList.setBoolean(series, visible);
2157:         if (notify) {
2158:             fireChangeEvent();
2159:         }
2160:     }
2161: 
2162:     /**
2163:      * Returns the base setting for item label visibility.  A <code>null</code>
2164:      * result should be interpreted as equivalent to <code>Boolean.FALSE</code>.
2165:      * 
2166:      * @return A flag (possibly <code>null</code>).
2167:      * 
2168:      * @see #setBaseItemLabelsVisible(boolean)
2169:      */
2170:     public Boolean getBaseItemLabelsVisible() {
2171:         // this should have been defined as a boolean primitive, because 
2172:         // allowing null values is a nuisance...but it is part of the final
2173:         // API now, so we'll have to support it.
2174:         return this.baseItemLabelsVisible;
2175:     }
2176: 
2177:     /**
2178:      * Sets the base flag that controls whether or not item labels are visible,
2179:      * and sends a {@link RendererChangeEvent} to all registered listeners.
2180:      * 
2181:      * @param visible  the flag.
2182:      * 
2183:      * @see #getBaseItemLabelsVisible()
2184:      */
2185:     public void setBaseItemLabelsVisible(boolean visible) {
2186:         setBaseItemLabelsVisible(BooleanUtilities.valueOf(visible));
2187:     }
2188:     
2189:     /**
2190:      * Sets the base setting for item label visibility and sends a 
2191:      * {@link RendererChangeEvent} to all registered listeners.
2192:      * 
2193:      * @param visible  the flag (<code>null</code> is permitted, and viewed
2194:      *     as equivalent to <code>Boolean.FALSE</code>).
2195:      */
2196:     public void setBaseItemLabelsVisible(Boolean visible) {
2197:         setBaseItemLabelsVisible(visible, true);
2198:     }
2199: 
2200:     /**
2201:      * Sets the base visibility for item labels and, if requested, sends a 
2202:      * {@link RendererChangeEvent} to all registered listeners.
2203:      * 
2204:      * @param visible  the flag (<code>null</code> is permitted, and viewed
2205:      *     as equivalent to <code>Boolean.FALSE</code>).
2206:      * @param notify  a flag that controls whether or not listeners are 
2207:      *                notified.
2208:      *                
2209:      * @see #getBaseItemLabelsVisible()
2210:      */
2211:     public void setBaseItemLabelsVisible(Boolean visible, boolean notify) {
2212:         this.baseItemLabelsVisible = visible;
2213:         if (notify) {
2214:             fireChangeEvent();
2215:         }
2216:     }
2217: 
2218:     //// ITEM LABEL FONT //////////////////////////////////////////////////////
2219: 
2220:     /**
2221:      * Returns the font for an item label.
2222:      * 
2223:      * @param row  the row index (zero-based).
2224:      * @param column  the column index (zero-based).
2225:      * 
2226:      * @return The font (never <code>null</code>).
2227:      */
2228:     public Font getItemLabelFont(int row, int column) {
2229:         Font result = this.itemLabelFont;
2230:         if (result == null) {
2231:             result = getSeriesItemLabelFont(row);
2232:             if (result == null) {
2233:                 result = this.baseItemLabelFont;   
2234:             }
2235:         }
2236:         return result;
2237:     }
2238: 
2239:     /**
2240:      * Returns the font used for all item labels.  This may be 
2241:      * <code>null</code>, in which case the per series font settings will apply.
2242:      * 
2243:      * @return The font (possibly <code>null</code>).
2244:      * 
2245:      * @deprecated This method should no longer be used (as of version 1.0.6). 
2246:      *     It is sufficient to rely on {@link #getSeriesItemLabelFont(int)} and
2247:      *     {@link #getBaseItemLabelFont()}.
2248:      */
2249:     public Font getItemLabelFont() {
2250:         return this.itemLabelFont;   
2251:     }
2252:     
2253:     /**
2254:      * Sets the item label font for ALL series and sends a 
2255:      * {@link RendererChangeEvent} to all registered listeners.  You can set 
2256:      * this to <code>null</code> if you prefer to set the font on a per series 
2257:      * basis.
2258:      * 
2259:      * @param font  the font (<code>null</code> permitted).
2260:      * 
2261:      * @deprecated This method should no longer be used (as of version 1.0.6). 
2262:      *     It is sufficient to rely on {@link #setSeriesItemLabelFont(int, 
2263:      *     Font)} and {@link #setBaseItemLabelFont(Font)}.
2264:      */
2265:     public void setItemLabelFont(Font font) {
2266:         setItemLabelFont(font, true);
2267:     }
2268:     
2269:     /**
2270:      * Sets the item label font for ALL series and, if requested, sends a 
2271:      * {@link RendererChangeEvent} to all registered listeners.
2272:      * 
2273:      * @param font  the font (<code>null</code> permitted).
2274:      * @param notify  a flag that controls whether or not listeners are 
2275:      *                notified.
2276:      * 
2277:      * @deprecated This method should no longer be used (as of version 1.0.6). 
2278:      *     It is sufficient to rely on {@link #setSeriesItemLabelFont(int, 
2279:      *     Font, boolean)} and {@link #setBaseItemLabelFont(Font, boolean)}.
2280:      */
2281:     public void setItemLabelFont(Font font, boolean notify) {
2282:         this.itemLabelFont = font;
2283:         if (notify) {
2284:             fireChangeEvent();
2285:         }
2286:     }
2287: 
2288:     /**
2289:      * Returns the font for all the item labels in a series.
2290:      * 
2291:      * @param series  the series index (zero-based).
2292:      * 
2293:      * @return The font (possibly <code>null</code>).
2294:      * 
2295:      * @see #setSeriesItemLabelFont(int, Font)
2296:      */
2297:     public Font getSeriesItemLabelFont(int series) {
2298:         return (Font) this.itemLabelFontList.get(series);
2299:     }
2300: 
2301:     /**
2302:      * Sets the item label font for a series and sends a 
2303:      * {@link RendererChangeEvent} to all registered listeners.  
2304:      * 
2305:      * @param series  the series index (zero-based).
2306:      * @param font  the font (<code>null</code> permitted).
2307:      * 
2308:      * @see #getSeriesItemLabelFont(int)
2309:      */
2310:     public void setSeriesItemLabelFont(int series, Font font) {
2311:         setSeriesItemLabelFont(series, font, true);
2312:     }
2313: 
2314:     /**
2315:      * Sets the item label font for a series and, if requested, sends a 
2316:      * {@link RendererChangeEvent} to all registered listeners.
2317:      * 
2318:      * @param series  the series index (zero based).
2319:      * @param font  the font (<code>null</code> permitted).
2320:      * @param notify  a flag that controls whether or not listeners are 
2321:      *                notified.
2322:      *                
2323:      * @see #getSeriesItemLabelFont(int)
2324:      */
2325:     public void setSeriesItemLabelFont(int series, Font font, boolean notify) {
2326:         this.itemLabelFontList.set(series, font);
2327:         if (notify) {
2328:             fireChangeEvent();
2329:         }
2330:     }
2331:     
2332:     /**
2333:      * Returns the base item label font (this is used when no other font 
2334:      * setting is available).
2335:      * 
2336:      * @return The font (<code>never</code> null).
2337:      * 
2338:      * @see #setBaseItemLabelFont(Font)
2339:      */
2340:     public Font getBaseItemLabelFont() {
2341:         return this.baseItemLabelFont;
2342:     }
2343: 
2344:     /**
2345:      * Sets the base item label font and sends a {@link RendererChangeEvent} to 
2346:      * all registered listeners.  
2347:      * 
2348:      * @param font  the font (<code>null</code> not permitted).
2349:      * 
2350:      * @see #getBaseItemLabelFont()
2351:      */
2352:     public void setBaseItemLabelFont(Font font) {
2353:         if (font == null) {
2354:             throw new IllegalArgumentException("Null 'font' argument.");
2355:         }
2356:         setBaseItemLabelFont(font, true);
2357:     }
2358: 
2359:     /**
2360:      * Sets the base item label font and, if requested, sends a 
2361:      * {@link RendererChangeEvent} to all registered listeners.
2362:      * 
2363:      * @param font  the font (<code>null</code> not permitted).
2364:      * @param notify  a flag that controls whether or not listeners are 
2365:      *                notified.
2366:      *                
2367:      * @see #getBaseItemLabelFont()
2368:      */
2369:     public void setBaseItemLabelFont(Font font, boolean notify) {
2370:         this.baseItemLabelFont = font;
2371:         if (notify) {
2372:             fireChangeEvent();
2373:         }
2374:     }
2375: 
2376:     //// ITEM LABEL PAINT  ////////////////////////////////////////////////////
2377: 
2378:     /**
2379:      * Returns the paint used to draw an item label.
2380:      * 
2381:      * @param row  the row index (zero based).
2382:      * @param column  the column index (zero based).
2383:      * 
2384:      * @return The paint (never <code>null</code>).
2385:      */
2386:     public Paint getItemLabelPaint(int row, int column) {
2387:         Paint result = this.itemLabelPaint;
2388:         if (result == null) {
2389:             result = getSeriesItemLabelPaint(row);
2390:             if (result == null) {
2391:                 result = this.baseItemLabelPaint;   
2392:             }
2393:         }
2394:         return result;
2395:     }
2396:     
2397:     /**
2398:      * Returns the paint used for all item labels.  This may be 
2399:      * <code>null</code>, in which case the per series paint settings will 
2400:      * apply.
2401:      * 
2402:      * @return The paint (possibly <code>null</code>).
2403:      * 
2404:      * @deprecated This method should no longer be used (as of version 1.0.6). 
2405:      *     It is sufficient to rely on {@link #getSeriesItemLabelPaint(int)} 
2406:      *     and {@link #getBaseItemLabelPaint()}.
2407:      */
2408:     public Paint getItemLabelPaint() {
2409:         return this.itemLabelPaint;   
2410:     }
2411: 
2412:     /**
2413:      * Sets the item label paint for ALL series and sends a 
2414:      * {@link RendererChangeEvent} to all registered listeners.
2415:      * 
2416:      * @param paint  the paint (<code>null</code> permitted).
2417:      * 
2418:      * @deprecated This method should no longer be used (as of version 1.0.6). 
2419:      *     It is sufficient to rely on {@link #setSeriesItemLabelPaint(int, 
2420:      *     Paint)} and {@link #setBaseItemLabelPaint(Paint)}.
2421:      */
2422:     public void setItemLabelPaint(Paint paint) {
2423:         setItemLabelPaint(paint, true);
2424:     }
2425: 
2426:     /**
2427:      * Sets the item label paint for ALL series and, if requested, sends a 
2428:      * {@link RendererChangeEvent} to all registered listeners.
2429:      * 
2430:      * @param paint  the paint.
2431:      * @param notify  a flag that controls whether or not listeners are 
2432:      *                notified.
2433:      * 
2434:      * @deprecated This method should no longer be used (as of version 1.0.6). 
2435:      *     It is sufficient to rely on {@link #setSeriesItemLabelPaint(int, 
2436:      *     Paint, boolean)} and {@link #setBaseItemLabelPaint(Paint, boolean)}.
2437:      */
2438:     public void setItemLabelPaint(Paint paint, boolean notify) {
2439:         this.itemLabelPaint = paint;
2440:         if (notify) {
2441:             fireChangeEvent();
2442:         }
2443:     }
2444:     
2445:     /**
2446:      * Returns the paint used to draw the item labels for a series.
2447:      * 
2448:      * @param series  the series index (zero based).
2449:      * 
2450:      * @return The paint (possibly <code>null<code>).
2451:      * 
2452:      * @see #setSeriesItemLabelPaint(int, Paint)
2453:      */
2454:     public Paint getSeriesItemLabelPaint(int series) {
2455:         return this.itemLabelPaintList.getPaint(series);
2456:     }
2457: 
2458:     /**
2459:      * Sets the item label paint for a series and sends a 
2460:      * {@link RendererChangeEvent} to all registered listeners.
2461:      * 
2462:      * @param series  the series (zero based index).
2463:      * @param paint  the paint (<code>null</code> permitted).
2464:      * 
2465:      * @see #getSeriesItemLabelPaint(int)
2466:      */
2467:     public void setSeriesItemLabelPaint(int series, Paint paint) {
2468:         setSeriesItemLabelPaint(series, paint, true);
2469:     }
2470:     
2471:     /**
2472:      * Sets the item label paint for a series and, if requested, sends a 
2473:      * {@link RendererChangeEvent} to all registered listeners.
2474:      * 
2475:      * @param series  the series index (zero based).
2476:      * @param paint  the paint (<code>null</code> permitted).
2477:      * @param notify  a flag that controls whether or not listeners are 
2478:      *                notified.
2479:      *                
2480:      * @see #getSeriesItemLabelPaint(int)
2481:      */
2482:     public void setSeriesItemLabelPaint(int series, Paint paint, 
2483:                                         boolean notify) {
2484:         this.itemLabelPaintList.setPaint(series, paint);
2485:         if (notify) {
2486:             fireChangeEvent();
2487:         }
2488:     }
2489:     
2490:     /**
2491:      * Returns the base item label paint.
2492:      * 
2493:      * @return The paint (never <code>null<code>).
2494:      * 
2495:      * @see #setBaseItemLabelPaint(Paint)
2496:      */
2497:     public Paint getBaseItemLabelPaint() {
2498:         return this.baseItemLabelPaint;
2499:     }
2500: 
2501:     /**
2502:      * Sets the base item label paint and sends a {@link RendererChangeEvent} 
2503:      * to all registered listeners.
2504:      * 
2505:      * @param paint  the paint (<code>null</code> not permitted).
2506:      * 
2507:      * @see #getBaseItemLabelPaint()
2508:      */
2509:     public void setBaseItemLabelPaint(Paint paint) {
2510:         // defer argument checking...
2511:         setBaseItemLabelPaint(paint, true);
2512:     }
2513: 
2514:     /**
2515:      * Sets the base item label paint and, if requested, sends a 
2516:      * {@link RendererChangeEvent} to all registered listeners..
2517:      * 
2518:      * @param paint  the paint (<code>null</code> not permitted).
2519:      * @param notify  a flag that controls whether or not listeners are 
2520:      *                notified.
2521:      *                
2522:      * @see #getBaseItemLabelPaint()
2523:      */
2524:     public void setBaseItemLabelPaint(Paint paint, boolean notify) {
2525:         if (paint == null) {
2526:             throw new IllegalArgumentException("Null 'paint' argument.");   
2527:         }
2528:         this.baseItemLabelPaint = paint;
2529:         if (notify) {
2530:             fireChangeEvent();
2531:         }
2532:     }
2533:     
2534:     // POSITIVE ITEM LABEL POSITION...
2535: 
2536:     /**
2537:      * Returns the item label position for positive values.
2538:      * 
2539:      * @param row  the row index (zero-based).
2540:      * @param column  the column index (zero-based).
2541:      * 
2542:      * @return The item label position (never <code>null</code>).
2543:      * 
2544:      * @see #getNegativeItemLabelPosition(int, int)
2545:      */
2546:     public ItemLabelPosition getPositiveItemLabelPosition(int row, int column) {
2547:         return getSeriesPositiveItemLabelPosition(row);
2548:     }
2549: 
2550:     /**
2551:      * Returns the item label position for positive values in ALL series.
2552:      * 
2553:      * @return The item label position (possibly <code>null</code>).
2554:      * 
2555:      * @see #setPositiveItemLabelPosition(ItemLabelPosition)
2556:      * 
2557:      * @deprecated This method should no longer be used (as of version 1.0.6). 
2558:      *     It is sufficient to rely on 
2559:      *     {@link #getSeriesPositiveItemLabelPosition(int)} 
2560:      *     and {@link #getBasePositiveItemLabelPosition()}.
2561:      */
2562:     public ItemLabelPosition getPositiveItemLabelPosition() {
2563:         return this.positiveItemLabelPosition;
2564:     }
2565: 
2566:     /**
2567:      * Sets the item label position for positive values in ALL series, and 
2568:      * sends a {@link RendererChangeEvent} to all registered listeners.  You 
2569:      * need to set this to <code>null</code> to expose the settings for 
2570:      * individual series.
2571:      * 
2572:      * @param position  the position (<code>null</code> permitted).
2573:      * 
2574:      * @see #getPositiveItemLabelPosition()
2575:      * 
2576:      * @deprecated This method should no longer be used (as of version 1.0.6). 
2577:      *     It is sufficient to rely on 
2578:      *     {@link #setSeriesPositiveItemLabelPosition(int, ItemLabelPosition)} 
2579:      *     and {@link #setBasePositiveItemLabelPosition(ItemLabelPosition)}.
2580:      */
2581:     public void setPositiveItemLabelPosition(ItemLabelPosition position) {
2582:         setPositiveItemLabelPosition(position, true);
2583:     }
2584:     
2585:     /**
2586:      * Sets the positive item label position for ALL series and (if requested) 
2587:      * sends a {@link RendererChangeEvent} to all registered listeners.
2588:      * 
2589:      * @param position  the position (<code>null</code> permitted).
2590:      * @param notify  notify registered listeners?
2591:      * 
2592:      * @see #getPositiveItemLabelPosition()
2593:      * 
2594:      * @deprecated This method should no longer be used (as of version 1.0.6). 
2595:      *     It is sufficient to rely on 
2596:      *     {@link #setSeriesPositiveItemLabelPosition(int, ItemLabelPosition, 
2597:      *     boolean)} and {@link #setBasePositiveItemLabelPosition(
2598:      *     ItemLabelPosition, boolean)}.
2599:      */
2600:     public void setPositiveItemLabelPosition(ItemLabelPosition position, 
2601:                                              boolean notify) {
2602:         this.positiveItemLabelPosition = position;
2603:         if (notify) {
2604:             fireChangeEvent();
2605:         }
2606:     }
2607: 
2608:     /**
2609:      * Returns the item label position for all positive values in a series.
2610:      * 
2611:      * @param series  the series index (zero-based).
2612:      * 
2613:      * @return The item label position (never <code>null</code>).
2614:      * 
2615:      * @see #setSeriesPositiveItemLabelPosition(int, ItemLabelPosition)
2616:      */
2617:     public ItemLabelPosition getSeriesPositiveItemLabelPosition(int series) {
2618: 
2619:         // return the override, if there is one...
2620:         if (this.positiveItemLabelPosition != null) {
2621:             return this.positiveItemLabelPosition;
2622:         }
2623: 
2624:         // otherwise look up the position table
2625:         ItemLabelPosition position = (ItemLabelPosition) 
2626:             this.positiveItemLabelPositionList.get(series);
2627:         if (position == null) {
2628:             position = this.basePositiveItemLabelPosition;
2629:         }
2630:         return position;
2631: 
2632:     }
2633:     
2634:     /**
2635:      * Sets the item label position for all positive values in a series and 
2636:      * sends a {@link RendererChangeEvent} to all registered listeners.
2637:      * 
2638:      * @param series  the series index (zero-based).
2639:      * @param position  the position (<code>null</code> permitted).
2640:      * 
2641:      * @see #getSeriesPositiveItemLabelPosition(int)
2642:      */
2643:     public void setSeriesPositiveItemLabelPosition(int series, 
2644:                                                    ItemLabelPosition position) {
2645:         setSeriesPositiveItemLabelPosition(series, position, true);
2646:     }
2647: 
2648:     /**
2649:      * Sets the item label position for all positive values in a series and (if
2650:      * requested) sends a {@link RendererChangeEvent} to all registered 
2651:      * listeners.
2652:      * 
2653:      * @param series  the series index (zero-based).
2654:      * @param position  the position (<code>null</code> permitted).
2655:      * @param notify  notify registered listeners?
2656:      * 
2657:      * @see #getSeriesPositiveItemLabelPosition(int)
2658:      */
2659:     public void setSeriesPositiveItemLabelPosition(int series, 
2660:                                                    ItemLabelPosition position, 
2661:                                                    boolean notify) {
2662:         this.positiveItemLabelPositionList.set(series, position);
2663:         if (notify) {
2664:             fireChangeEvent();
2665:         }
2666:     }
2667: 
2668:     /**
2669:      * Returns the base positive item label position.
2670:      * 
2671:      * @return The position (never <code>null</code>).
2672:      * 
2673:      * @see #setBasePositiveItemLabelPosition(ItemLabelPosition)
2674:      */
2675:     public ItemLabelPosition getBasePositiveItemLabelPosition() {
2676:         return this.basePositiveItemLabelPosition;
2677:     }
2678: 
2679:     /**
2680:      * Sets the base positive item label position.
2681:      * 
2682:      * @param position  the position (<code>null</code> not permitted).
2683:      * 
2684:      * @see #getBasePositiveItemLabelPosition()
2685:      */
2686:     public void setBasePositiveItemLabelPosition(ItemLabelPosition position) {
2687:         // defer argument checking...
2688:         setBasePositiveItemLabelPosition(position, true);
2689:     }
2690:     
2691:     /**
2692:      * Sets the base positive item label position and, if requested, sends a 
2693:      * {@link RendererChangeEvent} to all registered listeners.
2694:      * 
2695:      * @param position  the position (<code>null</code> not permitted).
2696:      * @param notify  notify registered listeners?
2697:      * 
2698:      * @see #getBasePositiveItemLabelPosition()
2699:      */
2700:     public void setBasePositiveItemLabelPosition(ItemLabelPosition position, 
2701:                                                  boolean notify) {
2702:         if (position == null) {
2703:             throw new IllegalArgumentException("Null 'position' argument.");   
2704:         }
2705:         this.basePositiveItemLabelPosition = position;
2706:         if (notify) {
2707:             fireChangeEvent();
2708:         }
2709:     }
2710: 
2711:     // NEGATIVE ITEM LABEL POSITION...
2712: 
2713:     /**
2714:      * Returns the item label position for negative values.  This method can be 
2715:      * overridden to provide customisation of the item label position for 
2716:      * individual data items.
2717:      * 
2718:      * @param row  the row index (zero-based).
2719:      * @param column  the column (zero-based).
2720:      * 
2721:      * @return The item label position (never <code>null</code>).
2722:      * 
2723:      * @see #getPositiveItemLabelPosition(int, int)
2724:      */
2725:     public ItemLabelPosition getNegativeItemLabelPosition(int row, int column) {
2726:         return getSeriesNegativeItemLabelPosition(row);
2727:     }
2728: 
2729:     /**
2730:      * Returns the item label position for negative values in ALL series.
2731:      * 
2732:      * @return The item label position (possibly <code>null</code>).
2733:      * 
2734:      * @see #setNegativeItemLabelPosition(ItemLabelPosition)
2735:      * 
2736:      * @deprecated This method should no longer be used (as of version 1.0.6). 
2737:      *     It is sufficient to rely on 
2738:      *     {@link #getSeriesNegativeItemLabelPosition(int)} 
2739:      *     and {@link #getBaseNegativeItemLabelPosition()}.
2740:      */
2741:     public ItemLabelPosition getNegativeItemLabelPosition() {
2742:         return this.negativeItemLabelPosition;
2743:     }
2744: 
2745:     /**
2746:      * Sets the item label position for negative values in ALL series, and 
2747:      * sends a {@link RendererChangeEvent} to all registered listeners.  You 
2748:      * need to set this to <code>null</code> to expose the settings for 
2749:      * individual series.
2750:      * 
2751:      * @param position  the position (<code>null</code> permitted).
2752:      * 
2753:      * @see #getNegativeItemLabelPosition()
2754:      * 
2755:      * @deprecated This method should no longer be used (as of version 1.0.6). 
2756:      *     It is sufficient to rely on 
2757:      *     {@link #setSeriesNegativeItemLabelPosition(int, ItemLabelPosition)} 
2758:      *     and {@link #setBaseNegativeItemLabelPosition(ItemLabelPosition)}.
2759:      */
2760:     public void setNegativeItemLabelPosition(ItemLabelPosition position) {
2761:         setNegativeItemLabelPosition(position, true);
2762:     }
2763:     
2764:     /**
2765:      * Sets the item label position for negative values in ALL series and (if 
2766:      * requested) sends a {@link RendererChangeEvent} to all registered 
2767:      * listeners.  
2768:      * 
2769:      * @param position  the position (<code>null</code> permitted).
2770:      * @param notify  notify registered listeners?
2771:      * 
2772:      * @see #getNegativeItemLabelPosition()
2773:      * 
2774:      * @deprecated This method should no longer be used (as of version 1.0.6). 
2775:      *     It is sufficient to rely on 
2776:      *     {@link #setSeriesNegativeItemLabelPosition(int, ItemLabelPosition, 
2777:      *     boolean)} and {@link #setBaseNegativeItemLabelPosition(
2778:      *     ItemLabelPosition, boolean)}.
2779:      */
2780:     public void setNegativeItemLabelPosition(ItemLabelPosition position, 
2781:                                              boolean notify) {
2782:         this.negativeItemLabelPosition = position;
2783:         if (notify) {
2784:             fireChangeEvent();
2785:         }
2786:     }
2787: 
2788:     /**
2789:      * Returns the item label position for all negative values in a series.
2790:      * 
2791:      * @param series  the series index (zero-based).
2792:      * 
2793:      * @return The item label position (never <code>null</code>).
2794:      * 
2795:      * @see #setSeriesNegativeItemLabelPosition(int, ItemLabelPosition)
2796:      */
2797:     public ItemLabelPosition getSeriesNegativeItemLabelPosition(int series) {
2798: 
2799:         // return the override, if there is one...
2800:         if (this.negativeItemLabelPosition != null) {
2801:             return this.negativeItemLabelPosition;
2802:         }
2803: 
2804:         // otherwise look up the position list
2805:         ItemLabelPosition position = (ItemLabelPosition) 
2806:             this.negativeItemLabelPositionList.get(series);
2807:         if (position == null) {
2808:             position = this.baseNegativeItemLabelPosition;
2809:         }
2810:         return position;
2811: 
2812:     }
2813: 
2814:     /**
2815:      * Sets the item label position for negative values in a series and sends a 
2816:      * {@link RendererChangeEvent} to all registered listeners.
2817:      * 
2818:      * @param series  the series index (zero-based).
2819:      * @param position  the position (<code>null</code> permitted).
2820:      * 
2821:      * @see #getSeriesNegativeItemLabelPosition(int)
2822:      */
2823:     public void setSeriesNegativeItemLabelPosition(int series, 
2824:                                                    ItemLabelPosition position) {
2825:         setSeriesNegativeItemLabelPosition(series, position, true);
2826:     }
2827: 
2828:     /**
2829:      * Sets the item label position for negative values in a series and (if 
2830:      * requested) sends a {@link RendererChangeEvent} to all registered 
2831:      * listeners.
2832:      * 
2833:      * @param series  the series index (zero-based).
2834:      * @param position  the position (<code>null</code> permitted).
2835:      * @param notify  notify registered listeners?
2836:      * 
2837:      * @see #getSeriesNegativeItemLabelPosition(int)
2838:      */
2839:     public void setSeriesNegativeItemLabelPosition(int series, 
2840:                                                    ItemLabelPosition position, 
2841:                                                    boolean notify) {
2842:         this.negativeItemLabelPositionList.set(series, position);
2843:         if (notify) {
2844:             fireChangeEvent();
2845:         }
2846:     }
2847: 
2848:     /**
2849:      * Returns the base item label position for negative values.
2850:      * 
2851:      * @return The position (never <code>null</code>).
2852:      * 
2853:      * @see #setBaseNegativeItemLabelPosition(ItemLabelPosition)
2854:      */
2855:     public ItemLabelPosition getBaseNegativeItemLabelPosition() {
2856:         return this.baseNegativeItemLabelPosition;
2857:     }
2858: 
2859:     /**
2860:      * Sets the base item label position for negative values and sends a 
2861:      * {@link RendererChangeEvent} to all registered listeners.
2862:      * 
2863:      * @param position  the position (<code>null</code> not permitted).
2864:      * 
2865:      * @see #getBaseNegativeItemLabelPosition()
2866:      */
2867:     public void setBaseNegativeItemLabelPosition(ItemLabelPosition position) {
2868:         setBaseNegativeItemLabelPosition(position, true);
2869:     }
2870:     
2871:     /**
2872:      * Sets the base negative item label position and, if requested, sends a 
2873:      * {@link RendererChangeEvent} to all registered listeners.
2874:      * 
2875:      * @param position  the position (<code>null</code> not permitted).
2876:      * @param notify  notify registered listeners?
2877:      * 
2878:      * @see #getBaseNegativeItemLabelPosition()
2879:      */
2880:     public void setBaseNegativeItemLabelPosition(ItemLabelPosition position, 
2881:                                                  boolean notify) {
2882:         if (position == null) {
2883:             throw new IllegalArgumentException("Null 'position' argument.");   
2884:         }
2885:         this.baseNegativeItemLabelPosition = position;
2886:         if (notify) {
2887:             fireChangeEvent();
2888:         }
2889:     }
2890: 
2891:     /**
2892:      * Returns the item label anchor offset.
2893:      *
2894:      * @return The offset.
2895:      * 
2896:      * @see #setItemLabelAnchorOffset(double)
2897:      */
2898:     public double getItemLabelAnchorOffset() {
2899:         return this.itemLabelAnchorOffset;
2900:     }
2901: 
2902:     /**
2903:      * Sets the item label anchor offset.
2904:      *
2905:      * @param offset  the offset.
2906:      * 
2907:      * @see #getItemLabelAnchorOffset()
2908:      */
2909:     public void setItemLabelAnchorOffset(double offset) {
2910:         this.itemLabelAnchorOffset = offset;
2911:         fireChangeEvent();
2912:     }
2913: 
2914:     /**
2915:      * Returns a boolean that indicates whether or not the specified item 
2916:      * should have a chart entity created for it.
2917:      * 
2918:      * @param series  the series index.
2919:      * @param item  the item index.
2920:      * 
2921:      * @return A boolean.
2922:      */
2923:     public boolean getItemCreateEntity(int series, int item) {
2924:         if (this.createEntities != null) {
2925:             return this.createEntities.booleanValue();
2926:         }
2927:         else {
2928:             Boolean b = getSeriesCreateEntities(series);
2929:             if (b != null) {
2930:                 return b.booleanValue();
2931:             }
2932:             else {
2933:                 return this.baseCreateEntities;
2934:             }
2935:         }
2936:     }
2937:     
2938:     /**
2939:      * Returns the flag that controls whether or not chart entities are created 
2940:      * for the items in ALL series.  This flag overrides the per series and 
2941:      * default settings - you must set it to <code>null</code> if you want the
2942:      * other settings to apply.
2943:      * 
2944:      * @return The flag (possibly <code>null</code>).
2945:      * 
2946:      * @deprecated This method should no longer be used (as of version 1.0.6). 
2947:      *     It is sufficient to rely on {@link #getSeriesCreateEntities(int)} 
2948:      *     and {@link #getBaseCreateEntities()}.
2949:      */
2950:     public Boolean getCreateEntities() {
2951:         return this.createEntities;  
2952:     }
2953:     
2954:     /**
2955:      * Sets the flag that controls whether or not chart entities are created 
2956:      * for the items in ALL series, and sends a {@link RendererChangeEvent} to 
2957:      * all registered listeners.  This flag overrides the per series and 
2958:      * default settings - you must set it to <code>null</code> if you want the
2959:      * other settings to apply.
2960:      * 
2961:      * @param create  the flag (<code>null</code> permitted).
2962:      * 
2963:      * @deprecated This method should no longer be used (as of version 1.0.6). 
2964:      *     It is sufficient to rely on {@link #setSeriesCreateEntities(int, 
2965:      *     Boolean)} and {@link #setBaseCreateEntities(boolean)}.
2966:      */
2967:     public void setCreateEntities(Boolean create) {
2968:          setCreateEntities(create, true);
2969:     }
2970:     
2971:     /**
2972:      * Sets the flag that controls whether or not chart entities are created 
2973:      * for the items in ALL series, and sends a {@link RendererChangeEvent} to 
2974:      * all registered listeners.  This flag overrides the per series and 
2975:      * default settings - you must set it to <code>null</code> if you want the
2976:      * other settings to apply.
2977:      * 
2978:      * @param create  the flag (<code>null</code> permitted).
2979:      * @param notify  notify listeners?
2980:      * 
2981:      * @deprecated This method should no longer be used (as of version 1.0.6). 
2982:      *     It is sufficient to rely on {@link #setSeriesItemLabelFont(int, 
2983:      *     Font, boolean)} and {@link #setBaseItemLabelFont(Font, boolean)}.
2984:      */
2985:     public void setCreateEntities(Boolean create, boolean notify) {
2986:         this.createEntities = create;   
2987:         if (notify) {
2988:             fireChangeEvent();
2989:         }
2990:     }
2991:     
2992:     /**
2993:      * Returns the flag that controls whether entities are created for a
2994:      * series.
2995:      *
2996:      * @param series  the series index (zero-based).
2997:      *
2998:      * @return The flag (possibly <code>null</code>).
2999:      * 
3000:      * @see #setSeriesCreateEntities(int, Boolean)
3001:      */
3002:     public Boolean getSeriesCreateEntities(int series) {
3003:         return this.createEntitiesList.getBoolean(series);
3004:     }
3005:     
3006:     /**
3007:      * Sets the flag that controls whether entities are created for a series,
3008:      * and sends a {@link RendererChangeEvent} to all registered listeners.
3009:      *
3010:      * @param series  the series index (zero-based).
3011:      * @param create  the flag (<code>null</code> permitted).
3012:      * 
3013:      * @see #getSeriesCreateEntities(int)
3014:      */
3015:     public void setSeriesCreateEntities(int series, Boolean create) {
3016:         setSeriesCreateEntities(series, create, true);
3017:     }
3018:     
3019:     /**
3020:      * Sets the flag that controls whether entities are created for a series
3021:      * and, if requested, sends a {@link RendererChangeEvent} to all registered 
3022:      * listeners.
3023:      * 
3024:      * @param series  the series index.
3025:      * @param create  the flag (<code>null</code> permitted).
3026:      * @param notify  notify listeners?
3027:      * 
3028:      * @see #getSeriesCreateEntities(int)
3029:      */
3030:     public void setSeriesCreateEntities(int series, Boolean create, 
3031:                                         boolean notify) {
3032:         this.createEntitiesList.setBoolean(series, create);       
3033:         if (notify) {
3034:             fireChangeEvent();
3035:         }
3036:     }
3037: 
3038:     /**
3039:      * Returns the base visibility for all series.
3040:      *
3041:      * @return The base visibility.
3042:      * 
3043:      * @see #setBaseCreateEntities(boolean)
3044:      */
3045:     public boolean getBaseCreateEntities() {
3046:         return this.baseCreateEntities;
3047:     }
3048: 
3049:     /**
3050:      * Sets the base flag that controls whether entities are created
3051:      * for a series, and sends a {@link RendererChangeEvent} 
3052:      * to all registered listeners.
3053:      *
3054:      * @param create  the flag.
3055:      * 
3056:      * @see #getBaseCreateEntities()
3057:      */
3058:     public void setBaseCreateEntities(boolean create) {
3059:         // defer argument checking...
3060:         setBaseCreateEntities(create, true);
3061:     }
3062:     
3063:     /**
3064:      * Sets the base flag that controls whether entities are created and, 
3065:      * if requested, sends a {@link RendererChangeEvent} to all registered 
3066:      * listeners.
3067:      * 
3068:      * @param create  the visibility.
3069:      * @param notify  notify listeners?
3070:      * 
3071:      * @see #getBaseCreateEntities()
3072:      */
3073:     public void setBaseCreateEntities(boolean create, boolean notify) {
3074:         this.baseCreateEntities = create;
3075:         if (notify) {
3076:             fireChangeEvent();
3077:         }
3078:     }
3079: 
3080:     /** The adjacent offset. */
3081:     private static final double ADJ = Math.cos(Math.PI / 6.0);
3082:     
3083:     /** The opposite offset. */
3084:     private static final double OPP = Math.sin(Math.PI / 6.0);
3085:     
3086:     /**
3087:      * Calculates the item label anchor point.
3088:      *
3089:      * @param anchor  the anchor.
3090:      * @param x  the x coordinate.
3091:      * @param y  the y coordinate.
3092:      * @param orientation  the plot orientation.
3093:      *
3094:      * @return The anchor point (never <code>null</code>).
3095:      */
3096:     protected Point2D calculateLabelAnchorPoint(ItemLabelAnchor anchor,
3097:             double x, double y, PlotOrientation orientation) {
3098:         Point2D result = null;
3099:         if (anchor == ItemLabelAnchor.CENTER) {
3100:             result = new Point2D.Double(x, y);
3101:         }
3102:         else if (anchor == ItemLabelAnchor.INSIDE1) {
3103:             result = new Point2D.Double(x + OPP * this.itemLabelAnchorOffset, 
3104:                     y - ADJ * this.itemLabelAnchorOffset);
3105:         }
3106:         else if (anchor == ItemLabelAnchor.INSIDE2) {
3107:             result = new Point2D.Double(x + ADJ * this.itemLabelAnchorOffset, 
3108:                     y - OPP * this.itemLabelAnchorOffset);
3109:         }
3110:         else if (anchor == ItemLabelAnchor.INSIDE3) {
3111:             result = new Point2D.Double(x + this.itemLabelAnchorOffset, y);
3112:         }
3113:         else if (anchor == ItemLabelAnchor.INSIDE4) {
3114:             result = new Point2D.Double(x + ADJ * this.itemLabelAnchorOffset, 
3115:                     y + OPP * this.itemLabelAnchorOffset);
3116:         }
3117:         else if (anchor == ItemLabelAnchor.INSIDE5) {
3118:             result = new Point2D.Double(x + OPP * this.itemLabelAnchorOffset, 
3119:                     y + ADJ * this.itemLabelAnchorOffset);
3120:         }
3121:         else if (anchor == ItemLabelAnchor.INSIDE6) {
3122:             result = new Point2D.Double(x, y + this.itemLabelAnchorOffset);
3123:         }
3124:         else if (anchor == ItemLabelAnchor.INSIDE7) {
3125:             result = new Point2D.Double(x - OPP * this.itemLabelAnchorOffset, 
3126:                     y + ADJ * this.itemLabelAnchorOffset);
3127:         }
3128:         else if (anchor == ItemLabelAnchor.INSIDE8) {
3129:             result = new Point2D.Double(x - ADJ * this.itemLabelAnchorOffset, 
3130:                     y + OPP * this.itemLabelAnchorOffset);
3131:         }
3132:         else if (anchor == ItemLabelAnchor.INSIDE9) {
3133:             result = new Point2D.Double(x - this.itemLabelAnchorOffset, y);
3134:         }
3135:         else if (anchor == ItemLabelAnchor.INSIDE10) {
3136:             result = new Point2D.Double(x - ADJ * this.itemLabelAnchorOffset, 
3137:                     y - OPP * this.itemLabelAnchorOffset);
3138:         }
3139:         else if (anchor == ItemLabelAnchor.INSIDE11) {
3140:             result = new Point2D.Double(x - OPP * this.itemLabelAnchorOffset, 
3141:                     y - ADJ * this.itemLabelAnchorOffset);
3142:         }
3143:         else if (anchor == ItemLabelAnchor.INSIDE12) {
3144:             result = new Point2D.Double(x, y - this.itemLabelAnchorOffset);
3145:         }
3146:         else if (anchor == ItemLabelAnchor.OUTSIDE1) {
3147:             result = new Point2D.Double(
3148:                     x + 2.0 * OPP * this.itemLabelAnchorOffset, 
3149:                     y - 2.0 * ADJ * this.itemLabelAnchorOffset);
3150:         }
3151:         else if (anchor == ItemLabelAnchor.OUTSIDE2) {
3152:             result = new Point2D.Double(
3153:                     x + 2.0 * ADJ * this.itemLabelAnchorOffset, 
3154:                     y - 2.0 * OPP * this.itemLabelAnchorOffset);
3155:         }
3156:         else if (anchor == ItemLabelAnchor.OUTSIDE3) {
3157:             result = new Point2D.Double(x + 2.0 * this.itemLabelAnchorOffset, 
3158:                     y);
3159:         }
3160:         else if (anchor == ItemLabelAnchor.OUTSIDE4) {
3161:             result = new Point2D.Double(
3162:                     x + 2.0 * ADJ * this.itemLabelAnchorOffset, 
3163:                     y + 2.0 * OPP * this.itemLabelAnchorOffset);
3164:         }
3165:         else if (anchor == ItemLabelAnchor.OUTSIDE5) {
3166:             result = new Point2D.Double(
3167:                     x + 2.0 * OPP * this.itemLabelAnchorOffset, 
3168:                     y + 2.0 * ADJ * this.itemLabelAnchorOffset);
3169:         }
3170:         else if (anchor == ItemLabelAnchor.OUTSIDE6) {
3171:             result = new Point2D.Double(x, 
3172:                     y + 2.0 * this.itemLabelAnchorOffset);
3173:         }
3174:         else if (anchor == ItemLabelAnchor.OUTSIDE7) {
3175:             result = new Point2D.Double(
3176:                     x - 2.0 * OPP * this.itemLabelAnchorOffset, 
3177:                     y + 2.0 * ADJ * this.itemLabelAnchorOffset);
3178:         }
3179:         else if (anchor == ItemLabelAnchor.OUTSIDE8) {
3180:             result = new Point2D.Double(
3181:                     x - 2.0 * ADJ * this.itemLabelAnchorOffset, 
3182:                     y + 2.0 * OPP * this.itemLabelAnchorOffset);
3183:         }
3184:         else if (anchor == ItemLabelAnchor.OUTSIDE9) {
3185:             result = new Point2D.Double(x - 2.0 * this.itemLabelAnchorOffset, 
3186:                     y);
3187:         }
3188:         else if (anchor == ItemLabelAnchor.OUTSIDE10) {
3189:             result = new Point2D.Double(
3190:                     x - 2.0 * ADJ * this.itemLabelAnchorOffset, 
3191:                     y - 2.0 * OPP * this.itemLabelAnchorOffset);
3192:         }
3193:         else if (anchor == ItemLabelAnchor.OUTSIDE11) {
3194:             result = new Point2D.Double(
3195:                 x - 2.0 * OPP * this.itemLabelAnchorOffset, 
3196:                 y - 2.0 * ADJ * this.itemLabelAnchorOffset);
3197:         }
3198:         else if (anchor == ItemLabelAnchor.OUTSIDE12) {
3199:             result = new Point2D.Double(x, 
3200:                     y - 2.0 * this.itemLabelAnchorOffset);
3201:         }
3202:         return result;
3203:     }
3204:     
3205:     /**
3206:      * Registers an object to receive notification of changes to the renderer.
3207:      *
3208:      * @param listener  the listener (<code>null</code> not permitted).
3209:      * 
3210:      * @see #removeChangeListener(RendererChangeListener)
3211:      */
3212:     public void addChangeListener(RendererChangeListener listener) {
3213:         if (listener == null) {
3214:             throw new IllegalArgumentException("Null 'listener' argument.");   
3215:         }
3216:         this.listenerList.add(RendererChangeListener.class, listener);
3217:     }
3218: 
3219:     /**
3220:      * Deregisters an object so that it no longer receives 
3221:      * notification of changes to the renderer.
3222:      *
3223:      * @param listener  the object (<code>null</code> not permitted).
3224:      * 
3225:      * @see #addChangeListener(RendererChangeListener)
3226:      */
3227:     public void removeChangeListener(RendererChangeListener listener) {
3228:         if (listener == null) {
3229:             throw new IllegalArgumentException("Null 'listener' argument.");   
3230:         }
3231:         this.listenerList.remove(RendererChangeListener.class, listener);
3232:     }
3233: 
3234:     /**
3235:      * Returns <code>true</code> if the specified object is registered with
3236:      * the dataset as a listener.  Most applications won't need to call this 
3237:      * method, it exists mainly for use by unit testing code.
3238:      * 
3239:      * @param listener  the listener.
3240:      * 
3241:      * @return A boolean.
3242:      */
3243:     public boolean hasListener(EventListener listener) {
3244:         List list = Arrays.asList(this.listenerList.getListenerList());
3245:         return list.contains(listener);
3246:     }
3247:     
3248:     /**
3249:      * Sends a {@link RendererChangeEvent} to all registered listeners.
3250:      * 
3251:      * @since 1.0.5
3252:      */
3253:     protected void fireChangeEvent() {
3254:         
3255:         // the commented out code would be better, but only if 
3256:         // RendererChangeEvent is immutable, which it isn't.  See if there is
3257:         // a way to fix this...
3258:         
3259:         //if (this.event == null) {
3260:         //    this.event = new RendererChangeEvent(this);
3261:         //}
3262:         //notifyListeners(this.event);
3263:         
3264:         notifyListeners(new RendererChangeEvent(this));
3265:     }
3266:     
3267:     /**
3268:      * Notifies all registered listeners that the renderer has been modified.
3269:      *
3270:      * @param event  information about the change event.
3271:      */
3272:     public void notifyListeners(RendererChangeEvent event) {
3273:         Object[] ls = this.listenerList.getListenerList();
3274:         for (int i = ls.length - 2; i >= 0; i -= 2) {
3275:             if (ls[i] == RendererChangeListener.class) {
3276:                 ((RendererChangeListener) ls[i + 1]).rendererChanged(event);
3277:             }
3278:         }
3279:     }
3280: 
3281:     /**
3282:      * Tests this renderer for equality with another object.
3283:      *
3284:      * @param obj  the object (<code>null</code> permitted).
3285:      *
3286:      * @return <code>true</code> or <code>false</code>.
3287:      */
3288:     public boolean equals(Object obj) {
3289:         if (obj == this) {
3290:             return true;
3291:         }
3292:         if (!(obj instanceof AbstractRenderer)) {
3293:             return false;
3294:         }
3295:         AbstractRenderer that = (AbstractRenderer) obj;
3296:         if (!ObjectUtilities.equal(this.seriesVisible, that.seriesVisible)) {
3297:             return false;   
3298:         }
3299:         if (!this.seriesVisibleList.equals(that.seriesVisibleList)) {
3300:             return false;   
3301:         }
3302:         if (this.baseSeriesVisible != that.baseSeriesVisible) {
3303:             return false;   
3304:         }
3305:         if (!ObjectUtilities.equal(this.seriesVisibleInLegend, 
3306:                 that.seriesVisibleInLegend)) {
3307:             return false;   
3308:         }
3309:         if (!this.seriesVisibleInLegendList.equals(
3310:                 that.seriesVisibleInLegendList)) {
3311:             return false;   
3312:         }
3313:         if (this.baseSeriesVisibleInLegend != that.baseSeriesVisibleInLegend) {
3314:             return false;   
3315:         }
3316:         if (!PaintUtilities.equal(this.paint, that.paint)) {
3317:             return false;
3318:         }
3319:         if (!ObjectUtilities.equal(this.paintList, that.paintList)) {
3320:             return false;
3321:         }
3322:         if (!PaintUtilities.equal(this.basePaint, that.basePaint)) {
3323:             return false;
3324:         }
3325:         if (!PaintUtilities.equal(this.fillPaint, that.fillPaint)) {
3326:             return false;
3327:         }
3328:         if (!ObjectUtilities.equal(this.fillPaintList, that.fillPaintList)) {
3329:             return false;
3330:         }
3331:         if (!PaintUtilities.equal(this.baseFillPaint, that.baseFillPaint)) {
3332:             return false;
3333:         }
3334:         if (!PaintUtilities.equal(this.outlinePaint, that.outlinePaint)) {
3335:             return false;
3336:         }
3337:         if (!ObjectUtilities.equal(this.outlinePaintList,
3338:                 that.outlinePaintList)) {
3339:             return false;
3340:         }
3341:         if (!PaintUtilities.equal(this.baseOutlinePaint, 
3342:                 that.baseOutlinePaint)) {
3343:             return false;
3344:         }
3345:         if (!ObjectUtilities.equal(this.stroke, that.stroke)) {
3346:             return false;
3347:         }
3348:         if (!ObjectUtilities.equal(this.strokeList, that.strokeList)) {
3349:             return false;
3350:         }
3351:         if (!ObjectUtilities.equal(this.baseStroke, that.baseStroke)) {
3352:             return false;
3353:         }
3354:         if (!ObjectUtilities.equal(this.outlineStroke, that.outlineStroke)) {
3355:             return false;
3356:         }
3357:         if (!ObjectUtilities.equal(this.outlineStrokeList, 
3358:                 that.outlineStrokeList)) {
3359:             return false;
3360:         }
3361:         if (!ObjectUtilities.equal(
3362:             this.baseOutlineStroke, that.baseOutlineStroke)
3363:         ) {
3364:             return false;
3365:         }
3366:         if (!ObjectUtilities.equal(this.shape, that.shape)) {
3367:             return false;
3368:         }
3369:         if (!ObjectUtilities.equal(this.shapeList, that.shapeList)) {
3370:             return false;
3371:         }
3372:         if (!ObjectUtilities.equal(this.baseShape, that.baseShape)) {
3373:             return false;
3374:         }
3375:         if (!ObjectUtilities.equal(this.itemLabelsVisible, 
3376:                 that.itemLabelsVisible)) {
3377:             return false;
3378:         }
3379:         if (!ObjectUtilities.equal(this.itemLabelsVisibleList, 
3380:                 that.itemLabelsVisibleList)) {
3381:             return false;
3382:         }
3383:         if (!ObjectUtilities.equal(this.baseItemLabelsVisible, 
3384:                 that.baseItemLabelsVisible)) {
3385:             return false;
3386:         }
3387:         if (!ObjectUtilities.equal(this.itemLabelFont, that.itemLabelFont)) {
3388:             return false;
3389:         }
3390:         if (!ObjectUtilities.equal(this.itemLabelFontList, 
3391:                 that.itemLabelFontList)) {
3392:             return false;
3393:         }
3394:         if (!ObjectUtilities.equal(this.baseItemLabelFont, 
3395:                 that.baseItemLabelFont)) {
3396:             return false;
3397:         }
3398:  
3399:         if (!PaintUtilities.equal(this.itemLabelPaint, that.itemLabelPaint)) {
3400:             return false;
3401:         }
3402:         if (!ObjectUtilities.equal(this.itemLabelPaintList, 
3403:                 that.itemLabelPaintList)) {
3404:             return false;
3405:         }
3406:         if (!PaintUtilities.equal(this.baseItemLabelPaint, 
3407:                 that.baseItemLabelPaint)) {
3408:             return false;
3409:         }
3410: 
3411:         if (!ObjectUtilities.equal(this.positiveItemLabelPosition, 
3412:                 that.positiveItemLabelPosition)) {
3413:             return false;
3414:         }
3415:         if (!ObjectUtilities.equal(this.positiveItemLabelPositionList, 
3416:                 that.positiveItemLabelPositionList)) {
3417:             return false;
3418:         }
3419:         if (!ObjectUtilities.equal(this.basePositiveItemLabelPosition, 
3420:                 that.basePositiveItemLabelPosition)) {
3421:             return false;
3422:         }
3423: 
3424:         if (!ObjectUtilities.equal(this.negativeItemLabelPosition, 
3425:                 that.negativeItemLabelPosition)) {
3426:             return false;
3427:         }
3428:         if (!ObjectUtilities.equal(this.negativeItemLabelPositionList, 
3429:                 that.negativeItemLabelPositionList)) {
3430:             return false;
3431:         }
3432:         if (!ObjectUtilities.equal(this.baseNegativeItemLabelPosition, 
3433:                 that.baseNegativeItemLabelPosition)) {
3434:             return false;
3435:         }
3436:         if (this.itemLabelAnchorOffset != that.itemLabelAnchorOffset) {
3437:             return false;
3438:         }
3439:         if (!ObjectUtilities.equal(this.createEntities, that.createEntities)) {
3440:             return false;   
3441:         }
3442:         if (!ObjectUtilities.equal(this.createEntitiesList, 
3443:                 that.createEntitiesList)) {
3444:             return false;   
3445:         }
3446:         if (this.baseCreateEntities != that.baseCreateEntities) {
3447:             return false;   
3448:         }
3449:         return true;
3450:     }
3451:     
3452:     /**
3453:      * Returns a hashcode for the renderer.
3454:      * 
3455:      * @return The hashcode.
3456:      */
3457:     public int hashCode() {
3458:         int result = 193;   
3459:         result = 37 * result + ObjectUtilities.hashCode(this.stroke);     
3460:         result = 37 * result + ObjectUtilities.hashCode(this.baseStroke);    
3461:         result = 37 * result + ObjectUtilities.hashCode(this.outlineStroke);
3462:         result = 37 * result + ObjectUtilities.hashCode(this.baseOutlineStroke);
3463:         return result;
3464:     }
3465:     
3466:     /**
3467:      * Returns an independent copy of the renderer.
3468:      * 
3469:      * @return A clone.
3470:      * 
3471:      * @throws CloneNotSupportedException if some component of the renderer 
3472:      *         does not support cloning.
3473:      */
3474:     protected Object clone() throws CloneNotSupportedException {
3475:         AbstractRenderer clone = (AbstractRenderer) super.clone();
3476:         
3477:         if (this.seriesVisibleList != null) {
3478:             clone.seriesVisibleList 
3479:                     = (BooleanList) this.seriesVisibleList.clone();
3480:         }
3481:         
3482:         if (this.seriesVisibleInLegendList != null) {
3483:             clone.seriesVisibleInLegendList 
3484:                     = (BooleanList) this.seriesVisibleInLegendList.clone();
3485:         }
3486: 
3487:         // 'paint' : immutable, no need to clone reference
3488:         if (this.paintList != null) {
3489:             clone.paintList = (PaintList) this.paintList.clone();
3490:         }
3491:         // 'basePaint' : immutable, no need to clone reference
3492:         
3493:         if (this.fillPaintList != null) {
3494:             clone.fillPaintList = (PaintList) this.fillPaintList.clone();
3495:         }
3496:         // 'outlinePaint' : immutable, no need to clone reference
3497:         if (this.outlinePaintList != null) {
3498:             clone.outlinePaintList = (PaintList) this.outlinePaintList.clone();
3499:         }
3500:         // 'baseOutlinePaint' : immutable, no need to clone reference
3501:         
3502:         // 'stroke' : immutable, no need to clone reference
3503:         if (this.strokeList != null) {
3504:             clone.strokeList = (StrokeList) this.strokeList.clone();
3505:         }
3506:         // 'baseStroke' : immutable, no need to clone reference
3507:         
3508:         // 'outlineStroke' : immutable, no need to clone reference
3509:         if (this.outlineStrokeList != null) {
3510:             clone.outlineStrokeList 
3511:                 = (StrokeList) this.outlineStrokeList.clone();
3512:         }
3513:         // 'baseOutlineStroke' : immutable, no need to clone reference
3514:         
3515:         if (this.shape != null) {
3516:             clone.shape = ShapeUtilities.clone(this.shape);
3517:         }
3518:         if (this.shapeList != null) {
3519:             clone.shapeList = (ShapeList) this.shapeList.clone();
3520:         }
3521:         if (this.baseShape != null) {
3522:             clone.baseShape = ShapeUtilities.clone(this.baseShape);
3523:         }
3524:         
3525:         // 'itemLabelsVisible' : immutable, no need to clone reference
3526:         if (this.itemLabelsVisibleList != null) {
3527:             clone.itemLabelsVisibleList 
3528:                 = (BooleanList) this.itemLabelsVisibleList.clone();
3529:         }
3530:         // 'basePaint' : immutable, no need to clone reference
3531:         
3532:         // 'itemLabelFont' : immutable, no need to clone reference
3533:         if (this.itemLabelFontList != null) {
3534:             clone.itemLabelFontList 
3535:                 = (ObjectList) this.itemLabelFontList.clone();
3536:         }
3537:         // 'baseItemLabelFont' : immutable, no need to clone reference
3538: 
3539:         // 'itemLabelPaint' : immutable, no need to clone reference
3540:         if (this.itemLabelPaintList != null) {
3541:             clone.itemLabelPaintList 
3542:                 = (PaintList) this.itemLabelPaintList.clone();
3543:         }
3544:         // 'baseItemLabelPaint' : immutable, no need to clone reference
3545:         
3546:         // 'postiveItemLabelAnchor' : immutable, no need to clone reference
3547:         if (this.positiveItemLabelPositionList != null) {
3548:             clone.positiveItemLabelPositionList 
3549:                 = (ObjectList) this.positiveItemLabelPositionList.clone();
3550:         }
3551:         // 'baseItemLabelAnchor' : immutable, no need to clone reference
3552: 
3553:         // 'negativeItemLabelAnchor' : immutable, no need to clone reference
3554:         if (this.negativeItemLabelPositionList != null) {
3555:             clone.negativeItemLabelPositionList 
3556:                 = (ObjectList) this.negativeItemLabelPositionList.clone();
3557:         }
3558:         // 'baseNegativeItemLabelAnchor' : immutable, no need to clone reference
3559:         
3560:         if (this.createEntitiesList != null) {
3561:             clone.createEntitiesList 
3562:                     = (BooleanList) this.createEntitiesList.clone();
3563:         }
3564:         clone.listenerList = new EventListenerList();
3565:         clone.event = null;
3566:         return clone;
3567:     }
3568: 
3569:     /**
3570:      * Provides serialization support.
3571:      *
3572:      * @param stream  the output stream.
3573:      *
3574:      * @throws IOException  if there is an I/O error.
3575:      */
3576:     private void writeObject(ObjectOutputStream stream) throws IOException {
3577: 
3578:         stream.defaultWriteObject();
3579:         SerialUtilities.writePaint(this.paint, stream);
3580:         SerialUtilities.writePaint(this.basePaint, stream);
3581:         SerialUtilities.writePaint(this.fillPaint, stream);
3582:         SerialUtilities.writePaint(this.baseFillPaint, stream);
3583:         SerialUtilities.writePaint(this.outlinePaint, stream);
3584:         SerialUtilities.writePaint(this.baseOutlinePaint, stream);
3585:         SerialUtilities.writeStroke(this.stroke, stream);
3586:         SerialUtilities.writeStroke(this.baseStroke, stream);
3587:         SerialUtilities.writeStroke(this.outlineStroke, stream);
3588:         SerialUtilities.writeStroke(this.baseOutlineStroke, stream);
3589:         SerialUtilities.writeShape(this.shape, stream);
3590:         SerialUtilities.writeShape(this.baseShape, stream);
3591:         SerialUtilities.writePaint(this.itemLabelPaint, stream);
3592:         SerialUtilities.writePaint(this.baseItemLabelPaint, stream);
3593: 
3594:     }
3595: 
3596:     /**
3597:      * Provides serialization support.
3598:      *
3599:      * @param stream  the input stream.
3600:      *
3601:      * @throws IOException  if there is an I/O error.
3602:      * @throws ClassNotFoundException  if there is a classpath problem.
3603:      */
3604:     private void readObject(ObjectInputStream stream) 
3605:         throws IOException, ClassNotFoundException {
3606: 
3607:         stream.defaultReadObject();
3608:         this.paint = SerialUtilities.readPaint(stream);
3609:         this.basePaint = SerialUtilities.readPaint(stream);
3610:         this.fillPaint = SerialUtilities.readPaint(stream);
3611:         this.baseFillPaint = SerialUtilities.readPaint(stream);
3612:         this.outlinePaint = SerialUtilities.readPaint(stream);
3613:         this.baseOutlinePaint = SerialUtilities.readPaint(stream);
3614:         this.stroke = SerialUtilities.readStroke(stream);
3615:         this.baseStroke = SerialUtilities.readStroke(stream);
3616:         this.outlineStroke = SerialUtilities.readStroke(stream);
3617:         this.baseOutlineStroke = SerialUtilities.readStroke(stream);
3618:         this.shape = SerialUtilities.readShape(stream);
3619:         this.baseShape = SerialUtilities.readShape(stream);
3620:         this.itemLabelPaint = SerialUtilities.readPaint(stream);
3621:         this.baseItemLabelPaint = SerialUtilities.readPaint(stream);
3622:         
3623:         // listeners are not restored automatically, but storage must be 
3624:         // provided...
3625:         this.listenerList = new EventListenerList();
3626: 
3627:     }
3628: 
3629: }