Source for org.jfree.chart.renderer.AbstractRenderer

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