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