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