1 78 79 package org.jfree.chart.plot; 80 81 import java.awt.AlphaComposite ; 82 import java.awt.BasicStroke ; 83 import java.awt.Color ; 84 import java.awt.Composite ; 85 import java.awt.Font ; 86 import java.awt.FontMetrics ; 87 import java.awt.Graphics2D ; 88 import java.awt.Paint ; 89 import java.awt.Polygon ; 90 import java.awt.Shape ; 91 import java.awt.Stroke ; 92 import java.awt.geom.Arc2D ; 93 import java.awt.geom.Ellipse2D ; 94 import java.awt.geom.Line2D ; 95 import java.awt.geom.Point2D ; 96 import java.awt.geom.Rectangle2D ; 97 import java.io.IOException ; 98 import java.io.ObjectInputStream ; 99 import java.io.ObjectOutputStream ; 100 import java.io.Serializable ; 101 import java.text.NumberFormat ; 102 import java.util.Collections ; 103 import java.util.Iterator ; 104 import java.util.List ; 105 import java.util.ResourceBundle ; 106 107 import org.jfree.chart.LegendItem; 108 import org.jfree.chart.LegendItemCollection; 109 import org.jfree.chart.event.PlotChangeEvent; 110 import org.jfree.data.Range; 111 import org.jfree.data.general.DatasetChangeEvent; 112 import org.jfree.data.general.ValueDataset; 113 import org.jfree.io.SerialUtilities; 114 import org.jfree.text.TextUtilities; 115 import org.jfree.ui.RectangleInsets; 116 import org.jfree.util.ObjectUtilities; 117 118 123 public class MeterPlot extends Plot implements Serializable , Cloneable { 124 125 126 private static final long serialVersionUID = 2987472457734470962L; 127 128 129 static final Paint DEFAULT_DIAL_BACKGROUND_PAINT = Color.black; 130 131 132 static final Paint DEFAULT_NEEDLE_PAINT = Color.green; 133 134 135 static final Font DEFAULT_VALUE_FONT = new Font ("SansSerif", Font.BOLD, 12); 136 137 138 static final Paint DEFAULT_VALUE_PAINT = Color.yellow; 139 140 141 public static final int DEFAULT_METER_ANGLE = 270; 142 143 144 public static final float DEFAULT_BORDER_SIZE = 3f; 145 146 147 public static final float DEFAULT_CIRCLE_SIZE = 10f; 148 149 150 public static final Font DEFAULT_LABEL_FONT 151 = new Font ("SansSerif", Font.BOLD, 10); 152 153 154 private ValueDataset dataset; 155 156 157 private DialShape shape; 158 159 160 private int meterAngle; 161 162 163 private Range range; 164 165 166 private String units; 167 168 169 private Font valueFont; 170 171 172 private transient Paint valuePaint; 173 174 175 private boolean drawBorder; 176 177 178 private transient Paint dialOutlinePaint; 179 180 181 private transient Paint dialBackgroundPaint; 182 183 184 private transient Paint needlePaint; 185 186 187 private boolean tickLabelsVisible; 188 189 190 private Font tickLabelFont; 191 192 193 private NumberFormat tickLabelFormat; 194 195 196 protected static ResourceBundle localizationResources = 197 ResourceBundle.getBundle("org.jfree.chart.plot.LocalizationBundle"); 198 199 203 private List intervals; 204 205 209 public MeterPlot() { 210 this(null); 211 } 212 213 218 public MeterPlot(ValueDataset dataset) { 219 super(); 220 this.shape = DialShape.CIRCLE; 221 this.meterAngle = DEFAULT_METER_ANGLE; 222 this.range = new Range(0.0, 100.0); 223 this.units = "Units"; 224 this.needlePaint = MeterPlot.DEFAULT_NEEDLE_PAINT; 225 this.tickLabelsVisible = true; 226 this.tickLabelFont = MeterPlot.DEFAULT_LABEL_FONT; 227 this.tickLabelFormat = NumberFormat.getInstance(); 228 this.valueFont = MeterPlot.DEFAULT_VALUE_FONT; 229 this.valuePaint = MeterPlot.DEFAULT_VALUE_PAINT; 230 this.dialBackgroundPaint = MeterPlot.DEFAULT_DIAL_BACKGROUND_PAINT; 231 this.intervals = new java.util.ArrayList (); 232 setDataset(dataset); 233 } 234 235 240 public DialShape getDialShape() { 241 return this.shape; 242 } 243 244 250 public void setDialShape(DialShape shape) { 251 if (shape == null) { 252 throw new IllegalArgumentException ("Null 'shape' argument."); 253 } 254 this.shape = shape; 255 notifyListeners(new PlotChangeEvent(this)); 256 } 257 258 264 public int getMeterAngle() { 265 return this.meterAngle; 266 } 267 268 274 public void setMeterAngle(int angle) { 275 if (angle < 1 || angle > 360) { 276 throw new IllegalArgumentException ( 277 "Invalid 'angle' (" + angle + ")" 278 ); 279 } 280 this.meterAngle = angle; 281 notifyListeners(new PlotChangeEvent(this)); 282 } 283 284 289 public Range getRange() { 290 return this.range; 291 } 292 293 300 public void setRange(Range range) { 301 if (range == null) { 302 throw new IllegalArgumentException ("Null 'range' argument."); 303 } 304 if (!(range.getLength() > 0.0)) { 305 throw new IllegalArgumentException ( 306 "Range length must be positive." 307 ); 308 } 309 this.range = range; 310 notifyListeners(new PlotChangeEvent(this)); 311 } 312 313 318 public String getUnits() { 319 return this.units; 320 } 321 322 328 public void setUnits(String units) { 329 this.units = units; 330 notifyListeners(new PlotChangeEvent(this)); 331 } 332 333 338 public Paint getNeedlePaint() { 339 return this.needlePaint; 340 } 341 342 348 public void setNeedlePaint(Paint paint) { 349 if (paint == null) { 350 throw new IllegalArgumentException ("Null 'paint' argument."); 351 } 352 this.needlePaint = paint; 353 notifyListeners(new PlotChangeEvent(this)); 354 } 355 356 361 public boolean getTickLabelsVisible() { 362 return this.tickLabelsVisible; 363 } 364 365 371 public void setTickLabelsVisible(boolean visible) { 372 if (this.tickLabelsVisible != visible) { 373 this.tickLabelsVisible = visible; 374 notifyListeners(new PlotChangeEvent(this)); 375 } 376 } 377 378 383 public Font getTickLabelFont() { 384 return this.tickLabelFont; 385 } 386 387 393 public void setTickLabelFont(Font font) { 394 if (font == null) { 395 throw new IllegalArgumentException ("Null 'font' argument."); 396 } 397 if (!this.tickLabelFont.equals(font)) { 398 this.tickLabelFont = font; 399 notifyListeners(new PlotChangeEvent(this)); 400 } 401 } 402 403 408 public NumberFormat getTickLabelFormat() { 409 return this.tickLabelFormat; 410 } 411 412 418 public void setTickLabelFormat(NumberFormat format) { 419 if (format == null) { 420 throw new IllegalArgumentException ("Null 'format' argument."); 421 } 422 this.tickLabelFormat = format; 423 notifyListeners(new PlotChangeEvent(this)); 424 } 425 426 431 public Font getValueFont() { 432 return this.valueFont; 433 } 434 435 441 public void setValueFont(Font font) { 442 if (font == null) { 443 throw new IllegalArgumentException ("Null 'font' argument."); 444 } 445 this.valueFont = font; 446 notifyListeners(new PlotChangeEvent(this)); 447 } 448 449 454 public Paint getValuePaint() { 455 return this.valuePaint; 456 } 457 458 464 public void setValuePaint(Paint paint) { 465 if (paint == null) { 466 throw new IllegalArgumentException ("Null 'paint' argument."); 467 } 468 this.valuePaint = paint; 469 notifyListeners(new PlotChangeEvent(this)); 470 } 471 472 477 public Paint getDialBackgroundPaint() { 478 return this.dialBackgroundPaint; 479 } 480 481 487 public void setDialBackgroundPaint(Paint paint) { 488 this.dialBackgroundPaint = paint; 489 notifyListeners(new PlotChangeEvent(this)); 490 } 491 492 498 public boolean getDrawBorder() { 499 return this.drawBorder; 500 } 501 502 509 public void setDrawBorder(boolean draw) { 510 this.drawBorder = draw; 512 notifyListeners(new PlotChangeEvent(this)); 513 } 514 515 520 public Paint getDialOutlinePaint() { 521 return this.dialOutlinePaint; 522 } 523 524 530 public void setDialOutlinePaint(Paint paint) { 531 this.dialOutlinePaint = paint; 532 notifyListeners(new PlotChangeEvent(this)); 533 } 534 535 540 public ValueDataset getDataset() { 541 return this.dataset; 542 } 543 544 550 public void setDataset(ValueDataset dataset) { 551 552 ValueDataset existing = this.dataset; 555 if (existing != null) { 556 existing.removeChangeListener(this); 557 } 558 559 this.dataset = dataset; 561 if (dataset != null) { 562 setDatasetGroup(dataset.getGroup()); 563 dataset.addChangeListener(this); 564 } 565 566 DatasetChangeEvent event = new DatasetChangeEvent(this, dataset); 568 datasetChanged(event); 569 570 } 571 572 577 public List getIntervals() { 578 return Collections.unmodifiableList(this.intervals); 579 } 580 581 587 public void addInterval(MeterInterval interval) { 588 if (interval == null) { 589 throw new IllegalArgumentException ("Null 'interval' argument."); 590 } 591 this.intervals.add(interval); 592 notifyListeners(new PlotChangeEvent(this)); 593 } 594 595 599 public void clearIntervals() { 600 this.intervals.clear(); 601 notifyListeners(new PlotChangeEvent(this)); 602 } 603 604 609 public LegendItemCollection getLegendItems() { 610 LegendItemCollection result = new LegendItemCollection(); 611 Iterator iterator = this.intervals.iterator(); 612 while (iterator.hasNext()) { 613 MeterInterval mi = (MeterInterval) iterator.next(); 614 LegendItem item = new LegendItem( 615 mi.getLabel(), mi.getLabel(), null, null, 616 new Rectangle2D.Double (-4.0, -4.0, 8.0, 8.0), 617 mi.getOutlinePaint() 618 ); 619 result.add(item); 620 } 621 return result; 622 } 623 624 634 public void draw(Graphics2D g2, Rectangle2D area, Point2D anchor, 635 PlotState parentState, 636 PlotRenderingInfo info) { 637 638 if (info != null) { 639 info.setPlotArea(area); 640 } 641 642 RectangleInsets insets = getInsets(); 644 insets.trim(area); 645 646 area.setRect( 647 area.getX() + 4, area.getY() + 4, 648 area.getWidth() - 8, area.getHeight() - 8 649 ); 650 651 if (this.drawBorder) { 653 drawBackground(g2, area); 654 } 655 656 double gapHorizontal = (2 * DEFAULT_BORDER_SIZE); 658 double gapVertical = (2 * DEFAULT_BORDER_SIZE); 659 double meterX = area.getX() + gapHorizontal / 2; 660 double meterY = area.getY() + gapVertical / 2; 661 double meterW = area.getWidth() - gapHorizontal; 662 double meterH = area.getHeight() - gapVertical 663 + ((this.meterAngle <= 180) && (this.shape != DialShape.CIRCLE) 664 ? area.getHeight() / 1.25 : 0); 665 666 double min = Math.min(meterW, meterH) / 2; 667 meterX = (meterX + meterX + meterW) / 2 - min; 668 meterY = (meterY + meterY + meterH) / 2 - min; 669 meterW = 2 * min; 670 meterH = 2 * min; 671 672 Rectangle2D meterArea = new Rectangle2D.Double ( 673 meterX, meterY, meterW, meterH 674 ); 675 676 Rectangle2D.Double originalArea = new Rectangle2D.Double ( 677 meterArea.getX() - 4, meterArea.getY() - 4, 678 meterArea.getWidth() + 8, meterArea.getHeight() + 8 679 ); 680 681 double meterMiddleX = meterArea.getCenterX(); 682 double meterMiddleY = meterArea.getCenterY(); 683 684 ValueDataset data = getDataset(); 686 if (data != null) { 687 double dataMin = this.range.getLowerBound(); 688 double dataMax = this.range.getUpperBound(); 689 690 Shape savedClip = g2.getClip(); 691 g2.clip(originalArea); 692 Composite originalComposite = g2.getComposite(); 693 g2.setComposite(AlphaComposite.getInstance( 694 AlphaComposite.SRC_OVER, getForegroundAlpha()) 695 ); 696 697 if (this.dialBackgroundPaint != null) { 698 fillArc( 699 g2, originalArea, dataMin, dataMax, 700 this.dialBackgroundPaint, true 701 ); 702 } 703 drawTicks(g2, meterArea, dataMin, dataMax); 704 drawArcForInterval( 705 g2, meterArea, 706 new MeterInterval( 707 "", this.range, this.dialOutlinePaint, 708 new BasicStroke (1.0f), null 709 ) 710 ); 711 712 Iterator iterator = this.intervals.iterator(); 713 while (iterator.hasNext()) { 714 MeterInterval interval = (MeterInterval) iterator.next(); 715 drawArcForInterval(g2, meterArea, interval); 716 } 717 718 Number n = data.getValue(); 719 if (n != null) { 720 double value = n.doubleValue(); 721 drawTick( 722 g2, meterArea, value, true, this.valuePaint, true, 723 getUnits() 724 ); 725 726 if (this.range.contains(value)) { 727 g2.setPaint(this.needlePaint); 728 g2.setStroke(new BasicStroke (2.0f)); 729 730 double radius = (meterArea.getWidth() / 2) 731 + DEFAULT_BORDER_SIZE + 15; 732 double valueAngle = valueToAngle(value); 733 double valueP1 = meterMiddleX 734 + (radius * Math.cos(Math.PI * (valueAngle / 180))); 735 double valueP2 = meterMiddleY 736 - (radius * Math.sin(Math.PI * (valueAngle / 180))); 737 738 Polygon arrow = new Polygon (); 739 if ((valueAngle > 135 && valueAngle < 225) 740 || (valueAngle < 45 && valueAngle > -45)) { 741 742 double valueP3 = (meterMiddleY 743 - DEFAULT_CIRCLE_SIZE / 4); 744 double valueP4 = (meterMiddleY 745 + DEFAULT_CIRCLE_SIZE / 4); 746 arrow.addPoint((int) meterMiddleX, (int) valueP3); 747 arrow.addPoint((int) meterMiddleX, (int) valueP4); 748 749 } 750 else { 751 arrow.addPoint( 752 (int) (meterMiddleX - DEFAULT_CIRCLE_SIZE / 4), 753 (int) meterMiddleY 754 ); 755 arrow.addPoint( 756 (int) (meterMiddleX + DEFAULT_CIRCLE_SIZE / 4), 757 (int) meterMiddleY 758 ); 759 } 760 arrow.addPoint((int) valueP1, (int) valueP2); 761 g2.fill(arrow); 762 763 Ellipse2D circle = new Ellipse2D.Double ( 764 meterMiddleX - DEFAULT_CIRCLE_SIZE / 2, 765 meterMiddleY - DEFAULT_CIRCLE_SIZE / 2, 766 DEFAULT_CIRCLE_SIZE, DEFAULT_CIRCLE_SIZE 767 ); 768 g2.fill(circle); 769 } 770 } 771 772 773 g2.clip(savedClip); 774 g2.setComposite(originalComposite); 775 776 } 777 if (this.drawBorder) { 778 drawOutline(g2, area); 779 } 780 781 } 782 783 790 protected void drawArcForInterval(Graphics2D g2, Rectangle2D meterArea, 791 MeterInterval interval) { 792 793 double minValue = interval.getRange().getLowerBound(); 794 double maxValue = interval.getRange().getUpperBound(); 795 Paint outlinePaint = interval.getOutlinePaint(); 796 Stroke outlineStroke = interval.getOutlineStroke(); 797 Paint backgroundPaint = interval.getBackgroundPaint(); 798 799 if (backgroundPaint != null) { 800 fillArc(g2, meterArea, minValue, maxValue, backgroundPaint, false); 801 } 802 if (outlinePaint != null) { 803 if (outlineStroke != null) { 804 drawArc( 805 g2, meterArea, minValue, maxValue, 806 outlinePaint, outlineStroke 807 ); 808 } 809 drawTick(g2, meterArea, minValue, true, outlinePaint); 810 drawTick(g2, meterArea, maxValue, true, outlinePaint); 811 } 812 } 813 814 824 protected void drawArc(Graphics2D g2, Rectangle2D area, double minValue, 825 double maxValue, Paint paint, Stroke stroke) { 826 827 double startAngle = valueToAngle(maxValue); 828 double endAngle = valueToAngle(minValue); 829 double extent = endAngle - startAngle; 830 831 double x = area.getX(); 832 double y = area.getY(); 833 double w = area.getWidth(); 834 double h = area.getHeight(); 835 g2.setPaint(paint); 836 g2.setStroke(stroke); 837 838 if (paint != null && stroke != null) { 839 Arc2D.Double arc = new Arc2D.Double ( 840 x, y, w, h, startAngle, extent, Arc2D.OPEN 841 ); 842 g2.setPaint(paint); 843 g2.setStroke(stroke); 844 g2.draw(arc); 845 } 846 847 } 848 849 858 private void fillArc(Graphics2D g2, Rectangle2D area, 859 double minValue, double maxValue, Paint paint, 860 boolean dial) { 861 if (paint == null) { 862 throw new IllegalArgumentException ("Null 'paint' argument"); 863 } 864 double startAngle = valueToAngle(maxValue); 865 double endAngle = valueToAngle(minValue); 866 double extent = endAngle - startAngle; 867 868 double x = area.getX(); 869 double y = area.getY(); 870 double w = area.getWidth(); 871 double h = area.getHeight(); 872 int joinType = Arc2D.OPEN; 873 if (this.shape == DialShape.PIE) { 874 joinType = Arc2D.PIE; 875 } 876 else if (this.shape == DialShape.CHORD) { 877 if (dial && this.meterAngle > 180) { 878 joinType = Arc2D.CHORD; 879 } 880 else { 881 joinType = Arc2D.PIE; 882 } 883 } 884 else if (this.shape == DialShape.CIRCLE) { 885 joinType = Arc2D.PIE; 886 if (dial) { 887 extent = 360; 888 } 889 } 890 else { 891 throw new IllegalStateException ("DialShape not recognised."); 892 } 893 894 g2.setPaint(paint); 895 Arc2D.Double arc = new Arc2D.Double ( 896 x, y, w, h, startAngle, extent, joinType 897 ); 898 g2.fill(arc); 899 } 900 901 908 public double valueToAngle(double value) { 909 value = value - this.range.getLowerBound(); 910 double baseAngle = 180 + ((this.meterAngle - 180) / 2); 911 return baseAngle - ((value / this.range.getLength()) * this.meterAngle); 912 } 913 914 922 protected void drawTicks(Graphics2D g2, Rectangle2D meterArea, 923 double minValue, double maxValue) { 924 int numberOfTicks = 20; 925 double diff = (maxValue - minValue) / numberOfTicks; 926 for (double v = minValue; v <= maxValue; v += diff) { 927 drawTick(g2, meterArea, v); 928 } 929 } 930 931 938 protected void drawTick(Graphics2D g2, Rectangle2D meterArea, 939 double value) { 940 drawTick(g2, meterArea, value, false, null, false, null); 941 } 942 943 952 protected void drawTick(Graphics2D g2, Rectangle2D meterArea, double value, 953 boolean label, Paint paint) { 954 drawTick(g2, meterArea, value, label, paint, false, null); 955 } 956 957 969 protected void drawTick(Graphics2D g2, Rectangle2D meterArea, 970 double value, boolean label, Paint labelPaint, 971 boolean curValue, String units) { 972 973 double valueAngle = valueToAngle(value); 974 975 double meterMiddleX = meterArea.getCenterX(); 976 double meterMiddleY = meterArea.getCenterY(); 977 978 if (labelPaint == null) { 979 labelPaint = Color.white; 980 } 981 g2.setPaint(labelPaint); 982 g2.setStroke(new BasicStroke (2.0f)); 983 984 double valueP2X = 0; 985 double valueP2Y = 0; 986 987 if (!curValue) { 988 double radius = (meterArea.getWidth() / 2) + DEFAULT_BORDER_SIZE; 989 double radius1 = radius - 15; 990 991 double valueP1X = meterMiddleX 992 + (radius * Math.cos(Math.PI * (valueAngle / 180))); 993 double valueP1Y = meterMiddleY 994 - (radius * Math.sin(Math.PI * (valueAngle / 180))); 995 996 valueP2X = meterMiddleX 997 + (radius1 * Math.cos(Math.PI * (valueAngle / 180))); 998 valueP2Y = meterMiddleY 999 - (radius1 * Math.sin(Math.PI * (valueAngle / 180))); 1000 1001 Line2D.Double line = new Line2D.Double ( 1002 valueP1X, valueP1Y, valueP2X, valueP2Y 1003 ); 1004 g2.draw(line); 1005 } 1006 else { 1007 valueP2X = meterMiddleX; 1008 valueP2Y = meterMiddleY; 1009 valueAngle = 90; 1010 } 1011 1012 if (this.tickLabelsVisible && label) { 1013 1014 String tickLabel = this.tickLabelFormat.format(value); 1015 if (curValue && units != null) { 1016 tickLabel += " " + units; 1017 } 1018 if (curValue) { 1019 g2.setFont(getValueFont()); 1020 } 1021 else { 1022 if (this.tickLabelFont != null) { 1023 g2.setFont(this.tickLabelFont); 1024 } 1025 } 1026 1027 FontMetrics fm = g2.getFontMetrics(); 1028 Rectangle2D tickLabelBounds 1029 = TextUtilities.getTextBounds(tickLabel, g2, fm); 1030 1031 double x = valueP2X; 1032 double y = valueP2Y; 1033 if (curValue) { 1034 y += DEFAULT_CIRCLE_SIZE; 1035 } 1036 if (valueAngle == 90 || valueAngle == 270) { 1037 x = x - tickLabelBounds.getWidth() / 2; 1038 } 1039 else if (valueAngle < 90 || valueAngle > 270) { 1040 x = x - tickLabelBounds.getWidth(); 1041 } 1042 if ((valueAngle > 135 && valueAngle < 225) 1043 || valueAngle > 315 || valueAngle < 45) { 1044 y = y - tickLabelBounds.getHeight() / 2; 1045 } 1046 else { 1047 y = y + tickLabelBounds.getHeight() / 2; 1048 } 1049 g2.drawString(tickLabel, (float) x, (float) y); 1050 } 1051 } 1052 1053 1058 public String getPlotType() { 1059 return localizationResources.getString("Meter_Plot"); 1060 } 1061 1062 1069 public void zoom(double percent) { 1070 } 1072 1073 1081 public boolean equals(Object object) { 1082 if (object == this) { 1083 return true; 1084 } 1085 if (object instanceof MeterPlot && super.equals(object)) { 1086 MeterPlot that = (MeterPlot) object; 1087 if (!ObjectUtilities.equal(this.units, that.units)) { 1088 return false; 1089 } 1090 if (!ObjectUtilities.equal(this.range, that.range)) { 1091 return false; 1092 } 1093 if (!ObjectUtilities.equal(this.intervals, that.intervals)) { 1094 return false; 1095 } 1096 if (!ObjectUtilities.equal(this.dialOutlinePaint, 1097 that.dialOutlinePaint)) { 1098 return false; 1099 } 1100 if (this.shape != that.shape) { 1101 return false; 1102 } 1103 if (!ObjectUtilities.equal(this.dialBackgroundPaint, 1104 that.dialBackgroundPaint)) { 1105 return false; 1106 } 1107 if (!ObjectUtilities.equal(this.needlePaint, that.needlePaint)) { 1108 return false; 1109 } 1110 if (!ObjectUtilities.equal(this.valueFont, that.valueFont)) { 1111 return false; 1112 } 1113 if (!ObjectUtilities.equal(this.valuePaint, that.valuePaint)) { 1114 return false; 1115 } 1116 if (this.tickLabelsVisible != that.tickLabelsVisible) { 1117 return false; 1118 } 1119 if (!ObjectUtilities.equal(this.tickLabelFont, 1120 that.tickLabelFont)) { 1121 return false; 1122 } 1123 if (!ObjectUtilities.equal(this.tickLabelFormat, 1124 that.tickLabelFormat)) { 1125 return false; 1126 } 1127 if (this.drawBorder != that.drawBorder) { 1128 return false; 1129 } 1130 if (this.meterAngle != that.meterAngle) { 1131 return false; 1132 } 1133 1134 return true; 1135 } 1136 return false; 1137 } 1138 1139 1146 private void writeObject(ObjectOutputStream stream) throws IOException { 1147 stream.defaultWriteObject(); 1148 SerialUtilities.writePaint(this.dialBackgroundPaint, stream); 1149 SerialUtilities.writePaint(this.needlePaint, stream); 1150 SerialUtilities.writePaint(this.valuePaint, stream); 1151 } 1152 1153 1161 private void readObject(ObjectInputStream stream) 1162 throws IOException , ClassNotFoundException { 1163 stream.defaultReadObject(); 1164 this.dialBackgroundPaint = SerialUtilities.readPaint(stream); 1165 this.needlePaint = SerialUtilities.readPaint(stream); 1166 this.valuePaint = SerialUtilities.readPaint(stream); 1167 if (this.dataset != null) { 1168 this.dataset.addChangeListener(this); 1169 } 1170 } 1171 1172 1182 public Object clone() throws CloneNotSupportedException { 1183 MeterPlot clone = (MeterPlot) super.clone(); 1184 clone.tickLabelFormat = (NumberFormat ) this.tickLabelFormat.clone(); 1185 clone.intervals = new java.util.ArrayList (this.intervals); 1187 if (clone.dataset != null) { 1188 clone.dataset.addChangeListener(clone); 1189 } 1190 return clone; 1191 } 1192 1193} 1194 | Popular Tags |