| 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 |