| 1 63 64 package org.jfree.chart.plot; 65 66 import java.awt.AlphaComposite ; 67 import java.awt.BasicStroke ; 68 import java.awt.Color ; 69 import java.awt.Composite ; 70 import java.awt.Font ; 71 import java.awt.Graphics2D ; 72 import java.awt.Paint ; 73 import java.awt.Polygon ; 74 import java.awt.Rectangle ; 75 import java.awt.Shape ; 76 import java.awt.Stroke ; 77 import java.awt.font.FontRenderContext ; 78 import java.awt.font.LineMetrics ; 79 import java.awt.geom.Arc2D ; 80 import java.awt.geom.Ellipse2D ; 81 import java.awt.geom.Line2D ; 82 import java.awt.geom.Point2D ; 83 import java.awt.geom.Rectangle2D ; 84 import java.io.IOException ; 85 import java.io.ObjectInputStream ; 86 import java.io.ObjectOutputStream ; 87 import java.io.Serializable ; 88 import java.util.Iterator ; 89 import java.util.List ; 90 91 import org.jfree.chart.LegendItem; 92 import org.jfree.chart.LegendItemCollection; 93 import org.jfree.chart.entity.CategoryItemEntity; 94 import org.jfree.chart.entity.EntityCollection; 95 import org.jfree.chart.event.PlotChangeEvent; 96 import org.jfree.chart.labels.CategoryItemLabelGenerator; 97 import org.jfree.chart.labels.CategoryToolTipGenerator; 98 import org.jfree.chart.labels.StandardCategoryItemLabelGenerator; 99 import org.jfree.chart.urls.CategoryURLGenerator; 100 import org.jfree.data.category.CategoryDataset; 101 import org.jfree.data.general.DatasetChangeEvent; 102 import org.jfree.data.general.DatasetUtilities; 103 import org.jfree.io.SerialUtilities; 104 import org.jfree.ui.RectangleInsets; 105 import org.jfree.util.ObjectUtilities; 106 import org.jfree.util.PaintList; 107 import org.jfree.util.PaintUtilities; 108 import org.jfree.util.Rotation; 109 import org.jfree.util.ShapeUtilities; 110 import org.jfree.util.StrokeList; 111 import org.jfree.util.TableOrder; 112 113 118 public class SpiderWebPlot extends Plot implements Cloneable , Serializable { 119 120 121 private static final long serialVersionUID = -5376340422031599463L; 122 123 124 public static final double DEFAULT_HEAD = 0.01; 125 126 127 public static final double DEFAULT_AXIS_LABEL_GAP = 0.10; 128 129 130 public static final double DEFAULT_INTERIOR_GAP = 0.25; 131 132 133 public static final double MAX_INTERIOR_GAP = 0.40; 134 135 136 public static final double DEFAULT_START_ANGLE = 90.0; 137 138 139 public static final Font DEFAULT_LABEL_FONT = new Font ("SansSerif", 140 Font.PLAIN, 10); 141 142 143 public static final Paint DEFAULT_LABEL_PAINT = Color.black; 144 145 146 public static final Paint DEFAULT_LABEL_BACKGROUND_PAINT 147 = new Color (255, 255, 192); 148 149 150 public static final Paint DEFAULT_LABEL_OUTLINE_PAINT = Color.black; 151 152 153 public static final Stroke DEFAULT_LABEL_OUTLINE_STROKE 154 = new BasicStroke (0.5f); 155 156 157 public static final Paint DEFAULT_LABEL_SHADOW_PAINT = Color.lightGray; 158 159 163 public static final double DEFAULT_MAX_VALUE = -1.0; 164 165 166 protected double headPercent; 167 168 169 private double interiorGap; 170 171 172 private double axisLabelGap; 173 174 175 private CategoryDataset dataset; 176 177 178 private double maxValue; 179 180 186 private TableOrder dataExtractOrder; 187 188 189 private double startAngle; 190 191 192 private Rotation direction; 193 194 195 private transient Shape legendItemShape; 196 197 198 private transient Paint seriesPaint; 199 200 201 private PaintList seriesPaintList; 202 203 204 private transient Paint baseSeriesPaint; 205 206 207 private transient Paint seriesOutlinePaint; 208 209 210 private PaintList seriesOutlinePaintList; 211 212 213 private transient Paint baseSeriesOutlinePaint; 214 215 216 private transient Stroke seriesOutlineStroke; 217 218 219 private StrokeList seriesOutlineStrokeList; 220 221 222 private transient Stroke baseSeriesOutlineStroke; 223 224 225 private Font labelFont; 226 227 228 private transient Paint labelPaint; 229 230 231 private CategoryItemLabelGenerator labelGenerator; 232 233 234 private boolean webFilled = true; 235 236 237 private CategoryToolTipGenerator toolTipGenerator; 238 239 240 private CategoryURLGenerator urlGenerator; 241 242 245 public SpiderWebPlot() { 246 this(null); 247 } 248 249 255 public SpiderWebPlot(CategoryDataset dataset) { 256 this(dataset, TableOrder.BY_ROW); 257 } 258 259 266 public SpiderWebPlot(CategoryDataset dataset, TableOrder extract) { 267 super(); 268 if (extract == null) { 269 throw new IllegalArgumentException ("Null 'extract' argument."); 270 } 271 this.dataset = dataset; 272 if (dataset != null) { 273 dataset.addChangeListener(this); 274 } 275 276 this.dataExtractOrder = extract; 277 this.headPercent = DEFAULT_HEAD; 278 this.axisLabelGap = DEFAULT_AXIS_LABEL_GAP; 279 280 this.interiorGap = DEFAULT_INTERIOR_GAP; 281 this.startAngle = DEFAULT_START_ANGLE; 282 this.direction = Rotation.CLOCKWISE; 283 this.maxValue = DEFAULT_MAX_VALUE; 284 285 this.seriesPaint = null; 286 this.seriesPaintList = new PaintList(); 287 this.baseSeriesPaint = null; 288 289 this.seriesOutlinePaint = null; 290 this.seriesOutlinePaintList = new PaintList(); 291 this.baseSeriesOutlinePaint = DEFAULT_OUTLINE_PAINT; 292 293 this.seriesOutlineStroke = null; 294 this.seriesOutlineStrokeList = new StrokeList(); 295 this.baseSeriesOutlineStroke = DEFAULT_OUTLINE_STROKE; 296 297 this.labelFont = DEFAULT_LABEL_FONT; 298 this.labelPaint = DEFAULT_LABEL_PAINT; 299 this.labelGenerator = new StandardCategoryItemLabelGenerator(); 300 301 this.legendItemShape = DEFAULT_LEGEND_ITEM_CIRCLE; 302 } 303 304 309 public String getPlotType() { 310 return ("Spider Web Plot"); 312 } 313 314 319 public CategoryDataset getDataset() { 320 return this.dataset; 321 } 322 323 329 public void setDataset(CategoryDataset dataset) { 330 if (this.dataset != null) { 333 this.dataset.removeChangeListener(this); 334 } 335 336 this.dataset = dataset; 338 if (dataset != null) { 339 setDatasetGroup(dataset.getGroup()); 340 dataset.addChangeListener(this); 341 } 342 343 datasetChanged(new DatasetChangeEvent(this, dataset)); 345 } 346 347 352 public boolean isWebFilled() { 353 return this.webFilled; 354 } 355 356 362 public void setWebFilled(boolean flag) { 363 this.webFilled = flag; 364 notifyListeners(new PlotChangeEvent(this)); 365 } 366 367 374 public TableOrder getDataExtractOrder() { 375 return this.dataExtractOrder; 376 } 377 378 389 public void setDataExtractOrder(TableOrder order) { 390 if (order == null) { 391 throw new IllegalArgumentException ("Null 'order' argument"); 392 } 393 this.dataExtractOrder = order; 394 notifyListeners(new PlotChangeEvent(this)); 395 } 396 397 402 public double getHeadPercent() { 403 return this.headPercent; 404 } 405 406 412 public void setHeadPercent(double percent) { 413 this.headPercent = percent; 414 notifyListeners(new PlotChangeEvent(this)); 415 } 416 417 425 public double getStartAngle() { 426 return this.startAngle; 427 } 428 429 439 public void setStartAngle(double angle) { 440 this.startAngle = angle; 441 notifyListeners(new PlotChangeEvent(this)); 442 } 443 444 449 public double getMaxValue() { 450 return this.maxValue; 451 } 452 453 459 public void setMaxValue(double value) { 460 this.maxValue = value; 461 notifyListeners(new PlotChangeEvent(this)); 462 } 463 464 470 public Rotation getDirection() { 471 return this.direction; 472 } 473 474 480 public void setDirection(Rotation direction) { 481 if (direction == null) { 482 throw new IllegalArgumentException ("Null 'direction' argument."); 483 } 484 this.direction = direction; 485 notifyListeners(new PlotChangeEvent(this)); 486 } 487 488 494 public double getInteriorGap() { 495 return this.interiorGap; 496 } 497 498 505 public void setInteriorGap(double percent) { 506 if ((percent < 0.0) || (percent > MAX_INTERIOR_GAP)) { 507 throw new IllegalArgumentException ( 508 "Percentage outside valid range."); 509 } 510 if (this.interiorGap != percent) { 511 this.interiorGap = percent; 512 notifyListeners(new PlotChangeEvent(this)); 513 } 514 } 515 516 521 public double getAxisLabelGap() { 522 return this.axisLabelGap; 523 } 524 525 531 public void setAxisLabelGap(double gap) { 532 this.axisLabelGap = gap; 533 notifyListeners(new PlotChangeEvent(this)); 534 } 535 536 538 543 public Paint getSeriesPaint() { 544 return this.seriesPaint; 545 } 546 547 554 public void setSeriesPaint(Paint paint) { 555 this.seriesPaint = paint; 556 notifyListeners(new PlotChangeEvent(this)); 557 } 558 559 566 public Paint getSeriesPaint(int series) { 567 568 if (this.seriesPaint != null) { 570 return this.seriesPaint; 571 } 572 573 Paint result = this.seriesPaintList.getPaint(series); 575 if (result == null) { 576 DrawingSupplier supplier = getDrawingSupplier(); 577 if (supplier != null) { 578 Paint p = supplier.getNextPaint(); 579 this.seriesPaintList.setPaint(series, p); 580 result = p; 581 } 582 else { 583 result = this.baseSeriesPaint; 584 } 585 } 586 return result; 587 588 } 589 590 597 public void setSeriesPaint(int series, Paint paint) { 598 this.seriesPaintList.setPaint(series, paint); 599 notifyListeners(new PlotChangeEvent(this)); 600 } 601 602 608 public Paint getBaseSeriesPaint() { 609 return this.baseSeriesPaint; 610 } 611 612 617 public void setBaseSeriesPaint(Paint paint) { 618 if (paint == null) { 619 throw new IllegalArgumentException ("Null 'paint' argument."); 620 } 621 this.baseSeriesPaint = paint; 622 notifyListeners(new PlotChangeEvent(this)); 623 } 624 625 627 632 public Paint getSeriesOutlinePaint() { 633 return this.seriesOutlinePaint; 634 } 635 636 643 public void setSeriesOutlinePaint(Paint paint) { 644 this.seriesOutlinePaint = paint; 645 notifyListeners(new PlotChangeEvent(this)); 646 } 647 648 655 public Paint getSeriesOutlinePaint(int series) { 656 if (this.seriesOutlinePaint != null) { 658 return this.seriesOutlinePaint; 659 } 660 Paint result = this.seriesOutlinePaintList.getPaint(series); 662 if (result == null) { 663 result = this.baseSeriesOutlinePaint; 664 } 665 return result; 666 } 667 668 675 public void setSeriesOutlinePaint(int series, Paint paint) { 676 this.seriesOutlinePaintList.setPaint(series, paint); 677 notifyListeners(new PlotChangeEvent(this)); 678 } 679 680 686 public Paint getBaseSeriesOutlinePaint() { 687 return this.baseSeriesOutlinePaint; 688 } 689 690 695 public void setBaseSeriesOutlinePaint(Paint paint) { 696 if (paint == null) { 697 throw new IllegalArgumentException ("Null 'paint' argument."); 698 } 699 this.baseSeriesOutlinePaint = paint; 700 notifyListeners(new PlotChangeEvent(this)); 701 } 702 703 705 710 public Stroke getSeriesOutlineStroke() { 711 return this.seriesOutlineStroke; 712 } 713 714 721 public void setSeriesOutlineStroke(Stroke stroke) { 722 this.seriesOutlineStroke = stroke; 723 notifyListeners(new PlotChangeEvent(this)); 724 } 725 726 733 public Stroke getSeriesOutlineStroke(int series) { 734 735 if (this.seriesOutlineStroke != null) { 737 return this.seriesOutlineStroke; 738 } 739 740 Stroke result = this.seriesOutlineStrokeList.getStroke(series); 742 if (result == null) { 743 result = this.baseSeriesOutlineStroke; 744 } 745 return result; 746 747 } 748 749 756 public void setSeriesOutlineStroke(int series, Stroke stroke) { 757 this.seriesOutlineStrokeList.setStroke(series, stroke); 758 notifyListeners(new PlotChangeEvent(this)); 759 } 760 761 767 public Stroke getBaseSeriesOutlineStroke() { 768 return this.baseSeriesOutlineStroke; 769 } 770 771 776 public void setBaseSeriesOutlineStroke(Stroke stroke) { 777 if (stroke == null) { 778 throw new IllegalArgumentException ("Null 'stroke' argument."); 779 } 780 this.baseSeriesOutlineStroke = stroke; 781 notifyListeners(new PlotChangeEvent(this)); 782 } 783 784 789 public Shape getLegendItemShape() { 790 return this.legendItemShape; 791 } 792 793 798 public void setLegendItemShape(Shape shape) { 799 if (shape == null) { 800 throw new IllegalArgumentException ("Null 'shape' argument."); 801 } 802 this.legendItemShape = shape; 803 notifyListeners(new PlotChangeEvent(this)); 804 } 805 806 811 public Font getLabelFont() { 812 return this.labelFont; 813 } 814 815 821 public void setLabelFont(Font font) { 822 if (font == null) { 823 throw new IllegalArgumentException ("Null 'font' argument."); 824 } 825 this.labelFont = font; 826 notifyListeners(new PlotChangeEvent(this)); 827 } 828 829 834 public Paint getLabelPaint() { 835 return this.labelPaint; 836 } 837 838 844 public void setLabelPaint(Paint paint) { 845 if (paint == null) { 846 throw new IllegalArgumentException ("Null 'paint' argument."); 847 } 848 this.labelPaint = paint; 849 notifyListeners(new PlotChangeEvent(this)); 850 } 851 852 857 public CategoryItemLabelGenerator getLabelGenerator() { 858 return this.labelGenerator; 859 } 860 861 867 public void setLabelGenerator(CategoryItemLabelGenerator generator) { 868 if (generator == null) { 869 throw new IllegalArgumentException ("Null 'generator' argument."); 870 } 871 this.labelGenerator = generator; 872 } 873 874 883 public CategoryToolTipGenerator getToolTipGenerator() { 884 return this.toolTipGenerator; 885 } 886 887 897 public void setToolTipGenerator(CategoryToolTipGenerator generator) { 898 this.toolTipGenerator = generator; 899 this.notifyListeners(new PlotChangeEvent(this)); 900 } 901 902 911 public CategoryURLGenerator getURLGenerator() { 912 return this.urlGenerator; 913 } 914 915 925 public void setURLGenerator(CategoryURLGenerator generator) { 926 this.urlGenerator = generator; 927 this.notifyListeners(new PlotChangeEvent(this)); 928 } 929 930 |