1:
90:
91: package ;
92:
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: import ;
113: import ;
114:
115: import ;
116: import ;
117: import ;
118: import ;
119: import ;
120: import ;
121: import ;
122: import ;
123: import ;
124: import ;
125: import ;
126: import ;
127: import ;
128: import ;
129:
130:
148: public class ThermometerPlot extends Plot implements ValueAxisPlot,
149: Zoomable, Cloneable, Serializable {
150:
151:
152: private static final long serialVersionUID = 4087093313147984390L;
153:
154:
155: public static final int UNITS_NONE = 0;
156:
157:
158: public static final int UNITS_FAHRENHEIT = 1;
159:
160:
161: public static final int UNITS_CELCIUS = 2;
162:
163:
164: public static final int UNITS_KELVIN = 3;
165:
166:
167: public static final int NONE = 0;
168:
169:
170: public static final int RIGHT = 1;
171:
172:
173: public static final int LEFT = 2;
174:
175:
176: public static final int BULB = 3;
177:
178:
179: public static final int NORMAL = 0;
180:
181:
182: public static final int WARNING = 1;
183:
184:
185: public static final int CRITICAL = 2;
186:
187:
192: protected static final int BULB_RADIUS = 40;
193:
194:
199: protected static final int BULB_DIAMETER = BULB_RADIUS * 2;
200:
201:
206: protected static final int COLUMN_RADIUS = 20;
207:
208:
213: protected static final int COLUMN_DIAMETER = COLUMN_RADIUS * 2;
214:
215:
220: protected static final int GAP_RADIUS = 5;
221:
222:
227: protected static final int GAP_DIAMETER = GAP_RADIUS * 2;
228:
229:
230: protected static final int AXIS_GAP = 10;
231:
232:
233: protected static final String[] UNITS = {"", "\u00B0F", "\u00B0C",
234: "\u00B0K"};
235:
236:
237: protected static final int RANGE_LOW = 0;
238:
239:
240: protected static final int RANGE_HIGH = 1;
241:
242:
243: protected static final int DISPLAY_LOW = 2;
244:
245:
246: protected static final int DISPLAY_HIGH = 3;
247:
248:
249: protected static final double DEFAULT_LOWER_BOUND = 0.0;
250:
251:
252: protected static final double DEFAULT_UPPER_BOUND = 100.0;
253:
254:
259: protected static final int DEFAULT_BULB_RADIUS = 40;
260:
261:
266: protected static final int DEFAULT_COLUMN_RADIUS = 20;
267:
268:
273: protected static final int DEFAULT_GAP = 5;
274:
275:
276: private ValueDataset dataset;
277:
278:
279: private ValueAxis rangeAxis;
280:
281:
282: private double lowerBound = DEFAULT_LOWER_BOUND;
283:
284:
285: private double upperBound = DEFAULT_UPPER_BOUND;
286:
287:
292: private int bulbRadius = DEFAULT_BULB_RADIUS;
293:
294:
299: private int columnRadius = DEFAULT_COLUMN_RADIUS;
300:
301:
306: private int gap = DEFAULT_GAP;
307:
308:
311: private RectangleInsets padding;
312:
313:
314: private transient Stroke thermometerStroke = new BasicStroke(1.0f);
315:
316:
317: private transient Paint thermometerPaint = Color.black;
318:
319:
320: private int units = UNITS_CELCIUS;
321:
322:
323: private int valueLocation = BULB;
324:
325:
326: private int axisLocation = LEFT;
327:
328:
329: private Font valueFont = new Font("SansSerif", Font.BOLD, 16);
330:
331:
332: private transient Paint valuePaint = Color.white;
333:
334:
335: private NumberFormat valueFormat = new DecimalFormat();
336:
337:
338: private transient Paint mercuryPaint = Color.lightGray;
339:
340:
341: private boolean showValueLines = false;
342:
343:
344: private int subrange = -1;
345:
346:
347: private double[][] subrangeInfo = {
348: {0.0, 50.0, 0.0, 50.0},
349: {50.0, 75.0, 50.0, 75.0},
350: {75.0, 100.0, 75.0, 100.0}
351: };
352:
353:
357: private boolean followDataInSubranges = false;
358:
359:
363: private boolean useSubrangePaint = true;
364:
365:
366: private transient Paint[] subrangePaint = {Color.green, Color.orange,
367: Color.red};
368:
369:
370: private boolean subrangeIndicatorsVisible = true;
371:
372:
373: private transient Stroke subrangeIndicatorStroke = new BasicStroke(2.0f);
374:
375:
376: private transient Stroke rangeIndicatorStroke = new BasicStroke(3.0f);
377:
378:
379: protected static ResourceBundle localizationResources =
380: ResourceBundle.getBundle("org.jfree.chart.plot.LocalizationBundle");
381:
382:
385: public ThermometerPlot() {
386: this(new DefaultValueDataset());
387: }
388:
389:
394: public ThermometerPlot(ValueDataset dataset) {
395:
396: super();
397:
398: this.padding = new RectangleInsets(UnitType.RELATIVE, 0.05, 0.05, 0.05,
399: 0.05);
400: this.dataset = dataset;
401: if (dataset != null) {
402: dataset.addChangeListener(this);
403: }
404: NumberAxis axis = new NumberAxis(null);
405: axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
406: axis.setAxisLineVisible(false);
407: axis.setPlot(this);
408: axis.addChangeListener(this);
409: this.rangeAxis = axis;
410: setAxisRange();
411: }
412:
413:
420: public ValueDataset getDataset() {
421: return this.dataset;
422: }
423:
424:
432: public void setDataset(ValueDataset dataset) {
433:
434:
435:
436: ValueDataset existing = this.dataset;
437: if (existing != null) {
438: existing.removeChangeListener(this);
439: }
440:
441:
442: this.dataset = dataset;
443: if (dataset != null) {
444: setDatasetGroup(dataset.getGroup());
445: dataset.addChangeListener(this);
446: }
447:
448:
449: DatasetChangeEvent event = new DatasetChangeEvent(this, dataset);
450: datasetChanged(event);
451:
452: }
453:
454:
461: public ValueAxis getRangeAxis() {
462: return this.rangeAxis;
463: }
464:
465:
473: public void setRangeAxis(ValueAxis axis) {
474: if (axis == null) {
475: throw new IllegalArgumentException("Null 'axis' argument.");
476: }
477:
478: this.rangeAxis.removeChangeListener(this);
479:
480: axis.setPlot(this);
481: axis.addChangeListener(this);
482: this.rangeAxis = axis;
483: fireChangeEvent();
484: }
485:
486:
494: public double getLowerBound() {
495: return this.lowerBound;
496: }
497:
498:
505: public void setLowerBound(double lower) {
506: this.lowerBound = lower;
507: setAxisRange();
508: }
509:
510:
518: public double getUpperBound() {
519: return this.upperBound;
520: }
521:
522:
529: public void setUpperBound(double upper) {
530: this.upperBound = upper;
531: setAxisRange();
532: }
533:
534:
540: public void setRange(double lower, double upper) {
541: this.lowerBound = lower;
542: this.upperBound = upper;
543: setAxisRange();
544: }
545:
546:
554: public RectangleInsets getPadding() {
555: return this.padding;
556: }
557:
558:
566: public void setPadding(RectangleInsets padding) {
567: if (padding == null) {
568: throw new IllegalArgumentException("Null 'padding' argument.");
569: }
570: this.padding = padding;
571: fireChangeEvent();
572: }
573:
574:
582: public Stroke getThermometerStroke() {
583: return this.thermometerStroke;
584: }
585:
586:
594: public void setThermometerStroke(Stroke s) {
595: if (s != null) {
596: this.thermometerStroke = s;
597: fireChangeEvent();
598: }
599: }
600:
601:
609: public Paint getThermometerPaint() {
610: return this.thermometerPaint;
611: }
612:
613:
621: public void setThermometerPaint(Paint paint) {
622: if (paint != null) {
623: this.thermometerPaint = paint;
624: fireChangeEvent();
625: }
626: }
627:
628:
637: public int getUnits() {
638: return this.units;
639: }
640:
641:
656: public void setUnits(int u) {
657: if ((u >= 0) && (u < UNITS.length)) {
658: if (this.units != u) {
659: this.units = u;
660: fireChangeEvent();
661: }
662: }
663: }
664:
665:
673: public void setUnits(String u) {
674: if (u == null) {
675: return;
676: }
677:
678: u = u.toUpperCase().trim();
679: for (int i = 0; i < UNITS.length; ++i) {
680: if (u.equals(UNITS[i].toUpperCase().trim())) {
681: setUnits(i);
682: i = UNITS.length;
683: }
684: }
685: }
686:
687:
694: public int getValueLocation() {
695: return this.valueLocation;
696: }
697:
698:
710: public void setValueLocation(int location) {
711: if ((location >= 0) && (location < 4)) {
712: this.valueLocation = location;
713: fireChangeEvent();
714: }
715: else {
716: throw new IllegalArgumentException("Location not recognised.");
717: }
718: }
719:
720:
728: public int getAxisLocation() {
729: return this.axisLocation;
730: }
731:
732:
742: public void setAxisLocation(int location) {
743: if ((location >= 0) && (location < 3)) {
744: this.axisLocation = location;
745: fireChangeEvent();
746: }
747: else {
748: throw new IllegalArgumentException("Location not recognised.");
749: }
750: }
751:
752:
759: public Font getValueFont() {
760: return this.valueFont;
761: }
762:
763:
770: public void setValueFont(Font f) {
771: if (f == null) {
772: throw new IllegalArgumentException("Null 'font' argument.");
773: }
774: if (!this.valueFont.equals(f)) {
775: this.valueFont = f;
776: fireChangeEvent();
777: }
778: }
779:
780:
787: public Paint getValuePaint() {
788: return this.valuePaint;
789: }
790:
791:
799: public void setValuePaint(Paint paint) {
800: if (paint == null) {
801: throw new IllegalArgumentException("Null 'paint' argument.");
802: }
803: if (!this.valuePaint.equals(paint)) {
804: this.valuePaint = paint;
805: fireChangeEvent();
806: }
807: }
808:
809:
810:
811:
817: public void setValueFormat(NumberFormat formatter) {
818: if (formatter == null) {
819: throw new IllegalArgumentException("Null 'formatter' argument.");
820: }
821: this.valueFormat = formatter;
822: fireChangeEvent();
823: }
824:
825:
832: public Paint getMercuryPaint() {
833: return this.mercuryPaint;
834: }
835:
836:
844: public void setMercuryPaint(Paint paint) {
845: if (paint == null) {
846: throw new IllegalArgumentException("Null 'paint' argument.");
847: }
848: this.mercuryPaint = paint;
849: fireChangeEvent();
850: }
851:
852:
862: public boolean getShowValueLines() {
863: return this.showValueLines;
864: }
865:
866:
876: public void setShowValueLines(boolean b) {
877: this.showValueLines = b;
878: fireChangeEvent();
879: }
880:
881:
888: public void setSubrangeInfo(int range, double low, double hi) {
889: setSubrangeInfo(range, low, hi, low, hi);
890: }
891:
892:
901: public void setSubrangeInfo(int range,
902: double rangeLow, double rangeHigh,
903: double displayLow, double displayHigh) {
904:
905: if ((range >= 0) && (range < 3)) {
906: setSubrange(range, rangeLow, rangeHigh);
907: setDisplayRange(range, displayLow, displayHigh);
908: setAxisRange();
909: fireChangeEvent();
910: }
911:
912: }
913:
914:
921: public void setSubrange(int range, double low, double high) {
922: if ((range >= 0) && (range < 3)) {
923: this.subrangeInfo[range][RANGE_HIGH] = high;
924: this.subrangeInfo[range][RANGE_LOW] = low;
925: }
926: }
927:
928:
935: public void setDisplayRange(int range, double low, double high) {
936:
937: if ((range >= 0) && (range < this.subrangeInfo.length)
938: && isValidNumber(high) && isValidNumber(low)) {
939:
940: if (high > low) {
941: this.subrangeInfo[range][DISPLAY_HIGH] = high;
942: this.subrangeInfo[range][DISPLAY_LOW] = low;
943: }
944: else {
945: this.subrangeInfo[range][DISPLAY_HIGH] = low;
946: this.subrangeInfo[range][DISPLAY_LOW] = high;
947: }
948:
949: }
950:
951: }
952:
953:
962: public Paint getSubrangePaint(int range) {
963: if ((range >= 0) && (range < this.subrangePaint.length)) {
964: return this.subrangePaint[range];
965: }
966: else {
967: return this.mercuryPaint;
968: }
969: }
970:
971:
980: public void setSubrangePaint(int range, Paint paint) {
981: if ((range >= 0)
982: && (range < this.subrangePaint.length) && (paint != null)) {
983: this.subrangePaint[range] = paint;
984: fireChangeEvent();
985: }
986: }
987:
988:
994: public boolean getFollowDataInSubranges() {
995: return this.followDataInSubranges;
996: }
997:
998:
1004: public void setFollowDataInSubranges(boolean flag) {
1005: this.followDataInSubranges = flag;
1006: fireChangeEvent();
1007: }
1008:
1009:
1017: public boolean getUseSubrangePaint() {
1018: return this.useSubrangePaint;
1019: }
1020:
1021:
1028: public void setUseSubrangePaint(boolean flag) {
1029: this.useSubrangePaint = flag;
1030: fireChangeEvent();
1031: }
1032:
1033:
1040: public int getBulbRadius() {
1041: return this.bulbRadius;
1042: }
1043:
1044:
1054: public void setBulbRadius(int r) {
1055: this.bulbRadius = r;
1056: fireChangeEvent();
1057: }
1058:
1059:
1067: public int getBulbDiameter() {
1068: return getBulbRadius() * 2;
1069: }
1070:
1071:
1080: public int getColumnRadius() {
1081: return this.columnRadius;
1082: }
1083:
1084:
1094: public void setColumnRadius(int r) {
1095: this.columnRadius = r;
1096: fireChangeEvent();
1097: }
1098:
1099:
1107: public int getColumnDiameter() {
1108: return getColumnRadius() * 2;
1109: }
1110:
1111:
1121: public int getGap() {
1122: return this.gap;
1123: }
1124:
1125:
1136: public void setGap(int gap) {
1137: this.gap = gap;
1138: fireChangeEvent();
1139: }
1140:
1141:
1151: public void draw(Graphics2D g2, Rectangle2D area, Point2D anchor,
1152: PlotState parentState,
1153: PlotRenderingInfo info) {
1154:
1155: RoundRectangle2D outerStem = new RoundRectangle2D.Double();
1156: RoundRectangle2D innerStem = new RoundRectangle2D.Double();
1157: RoundRectangle2D mercuryStem = new RoundRectangle2D.Double();
1158: Ellipse2D outerBulb = new Ellipse2D.Double();
1159: Ellipse2D innerBulb = new Ellipse2D.Double();
1160: String temp = null;
1161: FontMetrics metrics = null;
1162: if (info != null) {
1163: info.setPlotArea(area);
1164: }
1165:
1166:
1167: RectangleInsets insets = getInsets();
1168: insets.trim(area);
1169: drawBackground(g2, area);
1170:
1171:
1172: Rectangle2D interior = (Rectangle2D) area.clone();
1173: this.padding.trim(interior);
1174: int midX = (int) (interior.getX() + (interior.getWidth() / 2));
1175: int midY = (int) (interior.getY() + (interior.getHeight() / 2));
1176: int stemTop = (int) (interior.getMinY() + getBulbRadius());
1177: int stemBottom = (int) (interior.getMaxY() - getBulbDiameter());
1178: Rectangle2D dataArea = new Rectangle2D.Double(midX - getColumnRadius(),
1179: stemTop, getColumnRadius(), stemBottom - stemTop);
1180:
1181: outerBulb.setFrame(midX - getBulbRadius(), stemBottom,
1182: getBulbDiameter(), getBulbDiameter());
1183:
1184: outerStem.setRoundRect(midX - getColumnRadius(), interior.getMinY(),
1185: getColumnDiameter(), stemBottom + getBulbDiameter() - stemTop,
1186: getColumnDiameter(), getColumnDiameter());
1187:
1188: Area outerThermometer = new Area(outerBulb);
1189: Area tempArea = new Area(outerStem);
1190: outerThermometer.add(tempArea);
1191:
1192: innerBulb.setFrame(midX - getBulbRadius() + getGap(), stemBottom
1193: + getGap(), getBulbDiameter() - getGap() * 2, getBulbDiameter()
1194: - getGap() * 2);
1195:
1196: innerStem.setRoundRect(midX - getColumnRadius() + getGap(),
1197: interior.getMinY() + getGap(), getColumnDiameter()
1198: - getGap() * 2, stemBottom + getBulbDiameter() - getGap() * 2
1199: - stemTop, getColumnDiameter() - getGap() * 2,
1200: getColumnDiameter() - getGap() * 2);
1201:
1202: Area innerThermometer = new Area(innerBulb);
1203: tempArea = new Area(innerStem);
1204: innerThermometer.add(tempArea);
1205:
1206: if ((this.dataset != null) && (this.dataset.getValue() != null)) {
1207: double current = this.dataset.getValue().doubleValue();
1208: double ds = this.rangeAxis.valueToJava2D(current, dataArea,
1209: RectangleEdge.LEFT);
1210:
1211: int i = getColumnDiameter() - getGap() * 2;
1212: int j = getColumnRadius() - getGap();
1213: int l = (i / 2);
1214: int k = (int) Math.round(ds);
1215: if (k < (getGap() + interior.getMinY())) {
1216: k = (int) (getGap() + interior.getMinY());
1217: l = getBulbRadius();
1218: }
1219:
1220: Area mercury = new Area(innerBulb);
1221:
1222: if (k < (stemBottom + getBulbRadius())) {
1223: mercuryStem.setRoundRect(midX - j, k, i,
1224: (stemBottom + getBulbRadius()) - k, l, l);
1225: tempArea = new Area(mercuryStem);
1226: mercury.add(tempArea);
1227: }
1228:
1229: g2.setPaint(getCurrentPaint());
1230: g2.fill(mercury);
1231:
1232:
1233: if (this.subrangeIndicatorsVisible) {
1234: g2.setStroke(this.subrangeIndicatorStroke);
1235: Range range = this.rangeAxis.getRange();
1236:
1237:
1238: double value = this.subrangeInfo[NORMAL][RANGE_LOW];
1239: if (range.contains(value)) {
1240: double x = midX + getColumnRadius() + 2;
1241: double y = this.rangeAxis.valueToJava2D(value, dataArea,
1242: RectangleEdge.LEFT);
1243: Line2D line = new Line2D.Double(x, y, x + 10, y);
1244: g2.setPaint(this.subrangePaint[NORMAL]);
1245: g2.draw(line);
1246: }
1247:
1248:
1249: value = this.subrangeInfo[WARNING][RANGE_LOW];
1250: if (range.contains(value)) {
1251: double x = midX + getColumnRadius() + 2;
1252: double y = this.rangeAxis.valueToJava2D(value, dataArea,
1253: RectangleEdge.LEFT);
1254: Line2D line = new Line2D.Double(x, y, x + 10, y);
1255: g2.setPaint(this.subrangePaint[WARNING]);
1256: g2.draw(line);
1257: }
1258:
1259:
1260: value = this.subrangeInfo[CRITICAL][RANGE_LOW];
1261: if (range.contains(value)) {
1262: double x = midX + getColumnRadius() + 2;
1263: double y = this.rangeAxis.valueToJava2D(value, dataArea,
1264: RectangleEdge.LEFT);
1265: Line2D line = new Line2D.Double(x, y, x + 10, y);
1266: g2.setPaint(this.subrangePaint[CRITICAL]);
1267: g2.draw(line);
1268: }
1269: }
1270:
1271:
1272: if ((this.rangeAxis != null) && (this.axisLocation != NONE)) {
1273: int drawWidth = AXIS_GAP;
1274: if (this.showValueLines) {
1275: drawWidth += getColumnDiameter();
1276: }
1277: Rectangle2D drawArea;
1278: double cursor = 0;
1279:
1280: switch (this.axisLocation) {
1281: case RIGHT:
1282: cursor = midX + getColumnRadius();
1283: drawArea = new Rectangle2D.Double(cursor,
1284: stemTop, drawWidth, (stemBottom - stemTop + 1));
1285: this.rangeAxis.draw(g2, cursor, area, drawArea,
1286: RectangleEdge.RIGHT, null);
1287: break;
1288:
1289: case LEFT:
1290: default:
1291:
1292: cursor = midX - getColumnRadius();
1293: drawArea = new Rectangle2D.Double(cursor, stemTop,
1294: drawWidth, (stemBottom - stemTop + 1));
1295: this.rangeAxis.draw(g2, cursor, area, drawArea,
1296: RectangleEdge.LEFT, null);
1297: break;
1298: }
1299:
1300: }
1301:
1302:
1303: g2.setFont(this.valueFont);
1304: g2.setPaint(this.valuePaint);
1305: metrics = g2.getFontMetrics();
1306: switch (this.valueLocation) {
1307: case RIGHT:
1308: g2.drawString(this.valueFormat.format(current),
1309: midX + getColumnRadius() + getGap(), midY);
1310: break;
1311: case LEFT:
1312: String valueString = this.valueFormat.format(current);
1313: int stringWidth = metrics.stringWidth(valueString);
1314: g2.drawString(valueString, midX - getColumnRadius()
1315: - getGap() - stringWidth, midY);
1316: break;
1317: case BULB:
1318: temp = this.valueFormat.format(current);
1319: i = metrics.stringWidth(temp) / 2;
1320: g2.drawString(temp, midX - i,
1321: stemBottom + getBulbRadius() + getGap());
1322: break;
1323: default:
1324: }
1325:
1326: }
1327:
1328: g2.setPaint(this.thermometerPaint);
1329: g2.setFont(this.valueFont);
1330:
1331:
1332: metrics = g2.getFontMetrics();
1333: int tickX1 = midX - getColumnRadius() - getGap() * 2
1334: - metrics.stringWidth(UNITS[this.units]);
1335: if (tickX1 > area.getMinX()) {
1336: g2.drawString(UNITS[this.units], tickX1,
1337: (int) (area.getMinY() + 20));
1338: }
1339:
1340:
1341: g2.setStroke(this.thermometerStroke);
1342: g2.draw(outerThermometer);
1343: g2.draw(innerThermometer);
1344:
1345: drawOutline(g2, area);
1346: }
1347:
1348:
1355: public void zoom(double percent) {
1356:
1357: }
1358:
1359:
1364: public String getPlotType() {
1365: return localizationResources.getString("Thermometer_Plot");
1366: }
1367:
1368:
1373: public void datasetChanged(DatasetChangeEvent event) {
1374: if (this.dataset != null) {
1375: Number vn = this.dataset.getValue();
1376: if (vn != null) {
1377: double value = vn.doubleValue();
1378: if (inSubrange(NORMAL, value)) {
1379: this.subrange = NORMAL;
1380: }
1381: else if (inSubrange(WARNING, value)) {
1382: this.subrange = WARNING;
1383: }
1384: else if (inSubrange(CRITICAL, value)) {
1385: this.subrange = CRITICAL;
1386: }
1387: else {
1388: this.subrange = -1;
1389: }
1390: setAxisRange();
1391: }
1392: }
1393: super.datasetChanged(event);
1394: }
1395:
1396:
1406: public Number getMinimumVerticalDataValue() {
1407: return new Double(this.lowerBound);
1408: }
1409:
1410:
1420: public Number getMaximumVerticalDataValue() {
1421: return new Double(this.upperBound);
1422: }
1423:
1424:
1431: public Range getDataRange(ValueAxis axis) {
1432: return new Range(this.lowerBound, this.upperBound);
1433: }
1434:
1435:
1438: protected void setAxisRange() {
1439: if ((this.subrange >= 0) && (this.followDataInSubranges)) {
1440: this.rangeAxis.setRange(
1441: new Range(this.subrangeInfo[this.subrange][DISPLAY_LOW],
1442: this.subrangeInfo[this.subrange][DISPLAY_HIGH]));
1443: }
1444: else {
1445: this.rangeAxis.setRange(this.lowerBound, this.upperBound);
1446: }
1447: }
1448:
1449:
1454: public LegendItemCollection getLegendItems() {
1455: return null;
1456: }
1457:
1458:
1463: public PlotOrientation getOrientation() {
1464: return PlotOrientation.VERTICAL;
1465: }
1466:
1467:
1475: protected static boolean isValidNumber(double d) {
1476: return (!(Double.isNaN(d) || Double.isInfinite(d)));
1477: }
1478:
1479:
1487: private boolean inSubrange(int subrange, double value) {
1488: return (value > this.subrangeInfo[subrange][RANGE_LOW]
1489: && value <= this.subrangeInfo[subrange][RANGE_HIGH]);
1490: }
1491:
1492:
1499: private Paint getCurrentPaint() {
1500: Paint result = this.mercuryPaint;
1501: if (this.useSubrangePaint) {
1502: double value = this.dataset.getValue().doubleValue();
1503: if (inSubrange(NORMAL, value)) {
1504: result = this.subrangePaint[NORMAL];
1505: }
1506: else if (inSubrange(WARNING, value)) {
1507: result = this.subrangePaint[WARNING];
1508: }
1509: else if (inSubrange(CRITICAL, value)) {
1510: result = this.subrangePaint[CRITICAL];
1511: }
1512: }
1513: return result;
1514: }
1515:
1516:
1524: public boolean equals(Object obj) {
1525: if (obj == this) {
1526: return true;
1527: }
1528: if (!(obj instanceof ThermometerPlot)) {
1529: return false;
1530: }
1531: ThermometerPlot that = (ThermometerPlot) obj;
1532: if (!super.equals(obj)) {
1533: return false;
1534: }
1535: if (!ObjectUtilities.equal(this.rangeAxis, that.rangeAxis)) {
1536: return false;
1537: }
1538: if (this.axisLocation != that.axisLocation) {
1539: return false;
1540: }
1541: if (this.lowerBound != that.lowerBound) {
1542: return false;
1543: }
1544: if (this.upperBound != that.upperBound) {
1545: return false;
1546: }
1547: if (!ObjectUtilities.equal(this.padding, that.padding)) {
1548: return false;
1549: }
1550: if (!ObjectUtilities.equal(this.thermometerStroke,
1551: that.thermometerStroke)) {
1552: return false;
1553: }
1554: if (!PaintUtilities.equal(this.thermometerPaint,
1555: that.thermometerPaint)) {
1556: return false;
1557: }
1558: if (this.units != that.units) {
1559: return false;
1560: }
1561: if (this.valueLocation != that.valueLocation) {
1562: return false;
1563: }
1564: if (!ObjectUtilities.equal(this.valueFont, that.valueFont)) {
1565: return false;
1566: }
1567: if (!PaintUtilities.equal(this.valuePaint, that.valuePaint)) {
1568: return false;
1569: }
1570: if (!ObjectUtilities.equal(this.valueFormat, that.valueFormat)) {
1571: return false;
1572: }
1573: if (!PaintUtilities.equal(this.mercuryPaint, that.mercuryPaint)) {
1574: return false;
1575: }
1576: if (this.showValueLines != that.showValueLines) {
1577: return false;
1578: }
1579: if (this.subrange != that.subrange) {
1580: return false;
1581: }
1582: if (this.followDataInSubranges != that.followDataInSubranges) {
1583: return false;
1584: }
1585: if (!equal(this.subrangeInfo, that.subrangeInfo)) {
1586: return false;
1587: }
1588: if (this.useSubrangePaint != that.useSubrangePaint) {
1589: return false;
1590: }
1591: if (this.bulbRadius != that.bulbRadius) {
1592: return false;
1593: }
1594: if (this.columnRadius != that.columnRadius) {
1595: return false;
1596: }
1597: if (this.gap != that.gap) {
1598: return false;
1599: }
1600: for (int i = 0; i < this.subrangePaint.length; i++) {
1601: if (!PaintUtilities.equal(this.subrangePaint[i],
1602: that.subrangePaint[i])) {
1603: return false;
1604: }
1605: }
1606: return true;
1607: }
1608:
1609:
1617: private static boolean equal(double[][] array1, double[][] array2) {
1618: if (array1 == null) {
1619: return (array2 == null);
1620: }
1621: if (array2 == null) {
1622: return false;
1623: }
1624: if (array1.length != array2.length) {
1625: return false;
1626: }
1627: for (int i = 0; i < array1.length; i++) {
1628: if (!Arrays.equals(array1[i], array2[i])) {
1629: return false;
1630: }
1631: }
1632: return true;
1633: }
1634:
1635:
1642: public Object clone() throws CloneNotSupportedException {
1643:
1644: ThermometerPlot clone = (ThermometerPlot) super.clone();
1645:
1646: if (clone.dataset != null) {
1647: clone.dataset.addChangeListener(clone);
1648: }
1649: clone.rangeAxis = (ValueAxis) ObjectUtilities.clone(this.rangeAxis);
1650: if (clone.rangeAxis != null) {
1651: clone.rangeAxis.setPlot(clone);
1652: clone.rangeAxis.addChangeListener(clone);
1653: }
1654: clone.valueFormat = (NumberFormat) this.valueFormat.clone();
1655: clone.subrangePaint = (Paint[]) this.subrangePaint.clone();
1656:
1657: return clone;
1658:
1659: }
1660:
1661:
1668: private void writeObject(ObjectOutputStream stream) throws IOException {
1669: stream.defaultWriteObject();
1670: SerialUtilities.writeStroke(this.thermometerStroke, stream);
1671: SerialUtilities.writePaint(this.thermometerPaint, stream);
1672: SerialUtilities.writePaint(this.valuePaint, stream);
1673: SerialUtilities.writePaint(this.mercuryPaint, stream);
1674: SerialUtilities.writeStroke(this.subrangeIndicatorStroke, stream);
1675: SerialUtilities.writeStroke(this.rangeIndicatorStroke, stream);
1676: for (int i = 0; i < 3; i++) {
1677: SerialUtilities.writePaint(this.subrangePaint[i], stream);
1678: }
1679: }
1680:
1681:
1689: private void readObject(ObjectInputStream stream) throws IOException,
1690: ClassNotFoundException {
1691: stream.defaultReadObject();
1692: this.thermometerStroke = SerialUtilities.readStroke(stream);
1693: this.thermometerPaint = SerialUtilities.readPaint(stream);
1694: this.valuePaint = SerialUtilities.readPaint(stream);
1695: this.mercuryPaint = SerialUtilities.readPaint(stream);
1696: this.subrangeIndicatorStroke = SerialUtilities.readStroke(stream);
1697: this.rangeIndicatorStroke = SerialUtilities.readStroke(stream);
1698: this.subrangePaint = new Paint[3];
1699: for (int i = 0; i < 3; i++) {
1700: this.subrangePaint[i] = SerialUtilities.readPaint(stream);
1701: }
1702: if (this.rangeAxis != null) {
1703: this.rangeAxis.addChangeListener(this);
1704: }
1705: }
1706:
1707:
1714: public void zoomDomainAxes(double factor, PlotRenderingInfo state,
1715: Point2D source) {
1716:
1717: }
1718:
1719:
1730: public void zoomDomainAxes(double factor, PlotRenderingInfo state,
1731: Point2D source, boolean useAnchor) {
1732:
1733: }
1734:
1735:
1742: public void zoomRangeAxes(double factor, PlotRenderingInfo state,
1743: Point2D source) {
1744: this.rangeAxis.resizeRange(factor);
1745: }
1746:
1747:
1758: public void zoomRangeAxes(double factor, PlotRenderingInfo state,
1759: Point2D source, boolean useAnchor) {
1760: double anchorY = this.getRangeAxis().java2DToValue(source.getY(),
1761: state.getDataArea(), RectangleEdge.LEFT);
1762: this.rangeAxis.resizeRange(factor, anchorY);
1763: }
1764:
1765:
1773: public void zoomDomainAxes(double lowerPercent, double upperPercent,
1774: PlotRenderingInfo state, Point2D source) {
1775:
1776: }
1777:
1778:
1786: public void zoomRangeAxes(double lowerPercent, double upperPercent,
1787: PlotRenderingInfo state, Point2D source) {
1788: this.rangeAxis.zoomRange(lowerPercent, upperPercent);
1789: }
1790:
1791:
1796: public boolean isDomainZoomable() {
1797: return false;
1798: }
1799:
1800:
1805: public boolean isRangeZoomable() {
1806: return true;
1807: }
1808:
1809: }