1:
140:
141: package ;
142:
143: import ;
144: import ;
145: import ;
146: import ;
147: import ;
148: import ;
149: import ;
150: import ;
151: import ;
152: import ;
153: import ;
154: import ;
155: import ;
156: import ;
157: import ;
158: import ;
159: import ;
160: import ;
161: import ;
162: import ;
163:
164: import ;
165: import ;
166: import ;
167: import ;
168: import ;
169: import ;
170: import ;
171: import ;
172: import ;
173: import ;
174: import ;
175: import ;
176: import ;
177: import ;
178: import ;
179: import ;
180: import ;
181: import ;
182: import ;
183: import ;
184: import ;
185: import ;
186: import ;
187: import ;
188: import ;
189: import ;
190: import ;
191: import ;
192:
193:
209: public class PiePlot extends Plot implements Cloneable, Serializable {
210:
211:
212: private static final long serialVersionUID = -795612466005590431L;
213:
214:
215: public static final double DEFAULT_INTERIOR_GAP = 0.25;
216:
217:
218: public static final double MAX_INTERIOR_GAP = 0.40;
219:
220:
221: public static final double DEFAULT_START_ANGLE = 90.0;
222:
223:
224: public static final Font DEFAULT_LABEL_FONT
225: = new Font("SansSerif", Font.PLAIN, 10);
226:
227:
228: public static final Paint DEFAULT_LABEL_PAINT = Color.black;
229:
230:
231: public static final Paint DEFAULT_LABEL_BACKGROUND_PAINT
232: = new Color(255, 255, 192);
233:
234:
235: public static final Paint DEFAULT_LABEL_OUTLINE_PAINT = Color.black;
236:
237:
238: public static final Stroke DEFAULT_LABEL_OUTLINE_STROKE
239: = new BasicStroke(0.5f);
240:
241:
242: public static final Paint DEFAULT_LABEL_SHADOW_PAINT = Color.lightGray;
243:
244:
245: public static final double DEFAULT_MINIMUM_ARC_ANGLE_TO_DRAW = 0.00001;
246:
247:
248: private PieDataset dataset;
249:
250:
251: private int pieIndex;
252:
253:
257: private double interiorGap;
258:
259:
260: private boolean circular;
261:
262:
263: private double startAngle;
264:
265:
266: private Rotation direction;
267:
268:
269: private transient Paint sectionPaint;
270:
271:
272: private PaintList sectionPaintList;
273:
274:
275: private transient Paint baseSectionPaint;
276:
277:
281: private boolean sectionOutlinesVisible;
282:
283:
284: private transient Paint sectionOutlinePaint;
285:
286:
287: private PaintList sectionOutlinePaintList;
288:
289:
290: private transient Paint baseSectionOutlinePaint;
291:
292:
293: private transient Stroke sectionOutlineStroke;
294:
295:
296: private StrokeList sectionOutlineStrokeList;
297:
298:
299: private transient Stroke baseSectionOutlineStroke;
300:
301:
302: private transient Paint shadowPaint = Color.gray;
303:
304:
305: private double shadowXOffset = 4.0f;
306:
307:
308: private double shadowYOffset = 4.0f;
309:
310:
311: private ObjectList explodePercentages;
312:
313:
314: private PieSectionLabelGenerator labelGenerator;
315:
316:
317: private Font labelFont;
318:
319:
320: private transient Paint labelPaint;
321:
322:
323: private transient Paint labelBackgroundPaint;
324:
325:
329: private transient Paint labelOutlinePaint;
330:
331:
335: private transient Stroke labelOutlineStroke;
336:
337:
341: private transient Paint labelShadowPaint;
342:
343:
344: private double maximumLabelWidth = 0.20;
345:
346:
350: private double labelGap = 0.05;
351:
352:
353: private boolean labelLinksVisible;
354:
355:
356: private double labelLinkMargin = 0.05;
357:
358:
359: private transient Paint labelLinkPaint = Color.black;
360:
361:
362: private transient Stroke labelLinkStroke = new BasicStroke(0.5f);
363:
364:
365: private PieToolTipGenerator toolTipGenerator;
366:
367:
368: private PieURLGenerator urlGenerator;
369:
370:
371: private PieSectionLabelGenerator legendLabelGenerator;
372:
373:
374: private PieSectionLabelGenerator legendLabelToolTipGenerator;
375:
376:
379: private boolean ignoreNullValues;
380:
381:
384: private boolean ignoreZeroValues;
385:
386:
387: private transient Shape legendItemShape;
388:
389:
400: private double minimumArcAngleToDraw;
401:
402:
403: protected static ResourceBundle localizationResources =
404: ResourceBundle.getBundle("org.jfree.chart.plot.LocalizationBundle");
405:
406:
409: public PiePlot() {
410: this(null);
411: }
412:
413:
418: public PiePlot(PieDataset dataset) {
419: super();
420: this.dataset = dataset;
421: if (dataset != null) {
422: dataset.addChangeListener(this);
423: }
424: this.pieIndex = 0;
425:
426: this.interiorGap = DEFAULT_INTERIOR_GAP;
427: this.circular = true;
428: this.startAngle = DEFAULT_START_ANGLE;
429: this.direction = Rotation.CLOCKWISE;
430: this.minimumArcAngleToDraw = DEFAULT_MINIMUM_ARC_ANGLE_TO_DRAW;
431:
432: this.sectionPaint = null;
433: this.sectionPaintList = new PaintList();
434: this.baseSectionPaint = null;
435:
436: this.sectionOutlinesVisible = true;
437: this.sectionOutlinePaint = null;
438: this.sectionOutlinePaintList = new PaintList();
439: this.baseSectionOutlinePaint = DEFAULT_OUTLINE_PAINT;
440:
441: this.sectionOutlineStroke = null;
442: this.sectionOutlineStrokeList = new StrokeList();
443: this.baseSectionOutlineStroke = DEFAULT_OUTLINE_STROKE;
444:
445: this.explodePercentages = new ObjectList();
446:
447: this.labelGenerator = new StandardPieSectionLabelGenerator();
448: this.labelFont = DEFAULT_LABEL_FONT;
449: this.labelPaint = DEFAULT_LABEL_PAINT;
450: this.labelBackgroundPaint = DEFAULT_LABEL_BACKGROUND_PAINT;
451: this.labelOutlinePaint = DEFAULT_LABEL_OUTLINE_PAINT;
452: this.labelOutlineStroke = DEFAULT_LABEL_OUTLINE_STROKE;
453: this.labelShadowPaint = DEFAULT_LABEL_SHADOW_PAINT;
454: this.labelLinksVisible = true;
455:
456: this.toolTipGenerator = null;
457: this.urlGenerator = null;
458: this.legendLabelGenerator = new StandardPieSectionLabelGenerator();
459: this.legendLabelToolTipGenerator = null;
460: this.legendItemShape = Plot.DEFAULT_LEGEND_ITEM_CIRCLE;
461:
462: this.ignoreNullValues = false;
463: this.ignoreZeroValues = false;
464: }
465:
466:
471: public PieDataset getDataset() {
472: return this.dataset;
473: }
474:
475:
480: public void setDataset(PieDataset dataset) {
481:
482:
483: PieDataset existing = this.dataset;
484: if (existing != null) {
485: existing.removeChangeListener(this);
486: }
487:
488:
489: this.dataset = dataset;
490: if (dataset != null) {
491: setDatasetGroup(dataset.getGroup());
492: dataset.addChangeListener(this);
493: }
494:
495:
496: DatasetChangeEvent event = new DatasetChangeEvent(this, dataset);
497: datasetChanged(event);
498: }
499:
500:
506: public int getPieIndex() {
507: return this.pieIndex;
508: }
509:
510:
516: public void setPieIndex(int index) {
517: this.pieIndex = index;
518: }
519:
520:
526: public double getStartAngle() {
527: return this.startAngle;
528: }
529:
530:
538: public void setStartAngle(double angle) {
539: this.startAngle = angle;
540: notifyListeners(new PlotChangeEvent(this));
541: }
542:
543:
549: public Rotation getDirection() {
550: return this.direction;
551: }
552:
553:
559: public void setDirection(Rotation direction) {
560: if (direction == null) {
561: throw new IllegalArgumentException("Null 'direction' argument.");
562: }
563: this.direction = direction;
564: notifyListeners(new PlotChangeEvent(this));
565:
566: }
567:
568:
574: public double getInteriorGap() {
575: return this.interiorGap;
576: }
577:
578:
586: public void setInteriorGap(double percent) {
587:
588:
589: if ((percent < 0.0) || (percent > MAX_INTERIOR_GAP)) {
590: throw new IllegalArgumentException(
591: "Invalid 'percent' (" + percent + ") argument.");
592: }
593:
594:
595: if (this.interiorGap != percent) {
596: this.interiorGap = percent;
597: notifyListeners(new PlotChangeEvent(this));
598: }
599:
600: }
601:
602:
608: public boolean isCircular() {
609: return this.circular;
610: }
611:
612:
618: public void setCircular(boolean flag) {
619: setCircular(flag, true);
620: }
621:
622:
629: public void setCircular(boolean circular, boolean notify) {
630: this.circular = circular;
631: if (notify) {
632: notifyListeners(new PlotChangeEvent(this));
633: }
634: }
635:
636:
642: public boolean getIgnoreNullValues() {
643: return this.ignoreNullValues;
644: }
645:
646:
654: public void setIgnoreNullValues(boolean flag) {
655: this.ignoreNullValues = flag;
656: notifyListeners(new PlotChangeEvent(this));
657: }
658:
659:
665: public boolean getIgnoreZeroValues() {
666: return this.ignoreZeroValues;
667: }
668:
669:
677: public void setIgnoreZeroValues(boolean flag) {
678: this.ignoreZeroValues = flag;
679: notifyListeners(new PlotChangeEvent(this));
680: }
681:
682:
683:
684:
689: public Paint getSectionPaint() {
690: return this.sectionPaint;
691: }
692:
693:
700: public void setSectionPaint(Paint paint) {
701: this.sectionPaint = paint;
702: notifyListeners(new PlotChangeEvent(this));
703: }
704:
705:
712: public Paint getSectionPaint(int section) {
713:
714:
715: if (this.sectionPaint != null) {
716: return this.sectionPaint;
717: }
718:
719:
720: Paint result = this.sectionPaintList.getPaint(section);
721: if (result == null) {
722: DrawingSupplier supplier = getDrawingSupplier();
723: if (supplier != null) {
724: Paint p = supplier.getNextPaint();
725: this.sectionPaintList.setPaint(section, p);
726: result = p;
727: }
728: else {
729: result = this.baseSectionPaint;
730: }
731: }
732: return result;
733:
734: }
735:
736:
743: public void setSectionPaint(int section, Paint paint) {
744: this.sectionPaintList.setPaint(section, paint);
745: notifyListeners(new PlotChangeEvent(this));
746: }
747:
748:
754: public Paint getBaseSectionPaint() {
755: return this.baseSectionPaint;
756: }
757:
758:
763: public void setBaseSectionPaint(Paint paint) {
764: if (paint == null) {
765: throw new IllegalArgumentException("Null 'paint' argument.");
766: }
767: this.baseSectionPaint = paint;
768: notifyListeners(new PlotChangeEvent(this));
769: }
770:
771:
772:
773:
780: public boolean getSectionOutlinesVisible() {
781: return this.sectionOutlinesVisible;
782: }
783:
784:
791: public void setSectionOutlinesVisible(boolean visible) {
792: this.sectionOutlinesVisible = visible;
793: notifyListeners(new PlotChangeEvent(this));
794: }
795:
796:
801: public Paint getSectionOutlinePaint() {
802: return this.sectionOutlinePaint;
803: }
804:
805:
812: public void setSectionOutlinePaint(Paint paint) {
813: this.sectionOutlinePaint = paint;
814: notifyListeners(new PlotChangeEvent(this));
815: }
816:
817:
824: public Paint getSectionOutlinePaint(int section) {
825:
826:
827: if (this.sectionOutlinePaint != null) {
828: return this.sectionOutlinePaint;
829: }
830:
831:
832: Paint result = this.sectionOutlinePaintList.getPaint(section);
833: if (result == null) {
834: result = this.baseSectionOutlinePaint;
835: }
836: return result;
837:
838: }
839:
840:
847: public void setSectionOutlinePaint(int section, Paint paint) {
848: this.sectionOutlinePaintList.setPaint(section, paint);
849: notifyListeners(new PlotChangeEvent(this));
850: }
851:
852:
858: public Paint getBaseSectionOutlinePaint() {
859: return this.baseSectionOutlinePaint;
860: }
861:
862:
867: public void setBaseSectionOutlinePaint(Paint paint) {
868: if (paint == null) {
869: throw new IllegalArgumentException("Null 'paint' argument.");
870: }
871: this.baseSectionOutlinePaint = paint;
872: notifyListeners(new PlotChangeEvent(this));
873: }
874:
875:
876:
877:
882: public Stroke getSectionOutlineStroke() {
883: return this.sectionOutlineStroke;
884: }
885:
886:
893: public void setSectionOutlineStroke(Stroke stroke) {
894: this.sectionOutlineStroke = stroke;
895: notifyListeners(new PlotChangeEvent(this));
896: }
897:
898:
905: public Stroke getSectionOutlineStroke(int section) {
906:
907:
908: if (this.sectionOutlineStroke != null) {
909: return this.sectionOutlineStroke;
910: }
911:
912:
913: Stroke result = this.sectionOutlineStrokeList.getStroke(section);
914: if (result == null) {
915: result = this.baseSectionOutlineStroke;
916: }
917: return result;
918:
919: }
920:
921:
928: public void setSectionOutlineStroke(int section, Stroke stroke) {
929: this.sectionOutlineStrokeList.setStroke(section, stroke);
930: notifyListeners(new PlotChangeEvent(this));
931: }
932:
933:
939: public Stroke getBaseSectionOutlineStroke() {
940: return this.baseSectionOutlineStroke;
941: }
942:
943:
948: public void setBaseSectionOutlineStroke(Stroke stroke) {
949: if (stroke == null) {
950: throw new IllegalArgumentException("Null 'stroke' argument.");
951: }
952: this.baseSectionOutlineStroke = stroke;
953: notifyListeners(new PlotChangeEvent(this));
954: }
955:
956:
961: public Paint getShadowPaint() {
962: return this.shadowPaint;
963: }
964:
965:
971: public void setShadowPaint(Paint paint) {
972: this.shadowPaint = paint;
973: notifyListeners(new PlotChangeEvent(this));
974: }
975:
976:
981: public double getShadowXOffset() {
982: return this.shadowXOffset;
983: }
984:
985:
991: public void setShadowXOffset(double offset) {
992: this.shadowXOffset = offset;
993: notifyListeners(new PlotChangeEvent(this));
994: }
995:
996:
1001: public double getShadowYOffset() {
1002: return this.shadowYOffset;
1003: }
1004:
1005:
1011: public void setShadowYOffset(double offset) {
1012: this.shadowYOffset = offset;
1013: notifyListeners(new PlotChangeEvent(this));
1014: }
1015:
1016:
1023: public double getExplodePercent(int section) {
1024: double result = 0.0;
1025: if (this.explodePercentages != null) {
1026: Number percent = (Number) this.explodePercentages.get(section);
1027: if (percent != null) {
1028: result = percent.doubleValue();
1029: }
1030: }
1031: return result;
1032: }
1033:
1034:
1041: public void setExplodePercent(int section, double percent) {
1042: if (this.explodePercentages == null) {
1043: this.explodePercentages = new ObjectList();
1044: }
1045: this.explodePercentages.set(section, new Double(percent));
1046: notifyListeners(new PlotChangeEvent(this));
1047: }
1048:
1049:
1054: public double getMaximumExplodePercent() {
1055: double result = 0.0;
1056: for (int i = 0; i < this.explodePercentages.size(); i++) {
1057: Number explode = (Number) this.explodePercentages.get(i);
1058: if (explode != null) {
1059: result = Math.max(result, explode.doubleValue());
1060: }
1061: }
1062: return result;
1063: }
1064:
1065:
1070: public PieSectionLabelGenerator getLabelGenerator() {
1071: return this.labelGenerator;
1072: }
1073:
1074:
1080: public void setLabelGenerator(PieSectionLabelGenerator generator) {
1081: this.labelGenerator = generator;
1082: notifyListeners(new PlotChangeEvent(this));
1083: }
1084:
1085:
1091: public double getLabelGap() {
1092: return this.labelGap;
1093: }
1094:
1095:
1102: public void setLabelGap(double gap) {
1103: this.labelGap = gap;
1104: notifyListeners(new PlotChangeEvent(this));
1105: }
1106:
1107:
1112: public double getMaximumLabelWidth() {
1113: return this.maximumLabelWidth;
1114: }
1115:
1116:
1122: public void setMaximumLabelWidth(double width) {
1123: this.maximumLabelWidth = width;
1124: notifyListeners(new PlotChangeEvent(this));
1125: }
1126:
1127:
1133: public boolean getLabelLinksVisible() {
1134: return this.labelLinksVisible;
1135: }
1136:
1137:
1146: public void setLabelLinksVisible(boolean visible) {
1147: this.labelLinksVisible = visible;
1148: notifyListeners(new PlotChangeEvent(this));
1149: }
1150:
1151:
1157: public double getLabelLinkMargin() {
1158: return this.labelLinkMargin;
1159: }
1160:
1161:
1167: public void setLabelLinkMargin(double margin) {
1168: this.labelLinkMargin = margin;
1169: notifyListeners(new PlotChangeEvent(this));
1170: }
1171:
1172:
1178: public Paint getLabelLinkPaint() {
1179: return this.labelLinkPaint;
1180: }
1181:
1182:
1189: public void setLabelLinkPaint(Paint paint) {
1190: if (paint == null) {
1191: throw new IllegalArgumentException("Null 'paint' argument.");
1192: }
1193: this.labelLinkPaint = paint;
1194: notifyListeners(new PlotChangeEvent(this));
1195: }
1196:
1197:
1202: public Stroke getLabelLinkStroke() {
1203: return this.labelLinkStroke;
1204: }
1205:
1206:
1212: public void setLabelLinkStroke(Stroke stroke) {
1213: if (stroke == null) {
1214: throw new IllegalArgumentException("Null 'stroke' argument.");
1215: }
1216: this.labelLinkStroke = stroke;
1217: notifyListeners(new PlotChangeEvent(this));
1218: }
1219:
1220:
1225: public Font getLabelFont() {
1226: return this.labelFont;
1227: }
1228:
1229:
1235: public void setLabelFont(Font font) {
1236: if (font == null) {
1237: throw new IllegalArgumentException("Null 'font' argument.");
1238: }
1239: this.labelFont = font;
1240: notifyListeners(new PlotChangeEvent(this));
1241: }
1242:
1243:
1248: public Paint getLabelPaint() {
1249: return this.labelPaint;
1250: }
1251:
1252:
1258: public void setLabelPaint(Paint paint) {
1259: if (paint == null) {
1260: throw new IllegalArgumentException("Null 'paint' argument.");
1261: }
1262: this.labelPaint = paint;
1263: notifyListeners(new PlotChangeEvent(this));
1264: }
1265:
1266:
1271: public Paint getLabelBackgroundPaint() {
1272: return this.labelBackgroundPaint;
1273: }
1274:
1275:
1281: public void setLabelBackgroundPaint(Paint paint) {
1282: this.labelBackgroundPaint = paint;
1283: notifyListeners(new PlotChangeEvent(this));
1284: }
1285:
1286:
1291: public Paint getLabelOutlinePaint() {
1292: return this.labelOutlinePaint;
1293: }
1294:
1295:
1301: public void setLabelOutlinePaint(Paint paint) {
1302: this.labelOutlinePaint = paint;
1303: notifyListeners(new PlotChangeEvent(this));
1304: }
1305:
1306:
1311: public Stroke getLabelOutlineStroke() {
1312: return this.labelOutlineStroke;
1313: }
1314:
1315:
1321: public void setLabelOutlineStroke(Stroke stroke) {
1322: this.labelOutlineStroke = stroke;
1323: notifyListeners(new PlotChangeEvent(this));
1324: }
1325:
1326:
1331: public Paint getLabelShadowPaint() {
1332: return this.labelShadowPaint;
1333: }
1334:
1335:
1341: public void setLabelShadowPaint(Paint paint) {
1342: this.labelShadowPaint = paint;
1343: notifyListeners(new PlotChangeEvent(this));
1344: }
1345:
1346:
1353: public PieToolTipGenerator getToolTipGenerator() {
1354: return this.toolTipGenerator;
1355: }
1356:
1357:
1364: public void setToolTipGenerator(PieToolTipGenerator generator) {
1365: this.toolTipGenerator = generator;
1366: notifyListeners(new PlotChangeEvent(this));
1367: }
1368:
1369:
1374: public PieURLGenerator getURLGenerator() {
1375: return this.urlGenerator;
1376: }
1377:
1378:
1384: public void setURLGenerator(PieURLGenerator generator) {
1385: this.urlGenerator = generator;
1386: notifyListeners(new PlotChangeEvent(this));
1387: }
1388:
1389:
1395: public double getMinimumArcAngleToDraw() {
1396: return this.minimumArcAngleToDraw;
1397: }
1398:
1399:
1415: public void setMinimumArcAngleToDraw(double angle) {
1416: this.minimumArcAngleToDraw = angle;
1417: }
1418:
1419:
1424: public Shape getLegendItemShape() {
1425: return this.legendItemShape;
1426: }
1427:
1428:
1433: public void setLegendItemShape(Shape shape) {
1434: if (shape == null) {
1435: throw new IllegalArgumentException("Null 'shape' argument.");
1436: }
1437: this.legendItemShape = shape;
1438: notifyListeners(new PlotChangeEvent(this));
1439: }
1440:
1441:
1446: public PieSectionLabelGenerator getLegendLabelToolTipGenerator() {
1447: return this.legendLabelToolTipGenerator;
1448: }
1449:
1450:
1456: public void setLegendLabelToolTipGenerator(
1457: PieSectionLabelGenerator generator) {
1458: this.legendLabelToolTipGenerator = generator;
1459: notifyListeners(new PlotChangeEvent(this));
1460: }
1461:
1462:
1467: public PieSectionLabelGenerator getLegendLabelGenerator() {
1468: return this.legendLabelGenerator;
1469: }
1470:
1471:
1477: public void setLegendLabelGenerator(PieSectionLabelGenerator generator) {
1478: if (generator == null) {
1479: throw new IllegalArgumentException("Null 'generator' argument.");
1480: }
1481: this.legendLabelGenerator = generator;
1482: notifyListeners(new PlotChangeEvent(this));
1483: }
1484:
1485:
1500: public PiePlotState initialise(Graphics2D g2, Rectangle2D plotArea,
1501: PiePlot plot, Integer index, PlotRenderingInfo info) {
1502:
1503: PiePlotState state = new PiePlotState(info);
1504: state.setPassesRequired(2);
1505: state.setTotal(DatasetUtilities.calculatePieDatasetTotal(
1506: plot.getDataset()));
1507: state.setLatestAngle(plot.getStartAngle());
1508: return state;
1509:
1510: }
1511:
1512:
1523: public void draw(Graphics2D g2, Rectangle2D area, Point2D anchor,
1524: PlotState parentState, PlotRenderingInfo info) {
1525:
1526:
1527: RectangleInsets insets = getInsets();
1528: insets.trim(area);
1529:
1530: if (info != null) {
1531: info.setPlotArea(area);
1532: info.setDataArea(area);
1533: }
1534:
1535: drawBackground(g2, area);
1536: drawOutline(g2, area);
1537:
1538: Shape savedClip = g2.getClip();
1539: g2.clip(area);
1540:
1541: Composite originalComposite = g2.getComposite();
1542: g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
1543: getForegroundAlpha()));
1544:
1545: if (!DatasetUtilities.isEmptyOrNull(this.dataset)) {
1546: drawPie(g2, area, info);
1547: }
1548: else {
1549: drawNoDataMessage(g2, area);
1550: }
1551:
1552: g2.setClip(savedClip);
1553: g2.setComposite(originalComposite);
1554:
1555: drawOutline(g2, area);
1556:
1557: }
1558:
1559:
1566: protected void drawPie(Graphics2D g2, Rectangle2D plotArea,
1567: PlotRenderingInfo info) {
1568:
1569: PiePlotState state = initialise(g2, plotArea, this, null, info);
1570:
1571:
1572: double labelWidth = 0.0;
1573: if (this.labelGenerator != null) {
1574: labelWidth = this.labelGap + this.maximumLabelWidth
1575: + this.labelLinkMargin;
1576: }
1577: double gapHorizontal
1578: = plotArea.getWidth() * (this.interiorGap + labelWidth);
1579: double gapVertical = plotArea.getHeight() * this.interiorGap;
1580:
1581: double linkX = plotArea.getX() + gapHorizontal / 2;
1582: double linkY = plotArea.getY() + gapVertical / 2;
1583: double linkW = plotArea.getWidth() - gapHorizontal;
1584: double linkH = plotArea.getHeight() - gapVertical;
1585:
1586:
1587: if (this.circular) {
1588: double min = Math.min(linkW, linkH) / 2;
1589: linkX = (linkX + linkX + linkW) / 2 - min;
1590: linkY = (linkY + linkY + linkH) / 2 - min;
1591: linkW = 2 * min;
1592: linkH = 2 * min;
1593: }
1594:
1595:
1596:
1597: Rectangle2D linkArea = new Rectangle2D.Double(linkX, linkY, linkW,
1598: linkH);
1599: state.setLinkArea(linkArea);
1600:
1601:
1602:
1603:
1604: double hh = linkArea.getWidth() * this.labelLinkMargin;
1605: double vv = linkArea.getHeight() * this.labelLinkMargin;
1606: Rectangle2D explodeArea = new Rectangle2D.Double(linkX + hh / 2.0,
1607: linkY + vv / 2.0, linkW - hh, linkH - vv);
1608:
1609: state.setExplodedPieArea(explodeArea);
1610:
1611:
1612:
1613:
1614: double maximumExplodePercent = getMaximumExplodePercent();
1615: double percent = maximumExplodePercent / (1.0 + maximumExplodePercent);
1616:
1617: double h1 = explodeArea.getWidth() * percent;
1618: double v1 = explodeArea.getHeight() * percent;
1619: Rectangle2D pieArea = new Rectangle2D.Double(explodeArea.getX()
1620: + h1 / 2.0, explodeArea.getY() + v1 / 2.0,
1621: explodeArea.getWidth() - h1, explodeArea.getHeight() - v1);
1622:
1623: state.setPieArea(pieArea);
1624: state.setPieCenterX(pieArea.getCenterX());
1625: state.setPieCenterY(pieArea.getCenterY());
1626: state.setPieWRadius(pieArea.getWidth() / 2.0);
1627: state.setPieHRadius(pieArea.getHeight() / 2.0);
1628:
1629: if ((this.dataset != null) && (this.dataset.getKeys().size() > 0)) {
1630:
1631: List keys = this.dataset.getKeys();
1632: double totalValue
1633: = DatasetUtilities.calculatePieDatasetTotal(this.dataset);
1634:
1635: int passesRequired = state.getPassesRequired();
1636: for (int pass = 0; pass < passesRequired; pass++) {
1637: double runningTotal = 0.0;
1638: for (int section = 0; section < keys.size(); section++) {
1639: Number n = this.dataset.getValue(section);
1640: if (n != null) {
1641: double value = n.doubleValue();
1642: if (value > 0.0) {
1643: runningTotal += value;
1644: drawItem(g2, section, explodeArea, state, pass);
1645: }
1646: }
1647: }
1648: }
1649:
1650: drawLabels(g2, keys, totalValue, plotArea, linkArea, state);
1651:
1652: }
1653: else {
1654: drawNoDataMessage(g2, plotArea);
1655: }
1656: }
1657:
1658:
1667: protected void drawItem(Graphics2D g2, int section, Rectangle2D dataArea,
1668: PiePlotState state, int currentPass) {
1669:
1670: Number n = this.dataset.getValue(section);
1671: if (n == null) {
1672: return;
1673: }
1674: double value = n.doubleValue();
1675: double angle1 = 0.0;
1676: double angle2 = 0.0;
1677:
1678: if (this.direction == Rotation.CLOCKWISE) {
1679: angle1 = state.getLatestAngle();
1680: angle2 = angle1 - value / state.getTotal() * 360.0;
1681: }
1682: else if (this.direction == Rotation.ANTICLOCKWISE) {
1683: angle1 = state.getLatestAngle();
1684: angle2 = angle1 + value / state.getTotal() * 360.0;
1685: }
1686: else {
1687: throw new IllegalStateException("Rotation type not recognised.");
1688: }
1689:
1690: double angle = (angle2 - angle1);
1691: if (Math.abs(angle) > getMinimumArcAngleToDraw()) {
1692: double ep = 0.0;
1693: double mep = getMaximumExplodePercent();
1694: if (mep > 0.0) {
1695: ep = getExplodePercent(section) / mep;
1696: }
1697: Rectangle2D arcBounds = getArcBounds(state.getPieArea(),
1698: state.getExplodedPieArea(), angle1, angle, ep);
1699: Arc2D.Double arc = new Arc2D.Double(arcBounds, angle1, angle,
1700: Arc2D.PIE);
1701:
1702: if (currentPass == 0) {
1703: if (this.shadowPaint != null) {
1704: Shape shadowArc = ShapeUtilities.createTranslatedShape(
1705: arc, (float) this.shadowXOffset,
1706: (float) this.shadowYOffset);
1707: g2.setPaint(this.shadowPaint);
1708: g2.fill(shadowArc);
1709: }
1710: }
1711: else if (currentPass == 1) {
1712:
1713: Paint paint = getSectionPaint(section);
1714: g2.setPaint(paint);
1715: g2.fill(arc);
1716:
1717: Paint outlinePaint = getSectionOutlinePaint(section);
1718: Stroke outlineStroke = getSectionOutlineStroke(section);
1719: if (this.sectionOutlinesVisible) {
1720: g2.setPaint(outlinePaint);
1721: g2.setStroke(outlineStroke);
1722: g2.draw(arc);
1723: }
1724:
1725:
1726:
1727: if (state.getInfo() != null) {
1728: EntityCollection entities = state.getEntityCollection();
1729: if (entities != null) {
1730: Comparable key = this.dataset.getKey(section);
1731: String tip = null;
1732: if (this.toolTipGenerator != null) {
1733: tip = this.toolTipGenerator.generateToolTip(
1734: this.dataset, key);
1735: }
1736: String url = null;
1737: if (this.urlGenerator != null) {
1738: url = this.urlGenerator.generateURL(this.dataset,
1739: key, this.pieIndex);
1740: }
1741: PieSectionEntity entity = new PieSectionEntity(
1742: arc, this.dataset, this.pieIndex, section, key,
1743: tip, url);
1744: entities.add(entity);
1745: }
1746: }
1747: }
1748: }
1749: state.setLatestAngle(angle2);
1750: }
1751:
1752:
1762: protected void drawLabels(Graphics2D g2, List keys, double totalValue,
1763: Rectangle2D plotArea, Rectangle2D linkArea,
1764: PiePlotState state) {
1765:
1766: Composite originalComposite = g2.getComposite();
1767: g2.setComposite(
1768: AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
1769:
1770:
1771: DefaultKeyedValues leftKeys = new DefaultKeyedValues();
1772: DefaultKeyedValues rightKeys = new DefaultKeyedValues();
1773:
1774: double runningTotal1 = 0.0;
1775: Iterator iterator1 = keys.iterator();
1776: while (iterator1.hasNext()) {
1777: Comparable key = (Comparable) iterator1.next();
1778: boolean include = true;
1779: double v = 0.0;
1780: Number n = this.dataset.getValue(key);
1781: if (n == null) {
1782: include = !this.ignoreNullValues;
1783: }
1784: else {
1785: v = n.doubleValue();
1786: include = this.ignoreZeroValues ? v > 0.0 : v >= 0.0;
1787: }
1788:
1789: if (include) {
1790: runningTotal1 = runningTotal1 + v;
1791:
1792:
1793: double mid = this.startAngle + (this.direction.getFactor()
1794: * ((runningTotal1 - v / 2.0) * 360) / totalValue);
1795: if (Math.cos(Math.toRadians(mid)) < 0.0) {
1796: leftKeys.addValue(key, new Double(mid));
1797: }
1798: else {
1799: rightKeys.addValue(key, new Double(mid));
1800: }
1801: }
1802: }
1803:
1804: g2.setFont(getLabelFont());
1805: float maxLabelWidth
1806: = (float) (getMaximumLabelWidth() * plotArea.getWidth());
1807:
1808:
1809: if (this.labelGenerator != null) {
1810: drawLeftLabels(leftKeys, g2, plotArea, linkArea, maxLabelWidth,
1811: state);
1812: drawRightLabels(rightKeys, g2, plotArea, linkArea, maxLabelWidth,
1813: state);
1814: }
1815: g2.setComposite(originalComposite);
1816:
1817: }
1818:
1819:
1829: protected void drawLeftLabels(KeyedValues leftKeys, Graphics2D g2,
1830: Rectangle2D plotArea, Rectangle2D linkArea,
1831: float maxLabelWidth, PiePlotState state) {
1832:
1833: PieLabelDistributor distributor1 = new PieLabelDistributor(
1834: leftKeys.getItemCount()
1835: );
1836: double lGap = plotArea.getWidth() * this.labelGap;
1837: double verticalLinkRadius = state.getLinkArea().getHeight() / 2.0;
1838: for (int i = 0; i < leftKeys.getItemCount(); i++) {
1839: String label = this.labelGenerator.generateSectionLabel(
1840: this.dataset, leftKeys.getKey(i));
1841: if (label != null) {
1842: TextBlock block = TextUtilities.createTextBlock(label,
1843: this.labelFont, this.labelPaint, maxLabelWidth,
1844: new G2TextMeasurer(g2));
1845: TextBox labelBox = new TextBox(block);
1846: labelBox.setBackgroundPaint(this.labelBackgroundPaint);
1847: labelBox.setOutlinePaint(this.labelOutlinePaint);
1848: labelBox.setOutlineStroke(this.labelOutlineStroke);
1849: labelBox.setShadowPaint(this.labelShadowPaint);
1850: double theta = Math.toRadians(
1851: leftKeys.getValue(i).doubleValue());
1852: double baseY = state.getPieCenterY() - Math.sin(theta)
1853: * verticalLinkRadius;
1854: double hh = labelBox.getHeight(g2);
1855:
1856: distributor1.addPieLabelRecord(new PieLabelRecord(
1857: leftKeys.getKey(i), theta, baseY, labelBox, hh,
1858: lGap / 2.0 + lGap / 2.0 * -Math.cos(theta), 0.9
1859: + getExplodePercent(this.dataset.getIndex(
1860: leftKeys.getKey(i)))));
1861: }
1862: }
1863: distributor1.distributeLabels(plotArea.getMinY(), plotArea.getHeight());
1864: for (int i = 0; i < distributor1.getItemCount(); i++) {
1865: drawLeftLabel(g2, state, distributor1.getPieLabelRecord(i));
1866: }
1867: }
1868:
1869:
1879: protected void drawRightLabels(KeyedValues keys, Graphics2D g2,
1880: Rectangle2D plotArea, Rectangle2D linkArea,
1881: float maxLabelWidth, PiePlotState state) {
1882:
1883:
1884: PieLabelDistributor distributor2
1885: = new PieLabelDistributor(keys.getItemCount());
1886: double lGap = plotArea.getWidth() * this.labelGap;
1887: double verticalLinkRadius = state.getLinkArea().getHeight() / 2.0;
1888:
1889: for (int i = 0; i < keys.getItemCount(); i++) {
1890: String label = this.labelGenerator.generateSectionLabel(
1891: this.dataset, keys.getKey(i));
1892:
1893: if (label != null) {
1894: TextBlock block = TextUtilities.createTextBlock(label,
1895: this.labelFont, this.labelPaint, maxLabelWidth,
1896: new G2TextMeasurer(g2));
1897: TextBox labelBox = new TextBox(block);
1898: labelBox.setBackgroundPaint(this.labelBackgroundPaint);
1899: labelBox.setOutlinePaint(this.labelOutlinePaint);
1900: labelBox.setOutlineStroke(this.labelOutlineStroke);
1901: labelBox.setShadowPaint(this.labelShadowPaint);
1902: double theta = Math.toRadians(keys.getValue(i).doubleValue());
1903: double baseY = state.getPieCenterY()
1904: - Math.sin(theta) * verticalLinkRadius;
1905: double hh = labelBox.getHeight(g2);
1906: distributor2.addPieLabelRecord(new PieLabelRecord(
1907: keys.getKey(i), theta, baseY, labelBox, hh,
1908: lGap / 2.0 + lGap / 2.0 * Math.cos(theta),
1909: 0.9 + getExplodePercent(this.dataset.getIndex(
1910: keys.getKey(i)))));
1911: }
1912: }
1913: distributor2.distributeLabels(plotArea.getMinY(), plotArea.getHeight());
1914: for (int i = 0; i < distributor2.getItemCount(); i++) {
1915: drawRightLabel(g2, state, distributor2.getPieLabelRecord(i));
1916: }
1917:
1918: }
1919:
1920:
1925: public LegendItemCollection getLegendItems() {
1926:
1927: LegendItemCollection result = new LegendItemCollection();
1928: if (this.dataset == null) {
1929: return result;
1930: }
1931: List keys = this.dataset.getKeys();
1932: int section = 0;
1933: Shape shape = getLegendItemShape();
1934: Iterator iterator = keys.iterator();
1935: while (iterator.hasNext()) {
1936: Comparable key = (Comparable) iterator.next();
1937: Number n = this.dataset.getValue(key);
1938: boolean include = true;
1939: if (n == null) {
1940: include = !this.ignoreNullValues;
1941: }
1942: else {
1943: double v = n.doubleValue();
1944: if (v == 0.0) {
1945: include = !this.ignoreZeroValues;
1946: }
1947: else {
1948: include = v > 0.0;
1949: }
1950: }
1951: if (include) {
1952: String label = this.legendLabelGenerator.generateSectionLabel(
1953: this.dataset, key);
1954: String description = label;
1955: String toolTipText = null;
1956: if (this.legendLabelToolTipGenerator != null) {
1957: toolTipText
1958: = this.legendLabelToolTipGenerator.generateSectionLabel(
1959: this.dataset, key);
1960: }
1961: String urlText = null;
1962: Paint paint = getSectionPaint(section);
1963: Paint outlinePaint = getSectionOutlinePaint(section);
1964: Stroke outlineStroke = getSectionOutlineStroke(section);
1965:
1966: LegendItem item = new LegendItem(label, description,
1967: toolTipText, urlText, true, shape, true, paint,
1968: true, outlinePaint, outlineStroke,
1969: false,
1970: new Line2D.Float(), new BasicStroke(), Color.black);
1971: result.add(item);
1972: section++;
1973: }
1974: else {
1975: section++;
1976: }
1977: }
1978: return result;
1979: }
1980:
1981:
1986: public String getPlotType() {
1987: return localizationResources.getString("Pie_Plot");
1988: }
1989:
1990:
1998: public void zoom(double percent) {
1999:
2000: }
2001:
2002:
2016: protected Rectangle2D getArcBounds(Rectangle2D unexploded,
2017: Rectangle2D exploded,
2018: double angle, double extent,
2019: double explodePercent) {
2020:
2021: if (explodePercent == 0.0) {
2022: return unexploded;
2023: }
2024: else {
2025: Arc2D arc1 = new Arc2D.Double(unexploded, angle, extent / 2,
2026: Arc2D.OPEN);
2027: Point2D point1 = arc1.getEndPoint();
2028: Arc2D.Double arc2 = new Arc2D.Double(exploded, angle, extent / 2,
2029: Arc2D.OPEN);
2030: Point2D point2 = arc2.getEndPoint();
2031: double deltaX = (point1.getX() - point2.getX()) * explodePercent;
2032: double deltaY = (point1.getY() - point2.getY()) * explodePercent;
2033: return new Rectangle2D.Double(unexploded.getX() - deltaX,
2034: unexploded.getY() - deltaY, unexploded.getWidth(),
2035: unexploded.getHeight());
2036: }
2037: }
2038:
2039:
2046: protected void drawLeftLabel(Graphics2D g2, PiePlotState state,
2047: PieLabelRecord record) {
2048:
2049: double anchorX = state.getLinkArea().getMinX();
2050: double targetX = anchorX - record.getGap();
2051: double targetY = record.getAllocatedY();
2052:
2053: if (this.labelLinksVisible) {
2054: double theta = record.getAngle();
2055: double linkX = state.getPieCenterX() + Math.cos(theta)
2056: * state.getPieWRadius() * record.getLinkPercent();
2057: double linkY = state.getPieCenterY() - Math.sin(theta)
2058: * state.getPieHRadius() * record.getLinkPercent();
2059: double elbowX = state.getPieCenterX() + Math.cos(theta)
2060: * state.getLinkArea().getWidth() / 2.0;
2061: double elbowY = state.getPieCenterY() - Math.sin(theta)
2062: * state.getLinkArea().getHeight() / 2.0;
2063: double anchorY = elbowY;
2064: g2.setPaint(this.labelLinkPaint);
2065: g2.setStroke(this.labelLinkStroke);
2066: g2.draw(new Line2D.Double(linkX, linkY, elbowX, elbowY));
2067: g2.draw(new Line2D.Double(anchorX, anchorY, elbowX, elbowY));
2068: g2.draw(new Line2D.Double(anchorX, anchorY, targetX, targetY));
2069: }
2070: TextBox tb = record.getLabel();
2071: tb.draw(g2, (float) targetX, (float) targetY, RectangleAnchor.RIGHT);
2072:
2073: }
2074:
2075:
2082: protected void drawRightLabel(Graphics2D g2, PiePlotState state,
2083: PieLabelRecord record) {
2084:
2085: double anchorX = state.getLinkArea().getMaxX();
2086: double targetX = anchorX + record.getGap();
2087: double targetY = record.getAllocatedY();
2088:
2089: if (this.labelLinksVisible) {
2090: double theta = record.getAngle();
2091: double linkX = state.getPieCenterX() + Math.cos(theta)
2092: * state.getPieWRadius() * record.getLinkPercent();
2093: double linkY = state.getPieCenterY() - Math.sin(theta)
2094: * state.getPieHRadius() * record.getLinkPercent();
2095: double elbowX = state.getPieCenterX() + Math.cos(theta)
2096: * state.getLinkArea().getWidth() / 2.0;
2097: double elbowY = state.getPieCenterY() - Math.sin(theta)
2098: * state.getLinkArea().getHeight() / 2.0;
2099: double anchorY = elbowY;
2100: g2.setPaint(this.labelLinkPaint);
2101: g2.setStroke(this.labelLinkStroke);
2102: g2.draw(new Line2D.Double(linkX, linkY, elbowX, elbowY));
2103: g2.draw(new Line2D.Double(anchorX, anchorY, elbowX, elbowY));
2104: g2.draw(new Line2D.Double(anchorX, anchorY, targetX, targetY));
2105: }
2106:
2107: TextBox tb = record.getLabel();
2108: tb.draw(g2, (float) targetX, (float) targetY, RectangleAnchor.LEFT);
2109:
2110: }
2111:
2112:
2120: public boolean equals(Object obj) {
2121: if (obj == this) {
2122: return true;
2123: }
2124: if (!(obj instanceof PiePlot)) {
2125: return false;
2126: }
2127: if (!super.equals(obj)) {
2128: return false;
2129: }
2130: PiePlot that = (PiePlot) obj;
2131: if (this.pieIndex != that.pieIndex) {
2132: return false;
2133: }
2134: if (this.interiorGap != that.interiorGap) {
2135: return false;
2136: }
2137: if (this.circular != that.circular) {
2138: return false;
2139: }
2140: if (this.startAngle != that.startAngle) {
2141: return false;
2142: }
2143: if (this.direction != that.direction) {
2144: return false;
2145: }
2146: if (this.ignoreZeroValues != that.ignoreZeroValues) {
2147: return false;
2148: }
2149: if (this.ignoreNullValues != that.ignoreNullValues) {
2150: return false;
2151: }
2152: if (!PaintUtilities.equal(this.sectionPaint, that.sectionPaint)) {
2153: return false;
2154: }
2155: if (!ObjectUtilities.equal(this.sectionPaintList,
2156: that.sectionPaintList)) {
2157: return false;
2158: }
2159: if (!PaintUtilities.equal(this.baseSectionPaint,
2160: that.baseSectionPaint)) {
2161: return false;
2162: }
2163: if (this.sectionOutlinesVisible != that.sectionOutlinesVisible) {
2164: return false;
2165: }
2166: if (!PaintUtilities.equal(this.sectionOutlinePaint,
2167: that.sectionOutlinePaint)) {
2168: return false;
2169: }
2170: if (!ObjectUtilities.equal(this.sectionOutlinePaintList,
2171: that.sectionOutlinePaintList)) {
2172: return false;
2173: }
2174: if (!PaintUtilities.equal(
2175: this.baseSectionOutlinePaint, that.baseSectionOutlinePaint
2176: )) {
2177: return false;
2178: }
2179: if (!ObjectUtilities.equal(this.sectionOutlineStroke,
2180: that.sectionOutlineStroke)) {
2181: return false;
2182: }
2183: if (!ObjectUtilities.equal(
2184: this.sectionOutlineStrokeList, that.sectionOutlineStrokeList
2185: )) {
2186: return false;
2187: }
2188: if (!ObjectUtilities.equal(
2189: this.baseSectionOutlineStroke, that.baseSectionOutlineStroke
2190: )) {
2191: return false;
2192: }
2193: if (!PaintUtilities.equal(this.shadowPaint, that.shadowPaint)) {
2194: return false;
2195: }
2196: if (!(this.shadowXOffset == that.shadowXOffset)) {
2197: return false;
2198: }
2199: if (!(this.shadowYOffset == that.shadowYOffset)) {
2200: return false;
2201: }
2202: if (!ObjectUtilities.equal(this.explodePercentages,
2203: that.explodePercentages)) {
2204: return false;
2205: }
2206: if (!ObjectUtilities.equal(this.labelGenerator,
2207: that.labelGenerator)) {
2208: return false;
2209: }
2210: if (!ObjectUtilities.equal(this.labelFont, that.labelFont)) {
2211: return false;
2212: }
2213: if (!PaintUtilities.equal(this.labelPaint, that.labelPaint)) {
2214: return false;
2215: }
2216: if (!PaintUtilities.equal(this.labelBackgroundPaint,
2217: that.labelBackgroundPaint)) {
2218: return false;
2219: }
2220: if (!PaintUtilities.equal(this.labelOutlinePaint,
2221: that.labelOutlinePaint)) {
2222: return false;
2223: }
2224: if (!ObjectUtilities.equal(this.labelOutlineStroke,
2225: that.labelOutlineStroke)) {
2226: return false;
2227: }
2228: if (!PaintUtilities.equal(this.labelShadowPaint,
2229: that.labelShadowPaint)) {
2230: return false;
2231: }
2232: if (!(this.maximumLabelWidth == that.maximumLabelWidth)) {
2233: return false;
2234: }
2235: if (!(this.labelGap == that.labelGap)) {
2236: return false;
2237: }
2238: if (!(this.labelLinkMargin == that.labelLinkMargin)) {
2239: return false;
2240: }
2241: if (this.labelLinksVisible != that.labelLinksVisible) {
2242: return false;
2243: }
2244: if (!PaintUtilities.equal(this.labelLinkPaint, that.labelLinkPaint)) {
2245: return false;
2246: }
2247: if (!ObjectUtilities.equal(this.labelLinkStroke,
2248: that.labelLinkStroke)) {
2249: return false;
2250: }
2251: if (!ObjectUtilities.equal(this.toolTipGenerator,
2252: that.toolTipGenerator)) {
2253: return false;
2254: }
2255: if (!ObjectUtilities.equal(this.urlGenerator, that.urlGenerator)) {
2256: return false;
2257: }
2258: if (!(this.minimumArcAngleToDraw == that.minimumArcAngleToDraw)) {
2259: return false;
2260: }
2261: if (!ShapeUtilities.equal(this.legendItemShape, that.legendItemShape)) {
2262: return false;
2263: }
2264:
2265: return true;
2266: }
2267:
2268:
2276: public Object clone() throws CloneNotSupportedException {
2277:
2278: PiePlot clone = (PiePlot) super.clone();
2279: if (clone.dataset != null) {
2280: clone.dataset.addChangeListener(clone);
2281: }
2282: return clone;
2283:
2284: }
2285:
2286:
2293: private void writeObject(ObjectOutputStream stream) throws IOException {
2294: stream.defaultWriteObject();
2295: SerialUtilities.writePaint(this.sectionPaint, stream);
2296: SerialUtilities.writePaint(this.baseSectionPaint, stream);
2297: SerialUtilities.writePaint(this.sectionOutlinePaint, stream);
2298: SerialUtilities.writePaint(this.baseSectionOutlinePaint, stream);
2299: SerialUtilities.writeStroke(this.sectionOutlineStroke, stream);
2300: SerialUtilities.writeStroke(this.baseSectionOutlineStroke, stream);
2301: SerialUtilities.writePaint(this.shadowPaint, stream);
2302: SerialUtilities.writePaint(this.labelPaint, stream);
2303: SerialUtilities.writePaint(this.labelBackgroundPaint, stream);
2304: SerialUtilities.writePaint(this.labelOutlinePaint, stream);
2305: SerialUtilities.writeStroke(this.labelOutlineStroke, stream);
2306: SerialUtilities.writePaint(this.labelShadowPaint, stream);
2307: SerialUtilities.writePaint(this.labelLinkPaint, stream);
2308: SerialUtilities.writeStroke(this.labelLinkStroke, stream);
2309: SerialUtilities.writeShape(this.legendItemShape, stream);
2310: }
2311:
2312:
2320: private void readObject(ObjectInputStream stream)
2321: throws IOException, ClassNotFoundException {
2322: stream.defaultReadObject();
2323: this.sectionPaint = SerialUtilities.readPaint(stream);
2324: this.baseSectionPaint = SerialUtilities.readPaint(stream);
2325: this.sectionOutlinePaint = SerialUtilities.readPaint(stream);
2326: this.baseSectionOutlinePaint = SerialUtilities.readPaint(stream);
2327: this.sectionOutlineStroke = SerialUtilities.readStroke(stream);
2328: this.baseSectionOutlineStroke = SerialUtilities.readStroke(stream);
2329: this.shadowPaint = SerialUtilities.readPaint(stream);
2330: this.labelPaint = SerialUtilities.readPaint(stream);
2331: this.labelBackgroundPaint = SerialUtilities.readPaint(stream);
2332: this.labelOutlinePaint = SerialUtilities.readPaint(stream);
2333: this.labelOutlineStroke = SerialUtilities.readStroke(stream);
2334: this.labelShadowPaint = SerialUtilities.readPaint(stream);
2335: this.labelLinkPaint = SerialUtilities.readPaint(stream);
2336: this.labelLinkStroke = SerialUtilities.readStroke(stream);
2337: this.legendItemShape = SerialUtilities.readShape(stream);
2338: }
2339:
2340: }