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