1 114 115 package org.jfree.chart.plot; 116 117 import java.awt.AlphaComposite ; 118 import java.awt.BasicStroke ; 119 import java.awt.Color ; 120 import java.awt.Composite ; 121 import java.awt.Font ; 122 import java.awt.Graphics2D ; 123 import java.awt.Image ; 124 import java.awt.Paint ; 125 import java.awt.Shape ; 126 import java.awt.Stroke ; 127 import java.awt.geom.Ellipse2D ; 128 import java.awt.geom.Point2D ; 129 import java.awt.geom.Rectangle2D ; 130 import java.io.IOException ; 131 import java.io.ObjectInputStream ; 132 import java.io.ObjectOutputStream ; 133 import java.io.Serializable ; 134 135 import javax.swing.event.EventListenerList ; 136 137 import org.jfree.chart.LegendItemCollection; 138 import org.jfree.chart.LegendItemSource; 139 import org.jfree.chart.axis.AxisLocation; 140 import org.jfree.chart.event.AxisChangeEvent; 141 import org.jfree.chart.event.AxisChangeListener; 142 import org.jfree.chart.event.ChartChangeEventType; 143 import org.jfree.chart.event.PlotChangeEvent; 144 import org.jfree.chart.event.PlotChangeListener; 145 import org.jfree.data.general.DatasetChangeEvent; 146 import org.jfree.data.general.DatasetChangeListener; 147 import org.jfree.data.general.DatasetGroup; 148 import org.jfree.io.SerialUtilities; 149 import org.jfree.text.G2TextMeasurer; 150 import org.jfree.text.TextBlock; 151 import org.jfree.text.TextBlockAnchor; 152 import org.jfree.text.TextUtilities; 153 import org.jfree.ui.Align; 154 import org.jfree.ui.RectangleEdge; 155 import org.jfree.ui.RectangleInsets; 156 import org.jfree.util.ObjectUtilities; 157 import org.jfree.util.PublicCloneable; 158 159 165 public abstract class Plot implements AxisChangeListener, 166 DatasetChangeListener, 167 LegendItemSource, 168 PublicCloneable, 169 Cloneable , 170 Serializable { 171 172 173 private static final long serialVersionUID = -8831571430103671324L; 174 175 176 public static final Number ZERO = new Integer (0); 177 178 179 public static final RectangleInsets DEFAULT_INSETS 180 = new RectangleInsets(4.0, 8.0, 4.0, 8.0); 181 182 183 public static final Stroke DEFAULT_OUTLINE_STROKE = new BasicStroke (0.5f); 184 185 186 public static final Paint DEFAULT_OUTLINE_PAINT = Color.gray; 187 188 189 public static final float DEFAULT_FOREGROUND_ALPHA = 1.0f; 190 191 192 public static final float DEFAULT_BACKGROUND_ALPHA = 1.0f; 193 194 195 public static final Paint DEFAULT_BACKGROUND_PAINT = Color.white; 196 197 198 public static final int MINIMUM_WIDTH_TO_DRAW = 10; 199 200 201 public static final int MINIMUM_HEIGHT_TO_DRAW = 10; 202 203 204 public static final Shape DEFAULT_LEGEND_ITEM_BOX 205 = new Rectangle2D.Double (-4.0, -4.0, 8.0, 8.0); 206 207 208 public static final Shape DEFAULT_LEGEND_ITEM_CIRCLE 209 = new Ellipse2D.Double (-4.0, -4.0, 8.0, 8.0); 210 211 212 private Plot parent; 213 214 215 private DatasetGroup datasetGroup; 216 217 218 private String noDataMessage; 219 220 221 private Font noDataMessageFont; 222 223 224 private transient Paint noDataMessagePaint; 225 226 227 private RectangleInsets insets; 228 229 230 private transient Stroke outlineStroke; 231 232 233 private transient Paint outlinePaint; 234 235 236 private transient Paint backgroundPaint; 237 238 239 private transient Image backgroundImage; 241 242 private int backgroundImageAlignment = Align.FIT; 243 244 245 private float foregroundAlpha; 246 247 248 private float backgroundAlpha; 249 250 251 private DrawingSupplier drawingSupplier; 252 253 254 private transient EventListenerList listenerList; 255 256 private double dataAreaRatio = 0.0; 267 270 protected Plot() { 271 272 this.parent = null; 273 this.insets = DEFAULT_INSETS; 274 this.backgroundPaint = DEFAULT_BACKGROUND_PAINT; 275 this.backgroundAlpha = DEFAULT_BACKGROUND_ALPHA; 276 this.backgroundImage = null; 277 this.outlineStroke = DEFAULT_OUTLINE_STROKE; 278 this.outlinePaint = DEFAULT_OUTLINE_PAINT; 279 this.foregroundAlpha = DEFAULT_FOREGROUND_ALPHA; 280 281 this.noDataMessage = null; 282 this.noDataMessageFont = new Font ("SansSerif", Font.PLAIN, 12); 283 this.noDataMessagePaint = Color.black; 284 285 this.drawingSupplier = new DefaultDrawingSupplier(); 286 287 this.listenerList = new EventListenerList (); 288 289 } 290 291 296 public DatasetGroup getDatasetGroup() { 297 return this.datasetGroup; 298 } 299 300 305 protected void setDatasetGroup(DatasetGroup group) { 306 this.datasetGroup = group; 307 } 308 309 315 public String getNoDataMessage() { 316 return this.noDataMessage; 317 } 318 319 324 public void setNoDataMessage(String message) { 325 this.noDataMessage = message; 326 } 327 328 333 public Font getNoDataMessageFont() { 334 return this.noDataMessageFont; 335 } 336 337 342 public void setNoDataMessageFont(Font font) { 343 this.noDataMessageFont = font; 344 } 345 346 351 public Paint getNoDataMessagePaint() { 352 return this.noDataMessagePaint; 353 } 354 355 360 public void setNoDataMessagePaint(Paint paint) { 361 this.noDataMessagePaint = paint; 362 } 363 364 372 public abstract String getPlotType(); 373 374 380 public Plot getParent() { 381 return this.parent; 382 } 383 384 389 public void setParent(Plot parent) { 390 this.parent = parent; 391 } 392 393 398 public Plot getRootPlot() { 399 400 Plot p = getParent(); 401 if (p == null) { 402 return this; 403 } 404 else { 405 return p.getRootPlot(); 406 } 407 408 } 409 410 416 public boolean isSubplot() { 417 return (getParent() != null); 418 } 419 420 425 public RectangleInsets getInsets() { 426 return this.insets; 427 } 428 429 435 public void setInsets(RectangleInsets insets) { 436 setInsets(insets, true); 437 } 438 439 447 public void setInsets(RectangleInsets insets, boolean notify) { 448 if (insets == null) { 449 throw new IllegalArgumentException ("Null 'insets' argument."); 450 } 451 if (!this.insets.equals(insets)) { 452 this.insets = insets; 453 if (notify) { 454 notifyListeners(new PlotChangeEvent(this)); 455 } 456 } 457 458 } 459 460 465 public Paint getBackgroundPaint() { 466 return this.backgroundPaint; 467 } 468 469 475 public void setBackgroundPaint(Paint paint) { 476 477 if (paint == null) { 478 if (this.backgroundPaint != null) { 479 this.backgroundPaint = null; 480 notifyListeners(new PlotChangeEvent(this)); 481 } 482 } 483 else { 484 if (this.backgroundPaint != null) { 485 if (this.backgroundPaint.equals(paint)) { 486 return; } 488 } 489 this.backgroundPaint = paint; 490 notifyListeners(new PlotChangeEvent(this)); 491 } 492 493 } 494 495 500 public float getBackgroundAlpha() { 501 return this.backgroundAlpha; 502 } 503 504 510 public void setBackgroundAlpha(float alpha) { 511 512 if (this.backgroundAlpha != alpha) { 513 this.backgroundAlpha = alpha; 514 notifyListeners(new PlotChangeEvent(this)); 515 } 516 517 } 518 519 524 public DrawingSupplier getDrawingSupplier() { 525 DrawingSupplier result = null; 526 Plot p = getParent(); 527 if (p != null) { 528 result = p.getDrawingSupplier(); 529 } 530 else { 531 result = this.drawingSupplier; 532 } 533 return result; 534 } 535 536 544 public void setDrawingSupplier(DrawingSupplier supplier) { 545 this.drawingSupplier = supplier; 546 notifyListeners(new PlotChangeEvent(this)); 547 } 548 549 555 public Image getBackgroundImage() { 556 return this.backgroundImage; 557 } 558 559 564 public void setBackgroundImage(Image image) { 565 this.backgroundImage = image; 566 notifyListeners(new PlotChangeEvent(this)); 567 } 568 569 576 public int getBackgroundImageAlignment() { 577 return this.backgroundImageAlignment; 578 } 579 580 588 public void setBackgroundImageAlignment(int alignment) { 589 if (this.backgroundImageAlignment != alignment) { 590 this.backgroundImageAlignment = alignment; 591 notifyListeners(new PlotChangeEvent(this)); 592 } 593 } 594 595 600 public Stroke getOutlineStroke() { 601 return this.outlineStroke; 602 } 603 604 611 public void setOutlineStroke(Stroke stroke) { 612 613 if (stroke == null) { 614 if (this.outlineStroke != null) { 615 this.outlineStroke = null; 616 notifyListeners(new PlotChangeEvent(this)); 617 } 618 } 619 else { 620 if (this.outlineStroke != null) { 621 if (this.outlineStroke.equals(stroke)) { 622 return; } 624 } 625 this.outlineStroke = stroke; 626 notifyListeners(new PlotChangeEvent(this)); 627 } 628 629 } 630 631 636 public Paint getOutlinePaint() { 637 return this.outlinePaint; 638 } 639 640 647 public void setOutlinePaint(Paint paint) { 648 649 if (paint == null) { 650 if (this.outlinePaint != null) { 651 this.outlinePaint = null; 652 notifyListeners(new PlotChangeEvent(this)); 653 } 654 } 655 else { 656 if (this.outlinePaint != null) { 657 if (this.outlinePaint.equals(paint)) { 658 return; } 660 } 661 this.outlinePaint = paint; 662 notifyListeners(new PlotChangeEvent(this)); 663 } 664 665 } 666 667 672 public float getForegroundAlpha() { 673 return this.foregroundAlpha; 674 } 675 676 681 public void setForegroundAlpha(float alpha) { 682 683 if (this.foregroundAlpha != alpha) { 684 this.foregroundAlpha = alpha; 685 notifyListeners(new PlotChangeEvent(this)); 686 } 687 688 } 689 690 697 public LegendItemCollection getLegendItems() { 698 return null; 699 } 700 701 706 public void addChangeListener(PlotChangeListener listener) { 707 this.listenerList.add(PlotChangeListener.class, listener); 708 } 709 710 715 public void removeChangeListener(PlotChangeListener listener) { 716 this.listenerList.remove(PlotChangeListener.class, listener); 717 } 718 719 724 public void notifyListeners(PlotChangeEvent event) { 725 726 Object [] listeners = this.listenerList.getListenerList(); 727 for (int i = listeners.length - 2; i >= 0; i -= 2) { 728 if (listeners[i] == PlotChangeListener.class) { 729 ((PlotChangeListener) listeners[i + 1]).plotChanged(event); 730 } 731 } 732 733 } 734 735 749 public abstract void draw(Graphics2D g2, 750 Rectangle2D area, 751 Point2D anchor, 752 PlotState parentState, 753 PlotRenderingInfo info); 754 755 765 public void drawBackground(Graphics2D g2, Rectangle2D area) { 766 fillBackground(g2, area); 767 drawBackgroundImage(g2, area); 768 } 769 770 776 protected void fillBackground(Graphics2D g2, Rectangle2D area) { 777 if (this.backgroundPaint != null) { 778 Composite originalComposite = g2.getComposite(); 779 g2.setComposite( 780 AlphaComposite.getInstance( 781 AlphaComposite.SRC_OVER, this.backgroundAlpha 782 ) 783 ); 784 g2.setPaint(this.backgroundPaint); 785 g2.fill(area); 786 g2.setComposite(originalComposite); 787 } 788 } 789 790 797 protected void drawBackgroundImage(Graphics2D g2, Rectangle2D area) { 798 if (this.backgroundImage != null) { 799 Composite originalComposite = g2.getComposite(); 800 g2.setComposite(AlphaComposite.getInstance( 801 AlphaComposite.SRC, this.backgroundAlpha 802 )); 803 Rectangle2D dest = new Rectangle2D.Double ( 804 0.0, 0.0, 805 this.backgroundImage.getWidth(null), 806 this.backgroundImage.getHeight(null) 807 ); 808 Align.align(dest, area, this.backgroundImageAlignment); 809 g2.drawImage( 810 this.backgroundImage, 811 (int) dest.getX(), (int) dest.getY(), 812 (int) dest.getWidth() + 1, (int) dest.getHeight() + 1, null 813 ); 814 g2.setComposite(originalComposite); 815 } 816 } 817 818 827 public void drawOutline(Graphics2D g2, Rectangle2D area) { 828 if ((this.outlineStroke != null) && (this.outlinePaint != null)) { 829 g2.setStroke(this.outlineStroke); 830 g2.setPaint(this.outlinePaint); 831 g2.draw(area); 832 } 833 } 834 835 841 protected void drawNoDataMessage(Graphics2D g2, Rectangle2D area) { 842 843 Shape savedClip = g2.getClip(); 844 g2.clip(area); 845 String message = this.noDataMessage; 846 if (message != null) { 847 g2.setFont(this.noDataMessageFont); 848 g2.setPaint(this.noDataMessagePaint); 849 TextBlock block = TextUtilities.createTextBlock( 850 this.noDataMessage, this.noDataMessageFont, 851 this.noDataMessagePaint, 852 0.9f * (float) area.getWidth(), new G2TextMeasurer(g2) 853 ); 854 block.draw( 855 g2, (float) area.getCenterX(), (float) area.getCenterY(), 856 TextBlockAnchor.CENTER 857 ); 858 } 859 g2.setClip(savedClip); 860 861 } 862 863 873 public void handleClick(int x, int y, PlotRenderingInfo info) { 874 } 876 877 883 public void zoom(double percent) { 884 } 886 887 892 public void axisChanged(AxisChangeEvent event) { 893 notifyListeners(new PlotChangeEvent(this)); 894 } 895 896 904 public void datasetChanged(DatasetChangeEvent event) { 905 PlotChangeEvent newEvent = new PlotChangeEvent(this); 906 newEvent.setType(ChartChangeEventType.DATASET_UPDATED); 907 notifyListeners(newEvent); 908 } 909 910 920 protected double getRectX(double x, double w1, double w2, 921 RectangleEdge edge) { 922 923 double result = x; 924 if (edge == RectangleEdge.LEFT) { 925 result = result + w1; 926 } 927 else if (edge == RectangleEdge.RIGHT) { 928 result = result + w2; 929 } 930 return result; 931 932 } 933 934 944 protected double getRectY(double y, double h1, double h2, 945 RectangleEdge edge) { 946 947 double result = y; 948 if (edge == RectangleEdge.TOP) { 949 result = result + h1; 950 } 951 else if (edge == RectangleEdge.BOTTOM) { 952 result = result + h2; 953 } 954 return result; 955 956 } 957 958 963 public double getDataAreaRatio() { 964 return this.dataAreaRatio; 965 } 966 967 972 public void setDataAreaRatio(double ratio) { 973 this.dataAreaRatio = ratio; 974 } 975 976 983 public boolean equals(Object obj) { 984 985 if (obj == this) { 986 return true; 987 } 988 989 if (!(obj instanceof Plot)) { 990 return false; 991 } 992 993 Plot that = (Plot) obj; 994 995 if (!ObjectUtilities.equal(this.noDataMessage, that.noDataMessage)) { 996 return false; 997 } 998 if (!ObjectUtilities.equal( 999 this.noDataMessageFont, that.noDataMessageFont 1000 )) { 1001 return false; 1002 } 1003 if (!ObjectUtilities.equal( 1004 this.noDataMessagePaint, that.noDataMessagePaint 1005 )) { 1006 return false; 1007 } 1008 1009 if (!ObjectUtilities.equal(this.insets, that.insets)) { 1010 return false; 1011 } 1012 if (!ObjectUtilities.equal(this.outlineStroke, that.outlineStroke)) { 1013 return false; 1014 } 1015 if (!ObjectUtilities.equal(this.outlinePaint, that.outlinePaint)) { 1016 return false; 1017 } 1018 1019 if (!ObjectUtilities.equal( 1020 this.backgroundPaint, that.backgroundPaint 1021 )) { 1022 return false; 1023 } 1024 if (!ObjectUtilities.equal( 1025 this.backgroundImage, that.backgroundImage 1026 )) { 1027 return false; 1028 } 1029 if (this.backgroundImageAlignment != that.backgroundImageAlignment) { 1030 return false; 1031 } 1032 1033 if (this.foregroundAlpha != that.foregroundAlpha) { 1034 return false; 1035 } 1036 if (this.backgroundAlpha != that.backgroundAlpha) { 1037 return false; 1038 } 1039 1040 return true; 1041 1042 } 1043 1044 1052 public Object clone() throws CloneNotSupportedException { 1053 1054 Plot clone = (Plot) super.clone(); 1055 if (this.datasetGroup != null) { 1058 clone.datasetGroup 1059 = (DatasetGroup) ObjectUtilities.clone(this.datasetGroup); 1060 } 1061 clone.drawingSupplier 1062 = (DrawingSupplier) ObjectUtilities.clone(this.drawingSupplier); 1063 clone.listenerList = new EventListenerList (); 1064 return clone; 1065 1066 } 1067 1068 1075 private void writeObject(ObjectOutputStream stream) throws IOException { 1076 stream.defaultWriteObject(); 1077 SerialUtilities.writePaint(this.noDataMessagePaint, stream); 1078 SerialUtilities.writeStroke(this.outlineStroke, stream); 1079 SerialUtilities.writePaint(this.outlinePaint, stream); 1080 SerialUtilities.writePaint(this.backgroundPaint, stream); 1082 } 1083 1084 1092 private void readObject(ObjectInputStream stream) 1093 throws IOException , ClassNotFoundException { 1094 stream.defaultReadObject(); 1095 this.noDataMessagePaint = SerialUtilities.readPaint(stream); 1096 this.outlineStroke = SerialUtilities.readStroke(stream); 1097 this.outlinePaint = SerialUtilities.readPaint(stream); 1098 this.backgroundPaint = SerialUtilities.readPaint(stream); 1100 1101 this.listenerList = new EventListenerList (); 1102 1103 } 1104 1105 1113 public static RectangleEdge resolveDomainAxisLocation( 1114 AxisLocation location, PlotOrientation orientation) { 1115 1116 if (location == null) { 1117 throw new IllegalArgumentException ("Null 'location' argument."); 1118 } 1119 if (orientation == null) { 1120 throw new IllegalArgumentException ("Null 'orientation' argument."); 1121 } 1122 1123 RectangleEdge result = null; 1124 1125 if (location == AxisLocation.TOP_OR_RIGHT) { 1126 if (orientation == PlotOrientation.HORIZONTAL) { 1127 result = RectangleEdge.RIGHT; 1128 } 1129 else if (orientation == PlotOrientation.VERTICAL) { 1130 result = RectangleEdge.TOP; 1131 } 1132 } 1133 else if (location == AxisLocation.TOP_OR_LEFT) { 1134 if (orientation == PlotOrientation.HORIZONTAL) { 1135 result = RectangleEdge.LEFT; 1136 } 1137 else if (orientation == PlotOrientation.VERTICAL) { 1138 result = RectangleEdge.TOP; 1139 } 1140 } 1141 else if (location == AxisLocation.BOTTOM_OR_RIGHT) { 1142 if (orientation == PlotOrientation.HORIZONTAL) { 1143 result = RectangleEdge.RIGHT; 1144 } 1145 else if (orientation == PlotOrientation.VERTICAL) { 1146 result = RectangleEdge.BOTTOM; 1147 } 1148 } 1149 else if (location == AxisLocation.BOTTOM_OR_LEFT) { 1150 if (orientation == PlotOrientation.HORIZONTAL) { 1151 result = RectangleEdge.LEFT; 1152 } 1153 else if (orientation == PlotOrientation.VERTICAL) { 1154 result = RectangleEdge.BOTTOM; 1155 } 1156 } 1157 if (result == null) { 1159 throw new IllegalStateException ("resolveDomainAxisLocation()"); 1160 } 1161 return result; 1162 1163 } 1164 1165 1173 public static RectangleEdge resolveRangeAxisLocation( 1174 AxisLocation location, PlotOrientation orientation) { 1175 1176 if (location == null) { 1177 throw new IllegalArgumentException ("Null 'location' argument."); 1178 } 1179 if (orientation == null) { 1180 throw new IllegalArgumentException ("Null 'orientation' argument."); 1181 } 1182 1183 RectangleEdge result = null; 1184 1185 if (location == AxisLocation.TOP_OR_RIGHT) { 1186 if (orientation == PlotOrientation.HORIZONTAL) { 1187 result = RectangleEdge.TOP; 1188 } 1189 else if (orientation == PlotOrientation.VERTICAL) { 1190 result = RectangleEdge.RIGHT; 1191 } 1192 } 1193 else if (location == AxisLocation.TOP_OR_LEFT) { 1194 if (orientation == PlotOrientation.HORIZONTAL) { 1195 result = RectangleEdge.TOP; 1196 } 1197 else if (orientation == PlotOrientation.VERTICAL) { 1198 result = RectangleEdge.LEFT; 1199 } 1200 } 1201 else if (location == AxisLocation.BOTTOM_OR_RIGHT) { 1202 if (orientation == PlotOrientation.HORIZONTAL) { 1203 result = RectangleEdge.BOTTOM; 1204 } 1205 else if (orientation == PlotOrientation.VERTICAL) { 1206 result = RectangleEdge.RIGHT; 1207 } 1208 } 1209 else if (location == AxisLocation.BOTTOM_OR_LEFT) { 1210 if (orientation == PlotOrientation.HORIZONTAL) { 1211 result = RectangleEdge.BOTTOM; 1212 } 1213 else if (orientation == PlotOrientation.VERTICAL) { 1214 result = RectangleEdge.LEFT; 1215 } 1216 } 1217 1218 if (result == null) { 1220 throw new IllegalStateException ("resolveRangeAxisLocation()"); 1221 } 1222 return result; 1223 1224 } 1225 1226} 1227 1228 | Popular Tags |