1:
84:
85: package ;
86:
87: import ;
88: import ;
89: import ;
90: import ;
91: import ;
92: import ;
93: import ;
94: import ;
95: import ;
96: import ;
97: import ;
98: import ;
99: import ;
100: import ;
101: import ;
102: import ;
103: import ;
104: import ;
105: import ;
106: import ;
107: import ;
108: import ;
109: import ;
110: import ;
111: import ;
112:
113: import ;
114: import ;
115: import ;
116: import ;
117: import ;
118: import ;
119: import ;
120: import ;
121: import ;
122: import ;
123: import ;
124: import ;
125:
126:
131: public class MeterPlot extends Plot implements Serializable, Cloneable {
132:
133:
134: private static final long serialVersionUID = 2987472457734470962L;
135:
136:
137: static final Paint DEFAULT_DIAL_BACKGROUND_PAINT = Color.black;
138:
139:
140: static final Paint DEFAULT_NEEDLE_PAINT = Color.green;
141:
142:
143: static final Font DEFAULT_VALUE_FONT = new Font("SansSerif", Font.BOLD, 12);
144:
145:
146: static final Paint DEFAULT_VALUE_PAINT = Color.yellow;
147:
148:
149: public static final int DEFAULT_METER_ANGLE = 270;
150:
151:
152: public static final float DEFAULT_BORDER_SIZE = 3f;
153:
154:
155: public static final float DEFAULT_CIRCLE_SIZE = 10f;
156:
157:
158: public static final Font DEFAULT_LABEL_FONT = new Font("SansSerif",
159: Font.BOLD, 10);
160:
161:
162: private ValueDataset dataset;
163:
164:
165: private DialShape shape;
166:
167:
168: private int meterAngle;
169:
170:
171: private Range range;
172:
173:
174: private double tickSize;
175:
176:
177: private transient Paint tickPaint;
178:
179:
180: private String units;
181:
182:
183: private Font valueFont;
184:
185:
186: private transient Paint valuePaint;
187:
188:
189: private boolean drawBorder;
190:
191:
192: private transient Paint dialOutlinePaint;
193:
194:
195: private transient Paint dialBackgroundPaint;
196:
197:
198: private transient Paint needlePaint;
199:
200:
201: private boolean tickLabelsVisible;
202:
203:
204: private Font tickLabelFont;
205:
206:
207: private transient Paint tickLabelPaint;
208:
209:
210: private NumberFormat tickLabelFormat;
211:
212:
213: protected static ResourceBundle localizationResources =
214: ResourceBundle.getBundle("org.jfree.chart.plot.LocalizationBundle");
215:
216:
220: private List intervals;
221:
222:
226: public MeterPlot() {
227: this(null);
228: }
229:
230:
235: public MeterPlot(ValueDataset dataset) {
236: super();
237: this.shape = DialShape.CIRCLE;
238: this.meterAngle = DEFAULT_METER_ANGLE;
239: this.range = new Range(0.0, 100.0);
240: this.tickSize = 10.0;
241: this.tickPaint = Color.white;
242: this.units = "Units";
243: this.needlePaint = MeterPlot.DEFAULT_NEEDLE_PAINT;
244: this.tickLabelsVisible = true;
245: this.tickLabelFont = MeterPlot.DEFAULT_LABEL_FONT;
246: this.tickLabelPaint = Color.black;
247: this.tickLabelFormat = NumberFormat.getInstance();
248: this.valueFont = MeterPlot.DEFAULT_VALUE_FONT;
249: this.valuePaint = MeterPlot.DEFAULT_VALUE_PAINT;
250: this.dialBackgroundPaint = MeterPlot.DEFAULT_DIAL_BACKGROUND_PAINT;
251: this.intervals = new java.util.ArrayList();
252: setDataset(dataset);
253: }
254:
255:
262: public DialShape getDialShape() {
263: return this.shape;
264: }
265:
266:
274: public void setDialShape(DialShape shape) {
275: if (shape == null) {
276: throw new IllegalArgumentException("Null 'shape' argument.");
277: }
278: this.shape = shape;
279: notifyListeners(new PlotChangeEvent(this));
280: }
281:
282:
290: public int getMeterAngle() {
291: return this.meterAngle;
292: }
293:
294:
302: public void setMeterAngle(int angle) {
303: if (angle < 1 || angle > 360) {
304: throw new IllegalArgumentException("Invalid 'angle' (" + angle
305: + ")");
306: }
307: this.meterAngle = angle;
308: notifyListeners(new PlotChangeEvent(this));
309: }
310:
311:
318: public Range getRange() {
319: return this.range;
320: }
321:
322:
331: public void setRange(Range range) {
332: if (range == null) {
333: throw new IllegalArgumentException("Null 'range' argument.");
334: }
335: if (!(range.getLength() > 0.0)) {
336: throw new IllegalArgumentException(
337: "Range length must be positive.");
338: }
339: this.range = range;
340: notifyListeners(new PlotChangeEvent(this));
341: }
342:
343:
350: public double getTickSize() {
351: return this.tickSize;
352: }
353:
354:
362: public void setTickSize(double size) {
363: if (size <= 0) {
364: throw new IllegalArgumentException("Requires 'size' > 0.");
365: }
366: this.tickSize = size;
367: notifyListeners(new PlotChangeEvent(this));
368: }
369:
370:
378: public Paint getTickPaint() {
379: return this.tickPaint;
380: }
381:
382:
390: public void setTickPaint(Paint paint) {
391: if (paint == null) {
392: throw new IllegalArgumentException("Null 'paint' argument.");
393: }
394: this.tickPaint = paint;
395: notifyListeners(new PlotChangeEvent(this));
396: }
397:
398:
405: public String getUnits() {
406: return this.units;
407: }
408:
409:
417: public void setUnits(String units) {
418: this.units = units;
419: notifyListeners(new PlotChangeEvent(this));
420: }
421:
422:
429: public Paint getNeedlePaint() {
430: return this.needlePaint;
431: }
432:
433:
441: public void setNeedlePaint(Paint paint) {
442: if (paint == null) {
443: throw new IllegalArgumentException("Null 'paint' argument.");
444: }
445: this.needlePaint = paint;
446: notifyListeners(new PlotChangeEvent(this));
447: }
448:
449:
456: public boolean getTickLabelsVisible() {
457: return this.tickLabelsVisible;
458: }
459:
460:
468: public void setTickLabelsVisible(boolean visible) {
469: if (this.tickLabelsVisible != visible) {
470: this.tickLabelsVisible = visible;
471: notifyListeners(new PlotChangeEvent(this));
472: }
473: }
474:
475:
482: public Font getTickLabelFont() {
483: return this.tickLabelFont;
484: }
485:
486:
494: public void setTickLabelFont(Font font) {
495: if (font == null) {
496: throw new IllegalArgumentException("Null 'font' argument.");
497: }
498: if (!this.tickLabelFont.equals(font)) {
499: this.tickLabelFont = font;
500: notifyListeners(new PlotChangeEvent(this));
501: }
502: }
503:
504:
511: public Paint getTickLabelPaint() {
512: return this.tickLabelPaint;
513: }
514:
515:
523: public void setTickLabelPaint(Paint paint) {
524: if (paint == null) {
525: throw new IllegalArgumentException("Null 'paint' argument.");
526: }
527: if (!this.tickLabelPaint.equals(paint)) {
528: this.tickLabelPaint = paint;
529: notifyListeners(new PlotChangeEvent(this));
530: }
531: }
532:
533:
540: public NumberFormat getTickLabelFormat() {
541: return this.tickLabelFormat;
542: }
543:
544:
552: public void setTickLabelFormat(NumberFormat format) {
553: if (format == null) {
554: throw new IllegalArgumentException("Null 'format' argument.");
555: }
556: this.tickLabelFormat = format;
557: notifyListeners(new PlotChangeEvent(this));
558: }
559:
560:
567: public Font getValueFont() {
568: return this.valueFont;
569: }
570:
571:
579: public void setValueFont(Font font) {
580: if (font == null) {
581: throw new IllegalArgumentException("Null 'font' argument.");
582: }
583: this.valueFont = font;
584: notifyListeners(new PlotChangeEvent(this));
585: }
586:
587:
594: public Paint getValuePaint() {
595: return this.valuePaint;
596: }
597:
598:
606: public void setValuePaint(Paint paint) {
607: if (paint == null) {
608: throw new IllegalArgumentException("Null 'paint' argument.");
609: }
610: this.valuePaint = paint;
611: notifyListeners(new PlotChangeEvent(this));
612: }
613:
614:
621: public Paint getDialBackgroundPaint() {
622: return this.dialBackgroundPaint;
623: }
624:
625:
633: public void setDialBackgroundPaint(Paint paint) {
634: this.dialBackgroundPaint = paint;
635: notifyListeners(new PlotChangeEvent(this));
636: }
637:
638:
646: public boolean getDrawBorder() {
647: return this.drawBorder;
648: }
649:
650:
659: public void setDrawBorder(boolean draw) {
660:
661: this.drawBorder = draw;
662: notifyListeners(new PlotChangeEvent(this));
663: }
664:
665:
672: public Paint getDialOutlinePaint() {
673: return this.dialOutlinePaint;
674: }
675:
676:
684: public void setDialOutlinePaint(Paint paint) {
685: this.dialOutlinePaint = paint;
686: notifyListeners(new PlotChangeEvent(this));
687: }
688:
689:
696: public ValueDataset getDataset() {
697: return this.dataset;
698: }
699:
700:
708: public void setDataset(ValueDataset dataset) {
709:
710:
711:
712: ValueDataset existing = this.dataset;
713: if (existing != null) {
714: existing.removeChangeListener(this);
715: }
716:
717:
718: this.dataset = dataset;
719: if (dataset != null) {
720: setDatasetGroup(dataset.getGroup());
721: dataset.addChangeListener(this);
722: }
723:
724:
725: DatasetChangeEvent event = new DatasetChangeEvent(this, dataset);
726: datasetChanged(event);
727:
728: }
729:
730:
737: public List getIntervals() {
738: return Collections.unmodifiableList(this.intervals);
739: }
740:
741:
750: public void addInterval(MeterInterval interval) {
751: if (interval == null) {
752: throw new IllegalArgumentException("Null 'interval' argument.");
753: }
754: this.intervals.add(interval);
755: notifyListeners(new PlotChangeEvent(this));
756: }
757:
758:
764: public void clearIntervals() {
765: this.intervals.clear();
766: notifyListeners(new PlotChangeEvent(this));
767: }
768:
769:
774: public LegendItemCollection getLegendItems() {
775: LegendItemCollection result = new LegendItemCollection();
776: Iterator iterator = this.intervals.iterator();
777: while (iterator.hasNext()) {
778: MeterInterval mi = (MeterInterval) iterator.next();
779: Paint color = mi.getBackgroundPaint();
780: if (color == null) {
781: color = mi.getOutlinePaint();
782: }
783: LegendItem item = new LegendItem(mi.getLabel(), mi.getLabel(),
784: null, null, new Rectangle2D.Double(-4.0, -4.0, 8.0, 8.0),
785: color);
786: result.add(item);
787: }
788: return result;
789: }
790:
791:
801: public void draw(Graphics2D g2, Rectangle2D area, Point2D anchor,
802: PlotState parentState,
803: PlotRenderingInfo info) {
804:
805: if (info != null) {
806: info.setPlotArea(area);
807: }
808:
809:
810: RectangleInsets insets = getInsets();
811: insets.trim(area);
812:
813: area.setRect(area.getX() + 4, area.getY() + 4, area.getWidth() - 8,
814: area.getHeight() - 8);
815:
816:
817: if (this.drawBorder) {
818: drawBackground(g2, area);
819: }
820:
821:
822: double gapHorizontal = (2 * DEFAULT_BORDER_SIZE);
823: double gapVertical = (2 * DEFAULT_BORDER_SIZE);
824: double meterX = area.getX() + gapHorizontal / 2;
825: double meterY = area.getY() + gapVertical / 2;
826: double meterW = area.getWidth() - gapHorizontal;
827: double meterH = area.getHeight() - gapVertical
828: + ((this.meterAngle <= 180) && (this.shape != DialShape.CIRCLE)
829: ? area.getHeight() / 1.25 : 0);
830:
831: double min = Math.min(meterW, meterH) / 2;
832: meterX = (meterX + meterX + meterW) / 2 - min;
833: meterY = (meterY + meterY + meterH) / 2 - min;
834: meterW = 2 * min;
835: meterH = 2 * min;
836:
837: Rectangle2D meterArea = new Rectangle2D.Double(meterX, meterY, meterW,
838: meterH);
839:
840: Rectangle2D.Double originalArea = new Rectangle2D.Double(
841: meterArea.getX() - 4, meterArea.getY() - 4,
842: meterArea.getWidth() + 8, meterArea.getHeight() + 8);
843:
844: double meterMiddleX = meterArea.getCenterX();
845: double meterMiddleY = meterArea.getCenterY();
846:
847:
848: ValueDataset data = getDataset();
849: if (data != null) {
850: double dataMin = this.range.getLowerBound();
851: double dataMax = this.range.getUpperBound();
852:
853: Shape savedClip = g2.getClip();
854: g2.clip(originalArea);
855: Composite originalComposite = g2.getComposite();
856: g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
857: getForegroundAlpha()));
858:
859: if (this.dialBackgroundPaint != null) {
860: fillArc(g2, originalArea, dataMin, dataMax,
861: this.dialBackgroundPaint, true);
862: }
863: drawTicks(g2, meterArea, dataMin, dataMax);
864: drawArcForInterval(g2, meterArea, new MeterInterval("", this.range,
865: this.dialOutlinePaint, new BasicStroke(1.0f), null));
866:
867: Iterator iterator = this.intervals.iterator();
868: while (iterator.hasNext()) {
869: MeterInterval interval = (MeterInterval) iterator.next();
870: drawArcForInterval(g2, meterArea, interval);
871: }
872:
873: Number n = data.getValue();
874: if (n != null) {
875: double value = n.doubleValue();
876: drawValueLabel(g2, meterArea);
877:
878: if (this.range.contains(value)) {
879: g2.setPaint(this.needlePaint);
880: g2.setStroke(new BasicStroke(2.0f));
881:
882: double radius = (meterArea.getWidth() / 2)
883: + DEFAULT_BORDER_SIZE + 15;
884: double valueAngle = valueToAngle(value);
885: double valueP1 = meterMiddleX
886: + (radius * Math.cos(Math.PI * (valueAngle / 180)));
887: double valueP2 = meterMiddleY
888: - (radius * Math.sin(Math.PI * (valueAngle / 180)));
889:
890: Polygon arrow = new Polygon();
891: if ((valueAngle > 135 && valueAngle < 225)
892: || (valueAngle < 45 && valueAngle > -45)) {
893:
894: double valueP3 = (meterMiddleY
895: - DEFAULT_CIRCLE_SIZE / 4);
896: double valueP4 = (meterMiddleY
897: + DEFAULT_CIRCLE_SIZE / 4);
898: arrow.addPoint((int) meterMiddleX, (int) valueP3);
899: arrow.addPoint((int) meterMiddleX, (int) valueP4);
900:
901: }
902: else {
903: arrow.addPoint((int) (meterMiddleX
904: - DEFAULT_CIRCLE_SIZE / 4), (int) meterMiddleY);
905: arrow.addPoint((int) (meterMiddleX
906: + DEFAULT_CIRCLE_SIZE / 4), (int) meterMiddleY);
907: }
908: arrow.addPoint((int) valueP1, (int) valueP2);
909: g2.fill(arrow);
910:
911: Ellipse2D circle = new Ellipse2D.Double(meterMiddleX
912: - DEFAULT_CIRCLE_SIZE / 2, meterMiddleY
913: - DEFAULT_CIRCLE_SIZE / 2, DEFAULT_CIRCLE_SIZE,
914: DEFAULT_CIRCLE_SIZE);
915: g2.fill(circle);
916: }
917: }
918:
919: g2.setClip(savedClip);
920: g2.setComposite(originalComposite);
921:
922: }
923: if (this.drawBorder) {
924: drawOutline(g2, area);
925: }
926:
927: }
928:
929:
936: protected void drawArcForInterval(Graphics2D g2, Rectangle2D meterArea,
937: MeterInterval interval) {
938:
939: double minValue = interval.getRange().getLowerBound();
940: double maxValue = interval.getRange().getUpperBound();
941: Paint outlinePaint = interval.getOutlinePaint();
942: Stroke outlineStroke = interval.getOutlineStroke();
943: Paint backgroundPaint = interval.getBackgroundPaint();
944:
945: if (backgroundPaint != null) {
946: fillArc(g2, meterArea, minValue, maxValue, backgroundPaint, false);
947: }
948: if (outlinePaint != null) {
949: if (outlineStroke != null) {
950: drawArc(g2, meterArea, minValue, maxValue, outlinePaint,
951: outlineStroke);
952: }
953: drawTick(g2, meterArea, minValue, true);
954: drawTick(g2, meterArea, maxValue, true);
955: }
956: }
957:
958:
968: protected void drawArc(Graphics2D g2, Rectangle2D area, double minValue,
969: double maxValue, Paint paint, Stroke stroke) {
970:
971: double startAngle = valueToAngle(maxValue);
972: double endAngle = valueToAngle(minValue);
973: double extent = endAngle - startAngle;
974:
975: double x = area.getX();
976: double y = area.getY();
977: double w = area.getWidth();
978: double h = area.getHeight();
979: g2.setPaint(paint);
980: g2.setStroke(stroke);
981:
982: if (paint != null && stroke != null) {
983: Arc2D.Double arc = new Arc2D.Double(x, y, w, h, startAngle,
984: extent, Arc2D.OPEN);
985: g2.setPaint(paint);
986: g2.setStroke(stroke);
987: g2.draw(arc);
988: }
989:
990: }
991:
992:
1003: protected void fillArc(Graphics2D g2, Rectangle2D area,
1004: double minValue, double maxValue, Paint paint,
1005: boolean dial) {
1006: if (paint == null) {
1007: throw new IllegalArgumentException("Null 'paint' argument");
1008: }
1009: double startAngle = valueToAngle(maxValue);
1010: double endAngle = valueToAngle(minValue);
1011: double extent = endAngle - startAngle;
1012:
1013: double x = area.getX();
1014: double y = area.getY();
1015: double w = area.getWidth();
1016: double h = area.getHeight();
1017: int joinType = Arc2D.OPEN;
1018: if (this.shape == DialShape.PIE) {
1019: joinType = Arc2D.PIE;
1020: }
1021: else if (this.shape == DialShape.CHORD) {
1022: if (dial && this.meterAngle > 180) {
1023: joinType = Arc2D.CHORD;
1024: }
1025: else {
1026: joinType = Arc2D.PIE;
1027: }
1028: }
1029: else if (this.shape == DialShape.CIRCLE) {
1030: joinType = Arc2D.PIE;
1031: if (dial) {
1032: extent = 360;
1033: }
1034: }
1035: else {
1036: throw new IllegalStateException("DialShape not recognised.");
1037: }
1038:
1039: g2.setPaint(paint);
1040: Arc2D.Double arc = new Arc2D.Double(x, y, w, h, startAngle, extent,
1041: joinType);
1042: g2.fill(arc);
1043: }
1044:
1045:
1052: public double valueToAngle(double value) {
1053: value = value - this.range.getLowerBound();
1054: double baseAngle = 180 + ((this.meterAngle - 180) / 2);
1055: return baseAngle - ((value / this.range.getLength()) * this.meterAngle);
1056: }
1057:
1058:
1066: protected void drawTicks(Graphics2D g2, Rectangle2D meterArea,
1067: double minValue, double maxValue) {
1068: for (double v = minValue; v <= maxValue; v += this.tickSize) {
1069: drawTick(g2, meterArea, v);
1070: }
1071: }
1072:
1073:
1080: protected void drawTick(Graphics2D g2, Rectangle2D meterArea,
1081: double value) {
1082: drawTick(g2, meterArea, value, false);
1083: }
1084:
1085:
1093: protected void drawTick(Graphics2D g2, Rectangle2D meterArea,
1094: double value, boolean label) {
1095:
1096: double valueAngle = valueToAngle(value);
1097:
1098: double meterMiddleX = meterArea.getCenterX();
1099: double meterMiddleY = meterArea.getCenterY();
1100:
1101: g2.setPaint(this.tickPaint);
1102: g2.setStroke(new BasicStroke(2.0f));
1103:
1104: double valueP2X = 0;
1105: double valueP2Y = 0;
1106:
1107: double radius = (meterArea.getWidth() / 2) + DEFAULT_BORDER_SIZE;
1108: double radius1 = radius - 15;
1109:
1110: double valueP1X = meterMiddleX
1111: + (radius * Math.cos(Math.PI * (valueAngle / 180)));
1112: double valueP1Y = meterMiddleY
1113: - (radius * Math.sin(Math.PI * (valueAngle / 180)));
1114:
1115: valueP2X = meterMiddleX
1116: + (radius1 * Math.cos(Math.PI * (valueAngle / 180)));
1117: valueP2Y = meterMiddleY
1118: - (radius1 * Math.sin(Math.PI * (valueAngle / 180)));
1119:
1120: Line2D.Double line = new Line2D.Double(valueP1X, valueP1Y, valueP2X,
1121: valueP2Y);
1122: g2.draw(line);
1123:
1124: if (this.tickLabelsVisible && label) {
1125:
1126: String tickLabel = this.tickLabelFormat.format(value);
1127: g2.setFont(this.tickLabelFont);
1128: g2.setPaint(this.tickLabelPaint);
1129:
1130: FontMetrics fm = g2.getFontMetrics();
1131: Rectangle2D tickLabelBounds
1132: = TextUtilities.getTextBounds(tickLabel, g2, fm);
1133:
1134: double x = valueP2X;
1135: double y = valueP2Y;
1136: if (valueAngle == 90 || valueAngle == 270) {
1137: x = x - tickLabelBounds.getWidth() / 2;
1138: }
1139: else if (valueAngle < 90 || valueAngle > 270) {
1140: x = x - tickLabelBounds.getWidth();
1141: }
1142: if ((valueAngle > 135 && valueAngle < 225)
1143: || valueAngle > 315 || valueAngle < 45) {
1144: y = y - tickLabelBounds.getHeight() / 2;
1145: }
1146: else {
1147: y = y + tickLabelBounds.getHeight() / 2;
1148: }
1149: g2.drawString(tickLabel, (float) x, (float) y);
1150: }
1151: }
1152:
1153:
1159: protected void drawValueLabel(Graphics2D g2, Rectangle2D area) {
1160: g2.setFont(this.valueFont);
1161: g2.setPaint(this.valuePaint);
1162: String valueStr = "No value";
1163: if (this.dataset != null) {
1164: Number n = this.dataset.getValue();
1165: if (n != null) {
1166: valueStr = this.tickLabelFormat.format(n.doubleValue()) + " "
1167: + this.units;
1168: }
1169: }
1170: float x = (float) area.getCenterX();
1171: float y = (float) area.getCenterY() + DEFAULT_CIRCLE_SIZE;
1172: TextUtilities.drawAlignedString(valueStr, g2, x, y,
1173: TextAnchor.TOP_CENTER);
1174: }
1175:
1176:
1181: public String getPlotType() {
1182: return localizationResources.getString("Meter_Plot");
1183: }
1184:
1185:
1192: public void zoom(double percent) {
1193:
1194: }
1195:
1196:
1204: public boolean equals(Object obj) {
1205: if (obj == this) {
1206: return true;
1207: }
1208: if (!(obj instanceof MeterPlot)) {
1209: return false;
1210: }
1211: if (!super.equals(obj)) {
1212: return false;
1213: }
1214: MeterPlot that = (MeterPlot) obj;
1215: if (!ObjectUtilities.equal(this.units, that.units)) {
1216: return false;
1217: }
1218: if (!ObjectUtilities.equal(this.range, that.range)) {
1219: return false;
1220: }
1221: if (!ObjectUtilities.equal(this.intervals, that.intervals)) {
1222: return false;
1223: }
1224: if (!PaintUtilities.equal(this.dialOutlinePaint,
1225: that.dialOutlinePaint)) {
1226: return false;
1227: }
1228: if (this.shape != that.shape) {
1229: return false;
1230: }
1231: if (!PaintUtilities.equal(this.dialBackgroundPaint,
1232: that.dialBackgroundPaint)) {
1233: return false;
1234: }
1235: if (!PaintUtilities.equal(this.needlePaint, that.needlePaint)) {
1236: return false;
1237: }
1238: if (!ObjectUtilities.equal(this.valueFont, that.valueFont)) {
1239: return false;
1240: }
1241: if (!PaintUtilities.equal(this.valuePaint, that.valuePaint)) {
1242: return false;
1243: }
1244: if (!PaintUtilities.equal(this.tickPaint, that.tickPaint)) {
1245: return false;
1246: }
1247: if (this.tickSize != that.tickSize) {
1248: return false;
1249: }
1250: if (this.tickLabelsVisible != that.tickLabelsVisible) {
1251: return false;
1252: }
1253: if (!ObjectUtilities.equal(this.tickLabelFont, that.tickLabelFont)) {
1254: return false;
1255: }
1256: if (!PaintUtilities.equal(this.tickLabelPaint, that.tickLabelPaint)) {
1257: return false;
1258: }
1259: if (!ObjectUtilities.equal(this.tickLabelFormat,
1260: that.tickLabelFormat)) {
1261: return false;
1262: }
1263: if (this.drawBorder != that.drawBorder) {
1264: return false;
1265: }
1266: if (this.meterAngle != that.meterAngle) {
1267: return false;
1268: }
1269: return true;
1270: }
1271:
1272:
1279: private void writeObject(ObjectOutputStream stream) throws IOException {
1280: stream.defaultWriteObject();
1281: SerialUtilities.writePaint(this.dialBackgroundPaint, stream);
1282: SerialUtilities.writePaint(this.needlePaint, stream);
1283: SerialUtilities.writePaint(this.valuePaint, stream);
1284: SerialUtilities.writePaint(this.tickPaint, stream);
1285: SerialUtilities.writePaint(this.tickLabelPaint, stream);
1286: }
1287:
1288:
1296: private void readObject(ObjectInputStream stream)
1297: throws IOException, ClassNotFoundException {
1298: stream.defaultReadObject();
1299: this.dialBackgroundPaint = SerialUtilities.readPaint(stream);
1300: this.needlePaint = SerialUtilities.readPaint(stream);
1301: this.valuePaint = SerialUtilities.readPaint(stream);
1302: this.tickPaint = SerialUtilities.readPaint(stream);
1303: this.tickLabelPaint = SerialUtilities.readPaint(stream);
1304: if (this.dataset != null) {
1305: this.dataset.addChangeListener(this);
1306: }
1307: }
1308:
1309:
1319: public Object clone() throws CloneNotSupportedException {
1320: MeterPlot clone = (MeterPlot) super.clone();
1321: clone.tickLabelFormat = (NumberFormat) this.tickLabelFormat.clone();
1322:
1323: clone.intervals = new java.util.ArrayList(this.intervals);
1324: if (clone.dataset != null) {
1325: clone.dataset.addChangeListener(clone);
1326: }
1327: return clone;
1328: }
1329:
1330: }