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