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 935 public LegendItemCollection getLegendItems() { 936 LegendItemCollection result = new LegendItemCollection(); 937 938 List keys = null; 939 940 if (this.dataExtractOrder == TableOrder.BY_ROW) { 941 keys = this.dataset.getRowKeys(); 942 } 943 else if (this.dataExtractOrder == TableOrder.BY_COLUMN) { 944 keys = this.dataset.getColumnKeys(); 945 } 946 947 if (keys != null) { 948 int series = 0; 949 Iterator iterator = keys.iterator(); 950 Shape shape = getLegendItemShape(); 951 952 while (iterator.hasNext()) { 953 String label = iterator.next().toString(); 954 String description = label; 955 956 Paint paint = getSeriesPaint(series); 957 Paint outlinePaint = getSeriesOutlinePaint(series); 958 Stroke stroke = getSeriesOutlineStroke(series); 959 LegendItem item = new LegendItem(label, description, 960 null, null, shape, paint, stroke, outlinePaint); 961 result.add(item); 962 series++; 963 } 964 } 965 966 return result; 967 } 968 969 978 protected Point2D getWebPoint(Rectangle2D bounds, 979 double angle, double length) { 980 981 double angrad = Math.toRadians(angle); 982 double x = Math.cos(angrad) * length * bounds.getWidth() / 2; 983 double y = -Math.sin(angrad) * length * bounds.getHeight() / 2; 984 985 return new Point2D.Double (bounds.getX() + x + bounds.getWidth() / 2, 986 bounds.getY() + y + bounds.getHeight() / 2); 987 } 988 989 999 public void draw(Graphics2D g2, Rectangle2D area, Point2D anchor, 1000 PlotState parentState, 1001 PlotRenderingInfo info) 1002 { 1003 RectangleInsets insets = getInsets(); 1005 insets.trim(area); 1006 1007 if (info != null) { 1008 info.setPlotArea(area); 1009 info.setDataArea(area); 1010 } 1011 1012 drawBackground(g2, area); 1013 drawOutline(g2, area); 1014 1015 Shape savedClip = g2.getClip(); 1016 1017 g2.clip(area); 1018 Composite originalComposite = g2.getComposite(); 1019 g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1020 getForegroundAlpha())); 1021 1022 if (!DatasetUtilities.isEmptyOrNull(this.dataset)) { 1023 int seriesCount = 0, catCount = 0; 1024 1025 if (this.dataExtractOrder == TableOrder.BY_ROW) { 1026 seriesCount = this.dataset.getRowCount(); 1027 catCount = this.dataset.getColumnCount(); 1028 } 1029 else { 1030 seriesCount = this.dataset.getColumnCount(); 1031 catCount = this.dataset.getRowCount(); 1032 } 1033 1034 if (this.maxValue == DEFAULT_MAX_VALUE) 1036 calculateMaxValue(seriesCount, catCount); 1037 1038 1040 1042 double gapHorizontal = area.getWidth() * getInteriorGap(); 1043 double gapVertical = area.getHeight() * getInteriorGap(); 1044 1045 double X = area.getX() + gapHorizontal / 2; 1046 double Y = area.getY() + gapVertical / 2; 1047 double W = area.getWidth() - gapHorizontal; 1048 double H = area.getHeight() - gapVertical; 1049 1050 double headW = area.getWidth() * this.headPercent; 1051 double headH = area.getHeight() * this.headPercent; 1052 1053 double min = Math.min(W, H) / 2; 1055 X = (X + X + W) / 2 - min; 1056 Y = (Y + Y + H) / 2 - min; 1057 W = 2 * min; 1058 H = 2 * min; 1059 1060 Point2D centre = new Point2D.Double (X + W / 2, Y + H / 2); 1061 Rectangle2D radarArea = new Rectangle2D.Double (X, Y, W, H); 1062 1063 1065 for (int series = 0; series < seriesCount; series++) { 1066 drawRadarPoly(g2, radarArea, centre, info, series, catCount, 1067 headH, headW); 1068 } 1069 } 1070 else { 1071 drawNoDataMessage(g2, area); 1072 } 1073 g2.clip(savedClip); 1074 g2.setComposite(originalComposite); 1075 drawOutline(g2, area); 1076 } 1077 1078 1085 private void calculateMaxValue(int seriesCount, int catCount) { 1086 double v = 0; 1087 Number nV = null; 1088 1089 for (int seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++) { 1090 for (int catIndex = 0; catIndex < catCount; catIndex++) { 1091 nV = getPlotValue(seriesIndex, catIndex); 1092 if (nV != null) { 1093 v = nV.doubleValue(); 1094 if (v > this.maxValue) { 1095 this.maxValue = v; 1096 } 1097 } 1098 } 1099 } 1100 } 1101 1102 1114 protected void drawRadarPoly(Graphics2D g2, 1115 Rectangle2D plotArea, 1116 Point2D centre, 1117 PlotRenderingInfo info, 1118 int series, int catCount, 1119 double headH, double headW) { 1120 1121 Polygon polygon = new Polygon (); 1122 1123 EntityCollection entities = null; 1124 if (info != null) { 1125 entities = info.getOwner().getEntityCollection(); 1126 } 1127 1128 for (int cat = 0; cat < catCount; cat++) { 1130 Number dataValue = getPlotValue(series, cat); 1131 1132 if (dataValue != null) { 1133 double value = dataValue.doubleValue(); 1134 1135 if (value >= 0) { 1137 1139 double angle = getStartAngle() 1140 + (getDirection().getFactor() * cat * 360 / catCount); 1141 1142 1149 1153 Point2D point = getWebPoint(plotArea, angle, 1154 value / this.maxValue); 1155 polygon.addPoint((int) point.getX(), (int) point.getY()); 1156 1157 1159 Paint paint = getSeriesPaint(series); 1160 Paint outlinePaint = getSeriesOutlinePaint(series); 1161 Stroke outlineStroke = getSeriesOutlineStroke(series); 1162 1163 Ellipse2D head = new Ellipse2D.Double (point.getX() 1164 - headW / 2, point.getY() - headH / 2, headW, 1165 headH); 1166 g2.setPaint(paint); 1167 g2.fill(head); 1168 g2.setStroke(outlineStroke); 1169 g2.setPaint(outlinePaint); 1170 g2.draw(head); 1171 1172 if (entities != null) { 1173 String tip = null; 1174 if (this.toolTipGenerator != null) { 1175 tip = this.toolTipGenerator.generateToolTip( 1176 this.dataset, series, cat); 1177 } 1178 1179 String url = null; 1180 if (this.urlGenerator != null) { 1181 url = this.urlGenerator.generateURL(this.dataset, 1182 series, cat); 1183 } 1184 1185 Shape area = new Rectangle ((int) (point.getX() - headW), 1186 (int) (point.getY() - headH), 1187 (int) (headW * 2), (int) (headH * 2)); 1188 CategoryItemEntity entity = new CategoryItemEntity( 1189 area, tip, url, this.dataset, series, 1190 dataset.getColumnKey(cat), cat); 1191 entities.add(entity); 1192 } 1193 1194 1197 if (series == 0) { 1198 Point2D endPoint = getWebPoint(plotArea, angle, 1); 1199 Line2D line = new Line2D.Double (centre, endPoint); 1201 g2.draw(line); 1202 drawLabel(g2, plotArea, value, cat, angle, 1203 360.0 / catCount); 1204 } 1205 } 1206 } 1207 } 1208 1210 Paint paint = getSeriesPaint(series); 1211 g2.setPaint(paint); 1212 g2.draw(polygon); 1213 1214 1216 if (this.webFilled) { 1217 g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1218 0.1f)); 1219 g2.fill(polygon); 1220 g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1221 getForegroundAlpha())); 1222 } 1223 } 1224 1225 1236 Number getPlotValue(int series, int cat) { 1237 Number value = null; 1238 if (this.dataExtractOrder == TableOrder.BY_ROW) { 1239 value = this.dataset.getValue(series, cat); 1240 } 1241 else if (this.dataExtractOrder == TableOrder.BY_COLUMN) { 1242 value = this.dataset.getValue(cat, series); 1243 } 1244 return value; 1245 } 1246 1247 1257 protected void drawLabel(Graphics2D g2, Rectangle2D plotArea, double value, 1258 int cat, double startAngle, double extent) { 1259 FontRenderContext frc = g2.getFontRenderContext(); 1260 1261 String label = null; 1262 if (this.dataExtractOrder == TableOrder.BY_ROW) { 1263 label = this.labelGenerator.generateColumnLabel(this.dataset, cat); 1265 } 1266 else { 1267 label = this.labelGenerator.generateRowLabel(this.dataset, cat); 1269 } 1270 1271 Rectangle2D labelBounds = getLabelFont().getStringBounds(label, frc); 1272 LineMetrics lm = getLabelFont().getLineMetrics(label, frc); 1273 double ascent = lm.getAscent(); 1274 1275 Point2D labelLocation = calculateLabelLocation(labelBounds, ascent, 1276 plotArea, startAngle); 1277 1278 Composite saveComposite = g2.getComposite(); 1279 1280 g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1281 1.0f)); 1282 g2.setPaint(getLabelPaint()); 1283 g2.setFont(getLabelFont()); 1284 g2.drawString(label, (float) labelLocation.getX(), 1285 (float) labelLocation.getY()); 1286 g2.setComposite(saveComposite); 1287 } 1288 1289 1299 protected Point2D calculateLabelLocation(Rectangle2D labelBounds, 1300 double ascent, 1301 Rectangle2D plotArea, 1302 double startAngle) 1303 { 1304 Arc2D arc1 = new Arc2D.Double (plotArea, startAngle, 0, Arc2D.OPEN); 1305 Point2D point1 = arc1.getEndPoint(); 1306 1307 double deltaX = -(point1.getX() - plotArea.getCenterX()) 1308 * this.axisLabelGap; 1309 double deltaY = -(point1.getY() - plotArea.getCenterY()) 1310 * this.axisLabelGap; 1311 1312 double labelX = point1.getX() - deltaX; 1313 double labelY = point1.getY() - deltaY; 1314 1315 if (labelX < plotArea.getCenterX()) { 1316 labelX -= labelBounds.getWidth(); 1317 } 1318 1319 if (labelX == plotArea.getCenterX()) { 1320 labelX -= labelBounds.getWidth() / 2; 1321 } 1322 1323 if (labelY > plotArea.getCenterY()) { 1324 labelY += ascent; 1325 } 1326 1327 return new Point2D.Double (labelX, labelY); 1328 } 1329 1330 1337 public boolean equals(Object obj) { 1338 if (obj == this) { 1339 return true; 1340 } 1341 if (!(obj instanceof SpiderWebPlot)) { 1342 return false; 1343 } 1344 if (!super.equals(obj)) { 1345 return false; 1346 } 1347 SpiderWebPlot that = (SpiderWebPlot) obj; 1348 if (!this.dataExtractOrder.equals(that.dataExtractOrder)) { 1349 return false; 1350 } 1351 if (this.headPercent != that.headPercent) { 1352 return false; 1353 } 1354 if (this.interiorGap != that.interiorGap) { 1355 return false; 1356 } 1357 if (this.startAngle != that.startAngle) { 1358 return false; 1359 } 1360 if (!this.direction.equals(that.direction)) { 1361 return false; 1362 } 1363 if (this.maxValue != that.maxValue) { 1364 return false; 1365 } 1366 if (this.webFilled != that.webFilled) { 1367 return false; 1368 } 1369 if (!ShapeUtilities.equal(this.legendItemShape, that.legendItemShape)) { 1370 return false; 1371 } 1372 if (!PaintUtilities.equal(this.seriesPaint, that.seriesPaint)) { 1373 return false; 1374 } 1375 if (!this.seriesPaintList.equals(that.seriesPaintList)) { 1376 return false; 1377 } 1378 if (!PaintUtilities.equal(this.baseSeriesPaint, that.baseSeriesPaint)) { 1379 return false; 1380 } 1381 if (!PaintUtilities.equal(this.seriesOutlinePaint, 1382 that.seriesOutlinePaint)) { 1383 return false; 1384 } 1385 if (!this.seriesOutlinePaintList.equals(that.seriesOutlinePaintList)) { 1386 return false; 1387 } 1388 if (!PaintUtilities.equal(this.baseSeriesOutlinePaint, 1389 that.baseSeriesOutlinePaint)) { 1390 return false; 1391 } 1392 if (!ObjectUtilities.equal(this.seriesOutlineStroke, 1393 that.seriesOutlineStroke)) { 1394 return false; 1395 } 1396 if (!this.seriesOutlineStrokeList.equals( 1397 that.seriesOutlineStrokeList)) { 1398 return false; 1399 } 1400 if (!this.baseSeriesOutlineStroke.equals( 1401 that.baseSeriesOutlineStroke)) { 1402 return false; 1403 } 1404 if (!this.labelFont.equals(that.labelFont)) { 1405 return false; 1406 } 1407 if (!PaintUtilities.equal(this.labelPaint, that.labelPaint)) { 1408 return false; 1409 } 1410 if (!this.labelGenerator.equals(that.labelGenerator)) { 1411 return false; 1412 } 1413 if (!ObjectUtilities.equal(this.toolTipGenerator, 1414 that.toolTipGenerator)) { 1415 return false; 1416 } 1417 if (!ObjectUtilities.equal(this.urlGenerator, 1418 that.urlGenerator)) { 1419 return false; 1420 } 1421 return true; 1422 } 1423 1424 1431 private void writeObject(ObjectOutputStream stream) throws IOException { 1432 stream.defaultWriteObject(); 1433 1434 SerialUtilities.writeShape(this.legendItemShape, stream); 1435 SerialUtilities.writePaint(this.seriesPaint, stream); 1436 SerialUtilities.writePaint(this.baseSeriesPaint, stream); 1437 SerialUtilities.writePaint(this.seriesOutlinePaint, stream); 1438 SerialUtilities.writePaint(this.baseSeriesOutlinePaint, stream); 1439 SerialUtilities.writeStroke(this.seriesOutlineStroke, stream); 1440 SerialUtilities.writeStroke(this.baseSeriesOutlineStroke, stream); 1441 SerialUtilities.writePaint(this.labelPaint, stream); 1442 } 1443 1444 1452 private void readObject(ObjectInputStream stream) throws IOException , 1453 ClassNotFoundException { 1454 stream.defaultReadObject(); 1455 1456 this.legendItemShape = SerialUtilities.readShape(stream); 1457 this.seriesPaint = SerialUtilities.readPaint(stream); 1458 this.baseSeriesPaint = SerialUtilities.readPaint(stream); 1459 this.seriesOutlinePaint = SerialUtilities.readPaint(stream); 1460 this.baseSeriesOutlinePaint = SerialUtilities.readPaint(stream); 1461 this.seriesOutlineStroke = SerialUtilities.readStroke(stream); 1462 this.baseSeriesOutlineStroke = SerialUtilities.readStroke(stream); 1463 this.labelPaint = SerialUtilities.readPaint(stream); 1464 1465 if (dataset != null) { 1466 dataset.addChangeListener(this); 1467 } 1468 } 1469 1470} 1471 | Popular Tags |