001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-2022, 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-2022, by David Gilbert. 031 * 032 * Original Author: David Gilbert; 033 * Contributor(s): Nicolas Brodu; 034 * 035 */ 036 037package org.jfree.chart.renderer; 038 039import java.awt.BasicStroke; 040import java.awt.Color; 041import java.awt.Font; 042import java.awt.Graphics2D; 043import java.awt.Paint; 044import java.awt.Shape; 045import java.awt.Stroke; 046import java.awt.geom.Point2D; 047import java.awt.geom.Rectangle2D; 048import java.io.IOException; 049import java.io.ObjectInputStream; 050import java.io.ObjectOutputStream; 051import java.io.Serializable; 052import java.util.Arrays; 053import java.util.EventListener; 054import java.util.HashMap; 055import java.util.List; 056import java.util.Map; 057import java.util.Objects; 058 059import javax.swing.event.EventListenerList; 060import org.jfree.chart.ChartElement; 061import org.jfree.chart.ChartElementVisitor; 062 063import org.jfree.chart.ChartHints; 064import org.jfree.chart.JFreeChart; 065import org.jfree.chart.api.PublicCloneable; 066import org.jfree.chart.event.RendererChangeEvent; 067import org.jfree.chart.event.RendererChangeListener; 068import org.jfree.chart.labels.ItemLabelAnchor; 069import org.jfree.chart.labels.ItemLabelPosition; 070import org.jfree.chart.legend.LegendTitle; 071import org.jfree.chart.plot.DrawingSupplier; 072import org.jfree.chart.plot.PlotOrientation; 073import org.jfree.chart.internal.Args; 074import org.jfree.chart.internal.CloneUtils; 075import org.jfree.chart.internal.HashUtils; 076import org.jfree.chart.internal.SerialUtils; 077import org.jfree.chart.text.TextAnchor; 078import org.jfree.chart.internal.PaintUtils; 079import org.jfree.chart.internal.ShapeUtils; 080import org.jfree.data.ItemKey; 081 082/** 083 * Base class providing common services for renderers. Most methods that update 084 * attributes of the renderer will fire a {@link RendererChangeEvent}, which 085 * normally means the plot that owns the renderer will receive notification that 086 * the renderer has been changed (the plot will, in turn, notify the chart). 087 * 088 * <b>Subclassing</b> 089 * If you create your own renderer that is a subclass of this, you should take 090 * care to ensure that the renderer implements cloning correctly, to ensure 091 * that {@link JFreeChart} instances that use your renderer are also 092 * cloneable. It is recommended that you also implement the 093 * {@link PublicCloneable} interface to provide simple access to the clone 094 * method. 095 */ 096public abstract class AbstractRenderer implements ChartElement, Cloneable, Serializable { 097 098 /** For serialization. */ 099 private static final long serialVersionUID = -828267569428206075L; 100 101 /** Zero represented as a {@code double}. */ 102 public static final Double ZERO = 0.0; 103 104 /** The default paint. */ 105 public static final Paint DEFAULT_PAINT = Color.BLUE; 106 107 /** The default outline paint. */ 108 public static final Paint DEFAULT_OUTLINE_PAINT = Color.GRAY; 109 110 /** The default stroke. */ 111 public static final Stroke DEFAULT_STROKE = new BasicStroke(1.0f); 112 113 /** The default outline stroke. */ 114 public static final Stroke DEFAULT_OUTLINE_STROKE = new BasicStroke(1.0f); 115 116 /** The default shape. */ 117 public static final Shape DEFAULT_SHAPE 118 = new Rectangle2D.Double(-3.0, -3.0, 6.0, 6.0); 119 120 /** The default value label font. */ 121 public static final Font DEFAULT_VALUE_LABEL_FONT 122 = new Font("SansSerif", Font.PLAIN, 10); 123 124 /** The default value label paint. */ 125 public static final Paint DEFAULT_VALUE_LABEL_PAINT = Color.BLACK; 126 127 /** A list of flags that controls whether or not each series is visible. */ 128 private Map<Integer, Boolean> seriesVisibleMap; 129 130 /** The default visibility for all series. */ 131 private boolean defaultSeriesVisible; 132 133 /** 134 * A list of flags that controls whether or not each series is visible in 135 * the legend. 136 */ 137 private Map<Integer, Boolean> seriesVisibleInLegendMap; 138 139 /** The default visibility for each series in the legend. */ 140 private boolean defaultSeriesVisibleInLegend; 141 142 /** The paint for each series. */ 143 private transient Map<Integer, Paint> seriesPaintMap; 144 145 /** 146 * A flag that controls whether or not the paintList is auto-populated 147 * in the {@link #lookupSeriesPaint(int)} method. 148 */ 149 private boolean autoPopulateSeriesPaint; 150 151 /** The default paint, used when there is no paint assigned for a series. */ 152 private transient Paint defaultPaint; 153 154 /** The fill paint list. */ 155 private transient Map<Integer, Paint> seriesFillPaintMap; 156 157 /** 158 * A flag that controls whether or not the fillPaintList is auto-populated 159 * in the {@link #lookupSeriesFillPaint(int)} method. 160 */ 161 private boolean autoPopulateSeriesFillPaint; 162 163 /** The base fill paint. */ 164 private transient Paint defaultFillPaint; 165 166 /** The outline paint list. */ 167 private transient Map<Integer, Paint> seriesOutlinePaintMap; 168 169 /** 170 * A flag that controls whether or not the outlinePaintList is 171 * auto-populated in the {@link #lookupSeriesOutlinePaint(int)} method. 172 */ 173 private boolean autoPopulateSeriesOutlinePaint; 174 175 /** The base outline paint. */ 176 private transient Paint defaultOutlinePaint; 177 178 /** The stroke list. */ 179 private transient Map<Integer, Stroke> seriesStrokeMap; 180 181 /** 182 * A flag that controls whether or not the strokeList is auto-populated 183 * in the {@link #lookupSeriesStroke(int)} method. 184 */ 185 private boolean autoPopulateSeriesStroke; 186 187 /** The base stroke. */ 188 private transient Stroke defaultStroke; 189 190 /** The outline stroke list. */ 191 private transient Map<Integer, Stroke> seriesOutlineStrokeMap; 192 193 /** The base outline stroke. */ 194 private transient Stroke defaultOutlineStroke; 195 196 /** 197 * A flag that controls whether or not the outlineStrokeList is 198 * auto-populated in the {@link #lookupSeriesOutlineStroke(int)} method. 199 */ 200 private boolean autoPopulateSeriesOutlineStroke; 201 202 /** The shapes to use for specific series. */ 203 private Map<Integer, Shape> seriesShapeMap; 204 205 /** 206 * A flag that controls whether or not the series shapes are auto-populated 207 * in the {@link #lookupSeriesShape(int)} method. 208 */ 209 private boolean autoPopulateSeriesShape; 210 211 /** The base shape. */ 212 private transient Shape defaultShape; 213 214 /** Visibility of the item labels PER series. */ 215 private Map<Integer, Boolean> seriesItemLabelsVisibleMap; 216 217 /** The base item labels visible. */ 218 private boolean defaultItemLabelsVisible; 219 220 /** The item label font list (one font per series). */ 221 private Map<Integer, Font> itemLabelFontMap; 222 223 /** The base item label font. */ 224 private Font defaultItemLabelFont; 225 226 /** The item label paint list (one paint per series). */ 227 private transient Map<Integer, Paint> itemLabelPaints; 228 229 /** The base item label paint. */ 230 private transient Paint defaultItemLabelPaint; 231 232 /** The positive item label position (per series). */ 233 private Map<Integer, ItemLabelPosition> positiveItemLabelPositionMap; 234 235 /** The fallback positive item label position. */ 236 private ItemLabelPosition defaultPositiveItemLabelPosition; 237 238 /** The negative item label position (per series). */ 239 private Map<Integer, ItemLabelPosition> negativeItemLabelPositionMap; 240 241 /** The fallback negative item label position. */ 242 private ItemLabelPosition defaultNegativeItemLabelPosition; 243 244 /** The item label anchor offset. */ 245 private double itemLabelAnchorOffset = 2.0; 246 247 /** 248 * Flags that control whether or not entities are generated for each 249 * series. This will be overridden by 'createEntities'. 250 */ 251 private Map<Integer, Boolean> seriesCreateEntitiesMap; 252 253 /** 254 * The default flag that controls whether or not entities are generated. 255 * This flag is used when both the above flags return null. 256 */ 257 private boolean defaultCreateEntities; 258 259 /** The per-series legend shape settings. */ 260 private Map<Integer, Shape> seriesLegendShapes; 261 262 /** 263 * The base shape for legend items. If this is {@code null}, the 264 * series shape will be used. 265 */ 266 private transient Shape defaultLegendShape; 267 268 /** 269 * A special flag that, if true, will cause the getLegendItem() method 270 * to configure the legend shape as if it were a line. 271 */ 272 private boolean treatLegendShapeAsLine; 273 274 /** The per-series legend text font. */ 275 private Map<Integer, Font> legendTextFontMap; 276 277 /** The base legend font. */ 278 private Font defaultLegendTextFont; 279 280 /** 281 * The per series legend text paint settings. 282 */ 283 private transient Map<Integer, Paint> legendTextPaints; 284 285 /** 286 * The default paint for the legend text items (if this is 287 * {@code null}, the {@link LegendTitle} class will determine the 288 * text paint to use. 289 */ 290 private transient Paint defaultLegendTextPaint; 291 292 /** 293 * A flag that controls whether or not the renderer will include the 294 * non-visible series when calculating the data bounds. 295 */ 296 private boolean dataBoundsIncludesVisibleSeriesOnly = true; 297 298 /** The default radius for the entity 'hotspot' */ 299 private int defaultEntityRadius; 300 301 /** Storage for registered change listeners. */ 302 private transient EventListenerList listenerList; 303 304 /** An event for re-use. */ 305 private transient RendererChangeEvent event; 306 307 /** 308 * Default constructor. 309 */ 310 public AbstractRenderer() { 311 this.seriesVisibleMap = new HashMap<>(); 312 this.defaultSeriesVisible = true; 313 314 this.seriesVisibleInLegendMap = new HashMap<>(); 315 this.defaultSeriesVisibleInLegend = true; 316 317 this.seriesPaintMap = new HashMap<>(); 318 this.defaultPaint = DEFAULT_PAINT; 319 this.autoPopulateSeriesPaint = true; 320 321 this.seriesFillPaintMap = new HashMap<>(); 322 this.defaultFillPaint = Color.WHITE; 323 this.autoPopulateSeriesFillPaint = false; 324 325 this.seriesOutlinePaintMap = new HashMap<>(); 326 this.defaultOutlinePaint = DEFAULT_OUTLINE_PAINT; 327 this.autoPopulateSeriesOutlinePaint = false; 328 329 this.seriesStrokeMap = new HashMap<>(); 330 this.defaultStroke = DEFAULT_STROKE; 331 this.autoPopulateSeriesStroke = true; 332 333 this.seriesOutlineStrokeMap = new HashMap<>(); 334 this.defaultOutlineStroke = DEFAULT_OUTLINE_STROKE; 335 this.autoPopulateSeriesOutlineStroke = false; 336 337 this.seriesShapeMap = new HashMap<>(); 338 this.defaultShape = DEFAULT_SHAPE; 339 this.autoPopulateSeriesShape = true; 340 341 this.seriesItemLabelsVisibleMap = new HashMap<>(); 342 this.defaultItemLabelsVisible = false; 343 344 this.itemLabelFontMap = new HashMap<>(); 345 this.defaultItemLabelFont = new Font("SansSerif", Font.PLAIN, 10); 346 347 this.itemLabelPaints = new HashMap<>(); 348 this.defaultItemLabelPaint = Color.BLACK; 349 350 this.positiveItemLabelPositionMap = new HashMap<>(); 351 this.defaultPositiveItemLabelPosition = new ItemLabelPosition( 352 ItemLabelAnchor.OUTSIDE12, TextAnchor.BOTTOM_CENTER); 353 354 this.negativeItemLabelPositionMap = new HashMap<>(); 355 this.defaultNegativeItemLabelPosition = new ItemLabelPosition( 356 ItemLabelAnchor.OUTSIDE6, TextAnchor.TOP_CENTER); 357 358 this.seriesCreateEntitiesMap = new HashMap<>(); 359 this.defaultCreateEntities = true; 360 361 this.defaultEntityRadius = 3; 362 363 this.seriesLegendShapes = new HashMap<>(); 364 this.defaultLegendShape = null; 365 366 this.treatLegendShapeAsLine = false; 367 368 this.legendTextFontMap = new HashMap<>(); 369 this.defaultLegendTextFont = null; 370 371 this.legendTextPaints = new HashMap<>(); 372 this.defaultLegendTextPaint = null; 373 374 this.listenerList = new EventListenerList(); 375 } 376 377 /** 378 * Receives a chart element visitor. 379 * 380 * @param visitor the visitor ({@code null} not permitted). 381 */ 382 @Override 383 public void receive(ChartElementVisitor visitor) { 384 visitor.visit(this); 385 } 386 387 /** 388 * Returns the drawing supplier from the plot. 389 * 390 * @return The drawing supplier. 391 */ 392 public abstract DrawingSupplier getDrawingSupplier(); 393 394 /** 395 * Adds a {@code KEY_BEGIN_ELEMENT} hint to the graphics target. This 396 * hint is recognised by <b>JFreeSVG</b> (in theory it could be used by 397 * other {@code Graphics2D} implementations also). 398 * 399 * @param g2 the graphics target ({@code null} not permitted). 400 * @param key the key ({@code null} not permitted). 401 * 402 * @see #endElementGroup(java.awt.Graphics2D) 403 */ 404 protected void beginElementGroup(Graphics2D g2, ItemKey key) { 405 Args.nullNotPermitted(key, "key"); 406 Map<String, String> m = new HashMap<>(1); 407 m.put("ref", key.toJSONString()); 408 g2.setRenderingHint(ChartHints.KEY_BEGIN_ELEMENT, m); 409 } 410 411 /** 412 * Adds a {@code KEY_END_ELEMENT} hint to the graphics target. 413 * 414 * @param g2 the graphics target ({@code null} not permitted). 415 * 416 * @see #beginElementGroup(java.awt.Graphics2D, org.jfree.data.ItemKey) 417 */ 418 protected void endElementGroup(Graphics2D g2) { 419 g2.setRenderingHint(ChartHints.KEY_END_ELEMENT, Boolean.TRUE); 420 } 421 422 // SERIES VISIBLE (not yet respected by all renderers) 423 424 /** 425 * Returns a boolean that indicates whether or not the specified item 426 * should be drawn. 427 * 428 * @param series the series index. 429 * @param item the item index. 430 * 431 * @return A boolean. 432 */ 433 public boolean getItemVisible(int series, int item) { 434 return isSeriesVisible(series); 435 } 436 437 /** 438 * Returns a boolean that indicates whether or not the specified series 439 * should be drawn. In fact this method should be named 440 * lookupSeriesVisible() to be consistent with the other series 441 * attributes and avoid confusion with the getSeriesVisible() method. 442 * 443 * @param series the series index. 444 * 445 * @return A boolean. 446 */ 447 public boolean isSeriesVisible(int series) { 448 boolean result = this.defaultSeriesVisible; 449 Boolean b = this.seriesVisibleMap.get(series); 450 if (b != null) { 451 result = b; 452 } 453 return result; 454 } 455 456 /** 457 * Returns the flag that controls whether a series is visible. 458 * 459 * @param series the series index (zero-based). 460 * 461 * @return The flag (possibly {@code null}). 462 * 463 * @see #setSeriesVisible(int, Boolean) 464 */ 465 public Boolean getSeriesVisible(int series) { 466 return this.seriesVisibleMap.get(series); 467 } 468 469 /** 470 * Sets the flag that controls whether a series is visible and sends a 471 * {@link RendererChangeEvent} to all registered listeners. 472 * 473 * @param series the series index (zero-based). 474 * @param visible the flag ({@code null} permitted). 475 * 476 * @see #getSeriesVisible(int) 477 */ 478 public void setSeriesVisible(int series, Boolean visible) { 479 setSeriesVisible(series, visible, true); 480 } 481 482 /** 483 * Sets the flag that controls whether a series is visible and, if 484 * requested, sends a {@link RendererChangeEvent} to all registered 485 * listeners. 486 * 487 * @param series the series index. 488 * @param visible the flag ({@code null} permitted). 489 * @param notify notify listeners? 490 * 491 * @see #getSeriesVisible(int) 492 */ 493 public void setSeriesVisible(int series, Boolean visible, boolean notify) { 494 this.seriesVisibleMap.put(series, visible); 495 if (notify) { 496 // we create an event with a special flag set...the purpose of 497 // this is to communicate to the plot (the default receiver of 498 // the event) that series visibility has changed so the axis 499 // ranges might need updating... 500 RendererChangeEvent e = new RendererChangeEvent(this, true); 501 notifyListeners(e); 502 } 503 } 504 505 /** 506 * Returns the default visibility for all series. 507 * 508 * @return The default visibility. 509 * 510 * @see #setDefaultSeriesVisible(boolean) 511 */ 512 public boolean getDefaultSeriesVisible() { 513 return this.defaultSeriesVisible; 514 } 515 516 /** 517 * Sets the default series visibility and sends a 518 * {@link RendererChangeEvent} to all registered listeners. 519 * 520 * @param visible the flag. 521 * 522 * @see #getDefaultSeriesVisible() 523 */ 524 public void setDefaultSeriesVisible(boolean visible) { 525 // defer argument checking... 526 setDefaultSeriesVisible(visible, true); 527 } 528 529 /** 530 * Sets the default series visibility and, if requested, sends 531 * a {@link RendererChangeEvent} to all registered listeners. 532 * 533 * @param visible the visibility. 534 * @param notify notify listeners? 535 * 536 * @see #getDefaultSeriesVisible() 537 */ 538 public void setDefaultSeriesVisible(boolean visible, boolean notify) { 539 this.defaultSeriesVisible = visible; 540 if (notify) { 541 // we create an event with a special flag set...the purpose of 542 // this is to communicate to the plot (the default receiver of 543 // the event) that series visibility has changed so the axis 544 // ranges might need updating... 545 RendererChangeEvent e = new RendererChangeEvent(this, true); 546 notifyListeners(e); 547 } 548 } 549 550 // SERIES VISIBLE IN LEGEND (not yet respected by all renderers) 551 552 /** 553 * Returns {@code true} if the series should be shown in the legend, 554 * and {@code false} otherwise. 555 * 556 * @param series the series index. 557 * 558 * @return A boolean. 559 */ 560 public boolean isSeriesVisibleInLegend(int series) { 561 boolean result = this.defaultSeriesVisibleInLegend; 562 Boolean b = this.seriesVisibleInLegendMap.get(series); 563 if (b != null) { 564 result = b; 565 } 566 return result; 567 } 568 569 /** 570 * Returns the flag that controls whether a series is visible in the 571 * legend. This method returns only the "per series" settings - to 572 * incorporate the default settings as well, you need to use the 573 * {@link #isSeriesVisibleInLegend(int)} method. 574 * 575 * @param series the series index (zero-based). 576 * 577 * @return The flag (possibly {@code null}). 578 * 579 * @see #setSeriesVisibleInLegend(int, Boolean) 580 */ 581 public Boolean getSeriesVisibleInLegend(int series) { 582 return this.seriesVisibleInLegendMap.get(series); 583 } 584 585 /** 586 * Sets the flag that controls whether a series is visible in the legend 587 * and sends a {@link RendererChangeEvent} to all registered listeners. 588 * 589 * @param series the series index (zero-based). 590 * @param visible the flag ({@code null} permitted). 591 * 592 * @see #getSeriesVisibleInLegend(int) 593 */ 594 public void setSeriesVisibleInLegend(int series, Boolean visible) { 595 setSeriesVisibleInLegend(series, visible, true); 596 } 597 598 /** 599 * Sets the flag that controls whether a series is visible in the legend 600 * and, if requested, sends a {@link RendererChangeEvent} to all registered 601 * listeners. 602 * 603 * @param series the series index. 604 * @param visible the flag ({@code null} permitted). 605 * @param notify notify listeners? 606 * 607 * @see #getSeriesVisibleInLegend(int) 608 */ 609 public void setSeriesVisibleInLegend(int series, Boolean visible, boolean notify) { 610 this.seriesVisibleInLegendMap.put(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.seriesPaintMap.get(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.seriesPaintMap.put(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.seriesPaintMap.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 series 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.seriesFillPaintMap.get(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.seriesFillPaintMap.put(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.seriesOutlinePaintMap.get(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.seriesOutlinePaintMap.put(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.seriesStrokeMap.get(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.seriesStrokeMap.put(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.seriesStrokeMap.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.seriesOutlineStrokeMap.get(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, boolean notify) { 1364 this.seriesOutlineStrokeMap.put(series, stroke); 1365 if (notify) { 1366 fireChangeEvent(); 1367 } 1368 } 1369 1370 /** 1371 * Returns the default outline stroke. 1372 * 1373 * @return The stroke (never {@code null}). 1374 * 1375 * @see #setDefaultOutlineStroke(Stroke) 1376 */ 1377 public Stroke getDefaultOutlineStroke() { 1378 return this.defaultOutlineStroke; 1379 } 1380 1381 /** 1382 * Sets the default outline stroke and sends a {@link RendererChangeEvent} 1383 * to all registered listeners. 1384 * 1385 * @param stroke the stroke ({@code null} not permitted). 1386 * 1387 * @see #getDefaultOutlineStroke() 1388 */ 1389 public void setDefaultOutlineStroke(Stroke stroke) { 1390 setDefaultOutlineStroke(stroke, true); 1391 } 1392 1393 /** 1394 * Sets the default outline stroke and, if requested, sends a 1395 * {@link RendererChangeEvent} to all registered listeners. 1396 * 1397 * @param stroke the stroke ({@code null} not permitted). 1398 * @param notify a flag that controls whether or not listeners are 1399 * notified. 1400 * 1401 * @see #getDefaultOutlineStroke() 1402 */ 1403 public void setDefaultOutlineStroke(Stroke stroke, boolean notify) { 1404 Args.nullNotPermitted(stroke, "stroke"); 1405 this.defaultOutlineStroke = stroke; 1406 if (notify) { 1407 fireChangeEvent(); 1408 } 1409 } 1410 1411 /** 1412 * Returns the flag that controls whether or not the series outline stroke 1413 * list is automatically populated when 1414 * {@link #lookupSeriesOutlineStroke(int)} is called. 1415 * 1416 * @return A boolean. 1417 * 1418 * @see #setAutoPopulateSeriesOutlineStroke(boolean) 1419 */ 1420 public boolean getAutoPopulateSeriesOutlineStroke() { 1421 return this.autoPopulateSeriesOutlineStroke; 1422 } 1423 1424 /** 1425 * Sets the flag that controls whether or not the series outline stroke list 1426 * is automatically populated when {@link #lookupSeriesOutlineStroke(int)} 1427 * is called. 1428 * 1429 * @param auto the new flag value. 1430 * 1431 * @see #getAutoPopulateSeriesOutlineStroke() 1432 */ 1433 public void setAutoPopulateSeriesOutlineStroke(boolean auto) { 1434 this.autoPopulateSeriesOutlineStroke = auto; 1435 } 1436 1437 // SHAPE 1438 1439 /** 1440 * Returns a shape used to represent a data item. 1441 * <p> 1442 * The default implementation passes control to the 1443 * {@link #lookupSeriesShape(int)} method. You can override this method if 1444 * you require different behaviour. 1445 * 1446 * @param row the row (or series) index (zero-based). 1447 * @param column the column (or category) index (zero-based). 1448 * 1449 * @return The shape (never {@code null}). 1450 */ 1451 public Shape getItemShape(int row, int column) { 1452 return lookupSeriesShape(row); 1453 } 1454 1455 /** 1456 * Returns a shape used to represent the items in a series. 1457 * 1458 * @param series the series (zero-based index). 1459 * 1460 * @return The shape (never {@code null}). 1461 */ 1462 public Shape lookupSeriesShape(int series) { 1463 1464 Shape result = getSeriesShape(series); 1465 if (result == null && this.autoPopulateSeriesShape) { 1466 DrawingSupplier supplier = getDrawingSupplier(); 1467 if (supplier != null) { 1468 result = supplier.getNextShape(); 1469 setSeriesShape(series, result, false); 1470 } 1471 } 1472 if (result == null) { 1473 result = this.defaultShape; 1474 } 1475 return result; 1476 1477 } 1478 1479 /** 1480 * Returns a shape used to represent the items in a series. 1481 * 1482 * @param series the series (zero-based index). 1483 * 1484 * @return The shape (possibly {@code null}). 1485 * 1486 * @see #setSeriesShape(int, Shape) 1487 */ 1488 public Shape getSeriesShape(int series) { 1489 return this.seriesShapeMap.get(series); 1490 } 1491 1492 /** 1493 * Sets the shape used for a series and sends a {@link RendererChangeEvent} 1494 * to all registered listeners. 1495 * 1496 * @param series the series index (zero-based). 1497 * @param shape the shape ({@code null} permitted). 1498 * 1499 * @see #getSeriesShape(int) 1500 */ 1501 public void setSeriesShape(int series, Shape shape) { 1502 setSeriesShape(series, shape, true); 1503 } 1504 1505 /** 1506 * Sets the shape for a series and, if requested, sends a 1507 * {@link RendererChangeEvent} to all registered listeners. 1508 * 1509 * @param series the series index (zero based). 1510 * @param shape the shape ({@code null} permitted). 1511 * @param notify notify listeners? 1512 * 1513 * @see #getSeriesShape(int) 1514 */ 1515 public void setSeriesShape(int series, Shape shape, boolean notify) { 1516 this.seriesShapeMap.put(series, shape); 1517 if (notify) { 1518 fireChangeEvent(); 1519 } 1520 } 1521 1522 /** 1523 * Returns the default shape. 1524 * 1525 * @return The shape (never {@code null}). 1526 * 1527 * @see #setDefaultShape(Shape) 1528 */ 1529 public Shape getDefaultShape() { 1530 return this.defaultShape; 1531 } 1532 1533 /** 1534 * Sets the default shape and sends a {@link RendererChangeEvent} to all 1535 * registered listeners. 1536 * 1537 * @param shape the shape ({@code null} not permitted). 1538 * 1539 * @see #getDefaultShape() 1540 */ 1541 public void setDefaultShape(Shape shape) { 1542 // defer argument checking... 1543 setDefaultShape(shape, true); 1544 } 1545 1546 /** 1547 * Sets the default shape and, if requested, sends a 1548 * {@link RendererChangeEvent} to all registered listeners. 1549 * 1550 * @param shape the shape ({@code null} not permitted). 1551 * @param notify notify listeners? 1552 * 1553 * @see #getDefaultShape() 1554 */ 1555 public void setDefaultShape(Shape shape, boolean notify) { 1556 Args.nullNotPermitted(shape, "shape"); 1557 this.defaultShape = shape; 1558 if (notify) { 1559 fireChangeEvent(); 1560 } 1561 } 1562 1563 /** 1564 * Returns the flag that controls whether or not the series shape list is 1565 * automatically populated when {@link #lookupSeriesShape(int)} is called. 1566 * 1567 * @return A boolean. 1568 * 1569 * @see #setAutoPopulateSeriesShape(boolean) 1570 */ 1571 public boolean getAutoPopulateSeriesShape() { 1572 return this.autoPopulateSeriesShape; 1573 } 1574 1575 /** 1576 * Sets the flag that controls whether or not the series shape list is 1577 * automatically populated when {@link #lookupSeriesShape(int)} is called. 1578 * 1579 * @param auto the new flag value. 1580 * 1581 * @see #getAutoPopulateSeriesShape() 1582 */ 1583 public void setAutoPopulateSeriesShape(boolean auto) { 1584 this.autoPopulateSeriesShape = auto; 1585 } 1586 1587 // ITEM LABEL VISIBILITY... 1588 1589 /** 1590 * Returns {@code true} if an item label is visible, and 1591 * {@code false} otherwise. 1592 * 1593 * @param row the row (or series) index (zero-based). 1594 * @param column the column (or category) index (zero-based). 1595 * 1596 * @return A boolean. 1597 */ 1598 public boolean isItemLabelVisible(int row, int column) { 1599 return isSeriesItemLabelsVisible(row); 1600 } 1601 1602 /** 1603 * Returns {@code true} if the item labels for a series are visible, 1604 * and {@code false} otherwise. 1605 * 1606 * @param series the series index (zero-based). 1607 * 1608 * @return A boolean. 1609 */ 1610 public boolean isSeriesItemLabelsVisible(int series) { 1611 Boolean b = this.seriesItemLabelsVisibleMap.get(series); 1612 if (b == null) { 1613 return this.defaultItemLabelsVisible; 1614 } 1615 return b; 1616 } 1617 1618 /** 1619 * Sets a flag that controls the visibility of the item labels for a series, 1620 * and sends a {@link RendererChangeEvent} to all registered listeners. 1621 * 1622 * @param series the series index (zero-based). 1623 * @param visible the flag. 1624 */ 1625 public void setSeriesItemLabelsVisible(int series, boolean visible) { 1626 setSeriesItemLabelsVisible(series, Boolean.valueOf(visible)); 1627 } 1628 1629 /** 1630 * Sets the visibility of the item labels for a series and sends a 1631 * {@link RendererChangeEvent} to all registered listeners. 1632 * 1633 * @param series the series index (zero-based). 1634 * @param visible the flag ({@code null} permitted). 1635 */ 1636 public void setSeriesItemLabelsVisible(int series, Boolean visible) { 1637 setSeriesItemLabelsVisible(series, visible, true); 1638 } 1639 1640 /** 1641 * Sets the visibility of item labels for a series and, if requested, sends 1642 * a {@link RendererChangeEvent} to all registered listeners. 1643 * 1644 * @param series the series index (zero-based). 1645 * @param visible the visible flag. 1646 * @param notify a flag that controls whether or not listeners are 1647 * notified. 1648 */ 1649 public void setSeriesItemLabelsVisible(int series, Boolean visible, boolean notify) { 1650 this.seriesItemLabelsVisibleMap.put(series, visible); 1651 if (notify) { 1652 fireChangeEvent(); 1653 } 1654 } 1655 1656 /** 1657 * Returns the base setting for item label visibility. A {@code null} 1658 * result should be interpreted as equivalent to {@code Boolean.FALSE}. 1659 * 1660 * @return A flag (possibly {@code null}). 1661 * 1662 * @see #setDefaultItemLabelsVisible(boolean) 1663 */ 1664 public boolean getDefaultItemLabelsVisible() { 1665 return this.defaultItemLabelsVisible; 1666 } 1667 1668 /** 1669 * Sets the base flag that controls whether or not item labels are visible, 1670 * and sends a {@link RendererChangeEvent} to all registered listeners. 1671 * 1672 * @param visible the flag. 1673 * 1674 * @see #getDefaultItemLabelsVisible() 1675 */ 1676 public void setDefaultItemLabelsVisible(boolean visible) { 1677 setDefaultItemLabelsVisible(visible, true); 1678 } 1679 1680 /** 1681 * Sets the base visibility for item labels and, if requested, sends a 1682 * {@link RendererChangeEvent} to all registered listeners. 1683 * 1684 * @param visible the flag ({@code null} is permitted, and viewed 1685 * as equivalent to {@code Boolean.FALSE}). 1686 * @param notify a flag that controls whether or not listeners are 1687 * notified. 1688 * 1689 * @see #getDefaultItemLabelsVisible() 1690 */ 1691 public void setDefaultItemLabelsVisible(boolean visible, boolean notify) { 1692 this.defaultItemLabelsVisible = visible; 1693 if (notify) { 1694 fireChangeEvent(); 1695 } 1696 } 1697 1698 //// ITEM LABEL FONT ////////////////////////////////////////////////////// 1699 1700 /** 1701 * Returns the font for an item label. 1702 * 1703 * @param row the row (or series) index (zero-based). 1704 * @param column the column (or category) index (zero-based). 1705 * 1706 * @return The font (never {@code null}). 1707 */ 1708 public Font getItemLabelFont(int row, int column) { 1709 Font result = getSeriesItemLabelFont(row); 1710 if (result == null) { 1711 result = this.defaultItemLabelFont; 1712 } 1713 return result; 1714 } 1715 1716 /** 1717 * Returns the font for all the item labels in a series. 1718 * 1719 * @param series the series index (zero-based). 1720 * 1721 * @return The font (possibly {@code null}). 1722 * 1723 * @see #setSeriesItemLabelFont(int, Font) 1724 */ 1725 public Font getSeriesItemLabelFont(int series) { 1726 return this.itemLabelFontMap.get(series); 1727 } 1728 1729 /** 1730 * Sets the item label font for a series and sends a 1731 * {@link RendererChangeEvent} to all registered listeners. 1732 * 1733 * @param series the series index (zero-based). 1734 * @param font the font ({@code null} permitted). 1735 * 1736 * @see #getSeriesItemLabelFont(int) 1737 */ 1738 public void setSeriesItemLabelFont(int series, Font font) { 1739 setSeriesItemLabelFont(series, font, true); 1740 } 1741 1742 /** 1743 * Sets the item label font for a series and, if requested, sends a 1744 * {@link RendererChangeEvent} to all registered listeners. 1745 * 1746 * @param series the series index (zero based). 1747 * @param font the font ({@code null} permitted). 1748 * @param notify a flag that controls whether or not listeners are 1749 * notified. 1750 * 1751 * @see #getSeriesItemLabelFont(int) 1752 */ 1753 public void setSeriesItemLabelFont(int series, Font font, boolean notify) { 1754 this.itemLabelFontMap.put(series, font); 1755 if (notify) { 1756 fireChangeEvent(); 1757 } 1758 } 1759 1760 /** 1761 * Returns the default item label font (this is used when no other font 1762 * setting is available). 1763 * 1764 * @return The font (never {@code null}). 1765 * 1766 * @see #setDefaultItemLabelFont(Font) 1767 */ 1768 public Font getDefaultItemLabelFont() { 1769 return this.defaultItemLabelFont; 1770 } 1771 1772 /** 1773 * Sets the default item label font and sends a {@link RendererChangeEvent} 1774 * to all registered listeners. 1775 * 1776 * @param font the font ({@code null} not permitted). 1777 * 1778 * @see #getDefaultItemLabelFont() 1779 */ 1780 public void setDefaultItemLabelFont(Font font) { 1781 Args.nullNotPermitted(font, "font"); 1782 setDefaultItemLabelFont(font, true); 1783 } 1784 1785 /** 1786 * Sets the base item label font and, if requested, sends a 1787 * {@link RendererChangeEvent} to all registered listeners. 1788 * 1789 * @param font the font ({@code null} not permitted). 1790 * @param notify a flag that controls whether or not listeners are 1791 * notified. 1792 * 1793 * @see #getDefaultItemLabelFont() 1794 */ 1795 public void setDefaultItemLabelFont(Font font, boolean notify) { 1796 this.defaultItemLabelFont = font; 1797 if (notify) { 1798 fireChangeEvent(); 1799 } 1800 } 1801 1802 //// ITEM LABEL PAINT //////////////////////////////////////////////////// 1803 1804 /** 1805 * Returns the paint used to draw an item label. 1806 * 1807 * @param row the row index (zero based). 1808 * @param column the column index (zero based). 1809 * 1810 * @return The paint (never {@code null}). 1811 */ 1812 public Paint getItemLabelPaint(int row, int column) { 1813 Paint result = getSeriesItemLabelPaint(row); 1814 if (result == null) { 1815 result = this.defaultItemLabelPaint; 1816 } 1817 return result; 1818 } 1819 1820 /** 1821 * Returns the paint used to draw the item labels for a series. 1822 * 1823 * @param series the series index (zero based). 1824 * 1825 * @return The paint (possibly {@code null}). 1826 * 1827 * @see #setSeriesItemLabelPaint(int, Paint) 1828 */ 1829 public Paint getSeriesItemLabelPaint(int series) { 1830 return this.itemLabelPaints.get(series); 1831 } 1832 1833 /** 1834 * Sets the item label paint for a series and sends a 1835 * {@link RendererChangeEvent} to all registered listeners. 1836 * 1837 * @param series the series (zero based index). 1838 * @param paint the paint ({@code null} permitted). 1839 * 1840 * @see #getSeriesItemLabelPaint(int) 1841 */ 1842 public void setSeriesItemLabelPaint(int series, Paint paint) { 1843 setSeriesItemLabelPaint(series, paint, true); 1844 } 1845 1846 /** 1847 * Sets the item label paint for a series and, if requested, sends a 1848 * {@link RendererChangeEvent} to all registered listeners. 1849 * 1850 * @param series the series index (zero based). 1851 * @param paint the paint ({@code null} permitted). 1852 * @param notify a flag that controls whether or not listeners are 1853 * notified. 1854 * 1855 * @see #getSeriesItemLabelPaint(int) 1856 */ 1857 public void setSeriesItemLabelPaint(int series, Paint paint, boolean notify) { 1858 this.itemLabelPaints.put(series, paint); 1859 if (notify) { 1860 fireChangeEvent(); 1861 } 1862 } 1863 1864 /** 1865 * Returns the default item label paint. 1866 * 1867 * @return The paint (never {@code null}). 1868 * 1869 * @see #setDefaultItemLabelPaint(Paint) 1870 */ 1871 public Paint getDefaultItemLabelPaint() { 1872 return this.defaultItemLabelPaint; 1873 } 1874 1875 /** 1876 * Sets the default item label paint and sends a {@link RendererChangeEvent} 1877 * to all registered listeners. 1878 * 1879 * @param paint the paint ({@code null} not permitted). 1880 * 1881 * @see #getDefaultItemLabelPaint() 1882 */ 1883 public void setDefaultItemLabelPaint(Paint paint) { 1884 // defer argument checking... 1885 setDefaultItemLabelPaint(paint, true); 1886 } 1887 1888 /** 1889 * Sets the default item label paint and, if requested, sends a 1890 * {@link RendererChangeEvent} to all registered listeners.. 1891 * 1892 * @param paint the paint ({@code null} not permitted). 1893 * @param notify a flag that controls whether or not listeners are 1894 * notified. 1895 * 1896 * @see #getDefaultItemLabelPaint() 1897 */ 1898 public void setDefaultItemLabelPaint(Paint paint, boolean notify) { 1899 Args.nullNotPermitted(paint, "paint"); 1900 this.defaultItemLabelPaint = paint; 1901 if (notify) { 1902 fireChangeEvent(); 1903 } 1904 } 1905 1906 // POSITIVE ITEM LABEL POSITION... 1907 1908 /** 1909 * Returns the item label position for positive values. 1910 * 1911 * @param row the row (or series) index (zero-based). 1912 * @param column the column (or category) index (zero-based). 1913 * 1914 * @return The item label position (never {@code null}). 1915 * 1916 * @see #getNegativeItemLabelPosition(int, int) 1917 */ 1918 public ItemLabelPosition getPositiveItemLabelPosition(int row, int column) { 1919 return getSeriesPositiveItemLabelPosition(row); 1920 } 1921 1922 /** 1923 * Returns the item label position for all positive values in a series. 1924 * 1925 * @param series the series index (zero-based). 1926 * 1927 * @return The item label position (never {@code null}). 1928 * 1929 * @see #setSeriesPositiveItemLabelPosition(int, ItemLabelPosition) 1930 */ 1931 public ItemLabelPosition getSeriesPositiveItemLabelPosition(int series) { 1932 // otherwise look up the position table 1933 ItemLabelPosition position = this.positiveItemLabelPositionMap.get(series); 1934 if (position == null) { 1935 position = this.defaultPositiveItemLabelPosition; 1936 } 1937 return position; 1938 } 1939 1940 /** 1941 * Sets the item label position for all positive values in a series and 1942 * sends a {@link RendererChangeEvent} to all registered listeners. 1943 * 1944 * @param series the series index (zero-based). 1945 * @param position the position ({@code null} permitted). 1946 * 1947 * @see #getSeriesPositiveItemLabelPosition(int) 1948 */ 1949 public void setSeriesPositiveItemLabelPosition(int series, 1950 ItemLabelPosition position) { 1951 setSeriesPositiveItemLabelPosition(series, position, true); 1952 } 1953 1954 /** 1955 * Sets the item label position for all positive values in a series and (if 1956 * requested) sends a {@link RendererChangeEvent} to all registered 1957 * listeners. 1958 * 1959 * @param series the series index (zero-based). 1960 * @param position the position ({@code null} permitted). 1961 * @param notify notify registered listeners? 1962 * 1963 * @see #getSeriesPositiveItemLabelPosition(int) 1964 */ 1965 public void setSeriesPositiveItemLabelPosition(int series, 1966 ItemLabelPosition position, boolean notify) { 1967 this.positiveItemLabelPositionMap.put(series, position); 1968 if (notify) { 1969 fireChangeEvent(); 1970 } 1971 } 1972 1973 /** 1974 * Returns the default positive item label position. 1975 * 1976 * @return The position (never {@code null}). 1977 * 1978 * @see #setDefaultPositiveItemLabelPosition(ItemLabelPosition) 1979 */ 1980 public ItemLabelPosition getDefaultPositiveItemLabelPosition() { 1981 return this.defaultPositiveItemLabelPosition; 1982 } 1983 1984 /** 1985 * Sets the default positive item label position. 1986 * 1987 * @param position the position ({@code null} not permitted). 1988 * 1989 * @see #getDefaultPositiveItemLabelPosition() 1990 */ 1991 public void setDefaultPositiveItemLabelPosition( 1992 ItemLabelPosition position) { 1993 // defer argument checking... 1994 setDefaultPositiveItemLabelPosition(position, true); 1995 } 1996 1997 /** 1998 * Sets the default positive item label position and, if requested, sends a 1999 * {@link RendererChangeEvent} to all registered listeners. 2000 * 2001 * @param position the position ({@code null} not permitted). 2002 * @param notify notify registered listeners? 2003 * 2004 * @see #getDefaultPositiveItemLabelPosition() 2005 */ 2006 public void setDefaultPositiveItemLabelPosition(ItemLabelPosition position, 2007 boolean notify) { 2008 Args.nullNotPermitted(position, "position"); 2009 this.defaultPositiveItemLabelPosition = position; 2010 if (notify) { 2011 fireChangeEvent(); 2012 } 2013 } 2014 2015 // NEGATIVE ITEM LABEL POSITION... 2016 2017 /** 2018 * Returns the item label position for negative values. This method can be 2019 * overridden to provide customisation of the item label position for 2020 * individual data items. 2021 * 2022 * @param row the row (or series) index (zero-based). 2023 * @param column the column (or category) index (zero-based). 2024 * 2025 * @return The item label position (never {@code null}). 2026 * 2027 * @see #getPositiveItemLabelPosition(int, int) 2028 */ 2029 public ItemLabelPosition getNegativeItemLabelPosition(int row, int column) { 2030 return getSeriesNegativeItemLabelPosition(row); 2031 } 2032 2033 /** 2034 * Returns the item label position for all negative values in a series. 2035 * 2036 * @param series the series index (zero-based). 2037 * 2038 * @return The item label position (never {@code null}). 2039 * 2040 * @see #setSeriesNegativeItemLabelPosition(int, ItemLabelPosition) 2041 */ 2042 public ItemLabelPosition getSeriesNegativeItemLabelPosition(int series) { 2043 // otherwise look up the position list 2044 ItemLabelPosition position 2045 = this.negativeItemLabelPositionMap.get(series); 2046 if (position == null) { 2047 position = this.defaultNegativeItemLabelPosition; 2048 } 2049 return position; 2050 } 2051 2052 /** 2053 * Sets the item label position for negative values in a series and sends a 2054 * {@link RendererChangeEvent} to all registered listeners. 2055 * 2056 * @param series the series index (zero-based). 2057 * @param position the position ({@code null} permitted). 2058 * 2059 * @see #getSeriesNegativeItemLabelPosition(int) 2060 */ 2061 public void setSeriesNegativeItemLabelPosition(int series, 2062 ItemLabelPosition position) { 2063 setSeriesNegativeItemLabelPosition(series, position, true); 2064 } 2065 2066 /** 2067 * Sets the item label position for negative values in a series and (if 2068 * requested) sends a {@link RendererChangeEvent} to all registered 2069 * listeners. 2070 * 2071 * @param series the series index (zero-based). 2072 * @param position the position ({@code null} permitted). 2073 * @param notify notify registered listeners? 2074 * 2075 * @see #getSeriesNegativeItemLabelPosition(int) 2076 */ 2077 public void setSeriesNegativeItemLabelPosition(int series, 2078 ItemLabelPosition position, boolean notify) { 2079 this.negativeItemLabelPositionMap.put(series, position); 2080 if (notify) { 2081 fireChangeEvent(); 2082 } 2083 } 2084 2085 /** 2086 * Returns the base item label position for negative values. 2087 * 2088 * @return The position (never {@code null}). 2089 * 2090 * @see #setDefaultNegativeItemLabelPosition(ItemLabelPosition) 2091 */ 2092 public ItemLabelPosition getDefaultNegativeItemLabelPosition() { 2093 return this.defaultNegativeItemLabelPosition; 2094 } 2095 2096 /** 2097 * Sets the default item label position for negative values and sends a 2098 * {@link RendererChangeEvent} to all registered listeners. 2099 * 2100 * @param position the position ({@code null} not permitted). 2101 * 2102 * @see #getDefaultNegativeItemLabelPosition() 2103 */ 2104 public void setDefaultNegativeItemLabelPosition( 2105 ItemLabelPosition position) { 2106 setDefaultNegativeItemLabelPosition(position, true); 2107 } 2108 2109 /** 2110 * Sets the default negative item label position and, if requested, sends a 2111 * {@link RendererChangeEvent} to all registered listeners. 2112 * 2113 * @param position the position ({@code null} not permitted). 2114 * @param notify notify registered listeners? 2115 * 2116 * @see #getDefaultNegativeItemLabelPosition() 2117 */ 2118 public void setDefaultNegativeItemLabelPosition(ItemLabelPosition position, 2119 boolean notify) { 2120 Args.nullNotPermitted(position, "position"); 2121 this.defaultNegativeItemLabelPosition = position; 2122 if (notify) { 2123 fireChangeEvent(); 2124 } 2125 } 2126 2127 /** 2128 * Returns the item label anchor offset. 2129 * 2130 * @return The offset. 2131 * 2132 * @see #setItemLabelAnchorOffset(double) 2133 */ 2134 public double getItemLabelAnchorOffset() { 2135 return this.itemLabelAnchorOffset; 2136 } 2137 2138 /** 2139 * Sets the item label anchor offset. 2140 * 2141 * @param offset the offset. 2142 * 2143 * @see #getItemLabelAnchorOffset() 2144 */ 2145 public void setItemLabelAnchorOffset(double offset) { 2146 this.itemLabelAnchorOffset = offset; 2147 fireChangeEvent(); 2148 } 2149 2150 /** 2151 * Returns a boolean that indicates whether or not the specified item 2152 * should have a chart entity created for it. 2153 * 2154 * @param series the series index. 2155 * @param item the item index. 2156 * 2157 * @return A boolean. 2158 */ 2159 public boolean getItemCreateEntity(int series, int item) { 2160 Boolean b = getSeriesCreateEntities(series); 2161 if (b != null) { 2162 return b; 2163 } 2164 // otherwise... 2165 return this.defaultCreateEntities; 2166 } 2167 2168 /** 2169 * Returns the flag that controls whether entities are created for a 2170 * series. 2171 * 2172 * @param series the series index (zero-based). 2173 * 2174 * @return The flag (possibly {@code null}). 2175 * 2176 * @see #setSeriesCreateEntities(int, Boolean) 2177 */ 2178 public Boolean getSeriesCreateEntities(int series) { 2179 return this.seriesCreateEntitiesMap.get(series); 2180 } 2181 2182 /** 2183 * Sets the flag that controls whether entities are created for a series, 2184 * and sends a {@link RendererChangeEvent} to all registered listeners. 2185 * 2186 * @param series the series index (zero-based). 2187 * @param create the flag ({@code null} permitted). 2188 * 2189 * @see #getSeriesCreateEntities(int) 2190 */ 2191 public void setSeriesCreateEntities(int series, Boolean create) { 2192 setSeriesCreateEntities(series, create, true); 2193 } 2194 2195 /** 2196 * Sets the flag that controls whether entities are created for a series 2197 * and, if requested, sends a {@link RendererChangeEvent} to all registered 2198 * listeners. 2199 * 2200 * @param series the series index. 2201 * @param create the flag ({@code null} permitted). 2202 * @param notify notify listeners? 2203 * 2204 * @see #getSeriesCreateEntities(int) 2205 */ 2206 public void setSeriesCreateEntities(int series, Boolean create, 2207 boolean notify) { 2208 this.seriesCreateEntitiesMap.put(series, create); 2209 if (notify) { 2210 fireChangeEvent(); 2211 } 2212 } 2213 2214 /** 2215 * Returns the default flag for creating entities. 2216 * 2217 * @return The default flag for creating entities. 2218 * 2219 * @see #setDefaultCreateEntities(boolean) 2220 */ 2221 public boolean getDefaultCreateEntities() { 2222 return this.defaultCreateEntities; 2223 } 2224 2225 /** 2226 * Sets the default flag that controls whether entities are created 2227 * for a series, and sends a {@link RendererChangeEvent} 2228 * to all registered listeners. 2229 * 2230 * @param create the flag. 2231 * 2232 * @see #getDefaultCreateEntities() 2233 */ 2234 public void setDefaultCreateEntities(boolean create) { 2235 // defer argument checking... 2236 setDefaultCreateEntities(create, true); 2237 } 2238 2239 /** 2240 * Sets the default flag that controls whether entities are created and, 2241 * if requested, sends a {@link RendererChangeEvent} to all registered 2242 * listeners. 2243 * 2244 * @param create the visibility. 2245 * @param notify notify listeners? 2246 * 2247 * @see #getDefaultCreateEntities() 2248 */ 2249 public void setDefaultCreateEntities(boolean create, boolean notify) { 2250 this.defaultCreateEntities = create; 2251 if (notify) { 2252 fireChangeEvent(); 2253 } 2254 } 2255 2256 /** 2257 * Returns the radius of the circle used for the default entity area 2258 * when no area is specified. 2259 * 2260 * @return A radius. 2261 * 2262 * @see #setDefaultEntityRadius(int) 2263 */ 2264 public int getDefaultEntityRadius() { 2265 return this.defaultEntityRadius; 2266 } 2267 2268 /** 2269 * Sets the radius of the circle used for the default entity area 2270 * when no area is specified. 2271 * 2272 * @param radius the radius. 2273 * 2274 * @see #getDefaultEntityRadius() 2275 */ 2276 public void setDefaultEntityRadius(int radius) { 2277 this.defaultEntityRadius = radius; 2278 } 2279 2280 /** 2281 * Performs a lookup for the legend shape. 2282 * 2283 * @param series the series index. 2284 * 2285 * @return The shape (possibly {@code null}). 2286 */ 2287 public Shape lookupLegendShape(int series) { 2288 Shape result = getLegendShape(series); 2289 if (result == null) { 2290 result = this.defaultLegendShape; 2291 } 2292 if (result == null) { 2293 result = lookupSeriesShape(series); 2294 } 2295 return result; 2296 } 2297 2298 /** 2299 * Returns the legend shape defined for the specified series (possibly 2300 * {@code null}). 2301 * 2302 * @param series the series index. 2303 * 2304 * @return The shape (possibly {@code null}). 2305 * 2306 * @see #lookupLegendShape(int) 2307 */ 2308 public Shape getLegendShape(int series) { 2309 return this.seriesLegendShapes.get(series); 2310 } 2311 2312 /** 2313 * Sets the shape used for the legend item for the specified series, and 2314 * sends a {@link RendererChangeEvent} to all registered listeners. 2315 * 2316 * @param series the series index. 2317 * @param shape the shape ({@code null} permitted). 2318 */ 2319 public void setLegendShape(int series, Shape shape) { 2320 this.seriesLegendShapes.put(series, shape); 2321 fireChangeEvent(); 2322 } 2323 2324 /** 2325 * Returns the default legend shape, which may be {@code null}. 2326 * 2327 * @return The default legend shape. 2328 */ 2329 public Shape getDefaultLegendShape() { 2330 return this.defaultLegendShape; 2331 } 2332 2333 /** 2334 * Sets the default legend shape and sends a 2335 * {@link RendererChangeEvent} to all registered listeners. 2336 * 2337 * @param shape the shape ({@code null} permitted). 2338 */ 2339 public void setDefaultLegendShape(Shape shape) { 2340 this.defaultLegendShape = shape; 2341 fireChangeEvent(); 2342 } 2343 2344 /** 2345 * Returns the flag that controls whether or not the legend shape is 2346 * treated as a line when creating legend items. 2347 * 2348 * @return A boolean. 2349 */ 2350 protected boolean getTreatLegendShapeAsLine() { 2351 return this.treatLegendShapeAsLine; 2352 } 2353 2354 /** 2355 * Sets the flag that controls whether or not the legend shape is 2356 * treated as a line when creating legend items. 2357 * 2358 * @param treatAsLine the new flag value. 2359 */ 2360 protected void setTreatLegendShapeAsLine(boolean treatAsLine) { 2361 if (this.treatLegendShapeAsLine != treatAsLine) { 2362 this.treatLegendShapeAsLine = treatAsLine; 2363 fireChangeEvent(); 2364 } 2365 } 2366 2367 /** 2368 * Performs a lookup for the legend text font. 2369 * 2370 * @param series the series index. 2371 * 2372 * @return The font (possibly {@code null}). 2373 */ 2374 public Font lookupLegendTextFont(int series) { 2375 Font result = getLegendTextFont(series); 2376 if (result == null) { 2377 result = this.defaultLegendTextFont; 2378 } 2379 return result; 2380 } 2381 2382 /** 2383 * Returns the legend text font defined for the specified series (possibly 2384 * {@code null}). 2385 * 2386 * @param series the series index. 2387 * 2388 * @return The font (possibly {@code null}). 2389 * 2390 * @see #lookupLegendTextFont(int) 2391 */ 2392 public Font getLegendTextFont(int series) { 2393 return this.legendTextFontMap.get(series); 2394 } 2395 2396 /** 2397 * Sets the font used for the legend text for the specified series, and 2398 * sends a {@link RendererChangeEvent} to all registered listeners. 2399 * 2400 * @param series the series index. 2401 * @param font the font ({@code null} permitted). 2402 */ 2403 public void setLegendTextFont(int series, Font font) { 2404 this.legendTextFontMap.put(series, font); 2405 fireChangeEvent(); 2406 } 2407 2408 /** 2409 * Returns the default legend text font, which may be {@code null}. 2410 * 2411 * @return The default legend text font. 2412 */ 2413 public Font getDefaultLegendTextFont() { 2414 return this.defaultLegendTextFont; 2415 } 2416 2417 /** 2418 * Sets the default legend text font and sends a 2419 * {@link RendererChangeEvent} to all registered listeners. 2420 * 2421 * @param font the font ({@code null} permitted). 2422 */ 2423 public void setDefaultLegendTextFont(Font font) { 2424 Args.nullNotPermitted(font, "font"); 2425 this.defaultLegendTextFont = font; 2426 fireChangeEvent(); 2427 } 2428 2429 /** 2430 * Performs a lookup for the legend text paint. 2431 * 2432 * @param series the series index. 2433 * 2434 * @return The paint (possibly {@code null}). 2435 */ 2436 public Paint lookupLegendTextPaint(int series) { 2437 Paint result = getLegendTextPaint(series); 2438 if (result == null) { 2439 result = this.defaultLegendTextPaint; 2440 } 2441 return result; 2442 } 2443 2444 /** 2445 * Returns the legend text paint defined for the specified series (possibly 2446 * {@code null}). 2447 * 2448 * @param series the series index. 2449 * 2450 * @return The paint (possibly {@code null}). 2451 * 2452 * @see #lookupLegendTextPaint(int) 2453 */ 2454 public Paint getLegendTextPaint(int series) { 2455 return this.legendTextPaints.get(series); 2456 } 2457 2458 /** 2459 * Sets the paint used for the legend text for the specified series, and 2460 * sends a {@link RendererChangeEvent} to all registered listeners. 2461 * 2462 * @param series the series index. 2463 * @param paint the paint ({@code null} permitted). 2464 */ 2465 public void setLegendTextPaint(int series, Paint paint) { 2466 this.legendTextPaints.put(series, paint); 2467 fireChangeEvent(); 2468 } 2469 2470 /** 2471 * Returns the default legend text paint, which may be {@code null}. 2472 * 2473 * @return The default legend text paint. 2474 */ 2475 public Paint getDefaultLegendTextPaint() { 2476 return this.defaultLegendTextPaint; 2477 } 2478 2479 /** 2480 * Sets the default legend text paint and sends a 2481 * {@link RendererChangeEvent} to all registered listeners. 2482 * 2483 * @param paint the paint ({@code null} permitted). 2484 */ 2485 public void setDefaultLegendTextPaint(Paint paint) { 2486 this.defaultLegendTextPaint = paint; 2487 fireChangeEvent(); 2488 } 2489 2490 /** 2491 * Returns the flag that controls whether or not the data bounds reported 2492 * by this renderer will exclude non-visible series. 2493 * 2494 * @return A boolean. 2495 */ 2496 public boolean getDataBoundsIncludesVisibleSeriesOnly() { 2497 return this.dataBoundsIncludesVisibleSeriesOnly; 2498 } 2499 2500 /** 2501 * Sets the flag that controls whether or not the data bounds reported 2502 * by this renderer will exclude non-visible series and sends a 2503 * {@link RendererChangeEvent} to all registered listeners. 2504 * 2505 * @param visibleOnly include only visible series. 2506 */ 2507 public void setDataBoundsIncludesVisibleSeriesOnly(boolean visibleOnly) { 2508 this.dataBoundsIncludesVisibleSeriesOnly = visibleOnly; 2509 notifyListeners(new RendererChangeEvent(this, true)); 2510 } 2511 2512 /** The adjacent offset. */ 2513 private static final double ADJ = Math.cos(Math.PI / 6.0); 2514 2515 /** The opposite offset. */ 2516 private static final double OPP = Math.sin(Math.PI / 6.0); 2517 2518 /** 2519 * Calculates the item label anchor point. 2520 * 2521 * @param anchor the anchor. 2522 * @param x the x coordinate. 2523 * @param y the y coordinate. 2524 * @param orientation the plot orientation. 2525 * 2526 * @return The anchor point (never {@code null}). 2527 */ 2528 protected Point2D calculateLabelAnchorPoint(ItemLabelAnchor anchor, 2529 double x, double y, PlotOrientation orientation) { 2530 Args.nullNotPermitted(anchor, "anchor"); 2531 Point2D result = null; 2532 switch (anchor) { 2533 case CENTER: 2534 result = new Point2D.Double(x, y); 2535 break; 2536 case INSIDE1: 2537 result = new Point2D.Double(x + OPP * this.itemLabelAnchorOffset, 2538 y - ADJ * this.itemLabelAnchorOffset); 2539 break; 2540 case INSIDE2: 2541 result = new Point2D.Double(x + ADJ * this.itemLabelAnchorOffset, 2542 y - OPP * this.itemLabelAnchorOffset); 2543 break; 2544 case INSIDE3: 2545 result = new Point2D.Double(x + this.itemLabelAnchorOffset, y); 2546 break; 2547 case INSIDE4: 2548 result = new Point2D.Double(x + ADJ * this.itemLabelAnchorOffset, 2549 y + OPP * this.itemLabelAnchorOffset); 2550 break; 2551 case INSIDE5: 2552 result = new Point2D.Double(x + OPP * this.itemLabelAnchorOffset, 2553 y + ADJ * this.itemLabelAnchorOffset); 2554 break; 2555 case INSIDE6: 2556 result = new Point2D.Double(x, y + this.itemLabelAnchorOffset); 2557 break; 2558 case INSIDE7: 2559 result = new Point2D.Double(x - OPP * this.itemLabelAnchorOffset, 2560 y + ADJ * this.itemLabelAnchorOffset); 2561 break; 2562 case INSIDE8: 2563 result = new Point2D.Double(x - ADJ * this.itemLabelAnchorOffset, 2564 y + OPP * this.itemLabelAnchorOffset); 2565 break; 2566 case INSIDE9: 2567 result = new Point2D.Double(x - this.itemLabelAnchorOffset, y); 2568 break; 2569 case INSIDE10: 2570 result = new Point2D.Double(x - ADJ * this.itemLabelAnchorOffset, 2571 y - OPP * this.itemLabelAnchorOffset); 2572 break; 2573 case INSIDE11: 2574 result = new Point2D.Double(x - OPP * this.itemLabelAnchorOffset, 2575 y - ADJ * this.itemLabelAnchorOffset); 2576 break; 2577 case INSIDE12: 2578 result = new Point2D.Double(x, y - this.itemLabelAnchorOffset); 2579 break; 2580 case OUTSIDE1: 2581 result = new Point2D.Double( 2582 x + 2.0 * OPP * this.itemLabelAnchorOffset, 2583 y - 2.0 * ADJ * this.itemLabelAnchorOffset); 2584 break; 2585 case OUTSIDE2: 2586 result = new Point2D.Double( 2587 x + 2.0 * ADJ * this.itemLabelAnchorOffset, 2588 y - 2.0 * OPP * this.itemLabelAnchorOffset); 2589 break; 2590 case OUTSIDE3: 2591 result = new Point2D.Double(x + 2.0 * this.itemLabelAnchorOffset, 2592 y); 2593 break; 2594 case OUTSIDE4: 2595 result = new Point2D.Double( 2596 x + 2.0 * ADJ * this.itemLabelAnchorOffset, 2597 y + 2.0 * OPP * this.itemLabelAnchorOffset); 2598 break; 2599 case OUTSIDE5: 2600 result = new Point2D.Double( 2601 x + 2.0 * OPP * this.itemLabelAnchorOffset, 2602 y + 2.0 * ADJ * this.itemLabelAnchorOffset); 2603 break; 2604 case OUTSIDE6: 2605 result = new Point2D.Double(x, 2606 y + 2.0 * this.itemLabelAnchorOffset); 2607 break; 2608 case OUTSIDE7: 2609 result = new Point2D.Double( 2610 x - 2.0 * OPP * this.itemLabelAnchorOffset, 2611 y + 2.0 * ADJ * this.itemLabelAnchorOffset); 2612 break; 2613 case OUTSIDE8: 2614 result = new Point2D.Double( 2615 x - 2.0 * ADJ * this.itemLabelAnchorOffset, 2616 y + 2.0 * OPP * this.itemLabelAnchorOffset); 2617 break; 2618 case OUTSIDE9: 2619 result = new Point2D.Double(x - 2.0 * this.itemLabelAnchorOffset, 2620 y); 2621 break; 2622 case OUTSIDE10: 2623 result = new Point2D.Double( 2624 x - 2.0 * ADJ * this.itemLabelAnchorOffset, 2625 y - 2.0 * OPP * this.itemLabelAnchorOffset); 2626 break; 2627 case OUTSIDE11: 2628 result = new Point2D.Double( 2629 x - 2.0 * OPP * this.itemLabelAnchorOffset, 2630 y - 2.0 * ADJ * this.itemLabelAnchorOffset); 2631 break; 2632 case OUTSIDE12: 2633 result = new Point2D.Double(x, 2634 y - 2.0 * this.itemLabelAnchorOffset); 2635 break; 2636 default: 2637 throw new IllegalStateException("Unexpected anchor value."); 2638 } 2639 return result; 2640 } 2641 2642 /** 2643 * Registers an object to receive notification of changes to the renderer. 2644 * 2645 * @param listener the listener ({@code null} not permitted). 2646 * 2647 * @see #removeChangeListener(RendererChangeListener) 2648 */ 2649 public void addChangeListener(RendererChangeListener listener) { 2650 Args.nullNotPermitted(listener, "listener"); 2651 this.listenerList.add(RendererChangeListener.class, listener); 2652 } 2653 2654 /** 2655 * Deregisters an object so that it no longer receives 2656 * notification of changes to the renderer. 2657 * 2658 * @param listener the object ({@code null} not permitted). 2659 * 2660 * @see #addChangeListener(RendererChangeListener) 2661 */ 2662 public void removeChangeListener(RendererChangeListener listener) { 2663 Args.nullNotPermitted(listener, "listener"); 2664 this.listenerList.remove(RendererChangeListener.class, listener); 2665 } 2666 2667 /** 2668 * Returns {@code true} if the specified object is registered with 2669 * the dataset as a listener. Most applications won't need to call this 2670 * method, it exists mainly for use by unit testing code. 2671 * 2672 * @param listener the listener. 2673 * 2674 * @return A boolean. 2675 */ 2676 public boolean hasListener(EventListener listener) { 2677 List<Object> list = Arrays.asList(this.listenerList.getListenerList()); 2678 return list.contains(listener); 2679 } 2680 2681 /** 2682 * Sends a {@link RendererChangeEvent} to all registered listeners. 2683 */ 2684 protected void fireChangeEvent() { 2685 notifyListeners(new RendererChangeEvent(this)); 2686 } 2687 2688 /** 2689 * Notifies all registered listeners that the renderer has been modified. 2690 * 2691 * @param event information about the change event. 2692 */ 2693 public void notifyListeners(RendererChangeEvent event) { 2694 Object[] ls = this.listenerList.getListenerList(); 2695 for (int i = ls.length - 2; i >= 0; i -= 2) { 2696 if (ls[i] == RendererChangeListener.class) { 2697 ((RendererChangeListener) ls[i + 1]).rendererChanged(event); 2698 } 2699 } 2700 } 2701 2702 /** 2703 * Tests this renderer for equality with another object. 2704 * 2705 * @param obj the object ({@code null} permitted). 2706 * 2707 * @return {@code true} or {@code false}. 2708 */ 2709 @Override 2710 public boolean equals(Object obj) { 2711 if (obj == this) { 2712 return true; 2713 } 2714 if (!(obj instanceof AbstractRenderer)) { 2715 return false; 2716 } 2717 AbstractRenderer that = (AbstractRenderer) obj; 2718 if (this.dataBoundsIncludesVisibleSeriesOnly 2719 != that.dataBoundsIncludesVisibleSeriesOnly) { 2720 return false; 2721 } 2722 if (this.treatLegendShapeAsLine != that.treatLegendShapeAsLine) { 2723 return false; 2724 } 2725 if (this.defaultEntityRadius != that.defaultEntityRadius) { 2726 return false; 2727 } 2728 if (!this.seriesVisibleMap.equals(that.seriesVisibleMap)) { 2729 return false; 2730 } 2731 if (this.defaultSeriesVisible != that.defaultSeriesVisible) { 2732 return false; 2733 } 2734 if (!this.seriesVisibleInLegendMap.equals(that.seriesVisibleInLegendMap)) { 2735 return false; 2736 } 2737 if (this.defaultSeriesVisibleInLegend 2738 != that.defaultSeriesVisibleInLegend) { 2739 return false; 2740 } 2741 if (!PaintUtils.equal(this.seriesPaintMap, that.seriesPaintMap)) { 2742 return false; 2743 } 2744 if (this.autoPopulateSeriesPaint != that.autoPopulateSeriesPaint) { 2745 return false; 2746 } 2747 if (!PaintUtils.equal(this.defaultPaint, that.defaultPaint)) { 2748 return false; 2749 } 2750 if (!PaintUtils.equal(this.seriesFillPaintMap, that.seriesFillPaintMap)) { 2751 return false; 2752 } 2753 if (this.autoPopulateSeriesFillPaint != that.autoPopulateSeriesFillPaint) { 2754 return false; 2755 } 2756 if (!PaintUtils.equal(this.defaultFillPaint, that.defaultFillPaint)) { 2757 return false; 2758 } 2759 if (!PaintUtils.equal(this.seriesOutlinePaintMap, that.seriesOutlinePaintMap)) { 2760 return false; 2761 } 2762 if (this.autoPopulateSeriesOutlinePaint != that.autoPopulateSeriesOutlinePaint) { 2763 return false; 2764 } 2765 if (!PaintUtils.equal(this.defaultOutlinePaint, that.defaultOutlinePaint)) { 2766 return false; 2767 } 2768 if (!Objects.equals(this.seriesStrokeMap, that.seriesStrokeMap)) { 2769 return false; 2770 } 2771 if (this.autoPopulateSeriesStroke != that.autoPopulateSeriesStroke) { 2772 return false; 2773 } 2774 if (!Objects.equals(this.defaultStroke, that.defaultStroke)) { 2775 return false; 2776 } 2777 if (!Objects.equals(this.seriesOutlineStrokeMap, that.seriesOutlineStrokeMap)) { 2778 return false; 2779 } 2780 if (this.autoPopulateSeriesOutlineStroke != that.autoPopulateSeriesOutlineStroke) { 2781 return false; 2782 } 2783 if (!Objects.equals(this.defaultOutlineStroke, that.defaultOutlineStroke)) { 2784 return false; 2785 } 2786 if (!ShapeUtils.equal(this.seriesShapeMap, that.seriesShapeMap)) { 2787 return false; 2788 } 2789 if (this.autoPopulateSeriesShape != that.autoPopulateSeriesShape) { 2790 return false; 2791 } 2792 if (!ShapeUtils.equal(this.defaultShape, that.defaultShape)) { 2793 return false; 2794 } 2795 if (!Objects.equals(this.seriesItemLabelsVisibleMap, that.seriesItemLabelsVisibleMap)) { 2796 return false; 2797 } 2798 if (!Objects.equals(this.defaultItemLabelsVisible, that.defaultItemLabelsVisible)) { 2799 return false; 2800 } 2801 if (!Objects.equals(this.itemLabelFontMap, that.itemLabelFontMap)) { 2802 return false; 2803 } 2804 if (!Objects.equals(this.defaultItemLabelFont, that.defaultItemLabelFont)) { 2805 return false; 2806 } 2807 2808 if (!PaintUtils.equal(this.itemLabelPaints, that.itemLabelPaints)) { 2809 return false; 2810 } 2811 if (!PaintUtils.equal(this.defaultItemLabelPaint, 2812 that.defaultItemLabelPaint)) { 2813 return false; 2814 } 2815 2816 if (!Objects.equals(this.positiveItemLabelPositionMap, that.positiveItemLabelPositionMap)) { 2817 return false; 2818 } 2819 if (!Objects.equals(this.defaultPositiveItemLabelPosition, that.defaultPositiveItemLabelPosition)) { 2820 return false; 2821 } 2822 2823 if (!Objects.equals(this.negativeItemLabelPositionMap, that.negativeItemLabelPositionMap)) { 2824 return false; 2825 } 2826 if (!Objects.equals(this.defaultNegativeItemLabelPosition, that.defaultNegativeItemLabelPosition)) { 2827 return false; 2828 } 2829 if (this.itemLabelAnchorOffset != that.itemLabelAnchorOffset) { 2830 return false; 2831 } 2832 if (!Objects.equals(this.seriesCreateEntitiesMap, that.seriesCreateEntitiesMap)) { 2833 return false; 2834 } 2835 if (this.defaultCreateEntities != that.defaultCreateEntities) { 2836 return false; 2837 } 2838 if (!ShapeUtils.equal(this.seriesLegendShapes, that.seriesLegendShapes)) { 2839 return false; 2840 } 2841 if (!ShapeUtils.equal(this.defaultLegendShape, that.defaultLegendShape)) { 2842 return false; 2843 } 2844 if (!Objects.equals(this.legendTextFontMap, that.legendTextFontMap)) { 2845 return false; 2846 } 2847 if (!Objects.equals(this.defaultLegendTextFont, that.defaultLegendTextFont)) { 2848 return false; 2849 } 2850 if (!PaintUtils.equal(this.legendTextPaints, that.legendTextPaints)) { 2851 return false; 2852 } 2853 if (!PaintUtils.equal(this.defaultLegendTextPaint, 2854 that.defaultLegendTextPaint)) { 2855 return false; 2856 } 2857 return true; 2858 } 2859 2860 /** 2861 * Returns a hashcode for the renderer. 2862 * 2863 * @return The hashcode. 2864 */ 2865 @Override 2866 public int hashCode() { 2867 int result = 193; 2868 result = HashUtils.hashCode(result, this.seriesVisibleMap); 2869 result = HashUtils.hashCode(result, this.defaultSeriesVisible); 2870 result = HashUtils.hashCode(result, this.seriesVisibleInLegendMap); 2871 result = HashUtils.hashCode(result, this.defaultSeriesVisibleInLegend); 2872 result = HashUtils.hashCode(result, this.seriesPaintMap); 2873 result = HashUtils.hashCode(result, this.defaultPaint); 2874 result = HashUtils.hashCode(result, this.seriesFillPaintMap); 2875 result = HashUtils.hashCode(result, this.defaultFillPaint); 2876 result = HashUtils.hashCode(result, this.seriesOutlinePaintMap); 2877 result = HashUtils.hashCode(result, this.defaultOutlinePaint); 2878 result = HashUtils.hashCode(result, this.seriesStrokeMap); 2879 result = HashUtils.hashCode(result, this.defaultStroke); 2880 result = HashUtils.hashCode(result, this.seriesOutlineStrokeMap); 2881 result = HashUtils.hashCode(result, this.defaultOutlineStroke); 2882 // shapeList 2883 // baseShape 2884 result = HashUtils.hashCode(result, this.seriesItemLabelsVisibleMap); 2885 result = HashUtils.hashCode(result, this.defaultItemLabelsVisible); 2886 // itemLabelFontList 2887 // baseItemLabelFont 2888 // itemLabelPaintList 2889 // baseItemLabelPaint 2890 // positiveItemLabelPositionList 2891 // basePositiveItemLabelPosition 2892 // negativeItemLabelPositionList 2893 // baseNegativeItemLabelPosition 2894 // itemLabelAnchorOffset 2895 // createEntityList 2896 // baseCreateEntities 2897 return result; 2898 } 2899 2900 /** 2901 * Returns an independent copy of the renderer. 2902 * 2903 * @return A clone. 2904 * 2905 * @throws CloneNotSupportedException if some component of the renderer 2906 * does not support cloning. 2907 */ 2908 @Override 2909 protected Object clone() throws CloneNotSupportedException { 2910 AbstractRenderer clone = (AbstractRenderer) super.clone(); 2911 2912 if (this.seriesVisibleMap != null) { 2913 clone.seriesVisibleMap = new HashMap<>(this.seriesVisibleMap); 2914 } 2915 2916 if (this.seriesVisibleInLegendMap != null) { 2917 clone.seriesVisibleInLegendMap = new HashMap<>(this.seriesVisibleInLegendMap); 2918 } 2919 2920 // 'paint' : immutable, no need to clone reference 2921 if (this.seriesPaintMap != null) { 2922 clone.seriesPaintMap = new HashMap<>(this.seriesPaintMap); 2923 } 2924 // 'basePaint' : immutable, no need to clone reference 2925 2926 if (this.seriesFillPaintMap != null) { 2927 clone.seriesFillPaintMap = new HashMap<>(this.seriesFillPaintMap); 2928 } 2929 // 'outlinePaint' : immutable, no need to clone reference 2930 if (this.seriesOutlinePaintMap != null) { 2931 clone.seriesOutlinePaintMap = new HashMap<>(this.seriesOutlinePaintMap); 2932 } 2933 // 'baseOutlinePaint' : immutable, no need to clone reference 2934 2935 // 'stroke' : immutable, no need to clone reference 2936 if (this.seriesStrokeMap != null) { 2937 clone.seriesStrokeMap = CloneUtils.cloneMapValues(this.seriesStrokeMap); 2938 } 2939 // 'baseStroke' : immutable, no need to clone reference 2940 2941 // 'outlineStroke' : immutable, no need to clone reference 2942 if (this.seriesOutlineStrokeMap != null) { 2943 clone.seriesOutlineStrokeMap = CloneUtils.cloneMapValues(this.seriesOutlineStrokeMap); 2944 } 2945 // 'baseOutlineStroke' : immutable, no need to clone reference 2946 2947 if (this.seriesShapeMap != null) { 2948 clone.seriesShapeMap = ShapeUtils.cloneMap(this.seriesShapeMap); 2949 } 2950 clone.defaultShape = CloneUtils.clone(this.defaultShape); 2951 2952 2953 // 'seriesItemLabelsVisibleMap' : immutable, no need to clone reference 2954 if (this.seriesItemLabelsVisibleMap != null) { 2955 clone.seriesItemLabelsVisibleMap = new HashMap<>(this.seriesItemLabelsVisibleMap); 2956 } 2957 // 'basePaint' : immutable, no need to clone reference 2958 2959 // 'itemLabelFont' : immutable, no need to clone reference 2960 if (this.itemLabelFontMap != null) { 2961 clone.itemLabelFontMap = new HashMap<>(this.itemLabelFontMap); 2962 } 2963 // 'baseItemLabelFont' : immutable, no need to clone reference 2964 2965 // 'itemLabelPaint' : immutable, no need to clone reference 2966 if (this.itemLabelPaints != null) { 2967 clone.itemLabelPaints = new HashMap<>(this.itemLabelPaints); 2968 } 2969 // 'baseItemLabelPaint' : immutable, no need to clone reference 2970 2971 if (this.positiveItemLabelPositionMap != null) { 2972 clone.positiveItemLabelPositionMap 2973 = new HashMap<>(this.positiveItemLabelPositionMap); 2974 } 2975 2976 if (this.negativeItemLabelPositionMap != null) { 2977 clone.negativeItemLabelPositionMap 2978 = new HashMap<>(this.negativeItemLabelPositionMap); 2979 } 2980 2981 if (this.seriesCreateEntitiesMap != null) { 2982 clone.seriesCreateEntitiesMap = new HashMap<>(this.seriesCreateEntitiesMap); 2983 } 2984 2985 if (this.seriesLegendShapes != null) { 2986 clone.seriesLegendShapes = ShapeUtils.cloneMap(this.seriesLegendShapes); 2987 } 2988 if (this.legendTextFontMap != null) { 2989 // Font objects are immutable so just shallow copy the map 2990 clone.legendTextFontMap = new HashMap<>(this.legendTextFontMap); 2991 } 2992 if (this.legendTextPaints != null) { 2993 clone.legendTextPaints = new HashMap<>(this.legendTextPaints); 2994 } 2995 clone.listenerList = new EventListenerList(); 2996 clone.event = null; 2997 return clone; 2998 } 2999 3000 /** 3001 * Provides serialization support. 3002 * 3003 * @param stream the output stream. 3004 * 3005 * @throws IOException if there is an I/O error. 3006 */ 3007 private void writeObject(ObjectOutputStream stream) throws IOException { 3008 stream.defaultWriteObject(); 3009 SerialUtils.writeMapOfPaint(this.seriesPaintMap, stream); 3010 SerialUtils.writePaint(this.defaultPaint, stream); 3011 SerialUtils.writeMapOfPaint(this.seriesFillPaintMap, stream); 3012 SerialUtils.writePaint(this.defaultFillPaint, stream); 3013 SerialUtils.writeMapOfPaint(this.seriesOutlinePaintMap, stream); 3014 SerialUtils.writePaint(this.defaultOutlinePaint, stream); 3015 SerialUtils.writeMapOfStroke(this.seriesStrokeMap, stream); 3016 SerialUtils.writeStroke(this.defaultStroke, stream); 3017 SerialUtils.writeMapOfStroke(this.seriesOutlineStrokeMap, stream); 3018 SerialUtils.writeStroke(this.defaultOutlineStroke, stream); 3019 SerialUtils.writeShape(this.defaultShape, stream); 3020 SerialUtils.writeMapOfPaint(this.itemLabelPaints, stream); 3021 SerialUtils.writePaint(this.defaultItemLabelPaint, stream); 3022 SerialUtils.writeShape(this.defaultLegendShape, stream); 3023 SerialUtils.writeMapOfPaint(this.legendTextPaints, stream); 3024 SerialUtils.writePaint(this.defaultLegendTextPaint, stream); 3025 } 3026 3027 /** 3028 * Provides serialization support. 3029 * 3030 * @param stream the input stream. 3031 * 3032 * @throws IOException if there is an I/O error. 3033 * @throws ClassNotFoundException if there is a classpath problem. 3034 */ 3035 private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { 3036 stream.defaultReadObject(); 3037 this.seriesPaintMap = SerialUtils.readMapOfPaint(stream); 3038 this.defaultPaint = SerialUtils.readPaint(stream); 3039 this.seriesFillPaintMap = SerialUtils.readMapOfPaint(stream); 3040 this.defaultFillPaint = SerialUtils.readPaint(stream); 3041 this.seriesOutlinePaintMap = SerialUtils.readMapOfPaint(stream); 3042 this.defaultOutlinePaint = SerialUtils.readPaint(stream); 3043 this.seriesStrokeMap = SerialUtils.readMapOfStroke(stream); 3044 this.defaultStroke = SerialUtils.readStroke(stream); 3045 this.seriesOutlineStrokeMap = SerialUtils.readMapOfStroke(stream); 3046 this.defaultOutlineStroke = SerialUtils.readStroke(stream); 3047 this.defaultShape = SerialUtils.readShape(stream); 3048 this.itemLabelPaints = SerialUtils.readMapOfPaint(stream); 3049 this.defaultItemLabelPaint = SerialUtils.readPaint(stream); 3050 this.defaultLegendShape = SerialUtils.readShape(stream); 3051 this.legendTextPaints = SerialUtils.readMapOfPaint(stream); 3052 this.defaultLegendTextPaint = SerialUtils.readPaint(stream); 3053 3054 // listeners are not restored automatically, but storage must be 3055 // provided... 3056 this.listenerList = new EventListenerList(); 3057 } 3058 3059}