1 130 131 package org.jfree.chart.plot; 132 133 import java.awt.AlphaComposite ; 134 import java.awt.BasicStroke ; 135 import java.awt.Color ; 136 import java.awt.Composite ; 137 import java.awt.Font ; 138 import java.awt.Graphics2D ; 139 import java.awt.Paint ; 140 import java.awt.Shape ; 141 import java.awt.Stroke ; 142 import java.awt.geom.Arc2D ; 143 import java.awt.geom.Line2D ; 144 import java.awt.geom.Point2D ; 145 import java.awt.geom.Rectangle2D ; 146 import java.io.IOException ; 147 import java.io.ObjectInputStream ; 148 import java.io.ObjectOutputStream ; 149 import java.io.Serializable ; 150 import java.util.Iterator ; 151 import java.util.List ; 152 import java.util.ResourceBundle ; 153 154 import org.jfree.chart.LegendItem; 155 import org.jfree.chart.LegendItemCollection; 156 import org.jfree.chart.entity.EntityCollection; 157 import org.jfree.chart.entity.PieSectionEntity; 158 import org.jfree.chart.event.PlotChangeEvent; 159 import org.jfree.chart.labels.PieSectionLabelGenerator; 160 import org.jfree.chart.labels.PieToolTipGenerator; 161 import org.jfree.chart.labels.StandardPieItemLabelGenerator; 162 import org.jfree.chart.labels.StandardPieSectionLabelGenerator; 163 import org.jfree.chart.urls.PieURLGenerator; 164 import org.jfree.data.DefaultKeyedValues; 165 import org.jfree.data.KeyedValues; 166 import org.jfree.data.general.DatasetChangeEvent; 167 import org.jfree.data.general.DatasetUtilities; 168 import org.jfree.data.general.PieDataset; 169 import org.jfree.io.SerialUtilities; 170 import org.jfree.text.G2TextMeasurer; 171 import org.jfree.text.TextBlock; 172 import org.jfree.text.TextBox; 173 import org.jfree.text.TextUtilities; 174 import org.jfree.ui.RectangleAnchor; 175 import org.jfree.ui.RectangleInsets; 176 import org.jfree.util.ObjectList; 177 import org.jfree.util.ObjectUtilities; 178 import org.jfree.util.PaintList; 179 import org.jfree.util.Rotation; 180 import org.jfree.util.ShapeUtilities; 181 import org.jfree.util.StrokeList; 182 183 199 public class PiePlot extends Plot implements Cloneable , Serializable { 200 201 202 private static final long serialVersionUID = -795612466005590431L; 203 204 205 public static final double DEFAULT_INTERIOR_GAP = 0.25; 206 207 208 public static final double MAX_INTERIOR_GAP = 0.40; 209 210 211 public static final double DEFAULT_START_ANGLE = 90.0; 212 213 214 public static final Font DEFAULT_LABEL_FONT 215 = new Font ("SansSerif", Font.PLAIN, 10); 216 217 218 public static final Paint DEFAULT_LABEL_PAINT = Color.black; 219 220 221 public static final Paint DEFAULT_LABEL_BACKGROUND_PAINT 222 = new Color (255, 255, 192); 223 224 225 public static final Paint DEFAULT_LABEL_OUTLINE_PAINT = Color.black; 226 227 228 public static final Stroke DEFAULT_LABEL_OUTLINE_STROKE 229 = new BasicStroke (0.5f); 230 231 232 public static final Paint DEFAULT_LABEL_SHADOW_PAINT = Color.lightGray; 233 234 235 public static final double DEFAULT_MINIMUM_ARC_ANGLE_TO_DRAW = 0.00001; 236 237 238 private PieDataset dataset; 239 240 241 private int pieIndex; 242 243 247 private double interiorGap; 248 249 250 private boolean circular; 251 252 253 private double startAngle; 254 255 256 private Rotation direction; 257 258 259 private transient Paint sectionPaint; 260 261 262 private PaintList sectionPaintList; 263 264 265 private transient Paint baseSectionPaint; 266 267 268 private transient Paint sectionOutlinePaint; 269 270 271 private PaintList sectionOutlinePaintList; 272 273 274 private transient Paint baseSectionOutlinePaint; 275 276 277 private transient Stroke sectionOutlineStroke; 278 279 280 private StrokeList sectionOutlineStrokeList; 281 282 283 private transient Stroke baseSectionOutlineStroke; 284 285 286 private transient Paint shadowPaint = Color.gray; 287 288 289 private double shadowXOffset = 4.0f; 290 291 292 private double shadowYOffset = 4.0f; 293 294 295 private ObjectList explodePercentages; 296 297 298 private PieSectionLabelGenerator labelGenerator; 299 300 301 private Font labelFont; 302 303 304 private transient Paint labelPaint; 305 306 307 private transient Paint labelBackgroundPaint; 308 309 313 private transient Paint labelOutlinePaint; 314 315 319 private transient Stroke labelOutlineStroke; 320 321 325 private transient Paint labelShadowPaint; 326 327 328 private double maximumLabelWidth = 0.20; 329 330 334 private double labelGap = 0.05; 335 336 337 private boolean labelLinksVisible; 338 339 340 private double labelLinkMargin = 0.05; 341 342 343 private transient Paint labelLinkPaint = Color.black; 344 345 346 private transient Stroke labelLinkStroke = new BasicStroke (0.5f); 347 348 349 private PieToolTipGenerator toolTipGenerator; 350 351 352 private PieURLGenerator urlGenerator; 353 354 355 private PieSectionLabelGenerator legendLabelGenerator; 356 357 358 private PieSectionLabelGenerator legendLabelToolTipGenerator; 359 360 363 private boolean ignoreNullValues; 364 365 368 private boolean ignoreZeroValues; 369 370 371 private transient Shape legendItemShape; 372 373 384 private double minimumArcAngleToDraw; 385 386 387 protected static ResourceBundle localizationResources = 388 ResourceBundle.getBundle("org.jfree.chart.plot.LocalizationBundle"); 389 390 393 public PiePlot() { 394 this(null); 395 } 396 397 402 public PiePlot(PieDataset dataset) { 403 super(); 404 this.dataset = dataset; 405 if (dataset != null) { 406 dataset.addChangeListener(this); 407 } 408 this.pieIndex = 0; 409 410 this.interiorGap = DEFAULT_INTERIOR_GAP; 411 this.circular = true; 412 this.startAngle = DEFAULT_START_ANGLE; 413 this.direction = Rotation.CLOCKWISE; 414 this.minimumArcAngleToDraw = DEFAULT_MINIMUM_ARC_ANGLE_TO_DRAW; 415 416 this.sectionPaint = null; 417 this.sectionPaintList = new PaintList(); 418 this.baseSectionPaint = null; 419 420 this.sectionOutlinePaint = null; 421 this.sectionOutlinePaintList = new PaintList(); 422 this.baseSectionOutlinePaint = DEFAULT_OUTLINE_PAINT; 423 424 this.sectionOutlineStroke = null; 425 this.sectionOutlineStrokeList = new StrokeList(); 426 this.baseSectionOutlineStroke = DEFAULT_OUTLINE_STROKE; 427 428 this.explodePercentages = new ObjectList(); 429 430 this.labelGenerator = new StandardPieItemLabelGenerator(); 431 this.labelFont = DEFAULT_LABEL_FONT; 432 this.labelPaint = DEFAULT_LABEL_PAINT; 433 this.labelBackgroundPaint = DEFAULT_LABEL_BACKGROUND_PAINT; 434 this.labelOutlinePaint = DEFAULT_LABEL_OUTLINE_PAINT; 435 this.labelOutlineStroke = DEFAULT_LABEL_OUTLINE_STROKE; 436 this.labelShadowPaint = DEFAULT_LABEL_SHADOW_PAINT; 437 this.labelLinksVisible = true; 438 439 this.toolTipGenerator = null; 440 this.urlGenerator = null; 441 this.legendLabelGenerator = new StandardPieSectionLabelGenerator(); 442 this.legendLabelToolTipGenerator = null; 443 this.legendItemShape = Plot.DEFAULT_LEGEND_ITEM_CIRCLE; 444 445 this.ignoreNullValues = false; 446 this.ignoreZeroValues = false; 447 } 448 449 454 public PieDataset getDataset() { 455 return this.dataset; 456 } 457 458 463 public void setDataset(PieDataset dataset) { 464 PieDataset existing = this.dataset; 467 if (existing != null) { 468 existing.removeChangeListener(this); 469 } 470 471 this.dataset = dataset; 473 if (dataset != null) { 474 setDatasetGroup(dataset.getGroup()); 475 dataset.addChangeListener(this); 476 } 477 478 DatasetChangeEvent event = new DatasetChangeEvent(this, dataset); 480 datasetChanged(event); 481 } 482 483 489 public int getPieIndex() { 490 return this.pieIndex; 491 } 492 493 499 public void setPieIndex(int index) { 500 this.pieIndex = index; 501 } 502 503 509 public double getStartAngle() { 510 return this.startAngle; 511 } 512 513 521 public void setStartAngle(double angle) { 522 this.startAngle = angle; 523 notifyListeners(new PlotChangeEvent(this)); 524 } 525 526 532 public Rotation getDirection() { 533 return this.direction; 534 } 535 536 542 public void setDirection(Rotation direction) { 543 if (direction == null) { 544 throw new IllegalArgumentException ("Null 'direction' argument."); 545 } 546 this.direction = direction; 547 notifyListeners(new PlotChangeEvent(this)); 548 549 } 550 551 557 public double getInteriorGap() { 558 return this.interiorGap; 559 } 560 561 569 public void setInteriorGap(double percent) { 570 571 if ((percent < 0.0) || (percent > MAX_INTERIOR_GAP)) { 573 throw new IllegalArgumentException ( 574 "Invalid 'percent' (" + percent + ") argument."); 575 } 576 577 if (this.interiorGap != percent) { 579 this.interiorGap = percent; 580 notifyListeners(new PlotChangeEvent(this)); 581 } 582 583 } 584 585 591 public boolean isCircular() { 592 return this.circular; 593 } 594 595 601 public void setCircular(boolean flag) { 602 setCircular(flag, true); 603 } 604 605 612 public void setCircular(boolean circular, boolean notify) { 613 this.circular = circular; 614 if (notify) { 615 notifyListeners(new PlotChangeEvent(this)); 616 } 617 } 618 619 625 public boolean getIgnoreNullValues() { 626 return this.ignoreNullValues; 627 } 628 629 637 public void setIgnoreNullValues(boolean flag) { 638 this.ignoreNullValues = flag; 639 notifyListeners(new PlotChangeEvent(this)); 640 } 641 642 648 public boolean getIgnoreZeroValues() { 649 return this.ignoreZeroValues; 650 } 651 652 660 public void setIgnoreZeroValues(boolean flag) { 661 this.ignoreZeroValues = flag; 662 notifyListeners(new PlotChangeEvent(this)); 663 } 664 665 667 672 public Paint getSectionPaint() { 673 return this.sectionPaint; 674 } 675 676 683 public void setSectionPaint(Paint paint) { 684 this.sectionPaint = paint; 685 notifyListeners(new PlotChangeEvent(this)); 686 } 687 688 695 public Paint getSectionPaint(int section) { 696 697 if (this.sectionPaint != null) { 699 return this.sectionPaint; 700 } 701 702 Paint result = this.sectionPaintList.getPaint(section); 704 if (result == null) { 705 DrawingSupplier supplier = getDrawingSupplier(); 706 if (supplier != null) { 707 Paint p = supplier.getNextPaint(); 708 this.sectionPaintList.setPaint(section, p); 709 result = p; 710 } 711 else { 712 result = this.baseSectionPaint; 713 } 714 } 715 return result; 716 717 } 718 719 726 public void setSectionPaint(int section, Paint paint) { 727 this.sectionPaintList.setPaint(section, paint); 728 notifyListeners(new PlotChangeEvent(this)); 729 } 730 731 737 public Paint getBaseSectionPaint() { 738 return this.baseSectionPaint; 739 } 740 741 746 public void setBaseSectionPaint(Paint paint) { 747 if (paint == null) { 748 throw new IllegalArgumentException ("Null 'paint' argument."); 749 } 750 this.baseSectionPaint = paint; 751 notifyListeners(new PlotChangeEvent(this)); 752 } 753 754 756 761 public Paint getSectionOutlinePaint() { 762 return this.sectionOutlinePaint; 763 } 764 765 772 public void setSectionOutlinePaint(Paint paint) { 773 this.sectionOutlinePaint = paint; 774 notifyListeners(new PlotChangeEvent(this)); 775 } 776 777 784 public Paint getSectionOutlinePaint(int section) { 785 786 if (this.sectionOutlinePaint != null) { 788 return this.sectionOutlinePaint; 789 } 790 791 Paint result = this.sectionOutlinePaintList.getPaint(section); 793 if (result == null) { 794 result = this.baseSectionOutlinePaint; 795 } 796 return result; 797 798 } 799 800 807 public void setSectionOutlinePaint(int section, Paint paint) { 808 this.sectionOutlinePaintList.setPaint(section, paint); 809 notifyListeners(new PlotChangeEvent(this)); 810 } 811 812 818 public Paint getBaseSectionOutlinePaint() { 819 return this.baseSectionOutlinePaint; 820 } 821 822 827 public void setBaseSectionOutlinePaint(Paint paint) { 828 if (paint == null) { 829 throw new IllegalArgumentException ("Null 'paint' argument."); 830 } 831 this.baseSectionOutlinePaint = paint; 832 notifyListeners(new PlotChangeEvent(this)); 833 } 834 835 837 842 public Stroke getSectionOutlineStroke() { 843 return this.sectionOutlineStroke; 844 } 845 846 853 public void setSectionOutlineStroke(Stroke stroke) { 854 this.sectionOutlineStroke = stroke; 855 notifyListeners(new PlotChangeEvent(this)); 856 } 857 858 865 public Stroke getSectionOutlineStroke(int section) { 866 867 if (this.sectionOutlineStroke != null) { 869 return this.sectionOutlineStroke; 870 } 871 872 Stroke result = this.sectionOutlineStrokeList.getStroke(section); 874 if (result == null) { 875 result = this.baseSectionOutlineStroke; 876 } 877 return result; 878 879 } 880 881 888 public void setSectionOutlineStroke(int section, Stroke stroke) { 889 this.sectionOutlineStrokeList.setStroke(section, stroke); 890 notifyListeners(new PlotChangeEvent(this)); 891 } 892 893 899 public Stroke getBaseSectionOutlineStroke() { 900 return this.baseSectionOutlineStroke; 901 } 902 903 908 public void setBaseSectionOutlineStroke(Stroke stroke) { 909 if (stroke == null) { 910 throw new IllegalArgumentException ("Null 'stroke' argument."); 911 } 912 this.baseSectionOutlineStroke = stroke; 913 notifyListeners(new PlotChangeEvent(this)); 914 } 915 916 921 public Paint getShadowPaint() { 922 return this.shadowPaint; 923 } 924 925 931 public void setShadowPaint(Paint paint) { 932 this.shadowPaint = paint; 933 notifyListeners(new PlotChangeEvent(this)); 934 } 935 936 941 public double getShadowXOffset() { 942 return this.shadowXOffset; 943 } 944 945 951 public void setShadowXOffset(double offset) { 952 this.shadowXOffset = offset; 953 notifyListeners(new PlotChangeEvent(this)); 954 } 955 956 961 public double getShadowYOffset() { 962 return this.shadowYOffset; 963 } 964 965 971 public void setShadowYOffset(double offset) { 972 this.shadowYOffset = offset; 973 notifyListeners(new PlotChangeEvent(this)); 974 } 975 976 983 public double getExplodePercent(int section) { 984 double result = 0.0; 985 if (this.explodePercentages != null) { 986 Number percent = (Number ) this.explodePercentages.get(section); 987 if (percent != null) { 988 result = percent.doubleValue(); 989 } 990 } 991 return result; 992 } 993 994 1001 public void setExplodePercent(int section, double percent) { 1002 if (this.explodePercentages == null) { 1003 this.explodePercentages = new ObjectList(); 1004 } 1005 this.explodePercentages.set(section, new Double (percent)); 1006 notifyListeners(new PlotChangeEvent(this)); 1007 } 1008 1009 1014 public double getMaximumExplodePercent() { 1015 double result = 0.0; 1016 for (int i = 0; i < this.explodePercentages.size(); i++) { 1017 Number explode = (Number ) this.explodePercentages.get(i); 1018 if (explode != null) { 1019 result = Math.max(result, explode.doubleValue()); 1020 } 1021 } 1022 return result; 1023 } 1024 1025 1030 public PieSectionLabelGenerator getLabelGenerator() { 1031 return this.labelGenerator; 1032 } 1033 1034 1040 public void setLabelGenerator(PieSectionLabelGenerator generator) { 1041 this.labelGenerator = generator; 1042 notifyListeners(new PlotChangeEvent(this)); 1043 } 1044 1045 1051 public double getLabelGap() { 1052 return this.labelGap; 1053 } 1054 1055 1062 public void setLabelGap(double gap) { 1063 this.labelGap = gap; 1064 notifyListeners(new PlotChangeEvent(this)); 1065 } 1066 1067 1072 public double getMaximumLabelWidth() { 1073 return this.maximumLabelWidth; 1074 } 1075 1076 1082 public void setMaximumLabelWidth(double width) { 1083 this.maximumLabelWidth = width; 1084 notifyListeners(new PlotChangeEvent(this)); 1085 } 1086 1087 1093 public boolean getLabelLinksVisible() { 1094 return this.labelLinksVisible; 1095 } 1096 1097 1106 public void setLabelLinksVisible(boolean visible) { 1107 this.labelLinksVisible = visible; 1108 notifyListeners(new PlotChangeEvent(this)); 1109 } 1110 1111 1117 public double getLabelLinkMargin() { 1118 return this.labelLinkMargin; 1119 } 1120 1121 1127 public void setLabelLinkMargin(double margin) { 1128 this.labelLinkMargin = margin; 1129 notifyListeners(new PlotChangeEvent(this)); 1130 } 1131 1132 1138 public Paint getLabelLinkPaint() { 1139 return this.labelLinkPaint; 1140 } 1141 1142 1149 public void setLabelLinkPaint(Paint paint) { 1150 if (paint == null) { 1151 throw new IllegalArgumentException ("Null 'paint' argument."); 1152 } 1153 this.labelLinkPaint = paint; 1154 notifyListeners(new PlotChangeEvent(this)); 1155 } 1156 1157 1162 public Stroke getLabelLinkStroke() { 1163 return this.labelLinkStroke; 1164 } 1165 1166 1172 public void setLabelLinkStroke(Stroke stroke) { 1173 if (stroke == null) { 1174 throw new IllegalArgumentException ("Null 'stroke' argument."); 1175 } 1176 this.labelLinkStroke = stroke; 1177 notifyListeners(new PlotChangeEvent(this)); 1178 } 1179 1180 1185 public Font getLabelFont() { 1186 return this.labelFont; 1187 } 1188 1189 1195 public void setLabelFont(Font font) { 1196 if (font == null) { 1197 throw new IllegalArgumentException ("Null 'font' argument."); 1198 } 1199 this.labelFont = font; 1200 notifyListeners(new PlotChangeEvent(this)); 1201 } 1202 1203 1208 public Paint getLabelPaint() { 1209 return this.labelPaint; 1210 } 1211 1212 1218 public void setLabelPaint(Paint paint) { 1219 if (paint == null) { 1220 throw new IllegalArgumentException ("Null 'paint' argument."); 1221 } 1222 this.labelPaint = paint; 1223 notifyListeners(new PlotChangeEvent(this)); 1224 } 1225 1226 1231 public Paint getLabelBackgroundPaint() { 1232 return this.labelBackgroundPaint; 1233 } 1234 1235 1241 public void setLabelBackgroundPaint(Paint paint) { 1242 this.labelBackgroundPaint = paint; 1243 notifyListeners(new PlotChangeEvent(this)); 1244 } 1245 1246 1251 public Paint getLabelOutlinePaint() { 1252 return this.labelOutlinePaint; 1253 } 1254 1255 1261 public void setLabelOutlinePaint(Paint paint) { 1262 this.labelOutlinePaint = paint; 1263 notifyListeners(new PlotChangeEvent(this)); 1264 } 1265 1266 1271 public Stroke getLabelOutlineStroke() { 1272 return this.labelOutlineStroke; 1273 } 1274 1275 1281 public void setLabelOutlineStroke(Stroke stroke) { 1282 this.labelOutlineStroke = stroke; 1283 notifyListeners(new PlotChangeEvent(this)); 1284 } 1285 1286 1291 public Paint getLabelShadowPaint() { 1292 return this.labelShadowPaint; 1293 } 1294 1295 1301 public void setLabelShadowPaint(Paint paint) { 1302 this.labelShadowPaint = paint; 1303 notifyListeners(new PlotChangeEvent(this)); 1304 } 1305 1306 1313 public PieToolTipGenerator getToolTipGenerator() { 1314 return this.toolTipGenerator; 1315 } 1316 1317 1324 public void setToolTipGenerator(PieToolTipGenerator generator) { 1325 this.toolTipGenerator = generator; 1326 notifyListeners(new PlotChangeEvent(this)); 1327 } 1328 1329 1334 public PieURLGenerator getURLGenerator() { 1335 return this.urlGenerator; 1336 } 1337 1338 1344 public void setURLGenerator(PieURLGenerator generator) { 1345 this.urlGenerator = generator; 1346 notifyListeners(new PlotChangeEvent(this)); 1347 } 1348 1349 1355 public double getMinimumArcAngleToDraw() { 1356 return this.minimumArcAngleToDraw; 1357 } 1358 1359 1375 public void setMinimumArcAngleToDraw(double angle) { 1376 this.minimumArcAngleToDraw = angle; 1377 } 1378 1379 1384 public Shape getLegendItemShape() { 1385 return this.legendItemShape; 1386 } 1387 1388 1393 public void setLegendItemShape(Shape shape) { 1394 if (shape == null) { 1395 throw new IllegalArgumentException ("Null 'shape' argument."); 1396 } 1397 this.legendItemShape = shape; 1398 notifyListeners(new PlotChangeEvent(this)); 1399 } 1400 1401 1406 public PieSectionLabelGenerator getLegendLabelToolTipGenerator() { 1407 return this.legendLabelToolTipGenerator; 1408 } 1409 1410 1416 public void setLegendLabelToolTipGenerator( 1417 PieSectionLabelGenerator generator) { 1418 this.legendLabelToolTipGenerator = generator; 1419 notifyListeners(new PlotChangeEvent(this)); 1420 } 1421 1422 1427 public PieSectionLabelGenerator getLegendLabelGenerator() { 1428 return this.legendLabelGenerator; 1429 } 1430 1431 1437 public void setLegendLabelGenerator(PieSectionLabelGenerator generator) { 1438 if (generator == null) { 1439 throw new IllegalArgumentException ("Null 'generator' argument."); 1440 } 1441 this.legendLabelGenerator = generator; 1442 notifyListeners(new PlotChangeEvent(this)); 1443 } 1444 1445 1460 public PiePlotState initialise(Graphics2D g2, 1461 Rectangle2D plotArea, 1462 PiePlot plot, 1463 Integer index, 1464 PlotRenderingInfo info) { 1465 1466 PiePlotState state = new PiePlotState(info); 1467 state.setPassesRequired(2); 1468 state.setTotal( 1469 DatasetUtilities.calculatePieDatasetTotal(plot.getDataset()) 1470 ); 1471 state.setLatestAngle(plot.getStartAngle()); 1472 return state; 1473 1474 } 1475 1476 1487 public void draw(Graphics2D g2, Rectangle2D area, Point2D anchor, 1488 PlotState parentState, 1489 PlotRenderingInfo info) { 1490 1491 RectangleInsets insets = getInsets(); 1493 insets.trim(area); 1494 1495 if (info != null) { 1496 info.setPlotArea(area); 1497 info.setDataArea(area); 1498 } 1499 1500 drawBackground(g2, area); 1501 drawOutline(g2, area); 1502 1503 Shape savedClip = g2.getClip(); 1504 g2.clip(area); 1505 1506 Composite originalComposite = g2.getComposite(); 1507 g2.setComposite( 1508 AlphaComposite.getInstance( 1509 AlphaComposite.SRC_OVER, getForegroundAlpha() 1510 ) 1511 ); 1512 1513 if (!DatasetUtilities.isEmptyOrNull(this.dataset)) { 1514 drawPie(g2, area, info); 1515 } 1516 else { 1517 drawNoDataMessage(g2, area); 1518 } 1519 1520 g2.setClip(savedClip); 1521 g2.setComposite(originalComposite); 1522 1523 drawOutline(g2, area); 1524 1525 } 1526 1527 1534 protected void drawPie(Graphics2D g2, 1535 Rectangle2D plotArea, 1536 PlotRenderingInfo info) { 1537 1538 PiePlotState state = initialise(g2, plotArea, this, null, info); 1539 1540 double labelWidth = 0.0; 1542 if (this.labelGenerator != null) { 1543 labelWidth = this.labelGap + this.maximumLabelWidth 1544 + this.labelLinkMargin; 1545 } 1546 double gapHorizontal 1547 = plotArea.getWidth() * (this.interiorGap + labelWidth); 1548 double gapVertical = plotArea.getHeight() * this.interiorGap; 1549 1550 double linkX = plotArea.getX() + gapHorizontal / 2; 1551 double linkY = plotArea.getY() + gapVertical / 2; 1552 double linkW = plotArea.getWidth() - gapHorizontal; 1553 double linkH = plotArea.getHeight() - gapVertical; 1554 1555 if (this.circular) { 1557 double min = Math.min(linkW, linkH) / 2; 1558 linkX = (linkX + linkX + linkW) / 2 - min; 1559 linkY = (linkY + linkY + linkH) / 2 - min; 1560 linkW = 2 * min; 1561 linkH = 2 * min; 1562 } 1563 1564 Rectangle2D linkArea = new Rectangle2D.Double ( 1567 linkX, linkY, linkW, linkH 1568 ); 1569 state.setLinkArea(linkArea); 1570 1571 double hh = linkArea.getWidth() * this.labelLinkMargin; 1575 double vv = linkArea.getHeight() * this.labelLinkMargin; 1576 Rectangle2D explodeArea = new Rectangle2D.Double ( 1577 linkX + hh / 2.0, linkY + vv / 2.0, linkW - hh, linkH - vv 1578 ); 1579 1580 state.setExplodedPieArea(explodeArea); 1581 1582 double maximumExplodePercent = getMaximumExplodePercent(); 1586 double percent = maximumExplodePercent / (1.0 + maximumExplodePercent); 1587 1588 double h1 = explodeArea.getWidth() * percent; 1589 double v1 = explodeArea.getHeight() * percent; 1590 Rectangle2D pieArea = new Rectangle2D.Double ( 1591 explodeArea.getX() + h1 / 2.0, explodeArea.getY() + v1 / 2.0, 1592 explodeArea.getWidth() - h1, explodeArea.getHeight() - v1 1593 ); 1594 1595 state.setPieArea(pieArea); 1596 state.setPieCenterX(pieArea.getCenterX()); 1597 state.setPieCenterY(pieArea.getCenterY()); 1598 state.setPieWRadius(pieArea.getWidth() / 2.0); 1599 state.setPieHRadius(pieArea.getHeight() / 2.0); 1600 if ((this.dataset != null) && (this.dataset.getKeys().size() > 0)) { 1602 1603 List keys = this.dataset.getKeys(); 1604 double totalValue 1605 = DatasetUtilities.calculatePieDatasetTotal(this.dataset); 1606 1607 int passesRequired = state.getPassesRequired(); 1608 for (int pass = 0; pass < passesRequired; pass++) { 1609 double runningTotal = 0.0; 1610 for (int section = 0; section < keys.size(); section++) { 1611 Number n = this.dataset.getValue(section); 1612 if (n != null) { 1613 double value = n.doubleValue(); 1614 if (value > 0.0) { 1615 runningTotal += value; 1616 drawItem(g2, section, explodeArea, state, pass); 1617 } 1618 } 1619 } 1620 } 1621 1622 drawLabels(g2, keys, totalValue, plotArea, linkArea, state); 1623 1624 } 1625 else { 1626 drawNoDataMessage(g2, plotArea); 1627 } 1628 } 1629 1630 1639 protected void drawItem(Graphics2D g2, 1640 int section, 1641 Rectangle2D dataArea, 1642 PiePlotState state, 1643 int currentPass) { 1644 1645 Number n = this.dataset.getValue(section); 1646 if (n == null) { 1647 return; 1648 } 1649 double value = n.doubleValue(); 1650 double angle1 = 0.0; 1651 double angle2 = 0.0; 1652 1653 if (this.direction == Rotation.CLOCKWISE) { 1654 angle1 = state.getLatestAngle(); 1655 angle2 = angle1 - value / state.getTotal() * 360.0; 1656 } 1657 else if (this.direction == Rotation.ANTICLOCKWISE) { 1658 angle1 = state.getLatestAngle(); 1659 angle2 = angle1 + value / state.getTotal() * 360.0; 1660 } 1661 else { 1662 throw new IllegalStateException ("Rotation type not recognised."); 1663 } 1664 1665 double angle = (angle2 - angle1); 1666 if (Math.abs(angle) > getMinimumArcAngleToDraw()) { 1667 double ep = 0.0; 1668 double mep = getMaximumExplodePercent(); 1669 if (mep > 0.0) { 1670 ep = getExplodePercent(section) / mep; 1671 } 1672 Rectangle2D arcBounds = getArcBounds( 1673 state.getPieArea(), state.getExplodedPieArea(), 1674 angle1, angle, ep 1675 ); 1676 Arc2D.Double arc = new Arc2D.Double ( 1677 arcBounds, angle1, angle, Arc2D.PIE 1678 ); 1679 1680 if (currentPass == 0) { 1681 if (this.shadowPaint != null) { 1682 Shape shadowArc = ShapeUtilities.createTranslatedShape( 1683 arc, (float) this.shadowXOffset, 1684 (float) this.shadowYOffset 1685 ); 1686 g2.setPaint(this.shadowPaint); 1687 g2.fill(shadowArc); 1688 } 1689 } 1690 else if (currentPass == 1) { 1691 1692 Paint paint = getSectionPaint(section); 1693 g2.setPaint(paint); 1694 g2.fill(arc); 1695 1696 Paint outlinePaint = getSectionOutlinePaint(section); 1697 Stroke outlineStroke = getSectionOutlineStroke(section); 1698 if (outlinePaint != null && outlineStroke != null) { 1699 g2.setPaint(outlinePaint); 1700 g2.setStroke(outlineStroke); 1701 g2.draw(arc); 1702 } 1703 1704 if (state.getInfo() != null) { 1707 EntityCollection entities 1708 = state.getInfo().getOwner().getEntityCollection(); 1709 if (entities != null) { 1710 Comparable key = this.dataset.getKey(section); 1711 String tip = null; 1712 if (this.toolTipGenerator != null) { 1713 tip = this.toolTipGenerator.generateToolTip( 1714 this.dataset, key 1715 ); 1716 } 1717 String url = null; 1718 if (this.urlGenerator != null) { 1719 url = this.urlGenerator.generateURL( 1720 this.dataset, key, this.pieIndex 1721 ); 1722 } 1723 PieSectionEntity entity = new PieSectionEntity( 1724 arc, this.dataset, this.pieIndex, section, key, 1725 tip, url 1726 ); 1727 entities.add(entity); 1728 } 1729 } 1730 } 1731 } 1732 state.setLatestAngle(angle2); 1733 } 1734 1735 1745 protected void drawLabels(Graphics2D g2, List keys, double totalValue, 1746 Rectangle2D plotArea, Rectangle2D linkArea, 1747 PiePlotState state) { 1748 1749 Composite originalComposite = g2.getComposite(); 1750 g2.setComposite( 1751 AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f) 1752 ); 1753 1754 DefaultKeyedValues leftKeys = new DefaultKeyedValues(); 1756 DefaultKeyedValues rightKeys = new DefaultKeyedValues(); 1757 1758 double runningTotal1 = 0.0; 1759 Iterator iterator1 = keys.iterator(); 1760 while (iterator1.hasNext()) { 1761 Comparable key = (Comparable ) iterator1.next(); 1762 Number n = this.dataset.getValue(key); 1763 if (n != null) { 1764 double v = n.doubleValue(); 1765 if (this.ignoreZeroValues ? v > 0.0 : v >= 0.0) { 1766 runningTotal1 = runningTotal1 + v; 1767 double mid = this.startAngle + (this.direction.getFactor() 1770 * ((runningTotal1 - v / 2.0) * 360) / totalValue); 1771 if (Math.cos(Math.toRadians(mid)) < 0.0) { 1772 leftKeys.addValue(key, new Double (mid)); 1773 } 1774 else { 1775 rightKeys.addValue(key, new Double (mid)); 1776 } 1777 } 1778 } 1779 } 1780 1781 g2.setFont(getLabelFont()); 1782 float maxLabelWidth 1783 = (float) (getMaximumLabelWidth() * plotArea.getWidth()); 1784 1785 if (this.labelGenerator != null) { 1787 drawLeftLabels( 1788 leftKeys, g2, plotArea, linkArea, maxLabelWidth, state 1789 ); 1790 drawRightLabels( 1791 rightKeys, g2, plotArea, linkArea, maxLabelWidth, state 1792 ); 1793 } 1794 g2.setComposite(originalComposite); 1795 1796 } 1797 1798 1808 protected void drawLeftLabels(KeyedValues leftKeys, Graphics2D g2, 1809 Rectangle2D plotArea, Rectangle2D linkArea, 1810 float maxLabelWidth, PiePlotState state) { 1811 1812 PieLabelDistributor distributor1 = new PieLabelDistributor( 1813 leftKeys.getItemCount() 1814 ); 1815 double lGap = plotArea.getWidth() * this.labelGap; 1816 double verticalLinkRadius = state.getLinkArea().getHeight() / 2.0; 1817 for (int i = 0; i < leftKeys.getItemCount(); i++) { 1818 String label = this.labelGenerator.generateSectionLabel( 1819 this.dataset, leftKeys.getKey(i) 1820 ); 1821 if (label != null) { 1822 TextBlock block = TextUtilities.createTextBlock( 1823 label, 1824 this.labelFont, this.labelPaint, maxLabelWidth, 1825 new G2TextMeasurer(g2) 1826 ); 1827 TextBox labelBox = new TextBox(block); 1828 labelBox.setBackgroundPaint(this.labelBackgroundPaint); 1829 labelBox.setOutlinePaint(this.labelOutlinePaint); 1830 labelBox.setOutlineStroke(this.labelOutlineStroke); 1831 labelBox.setShadowPaint(this.labelShadowPaint); 1832 double theta = Math.toRadians( 1833 leftKeys.getValue(i).doubleValue() 1834 ); 1835 double baseY = state.getPieCenterY() - Math.sin(theta) 1836 * verticalLinkRadius; 1837 double hh = labelBox.getHeight(g2); 1838 1839 distributor1.addPieLabelRecord( 1840 new PieLabelRecord( 1841 leftKeys.getKey(i), theta, baseY, labelBox, hh, 1842 lGap / 2.0 + lGap / 2.0 * -Math.cos(theta), 1843 0.9 + getExplodePercent(this.dataset.getIndex( 1844 leftKeys.getKey(i))) 1845 ) 1846 ); 1847 } 1848 } 1849 distributor1.distributeLabels(plotArea.getMinY(), plotArea.getHeight()); 1850 for (int i = 0; i < distributor1.getItemCount(); i++) { 1851 drawLeftLabel(g2, state, distributor1.getPieLabelRecord(i)); 1852 } 1853 } 1854 1855 1865 protected void drawRightLabels(KeyedValues keys, Graphics2D g2, 1866 Rectangle2D plotArea, Rectangle2D linkArea, 1867 float maxLabelWidth, PiePlotState state) { 1868 1869 PieLabelDistributor distributor2 1871 = new PieLabelDistributor(keys.getItemCount()); 1872 double lGap = plotArea.getWidth() * this.labelGap; 1873 double verticalLinkRadius = state.getLinkArea().getHeight() / 2.0; 1874 1875 for (int i = 0; i < keys.getItemCount(); i++) { 1876 String label = this.labelGenerator.generateSectionLabel( 1877 this.dataset, keys.getKey(i) 1878 ); 1879 1880 if (label != null) { 1881 TextBlock block = TextUtilities.createTextBlock( 1882 label, this.labelFont, this.labelPaint, 1883 maxLabelWidth, new G2TextMeasurer(g2) 1884 ); 1885 TextBox labelBox = new TextBox(block); 1886 labelBox.setBackgroundPaint(this.labelBackgroundPaint); 1887 labelBox.setOutlinePaint(this.labelOutlinePaint); 1888 labelBox.setOutlineStroke(this.labelOutlineStroke); 1889 labelBox.setShadowPaint(this.labelShadowPaint); 1890 double theta = Math.toRadians(keys.getValue(i).doubleValue()); 1891 double baseY = state.getPieCenterY() 1892 - Math.sin(theta) * verticalLinkRadius; 1893 double hh = labelBox.getHeight(g2); 1894 distributor2.addPieLabelRecord( 1895 new PieLabelRecord( 1896 keys.getKey(i), theta, baseY, labelBox, hh, 1897 lGap / 2.0 + lGap / 2.0 * Math.cos(theta), 1898 0.9 + getExplodePercent(this.dataset.getIndex( 1899 keys.getKey(i))) 1900 ) 1901 ); 1902 } 1903 } 1904 distributor2.distributeLabels(linkArea.getMinY(), linkArea.getHeight()); 1905 for (int i = 0; i < distributor2.getItemCount(); i++) { 1906 drawRightLabel(g2, state, distributor2.getPieLabelRecord(i)); 1907 } 1908 1909 } 1910 1911 1916 public LegendItemCollection getLegendItems() { 1917 1918 LegendItemCollection result = new LegendItemCollection(); 1919 1920 List keys = null; 1921 if (this.dataset != null) { 1922 keys = this.dataset.getKeys(); 1923 int section = 0; 1924 Shape shape = getLegendItemShape(); 1925 Iterator iterator = keys.iterator(); 1926 while (iterator.hasNext()) { 1927 Comparable key = (Comparable ) iterator.next(); 1928 Number n = this.dataset.getValue(key); 1929 if (n != null || !this.ignoreNullValues) { 1930 String label 1931 = this.legendLabelGenerator.generateSectionLabel( 1932 this.dataset, key 1933 ); 1934 String description = label; 1935 String toolTipText = null; 1936 if (this.legendLabelToolTipGenerator != null) { 1937 toolTipText 1938 = this.legendLabelToolTipGenerator.generateSectionLabel( 1939 this.dataset, key 1940 ); 1941 } 1942 String urlText = null; 1943 Paint paint = getSectionPaint(section); 1944 Paint outlinePaint = getSectionOutlinePaint(section); 1945 Stroke outlineStroke = getSectionOutlineStroke(section); 1946 1947 LegendItem item = new LegendItem( 1948 label, description, toolTipText, urlText, 1949 true, shape, 1950 true, paint, 1951 true, outlinePaint, outlineStroke, 1952 false, new Line2D.Float (), 1954 new BasicStroke (), 1955 Color.black 1956 ); 1957 1958 result.add(item); 1959 section++; 1960 } 1961 } 1962 } 1963 1964 return result; 1965 } 1966 1967 1972 public String getPlotType() { 1973 return localizationResources.getString("Pie_Plot"); 1974 } 1975 1976 1984 public void zoom(double percent) { 1985 } 1987 1988 2002 protected Rectangle2D getArcBounds(Rectangle2D unexploded, 2003 Rectangle2D exploded, 2004 double angle, double extent, 2005 double explodePercent) { 2006 2007 if (explodePercent == 0.0) { 2008 return unexploded; 2009 } 2010 else { 2011 Arc2D arc1 = new Arc2D.Double ( 2012 unexploded, angle, extent / 2, Arc2D.OPEN 2013 ); 2014 Point2D point1 = arc1.getEndPoint(); 2015 Arc2D.Double arc2 = new Arc2D.Double ( 2016 exploded, angle, extent / 2, Arc2D.OPEN 2017 ); 2018 Point2D point2 = arc2.getEndPoint(); 2019 double deltaX = (point1.getX() - point2.getX()) * explodePercent; 2020 double deltaY = (point1.getY() - point2.getY()) * explodePercent; 2021 return new Rectangle2D.Double ( 2022 unexploded.getX() - deltaX, unexploded.getY() - deltaY, 2023 unexploded.getWidth(), unexploded.getHeight() 2024 ); 2025 } 2026 } 2027 2028 2035 protected void drawLeftLabel(Graphics2D g2, PiePlotState state, 2036 PieLabelRecord record) { 2037 2038 double anchorX = state.getLinkArea().getMinX(); 2039 double targetX = anchorX - record.getGap(); 2040 double targetY = record.getAllocatedY(); 2041 2042 if (this.labelLinksVisible) { 2043 double theta = record.getAngle(); 2044 double linkX = state.getPieCenterX() + Math.cos(theta) 2045 * state.getPieWRadius() * record.getLinkPercent(); 2046 double linkY = state.getPieCenterY() - Math.sin(theta) 2047 * state.getPieHRadius() * record.getLinkPercent(); 2048 double elbowX = state.getPieCenterX() + Math.cos(theta) 2049 * state.getLinkArea().getWidth() / 2.0; 2050 double elbowY = state.getPieCenterY() - Math.sin(theta) 2051 * state.getLinkArea().getHeight() / 2.0; 2052 double anchorY = elbowY; 2053 g2.setPaint(this.labelLinkPaint); 2054 g2.setStroke(this.labelLinkStroke); 2055 g2.draw(new Line2D.Double (linkX, linkY, elbowX, elbowY)); 2056 g2.draw(new Line2D.Double (anchorX, anchorY, elbowX, elbowY)); 2057 g2.draw(new Line2D.Double (anchorX, anchorY, targetX, targetY)); 2058 } 2059 TextBox tb = record.getLabel(); 2060 tb.draw(g2, (float) targetX, (float) targetY, RectangleAnchor.RIGHT); 2061 2062 } 2063 2064 2071 protected void drawRightLabel(Graphics2D g2, PiePlotState state, 2072 PieLabelRecord record) { 2073 2074 double anchorX = state.getLinkArea().getMaxX(); 2075 double targetX = anchorX + record.getGap(); 2076 double targetY = record.getAllocatedY(); 2077 2078 if (this.labelLinksVisible) { 2079 double theta = record.getAngle(); 2080 double linkX = state.getPieCenterX() + Math.cos(theta) 2081 * state.getPieWRadius() * record.getLinkPercent(); 2082 double linkY = state.getPieCenterY() - Math.sin(theta) 2083 * state.getPieHRadius() * record.getLinkPercent(); 2084 double elbowX = state.getPieCenterX() + Math.cos(theta) 2085 * state.getLinkArea().getWidth() / 2.0; 2086 double elbowY = state.getPieCenterY() - Math.sin(theta) 2087 * state.getLinkArea().getHeight() / 2.0; 2088 double anchorY = elbowY; 2089 g2.setPaint(this.labelLinkPaint); 2090 g2.setStroke(this.labelLinkStroke); 2091 g2.draw(new Line2D.Double (linkX, linkY, elbowX, elbowY)); 2092 g2.draw(new Line2D.Double (anchorX, anchorY, elbowX, elbowY)); 2093 g2.draw(new Line2D.Double (anchorX, anchorY, targetX, targetY)); 2094 } 2095 2096 TextBox tb = record.getLabel(); 2097 tb.draw(g2, (float) targetX, (float) targetY, RectangleAnchor.LEFT); 2098 2099 } 2100 2101 2109 public boolean equals(Object obj) { 2110 2111 if (obj == this) { 2112 return true; 2113 } 2114 if (!(obj instanceof PiePlot)) { 2115 return false; 2116 } 2117 if (!super.equals(obj)) { 2118 return false; 2119 } 2120 PiePlot that = (PiePlot) obj; 2121 if (this.pieIndex != that.pieIndex) { 2122 return false; 2123 } 2124 if (this.interiorGap != that.interiorGap) { 2125 return false; 2126 } 2127 if (this.circular != that.circular) { 2128 return false; 2129 } 2130 if (this.startAngle != that.startAngle) { 2131 return false; 2132 } 2133 if (this.direction != that.direction) { 2134 return false; 2135 } 2136 if (this.ignoreZeroValues != that.ignoreZeroValues) { 2137 return false; 2138 } 2139 if (this.ignoreNullValues != that.ignoreNullValues) { 2140 return false; 2141 } 2142 if (!ObjectUtilities.equal(this.sectionPaint, that.sectionPaint)) { 2143 return false; 2144 } 2145 if (!ObjectUtilities.equal(this.sectionPaintList, 2146 that.sectionPaintList)) { 2147 return false; 2148 } 2149 if (!ObjectUtilities.equal(this.baseSectionPaint, 2150 that.baseSectionPaint)) { 2151 return false; 2152 } 2153 if (!ObjectUtilities.equal(this.sectionOutlinePaint, 2154 that.sectionOutlinePaint)) { 2155 return false; 2156 } 2157 if (!ObjectUtilities.equal(this.sectionOutlinePaintList, 2158 that.sectionOutlinePaintList)) { 2159 return false; 2160 } 2161 if (!ObjectUtilities.equal( 2162 this.baseSectionOutlinePaint, that.baseSectionOutlinePaint 2163 )) { 2164 return false; 2165 } 2166 if (!ObjectUtilities.equal(this.sectionOutlineStroke, 2167 that.sectionOutlineStroke)) { 2168 return false; 2169 } 2170 if (!ObjectUtilities.equal( 2171 this.sectionOutlineStrokeList, that.sectionOutlineStrokeList 2172 )) { 2173 return false; 2174 } 2175 if (!ObjectUtilities.equal( 2176 this.baseSectionOutlineStroke, that.baseSectionOutlineStroke 2177 )) { 2178 return false; 2179 } 2180 2181 if (!ObjectUtilities.equal(this.shadowPaint, that.shadowPaint)) { 2182 return false; 2183 } 2184 if (!(this.shadowXOffset == that.shadowXOffset)) { 2185 return false; 2186 } 2187 if (!(this.shadowYOffset == that.shadowYOffset)) { 2188 return false; 2189 } 2190 2191 if (!ObjectUtilities.equal(this.explodePercentages, 2192 that.explodePercentages)) { 2193 return false; 2194 } 2195 if (!ObjectUtilities.equal(this.labelGenerator, 2196 that.labelGenerator)) { 2197 return false; 2198 } 2199 if (!ObjectUtilities.equal(this.labelFont, that.labelFont)) { 2200 return false; 2201 } 2202 if (!ObjectUtilities.equal(this.labelPaint, that.labelPaint)) { 2203 return false; 2204 } 2205 2206 if (!ObjectUtilities.equal(this.labelBackgroundPaint, 2207 that.labelBackgroundPaint)) { 2208 return false; 2209 } 2210 if (!ObjectUtilities.equal(this.labelOutlinePaint, 2211 that.labelOutlinePaint)) { 2212 return false; 2213 } 2214 if (!ObjectUtilities.equal(this.labelOutlineStroke, 2215 that.labelOutlineStroke)) { 2216 return false; 2217 } 2218 if (!ObjectUtilities.equal(this.labelShadowPaint, 2219 that.labelShadowPaint)) { 2220 return false; 2221 } 2222 2223 if (!(this.maximumLabelWidth == that.maximumLabelWidth)) { 2224 return false; 2225 } 2226 if (!(this.labelGap == that.labelGap)) { 2227 return false; 2228 } 2229 if (!(this.labelLinkMargin == that.labelLinkMargin)) { 2230 return false; 2231 } 2232 if (this.labelLinksVisible != that.labelLinksVisible) { 2233 return false; 2234 } 2235 if (!ObjectUtilities.equal(this.labelLinkPaint, that.labelLinkPaint)) { 2236 return false; 2237 } 2238 if (!ObjectUtilities.equal(this.labelLinkStroke, 2239 that.labelLinkStroke)) { 2240 return false; 2241 } 2242 if (!ObjectUtilities.equal(this.toolTipGenerator, 2243 that.toolTipGenerator)) { 2244 return false; 2245 } 2246 if (!ObjectUtilities.equal(this.urlGenerator, that.urlGenerator)) { 2247 return false; 2248 } 2249 if (!(this.minimumArcAngleToDraw == that.minimumArcAngleToDraw)) { 2250 return false; 2251 } 2252 if (!ShapeUtilities.equal(this.legendItemShape, that.legendItemShape)) { 2253 return false; 2254 } 2255 2256 return true; 2258 2259 } 2260 2261 2269 public Object clone() throws CloneNotSupportedException { 2270 2271 PiePlot clone = (PiePlot) super.clone(); 2272 if (clone.dataset != null) { 2273 clone.dataset.addChangeListener(clone); 2274 } 2275 return clone; 2276 2277 } 2278 2279 2286 private void writeObject(ObjectOutputStream stream) throws IOException { 2287 stream.defaultWriteObject(); 2288 SerialUtilities.writePaint(this.sectionPaint, stream); 2289 SerialUtilities.writePaint(this.baseSectionPaint, stream); 2290 SerialUtilities.writePaint(this.sectionOutlinePaint, stream); 2291 SerialUtilities.writePaint(this.baseSectionOutlinePaint, stream); 2292 SerialUtilities.writeStroke(this.sectionOutlineStroke, stream); 2293 SerialUtilities.writeStroke(this.baseSectionOutlineStroke, stream); 2294 SerialUtilities.writePaint(this.shadowPaint, stream); 2295 SerialUtilities.writePaint(this.labelPaint, stream); 2296 SerialUtilities.writePaint(this.labelBackgroundPaint, stream); 2297 SerialUtilities.writePaint(this.labelOutlinePaint, stream); 2298 SerialUtilities.writeStroke(this.labelOutlineStroke, stream); 2299 SerialUtilities.writePaint(this.labelShadowPaint, stream); 2300 SerialUtilities.writePaint(this.labelLinkPaint, stream); 2301 SerialUtilities.writeStroke(this.labelLinkStroke, stream); 2302 SerialUtilities.writeShape(this.legendItemShape, stream); 2303 } 2304 2305 2313 private void readObject(ObjectInputStream stream) 2314 throws IOException , ClassNotFoundException { 2315 stream.defaultReadObject(); 2316 this.sectionPaint = SerialUtilities.readPaint(stream); 2317 this.baseSectionPaint = SerialUtilities.readPaint(stream); 2318 this.sectionOutlinePaint = SerialUtilities.readPaint(stream); 2319 this.baseSectionOutlinePaint = SerialUtilities.readPaint(stream); 2320 this.sectionOutlineStroke = SerialUtilities.readStroke(stream); 2321 this.baseSectionOutlineStroke = SerialUtilities.readStroke(stream); 2322 this.shadowPaint = SerialUtilities.readPaint(stream); 2323 this.labelPaint = SerialUtilities.readPaint(stream); 2324 this.labelBackgroundPaint = SerialUtilities.readPaint(stream); 2325 this.labelOutlinePaint = SerialUtilities.readPaint(stream); 2326 this.labelOutlineStroke = SerialUtilities.readStroke(stream); 2327 this.labelShadowPaint = SerialUtilities.readPaint(stream); 2328 this.labelLinkPaint = SerialUtilities.readPaint(stream); 2329 this.labelLinkStroke = SerialUtilities.readStroke(stream); 2330 this.legendItemShape = SerialUtilities.readShape(stream); 2331 } 2332 2333} 2334 | Popular Tags |