1 56 57 package org.jfree.chart.renderer; 58 59 import java.awt.Font ; 60 import java.awt.FontMetrics ; 61 import java.awt.Graphics2D ; 62 import java.awt.Paint ; 63 import java.awt.Shape ; 64 import java.awt.Stroke ; 65 import java.awt.font.FontRenderContext ; 66 import java.awt.font.LineMetrics ; 67 import java.awt.geom.Line2D ; 68 import java.awt.geom.Point2D ; 69 import java.awt.geom.Rectangle2D ; 70 import java.io.Serializable ; 71 72 import org.jfree.chart.LegendItem; 73 import org.jfree.chart.Marker; 74 import org.jfree.chart.MarkerLabelPosition; 75 import org.jfree.chart.axis.CategoryAxis; 76 import org.jfree.chart.axis.ValueAxis; 77 import org.jfree.chart.labels.CategoryItemLabelGenerator; 78 import org.jfree.chart.plot.CategoryPlot; 79 import org.jfree.chart.plot.DrawingSupplier; 80 import org.jfree.chart.plot.PlotOrientation; 81 import org.jfree.chart.plot.PlotRenderingInfo; 82 import org.jfree.chart.urls.CategoryURLGenerator; 83 import org.jfree.data.CategoryDataset; 84 import org.jfree.data.Range; 85 import org.jfree.ui.RefineryUtilities; 86 import org.jfree.util.NumberUtils; 87 import org.jfree.util.ObjectList; 88 import org.jfree.util.ObjectUtils; 89 90 98 public abstract class AbstractCategoryItemRenderer extends AbstractRenderer 99 implements CategoryItemRenderer, 100 Cloneable , 101 Serializable { 102 103 104 private CategoryPlot plot; 105 106 107 private CategoryItemLabelGenerator itemLabelGenerator; 108 109 110 private ObjectList itemLabelGeneratorList; 111 112 113 private CategoryItemLabelGenerator baseItemLabelGenerator; 114 115 116 private CategoryURLGenerator itemURLGenerator; 117 118 119 private ObjectList itemURLGeneratorList; 120 121 122 private CategoryURLGenerator baseItemURLGenerator; 123 124 125 private transient int rowCount; 126 127 128 private transient int columnCount; 129 130 131 private double itemLabelAnchorOffset = 2.0; 132 133 140 protected AbstractCategoryItemRenderer() { 141 this.itemLabelGenerator = null; 142 this.itemLabelGeneratorList = new ObjectList(); 143 this.itemURLGenerator = null; 144 this.itemURLGeneratorList = new ObjectList(); 145 } 146 147 152 public CategoryPlot getPlot() { 153 return this.plot; 154 } 155 156 161 public void setPlot(CategoryPlot plot) { 162 this.plot = plot; 163 } 164 165 174 public CategoryItemLabelGenerator getItemLabelGenerator(int row, int column) { 175 return getSeriesItemLabelGenerator(row); 176 } 177 178 185 public CategoryItemLabelGenerator getSeriesItemLabelGenerator(int series) { 186 187 if (this.itemLabelGenerator != null) { 189 return this.itemLabelGenerator; 190 } 191 192 CategoryItemLabelGenerator generator 194 = (CategoryItemLabelGenerator) this.itemLabelGeneratorList.get(series); 195 if (generator == null) { 196 generator = this.baseItemLabelGenerator; 197 } 198 return generator; 199 200 } 201 202 207 public void setItemLabelGenerator(CategoryItemLabelGenerator generator) { 208 this.itemLabelGenerator = generator; 209 } 210 211 217 public void setSeriesItemLabelGenerator(int series, CategoryItemLabelGenerator generator) { 218 this.itemLabelGeneratorList.set(series, generator); 219 } 220 221 226 public CategoryItemLabelGenerator getBaseItemLabelGenerator() { 227 return this.baseItemLabelGenerator; 228 } 229 230 235 public void setBaseItemLabelGenerator(CategoryItemLabelGenerator generator) { 236 this.baseItemLabelGenerator = generator; 237 } 238 239 248 public CategoryURLGenerator getItemURLGenerator(int row, int column) { 249 return getSeriesItemURLGenerator(row); 250 } 251 252 259 public CategoryURLGenerator getSeriesItemURLGenerator(int series) { 260 261 if (this.itemURLGenerator != null) { 263 return this.itemURLGenerator; 264 } 265 266 CategoryURLGenerator generator 268 = (CategoryURLGenerator) this.itemURLGeneratorList.get(series); 269 if (generator == null) { 270 generator = this.baseItemURLGenerator; 271 } 272 return generator; 273 274 } 275 276 281 public void setItemURLGenerator(CategoryURLGenerator generator) { 282 this.itemURLGenerator = generator; 283 } 284 285 291 public void setSeriesItemURLGenerator(int series, CategoryURLGenerator generator) { 292 this.itemURLGeneratorList.set(series, generator); 293 } 294 295 300 public CategoryURLGenerator getBaseItemURLGenerator() { 301 return this.baseItemURLGenerator; 302 } 303 304 309 public void setBaseItemURLGenerator(CategoryURLGenerator generator) { 310 this.baseItemURLGenerator = generator; 311 } 312 313 318 public double getItemLabelAnchorOffset() { 319 return this.itemLabelAnchorOffset; 320 } 321 322 327 public void setItemLabelAnchorOffset(double offset) { 328 this.itemLabelAnchorOffset = offset; 329 firePropertyChanged("ItemLabelAnchorOffset", null, null); 330 } 331 332 338 public int getRowCount() { 339 return this.rowCount; 340 } 341 342 348 public int getColumnCount() { 349 return this.columnCount; 350 } 351 352 372 public CategoryItemRendererState initialise(Graphics2D g2, 373 Rectangle2D dataArea, 374 CategoryPlot plot, 375 Integer index, 376 PlotRenderingInfo info) { 377 378 setPlot(plot); 379 CategoryDataset data = getDataset(plot, index); 380 if (data != null) { 381 this.rowCount = data.getRowCount(); 382 this.columnCount = data.getColumnCount(); 383 } 384 else { 385 this.rowCount = 0; 386 this.columnCount = 0; 387 } 388 return new CategoryItemRendererState(info); 389 390 } 391 392 402 public RangeType getRangeType() { 403 return RangeType.STANDARD; 404 } 405 406 414 public void drawBackground(Graphics2D g2, 415 CategoryPlot plot, 416 Rectangle2D dataArea) { 417 418 plot.drawBackground(g2, dataArea); 419 420 } 421 422 430 public void drawOutline(Graphics2D g2, 431 CategoryPlot plot, 432 Rectangle2D dataArea) { 433 434 plot.drawOutline(g2, dataArea); 435 436 } 437 438 449 public void drawDomainGridline(Graphics2D g2, 450 CategoryPlot plot, 451 Rectangle2D dataArea, 452 double value) { 453 454 Line2D line = null; 455 PlotOrientation orientation = plot.getOrientation(); 456 457 if (orientation == PlotOrientation.HORIZONTAL) { 458 line = new Line2D.Double (dataArea.getMinX(), value, dataArea.getMaxX(), value); 459 } 460 else if (orientation == PlotOrientation.VERTICAL) { 461 line = new Line2D.Double (value, dataArea.getMinY(), value, dataArea.getMaxY()); 462 } 463 464 Paint paint = plot.getDomainGridlinePaint(); 465 if (paint == null) { 466 paint = CategoryPlot.DEFAULT_GRIDLINE_PAINT; 467 } 468 g2.setPaint(paint); 469 470 Stroke stroke = plot.getDomainGridlineStroke(); 471 if (stroke == null) { 472 stroke = CategoryPlot.DEFAULT_GRIDLINE_STROKE; 473 } 474 g2.setStroke(stroke); 475 476 g2.draw(line); 477 478 } 479 480 490 public void drawRangeGridline(Graphics2D g2, 491 CategoryPlot plot, 492 ValueAxis axis, 493 Rectangle2D dataArea, 494 double value) { 495 496 Range range = axis.getRange(); 497 if (!range.contains(value)) { 498 return; 499 } 500 501 PlotOrientation orientation = plot.getOrientation(); 502 double v = axis.translateValueToJava2D(value, dataArea, plot.getRangeAxisEdge()); 503 Line2D line = null; 504 if (orientation == PlotOrientation.HORIZONTAL) { 505 line = new Line2D.Double (v, dataArea.getMinY(), v, dataArea.getMaxY()); 506 } 507 else if (orientation == PlotOrientation.VERTICAL) { 508 line = new Line2D.Double (dataArea.getMinX(), v, dataArea.getMaxX(), v); 509 } 510 511 Paint paint = plot.getRangeGridlinePaint(); 512 if (paint == null) { 513 paint = CategoryPlot.DEFAULT_GRIDLINE_PAINT; 514 } 515 g2.setPaint(paint); 516 517 Stroke stroke = plot.getRangeGridlineStroke(); 518 if (stroke == null) { 519 stroke = CategoryPlot.DEFAULT_GRIDLINE_STROKE; 520 } 521 g2.setStroke(stroke); 522 523 g2.draw(line); 524 525 } 526 527 538 public void drawRangeMarker(Graphics2D g2, 539 CategoryPlot plot, 540 ValueAxis axis, 541 Marker marker, 542 Rectangle2D dataArea) { 543 544 double value = marker.getValue(); 545 Range range = axis.getRange(); 546 547 if (!range.contains(value)) { 548 return; 549 } 550 551 PlotOrientation orientation = plot.getOrientation(); 552 double v = axis.translateValueToJava2D(value, dataArea, plot.getRangeAxisEdge()); 553 Line2D line = null; 554 if (orientation == PlotOrientation.HORIZONTAL) { 555 line = new Line2D.Double (v, dataArea.getMinY(), v, dataArea.getMaxY()); 556 } 557 else if (orientation == PlotOrientation.VERTICAL) { 558 line = new Line2D.Double (dataArea.getMinX(), v, dataArea.getMaxX(), v); 559 } 560 561 g2.setPaint(marker.getOutlinePaint()); 562 g2.setStroke(marker.getOutlineStroke()); 563 g2.draw(line); 564 565 String label = marker.getLabel(); 566 MarkerLabelPosition position = marker.getLabelPosition(); 567 if (label != null) { 568 Font labelFont = marker.getLabelFont(); 569 g2.setFont(labelFont); 570 g2.setPaint(marker.getLabelPaint()); 571 double[] coordinates = calculateRangeMarkerTextPosition(g2, orientation, dataArea, 572 v, label, labelFont, 573 position); 574 g2.drawString(label, (int) coordinates[0], (int) coordinates[1]); 575 } 576 577 } 578 579 592 private double[] calculateRangeMarkerTextPosition(Graphics2D g2, 593 PlotOrientation orientation, 594 Rectangle2D dataArea, 595 double coordinate, 596 String label, 597 Font font, 598 MarkerLabelPosition position) { 599 600 double[] result = new double[2]; 601 FontRenderContext frc = g2.getFontRenderContext(); 602 FontMetrics fm = g2.getFontMetrics(); 603 LineMetrics metrics = font.getLineMetrics(label, frc); 604 Rectangle2D bounds = fm.getStringBounds(label, g2); 605 if (orientation == PlotOrientation.HORIZONTAL) { 606 if (position == MarkerLabelPosition.TOP_LEFT) { 607 result[0] = coordinate - bounds.getWidth() - 2.0; 608 result[1] = dataArea.getMinY() + bounds.getHeight(); 609 } 610 else if (position == MarkerLabelPosition.TOP_RIGHT) { 611 result[0] = coordinate + 2.0; 612 result[1] = dataArea.getMinY() + bounds.getHeight(); 613 } 614 else if (position == MarkerLabelPosition.BOTTOM_LEFT) { 615 result[0] = coordinate - bounds.getWidth() - 2.0; 616 result[1] = dataArea.getMaxY() - metrics.getDescent() - metrics.getLeading(); 617 } 618 else if (position == MarkerLabelPosition.BOTTOM_RIGHT) { 619 result[0] = coordinate + 2.0; 620 result[1] = dataArea.getMaxY() - metrics.getDescent() - metrics.getLeading(); 621 } 622 } 623 else if (orientation == PlotOrientation.VERTICAL) { 624 if (position == MarkerLabelPosition.TOP_LEFT) { 625 result[0] = dataArea.getMinX() + 2.0; 626 result[1] = coordinate - metrics.getDescent() - metrics.getLeading(); 627 } 628 else if (position == MarkerLabelPosition.TOP_RIGHT) { 629 result[0] = dataArea.getMaxX() - bounds.getWidth() - 2.0; 630 result[1] = coordinate - metrics.getDescent() - metrics.getLeading(); 631 } 632 else if (position == MarkerLabelPosition.BOTTOM_LEFT) { 633 result[0] = dataArea.getMinX() + 2.0; 634 result[1] = coordinate + bounds.getHeight(); 635 } 636 else if (position == MarkerLabelPosition.BOTTOM_RIGHT) { 637 result[0] = dataArea.getMaxX() - bounds.getWidth() - 2.0; 638 result[1] = coordinate + bounds.getHeight(); 639 } 640 } 641 return result; 642 643 } 644 645 653 public LegendItem getLegendItem(int datasetIndex, int series) { 654 655 CategoryPlot plot = getPlot(); 656 if (plot == null) { 657 return null; 658 } 659 660 CategoryDataset dataset; 661 if (datasetIndex == 0) { 662 dataset = plot.getDataset(); 663 } 664 else { 665 dataset = plot.getSecondaryDataset(datasetIndex - 1); 666 } 667 String label = dataset.getRowKey(series).toString(); 668 String description = label; 669 Shape shape = getSeriesShape(series); 670 Paint paint = getSeriesPaint(series); 671 Paint outlinePaint = getSeriesOutlinePaint(series); 672 Stroke stroke = getSeriesStroke(series); 673 674 return new LegendItem(label, description, 675 shape, paint, outlinePaint, stroke); 676 677 } 678 679 686 public boolean equals(Object obj) { 687 688 boolean result = super.equals(obj); 689 690 if (obj instanceof AbstractCategoryItemRenderer) { 691 AbstractCategoryItemRenderer r = (AbstractCategoryItemRenderer) obj; 692 693 boolean b0 = ObjectUtils.equal(this.itemLabelGenerator, r.itemLabelGenerator); 694 boolean b1 = ObjectUtils.equal(this.itemLabelGeneratorList, r.itemLabelGeneratorList); 695 boolean b2 = ObjectUtils.equal(this.baseItemLabelGenerator, r.baseItemLabelGenerator); 696 boolean b3 = ObjectUtils.equal(this.itemURLGenerator, r.itemURLGenerator); 697 boolean b4 = ObjectUtils.equal(this.itemURLGeneratorList, r.itemURLGeneratorList); 698 boolean b5 = ObjectUtils.equal(this.baseItemURLGenerator, r.baseItemURLGenerator); 699 boolean b6 = NumberUtils.equal(this.itemLabelAnchorOffset, r.itemLabelAnchorOffset); 700 701 result = b0 && b1 && b2 && b3 && b4 && b5 && b6; 702 } 703 704 return result; 705 706 } 707 708 713 public int hashCode() { 714 int result = super.hashCode(); 715 return result; 716 } 717 718 723 public DrawingSupplier getDrawingSupplier() { 724 DrawingSupplier result = null; 725 CategoryPlot cp = getPlot(); 726 if (cp != null) { 727 result = cp.getDrawingSupplier(); 728 } 729 return result; 730 } 731 732 744 protected void drawItemLabel(Graphics2D g2, 745 PlotOrientation orientation, 746 CategoryDataset dataset, 747 int row, int column, 748 double x, double y, 749 boolean negative) { 750 751 CategoryItemLabelGenerator generator = getItemLabelGenerator(row, column); 752 if (generator != null) { 753 Font labelFont = getItemLabelFont(row, column); 754 g2.setFont(labelFont); 755 Paint paint = getItemLabelPaint(row, column); 756 g2.setPaint(paint); 757 String label = generator.generateItemLabel(dataset, row, column); 758 759 ItemLabelPosition position = null; 761 if (!negative) { 762 position = getPositiveItemLabelPosition(row, column); 763 } 764 else { 765 position = getNegativeItemLabelPosition(row, column); 766 } 767 768 Point2D anchorPoint = calculateLabelAnchorPoint(position.getItemLabelAnchor(), 770 x, 771 y, 772 orientation); 773 RefineryUtilities.drawRotatedString(label, g2, 774 (float) anchorPoint.getX(), 775 (float) anchorPoint.getY(), 776 position.getTextAnchor(), 777 position.getRotationAnchor(), 778 position.getAngle()); 779 } 780 781 } 782 783 793 private Point2D calculateLabelAnchorPoint(ItemLabelAnchor anchor, 794 double x, double y, PlotOrientation orientation) { 795 796 Point2D result = null; 797 798 if (anchor == ItemLabelAnchor.CENTER) { 799 result = new Point2D.Double (x, y); 800 } 801 else if (anchor == ItemLabelAnchor.INSIDE1) { 802 result = new Point2D.Double (x, y); 803 } 804 else if (anchor == ItemLabelAnchor.INSIDE2) { 805 result = new Point2D.Double (x, y); 806 } 807 else if (anchor == ItemLabelAnchor.INSIDE3) { 808 result = new Point2D.Double (x + this.itemLabelAnchorOffset, y); 809 } 810 else if (anchor == ItemLabelAnchor.INSIDE4) { 811 result = new Point2D.Double (x, y); 812 } 813 else if (anchor == ItemLabelAnchor.INSIDE5) { 814 result = new Point2D.Double (x, y); 815 } 816 else if (anchor == ItemLabelAnchor.INSIDE6) { 817 result = new Point2D.Double (x, y + this.itemLabelAnchorOffset); 818 } 819 else if (anchor == ItemLabelAnchor.INSIDE7) { 820 result = new Point2D.Double (x, y); 821 } 822 else if (anchor == ItemLabelAnchor.INSIDE8) { 823 result = new Point2D.Double (x, y); 824 } 825 else if (anchor == ItemLabelAnchor.INSIDE9) { 826 result = new Point2D.Double (x - this.itemLabelAnchorOffset, y); 827 } 828 else if (anchor == ItemLabelAnchor.INSIDE10) { 829 result = new Point2D.Double (x, y); 830 } 831 else if (anchor == ItemLabelAnchor.INSIDE11) { 832 result = new Point2D.Double (x, y); 833 } 834 else if (anchor == ItemLabelAnchor.INSIDE12) { 835 result = new Point2D.Double (x, y - this.itemLabelAnchorOffset); 836 } 837 else if (anchor == ItemLabelAnchor.OUTSIDE1) { 838 result = new Point2D.Double (x, y); 839 } 840 else if (anchor == ItemLabelAnchor.OUTSIDE2) { 841 result = new Point2D.Double (x, y); 842 } 843 else if (anchor == ItemLabelAnchor.OUTSIDE3) { 844 result = new Point2D.Double (x + 2.0 * this.itemLabelAnchorOffset, y); 845 } 846 else if (anchor == ItemLabelAnchor.OUTSIDE4) { 847 result = new Point2D.Double (x, y); 848 } 849 else if (anchor == ItemLabelAnchor.OUTSIDE5) { 850 result = new Point2D.Double (x, y); 851 } 852 else if (anchor == ItemLabelAnchor.OUTSIDE6) { 853 result = new Point2D.Double (x, y + 2.0 * this.itemLabelAnchorOffset); 854 } 855 else if (anchor == ItemLabelAnchor.OUTSIDE7) { 856 result = new Point2D.Double (x, y); 857 } 858 else if (anchor == ItemLabelAnchor.OUTSIDE8) { 859 result = new Point2D.Double (x, y); 860 } 861 else if (anchor == ItemLabelAnchor.OUTSIDE9) { 862 result = new Point2D.Double (x - 2.0 * this.itemLabelAnchorOffset, y); 863 } 864 else if (anchor == ItemLabelAnchor.OUTSIDE10) { 865 result = new Point2D.Double (x, y); 866 } 867 else if (anchor == ItemLabelAnchor.OUTSIDE11) { 868 result = new Point2D.Double (x, y); 869 } 870 else if (anchor == ItemLabelAnchor.OUTSIDE12) { 871 result = new Point2D.Double (x, y - 2.0 * this.itemLabelAnchorOffset); 872 } 873 874 return result; 875 876 } 877 878 887 public Object clone() throws CloneNotSupportedException { 888 AbstractCategoryItemRenderer clone = (AbstractCategoryItemRenderer) super.clone(); 889 890 if (this.itemLabelGenerator != null) { 891 clone.itemLabelGenerator = (CategoryItemLabelGenerator) this.itemLabelGenerator.clone(); 892 } 893 894 if (this.itemLabelGeneratorList != null) { 895 clone.itemLabelGeneratorList = (ObjectList) this.itemLabelGeneratorList.clone(); 896 } 897 898 if (this.baseItemLabelGenerator != null) { 899 clone.baseItemLabelGenerator 900 = (CategoryItemLabelGenerator) this.baseItemLabelGenerator.clone(); 901 } 902 903 if (this.itemURLGenerator != null) { 904 clone.itemURLGenerator = (CategoryURLGenerator) this.itemURLGenerator.clone(); 905 } 906 907 if (this.itemURLGeneratorList != null) { 908 clone.itemURLGeneratorList = (ObjectList) this.itemURLGeneratorList.clone(); 909 } 910 911 if (this.baseItemURLGenerator != null) { 912 clone.baseItemURLGenerator 913 = (CategoryURLGenerator) this.baseItemURLGenerator.clone(); 914 } 915 916 917 return clone; 918 } 919 920 928 protected CategoryAxis getDomainAxis(CategoryPlot plot, Integer index) { 929 CategoryAxis result = null; 930 if (index == null) { 931 result = plot.getDomainAxis(); 932 } 933 else { 934 result = plot.getSecondaryDomainAxis(index.intValue()); 935 if (result == null) { 936 result = plot.getDomainAxis(); 937 } 938 } 939 return result; 940 } 941 942 950 protected ValueAxis getRangeAxis(CategoryPlot plot, Integer index) { 951 ValueAxis result = null; 952 if (index == null) { 953 result = plot.getRangeAxis(); 954 } 955 else { 956 result = plot.getSecondaryRangeAxis(index.intValue()); 957 if (result == null) { 958 result = plot.getRangeAxis(); 959 } 960 } 961 return result; 962 } 963 964 972 protected CategoryDataset getDataset(CategoryPlot plot, Integer index) { 973 CategoryDataset result = null; 974 if (index == null) { 975 result = plot.getDataset(); 976 } 977 else { 978 result = plot.getSecondaryDataset(index.intValue()); 979 } 980 return result; 981 } 982 983 } 984 | Popular Tags |