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