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: notifyListeners(new PlotChangeEvent(this));
484:
485: }
486:
487:
495: public double getLowerBound() {
496: return this.lowerBound;
497: }
498:
499:
506: public void setLowerBound(double lower) {
507: this.lowerBound = lower;
508: setAxisRange();
509: }
510:
511:
519: public double getUpperBound() {
520: return this.upperBound;
521: }
522:
523:
530: public void setUpperBound(double upper) {
531: this.upperBound = upper;
532: setAxisRange();
533: }
534:
535:
541: public void setRange(double lower, double upper) {
542: this.lowerBound = lower;
543: this.upperBound = upper;
544: setAxisRange();
545: }
546:
547:
555: public RectangleInsets getPadding() {
556: return this.padding;
557: }
558:
559:
567: public void setPadding(RectangleInsets padding) {
568: if (padding == null) {
569: throw new IllegalArgumentException("Null 'padding' argument.");
570: }
571: this.padding = padding;
572: notifyListeners(new PlotChangeEvent(this));
573: }
574:
575:
583: public Stroke getThermometerStroke() {
584: return this.thermometerStroke;
585: }
586:
587:
595: public void setThermometerStroke(Stroke s) {
596: if (s != null) {
597: this.thermometerStroke = s;
598: notifyListeners(new PlotChangeEvent(this));
599: }
600: }
601:
602:
610: public Paint getThermometerPaint() {
611: return this.thermometerPaint;
612: }
613:
614:
622: public void setThermometerPaint(Paint paint) {
623: if (paint != null) {
624: this.thermometerPaint = paint;
625: notifyListeners(new PlotChangeEvent(this));
626: }
627: }
628:
629:
638: public int getUnits() {
639: return this.units;
640: }
641:
642:
657: public void setUnits(int u) {
658: if ((u >= 0) && (u < UNITS.length)) {
659: if (this.units != u) {
660: this.units = u;
661: notifyListeners(new PlotChangeEvent(this));
662: }
663: }
664: }
665:
666:
674: public void setUnits(String u) {
675: if (u == null) {
676: return;
677: }
678:
679: u = u.toUpperCase().trim();
680: for (int i = 0; i < UNITS.length; ++i) {
681: if (u.equals(UNITS[i].toUpperCase().trim())) {
682: setUnits(i);
683: i = UNITS.length;
684: }
685: }
686: }
687:
688:
695: public int getValueLocation() {
696: return this.valueLocation;
697: }
698:
699:
711: public void setValueLocation(int location) {
712: if ((location >= 0) && (location < 4)) {
713: this.valueLocation = location;
714: notifyListeners(new PlotChangeEvent(this));
715: }
716: else {
717: throw new IllegalArgumentException("Location not recognised.");
718: }
719: }
720:
721:
729: public int getAxisLocation() {
730: return this.axisLocation;
731: }
732:
733:
743: public void setAxisLocation(int location) {
744: if ((location >= 0) && (location < 3)) {
745: this.axisLocation = location;
746: notifyListeners(new PlotChangeEvent(this));
747: }
748: else {
749: throw new IllegalArgumentException("Location not recognised.");
750: }
751: }
752:
753:
760: public Font getValueFont() {
761: return this.valueFont;
762: }
763:
764:
771: public void setValueFont(Font f) {
772: if (f == null) {
773: throw new IllegalArgumentException("Null 'font' argument.");
774: }
775: if (!this.valueFont.equals(f)) {
776: this.valueFont = f;
777: notifyListeners(new PlotChangeEvent(this));
778: }
779: }
780:
781:
788: public Paint getValuePaint() {
789: return this.valuePaint;
790: }
791:
792:
800: public void setValuePaint(Paint paint) {
801: if (paint == null) {
802: throw new IllegalArgumentException("Null 'paint' argument.");
803: }
804: if (!this.valuePaint.equals(paint)) {
805: this.valuePaint = paint;
806: notifyListeners(new PlotChangeEvent(this));
807: }
808: }
809:
810:
811:
812:
818: public void setValueFormat(NumberFormat formatter) {
819: if (formatter == null) {
820: throw new IllegalArgumentException("Null 'formatter' argument.");
821: }
822: this.valueFormat = formatter;
823: notifyListeners(new PlotChangeEvent(this));
824: }
825:
826:
833: public Paint getMercuryPaint() {
834: return this.mercuryPaint;
835: }
836:
837:
845: public void setMercuryPaint(Paint paint) {
846: if (paint == null) {
847: throw new IllegalArgumentException("Null 'paint' argument.");
848: }
849: this.mercuryPaint = paint;
850: notifyListeners(new PlotChangeEvent(this));
851: }
852:
853:
863: public boolean getShowValueLines() {
864: return this.showValueLines;
865: }
866:
867:
877: public void setShowValueLines(boolean b) {
878: this.showValueLines = b;
879: notifyListeners(new PlotChangeEvent(this));
880: }
881:
882:
889: public void setSubrangeInfo(int range, double low, double hi) {
890: setSubrangeInfo(range, low, hi, low, hi);
891: }
892:
893:
902: public void setSubrangeInfo(int range,
903: double rangeLow, double rangeHigh,
904: double displayLow, double displayHigh) {
905:
906: if ((range >= 0) && (range < 3)) {
907: setSubrange(range, rangeLow, rangeHigh);
908: setDisplayRange(range, displayLow, displayHigh);
909: setAxisRange();
910: notifyListeners(new PlotChangeEvent(this));
911: }
912:
913: }
914:
915:
922: public void setSubrange(int range, double low, double high) {
923: if ((range >= 0) && (range < 3)) {
924: this.subrangeInfo[range][RANGE_HIGH] = high;
925: this.subrangeInfo[range][RANGE_LOW] = low;
926: }
927: }
928:
929:
936: public void setDisplayRange(int range, double low, double high) {
937:
938: if ((range >= 0) && (range < this.subrangeInfo.length)
939: && isValidNumber(high) && isValidNumber(low)) {
940:
941: if (high > low) {
942: this.subrangeInfo[range][DISPLAY_HIGH] = high;
943: this.subrangeInfo[range][DISPLAY_LOW] = low;
944: }
945: else {
946: this.subrangeInfo[range][DISPLAY_HIGH] = low;
947: this.subrangeInfo[range][DISPLAY_LOW] = high;
948: }
949:
950: }
951:
952: }
953:
954:
963: public Paint getSubrangePaint(int range) {
964: if ((range >= 0) && (range < this.subrangePaint.length)) {
965: return this.subrangePaint[range];
966: }
967: else {
968: return this.mercuryPaint;
969: }
970: }
971:
972:
981: public void setSubrangePaint(int range, Paint paint) {
982: if ((range >= 0)
983: && (range < this.subrangePaint.length) && (paint != null)) {
984: this.subrangePaint[range] = paint;
985: notifyListeners(new PlotChangeEvent(this));
986: }
987: }
988:
989:
995: public boolean getFollowDataInSubranges() {
996: return this.followDataInSubranges;
997: }
998:
999:
1005: public void setFollowDataInSubranges(boolean flag) {
1006: this.followDataInSubranges = flag;
1007: notifyListeners(new PlotChangeEvent(this));
1008: }
1009:
1010:
1018: public boolean getUseSubrangePaint() {
1019: return this.useSubrangePaint;
1020: }
1021:
1022:
1029: public void setUseSubrangePaint(boolean flag) {
1030: this.useSubrangePaint = flag;
1031: notifyListeners(new PlotChangeEvent(this));
1032: }
1033:
1034:
1041: public int getBulbRadius() {
1042: return this.bulbRadius;
1043: }
1044:
1045:
1055: public void setBulbRadius(int r) {
1056: this.bulbRadius = r;
1057: notifyListeners(new PlotChangeEvent(this));
1058: }
1059:
1060:
1068: public int getBulbDiameter() {
1069: return getBulbRadius() * 2;
1070: }
1071:
1072:
1081: public int getColumnRadius() {
1082: return this.columnRadius;
1083: }
1084:
1085:
1095: public void setColumnRadius(int r) {
1096: this.columnRadius = r;
1097: notifyListeners(new PlotChangeEvent(this));
1098: }
1099:
1100:
1108: public int getColumnDiameter() {
1109: return getColumnRadius() * 2;
1110: }
1111:
1112:
1122: public int getGap() {
1123: return this.gap;
1124: }
1125:
1126:
1137: public void setGap(int gap) {
1138: this.gap = gap;
1139: notifyListeners(new PlotChangeEvent(this));
1140: }
1141:
1142:
1152: public void draw(Graphics2D g2, Rectangle2D area, Point2D anchor,
1153: PlotState parentState,
1154: PlotRenderingInfo info) {
1155:
1156: RoundRectangle2D outerStem = new RoundRectangle2D.Double();
1157: RoundRectangle2D innerStem = new RoundRectangle2D.Double();
1158: RoundRectangle2D mercuryStem = new RoundRectangle2D.Double();
1159: Ellipse2D outerBulb = new Ellipse2D.Double();
1160: Ellipse2D innerBulb = new Ellipse2D.Double();
1161: String temp = null;
1162: FontMetrics metrics = null;
1163: if (info != null) {
1164: info.setPlotArea(area);
1165: }
1166:
1167:
1168: RectangleInsets insets = getInsets();
1169: insets.trim(area);
1170: drawBackground(g2, area);
1171:
1172:
1173: Rectangle2D interior = (Rectangle2D) area.clone();
1174: this.padding.trim(interior);
1175: int midX = (int) (interior.getX() + (interior.getWidth() / 2));
1176: int midY = (int) (interior.getY() + (interior.getHeight() / 2));
1177: int stemTop = (int) (interior.getMinY() + getBulbRadius());
1178: int stemBottom = (int) (interior.getMaxY() - getBulbDiameter());
1179: Rectangle2D dataArea = new Rectangle2D.Double(midX - getColumnRadius(),
1180: stemTop, getColumnRadius(), stemBottom - stemTop);
1181:
1182: outerBulb.setFrame(midX - getBulbRadius(), stemBottom,
1183: getBulbDiameter(), getBulbDiameter());
1184:
1185: outerStem.setRoundRect(midX - getColumnRadius(), interior.getMinY(),
1186: getColumnDiameter(), stemBottom + getBulbDiameter() - stemTop,
1187: getColumnDiameter(), getColumnDiameter());
1188:
1189: Area outerThermometer = new Area(outerBulb);
1190: Area tempArea = new Area(outerStem);
1191: outerThermometer.add(tempArea);
1192:
1193: innerBulb.setFrame(midX - getBulbRadius() + getGap(), stemBottom
1194: + getGap(), getBulbDiameter() - getGap() * 2, getBulbDiameter()
1195: - getGap() * 2);
1196:
1197: innerStem.setRoundRect(midX - getColumnRadius() + getGap(),
1198: interior.getMinY() + getGap(), getColumnDiameter()
1199: - getGap() * 2, stemBottom + getBulbDiameter() - getGap() * 2
1200: - stemTop, getColumnDiameter() - getGap() * 2,
1201: getColumnDiameter() - getGap() * 2);
1202:
1203: Area innerThermometer = new Area(innerBulb);
1204: tempArea = new Area(innerStem);
1205: innerThermometer.add(tempArea);
1206:
1207: if ((this.dataset != null) && (this.dataset.getValue() != null)) {
1208: double current = this.dataset.getValue().doubleValue();
1209: double ds = this.rangeAxis.valueToJava2D(current, dataArea,
1210: RectangleEdge.LEFT);
1211:
1212: int i = getColumnDiameter() - getGap() * 2;
1213: int j = getColumnRadius() - getGap();
1214: int l = (i / 2);
1215: int k = (int) Math.round(ds);
1216: if (k < (getGap() + interior.getMinY())) {
1217: k = (int) (getGap() + interior.getMinY());
1218: l = getBulbRadius();
1219: }
1220:
1221: Area mercury = new Area(innerBulb);
1222:
1223: if (k < (stemBottom + getBulbRadius())) {
1224: mercuryStem.setRoundRect(midX - j, k, i,
1225: (stemBottom + getBulbRadius()) - k, l, l);
1226: tempArea = new Area(mercuryStem);
1227: mercury.add(tempArea);
1228: }
1229:
1230: g2.setPaint(getCurrentPaint());
1231: g2.fill(mercury);
1232:
1233:
1234: if (this.subrangeIndicatorsVisible) {
1235: g2.setStroke(this.subrangeIndicatorStroke);
1236: Range range = this.rangeAxis.getRange();
1237:
1238:
1239: double value = this.subrangeInfo[NORMAL][RANGE_LOW];
1240: if (range.contains(value)) {
1241: double x = midX + getColumnRadius() + 2;
1242: double y = this.rangeAxis.valueToJava2D(value, dataArea,
1243: RectangleEdge.LEFT);
1244: Line2D line = new Line2D.Double(x, y, x + 10, y);
1245: g2.setPaint(this.subrangePaint[NORMAL]);
1246: g2.draw(line);
1247: }
1248:
1249:
1250: value = this.subrangeInfo[WARNING][RANGE_LOW];
1251: if (range.contains(value)) {
1252: double x = midX + getColumnRadius() + 2;
1253: double y = this.rangeAxis.valueToJava2D(value, dataArea,
1254: RectangleEdge.LEFT);
1255: Line2D line = new Line2D.Double(x, y, x + 10, y);
1256: g2.setPaint(this.subrangePaint[WARNING]);
1257: g2.draw(line);
1258: }
1259:
1260:
1261: value = this.subrangeInfo[CRITICAL][RANGE_LOW];
1262: if (range.contains(value)) {
1263: double x = midX + getColumnRadius() + 2;
1264: double y = this.rangeAxis.valueToJava2D(value, dataArea,
1265: RectangleEdge.LEFT);
1266: Line2D line = new Line2D.Double(x, y, x + 10, y);
1267: g2.setPaint(this.subrangePaint[CRITICAL]);
1268: g2.draw(line);
1269: }
1270: }
1271:
1272:
1273: if ((this.rangeAxis != null) && (this.axisLocation != NONE)) {
1274: int drawWidth = AXIS_GAP;
1275: if (this.showValueLines) {
1276: drawWidth += getColumnDiameter();
1277: }
1278: Rectangle2D drawArea;
1279: double cursor = 0;
1280:
1281: switch (this.axisLocation) {
1282: case RIGHT:
1283: cursor = midX + getColumnRadius();
1284: drawArea = new Rectangle2D.Double(cursor,
1285: stemTop, drawWidth, (stemBottom - stemTop + 1));
1286: this.rangeAxis.draw(g2, cursor, area, drawArea,
1287: RectangleEdge.RIGHT, null);
1288: break;
1289:
1290: case LEFT:
1291: default:
1292:
1293: cursor = midX - getColumnRadius();
1294: drawArea = new Rectangle2D.Double(cursor, stemTop,
1295: drawWidth, (stemBottom - stemTop + 1));
1296: this.rangeAxis.draw(g2, cursor, area, drawArea,
1297: RectangleEdge.LEFT, null);
1298: break;
1299: }
1300:
1301: }
1302:
1303:
1304: g2.setFont(this.valueFont);
1305: g2.setPaint(this.valuePaint);
1306: metrics = g2.getFontMetrics();
1307: switch (this.valueLocation) {
1308: case RIGHT:
1309: g2.drawString(this.valueFormat.format(current),
1310: midX + getColumnRadius() + getGap(), midY);
1311: break;
1312: case LEFT:
1313: String valueString = this.valueFormat.format(current);
1314: int stringWidth = metrics.stringWidth(valueString);
1315: g2.drawString(valueString, midX - getColumnRadius()
1316: - getGap() - stringWidth, midY);
1317: break;
1318: case BULB:
1319: temp = this.valueFormat.format(current);
1320: i = metrics.stringWidth(temp) / 2;
1321: g2.drawString(temp, midX - i,
1322: stemBottom + getBulbRadius() + getGap());
1323: break;
1324: default:
1325: }
1326:
1327: }
1328:
1329: g2.setPaint(this.thermometerPaint);
1330: g2.setFont(this.valueFont);
1331:
1332:
1333: metrics = g2.getFontMetrics();
1334: int tickX1 = midX - getColumnRadius() - getGap() * 2
1335: - metrics.stringWidth(UNITS[this.units]);
1336: if (tickX1 > area.getMinX()) {
1337: g2.drawString(UNITS[this.units], tickX1,
1338: (int) (area.getMinY() + 20));
1339: }
1340:
1341:
1342: g2.setStroke(this.thermometerStroke);
1343: g2.draw(outerThermometer);
1344: g2.draw(innerThermometer);
1345:
1346: drawOutline(g2, area);
1347: }
1348:
1349:
1356: public void zoom(double percent) {
1357:
1358: }
1359:
1360:
1365: public String getPlotType() {
1366: return localizationResources.getString("Thermometer_Plot");
1367: }
1368:
1369:
1374: public void datasetChanged(DatasetChangeEvent event) {
1375: if (this.dataset != null) {
1376: Number vn = this.dataset.getValue();
1377: if (vn != null) {
1378: double value = vn.doubleValue();
1379: if (inSubrange(NORMAL, value)) {
1380: this.subrange = NORMAL;
1381: }
1382: else if (inSubrange(WARNING, value)) {
1383: this.subrange = WARNING;
1384: }
1385: else if (inSubrange(CRITICAL, value)) {
1386: this.subrange = CRITICAL;
1387: }
1388: else {
1389: this.subrange = -1;
1390: }
1391: setAxisRange();
1392: }
1393: }
1394: super.datasetChanged(event);
1395: }
1396:
1397:
1407: public Number getMinimumVerticalDataValue() {
1408: return new Double(this.lowerBound);
1409: }
1410:
1411:
1421: public Number getMaximumVerticalDataValue() {
1422: return new Double(this.upperBound);
1423: }
1424:
1425:
1432: public Range getDataRange(ValueAxis axis) {
1433: return new Range(this.lowerBound, this.upperBound);
1434: }
1435:
1436:
1439: protected void setAxisRange() {
1440: if ((this.subrange >= 0) && (this.followDataInSubranges)) {
1441: this.rangeAxis.setRange(
1442: new Range(this.subrangeInfo[this.subrange][DISPLAY_LOW],
1443: this.subrangeInfo[this.subrange][DISPLAY_HIGH]));
1444: }
1445: else {
1446: this.rangeAxis.setRange(this.lowerBound, this.upperBound);
1447: }
1448: }
1449:
1450:
1455: public LegendItemCollection getLegendItems() {
1456: return null;
1457: }
1458:
1459:
1464: public PlotOrientation getOrientation() {
1465: return PlotOrientation.VERTICAL;
1466: }
1467:
1468:
1476: protected static boolean isValidNumber(double d) {
1477: return (!(Double.isNaN(d) || Double.isInfinite(d)));
1478: }
1479:
1480:
1488: private boolean inSubrange(int subrange, double value) {
1489: return (value > this.subrangeInfo[subrange][RANGE_LOW]
1490: && value <= this.subrangeInfo[subrange][RANGE_HIGH]);
1491: }
1492:
1493:
1500: private Paint getCurrentPaint() {
1501: Paint result = this.mercuryPaint;
1502: if (this.useSubrangePaint) {
1503: double value = this.dataset.getValue().doubleValue();
1504: if (inSubrange(NORMAL, value)) {
1505: result = this.subrangePaint[NORMAL];
1506: }
1507: else if (inSubrange(WARNING, value)) {
1508: result = this.subrangePaint[WARNING];
1509: }
1510: else if (inSubrange(CRITICAL, value)) {
1511: result = this.subrangePaint[CRITICAL];
1512: }
1513: }
1514: return result;
1515: }
1516:
1517:
1525: public boolean equals(Object obj) {
1526: if (obj == this) {
1527: return true;
1528: }
1529: if (!(obj instanceof ThermometerPlot)) {
1530: return false;
1531: }
1532: ThermometerPlot that = (ThermometerPlot) obj;
1533: if (!super.equals(obj)) {
1534: return false;
1535: }
1536: if (!ObjectUtilities.equal(this.rangeAxis, that.rangeAxis)) {
1537: return false;
1538: }
1539: if (this.axisLocation != that.axisLocation) {
1540: return false;
1541: }
1542: if (this.lowerBound != that.lowerBound) {
1543: return false;
1544: }
1545: if (this.upperBound != that.upperBound) {
1546: return false;
1547: }
1548: if (!ObjectUtilities.equal(this.padding, that.padding)) {
1549: return false;
1550: }
1551: if (!ObjectUtilities.equal(this.thermometerStroke,
1552: that.thermometerStroke)) {
1553: return false;
1554: }
1555: if (!PaintUtilities.equal(this.thermometerPaint,
1556: that.thermometerPaint)) {
1557: return false;
1558: }
1559: if (this.units != that.units) {
1560: return false;
1561: }
1562: if (this.valueLocation != that.valueLocation) {
1563: return false;
1564: }
1565: if (!ObjectUtilities.equal(this.valueFont, that.valueFont)) {
1566: return false;
1567: }
1568: if (!PaintUtilities.equal(this.valuePaint, that.valuePaint)) {
1569: return false;
1570: }
1571: if (!ObjectUtilities.equal(this.valueFormat, that.valueFormat)) {
1572: return false;
1573: }
1574: if (!PaintUtilities.equal(this.mercuryPaint, that.mercuryPaint)) {
1575: return false;
1576: }
1577: if (this.showValueLines != that.showValueLines) {
1578: return false;
1579: }
1580: if (this.subrange != that.subrange) {
1581: return false;
1582: }
1583: if (this.followDataInSubranges != that.followDataInSubranges) {
1584: return false;
1585: }
1586: if (!equal(this.subrangeInfo, that.subrangeInfo)) {
1587: return false;
1588: }
1589: if (this.useSubrangePaint != that.useSubrangePaint) {
1590: return false;
1591: }
1592: if (this.bulbRadius != that.bulbRadius) {
1593: return false;
1594: }
1595: if (this.columnRadius != that.columnRadius) {
1596: return false;
1597: }
1598: if (this.gap != that.gap) {
1599: return false;
1600: }
1601: for (int i = 0; i < this.subrangePaint.length; i++) {
1602: if (!PaintUtilities.equal(this.subrangePaint[i],
1603: that.subrangePaint[i])) {
1604: return false;
1605: }
1606: }
1607: return true;
1608: }
1609:
1610:
1618: private static boolean equal(double[][] array1, double[][] array2) {
1619: if (array1 == null) {
1620: return (array2 == null);
1621: }
1622: if (array2 == null) {
1623: return false;
1624: }
1625: if (array1.length != array2.length) {
1626: return false;
1627: }
1628: for (int i = 0; i < array1.length; i++) {
1629: if (!Arrays.equals(array1[i], array2[i])) {
1630: return false;
1631: }
1632: }
1633: return true;
1634: }
1635:
1636:
1643: public Object clone() throws CloneNotSupportedException {
1644:
1645: ThermometerPlot clone = (ThermometerPlot) super.clone();
1646:
1647: if (clone.dataset != null) {
1648: clone.dataset.addChangeListener(clone);
1649: }
1650: clone.rangeAxis = (ValueAxis) ObjectUtilities.clone(this.rangeAxis);
1651: if (clone.rangeAxis != null) {
1652: clone.rangeAxis.setPlot(clone);
1653: clone.rangeAxis.addChangeListener(clone);
1654: }
1655: clone.valueFormat = (NumberFormat) this.valueFormat.clone();
1656: clone.subrangePaint = (Paint[]) this.subrangePaint.clone();
1657:
1658: return clone;
1659:
1660: }
1661:
1662:
1669: private void writeObject(ObjectOutputStream stream) throws IOException {
1670: stream.defaultWriteObject();
1671: SerialUtilities.writeStroke(this.thermometerStroke, stream);
1672: SerialUtilities.writePaint(this.thermometerPaint, stream);
1673: SerialUtilities.writePaint(this.valuePaint, stream);
1674: SerialUtilities.writePaint(this.mercuryPaint, stream);
1675: SerialUtilities.writeStroke(this.subrangeIndicatorStroke, stream);
1676: SerialUtilities.writeStroke(this.rangeIndicatorStroke, stream);
1677: for (int i = 0; i < 3; i++) {
1678: SerialUtilities.writePaint(this.subrangePaint[i], stream);
1679: }
1680: }
1681:
1682:
1690: private void readObject(ObjectInputStream stream) throws IOException,
1691: ClassNotFoundException {
1692: stream.defaultReadObject();
1693: this.thermometerStroke = SerialUtilities.readStroke(stream);
1694: this.thermometerPaint = SerialUtilities.readPaint(stream);
1695: this.valuePaint = SerialUtilities.readPaint(stream);
1696: this.mercuryPaint = SerialUtilities.readPaint(stream);
1697: this.subrangeIndicatorStroke = SerialUtilities.readStroke(stream);
1698: this.rangeIndicatorStroke = SerialUtilities.readStroke(stream);
1699: this.subrangePaint = new Paint[3];
1700: for (int i = 0; i < 3; i++) {
1701: this.subrangePaint[i] = SerialUtilities.readPaint(stream);
1702: }
1703: if (this.rangeAxis != null) {
1704: this.rangeAxis.addChangeListener(this);
1705: }
1706: }
1707:
1708:
1715: public void zoomDomainAxes(double factor, PlotRenderingInfo state,
1716: Point2D source) {
1717:
1718: }
1719:
1720:
1731: public void zoomDomainAxes(double factor, PlotRenderingInfo state,
1732: Point2D source, boolean useAnchor) {
1733:
1734: }
1735:
1736:
1743: public void zoomRangeAxes(double factor, PlotRenderingInfo state,
1744: Point2D source) {
1745: this.rangeAxis.resizeRange(factor);
1746: }
1747:
1748:
1759: public void zoomRangeAxes(double factor, PlotRenderingInfo state,
1760: Point2D source, boolean useAnchor) {
1761: double anchorY = this.getRangeAxis().java2DToValue(source.getY(),
1762: state.getDataArea(), RectangleEdge.LEFT);
1763: this.rangeAxis.resizeRange(factor, anchorY);
1764: }
1765:
1766:
1774: public void zoomDomainAxes(double lowerPercent, double upperPercent,
1775: PlotRenderingInfo state, Point2D source) {
1776:
1777: }
1778:
1779:
1787: public void zoomRangeAxes(double lowerPercent, double upperPercent,
1788: PlotRenderingInfo state, Point2D source) {
1789: this.rangeAxis.zoomRange(lowerPercent, upperPercent);
1790: }
1791:
1792:
1797: public boolean isDomainZoomable() {
1798: return false;
1799: }
1800:
1801:
1806: public boolean isRangeZoomable() {
1807: return true;
1808: }
1809:
1810: }