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