// This example is from the book Developing Java Beans by Robert Englander.
// Copyright (c) 1997 O'Reilly & Associates.
// You may study, use, modify, and distribute this example for any purpose.
// This example is provided WITHOUT WARRANTY either expressed or implied.
// Chapter 8 -- The Thermostat class
package BeansBook.Simulator;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.util.*;
import java.io.*;
// the Thermostat bean class definition
public class Thermostat extends Panel // subclasses Panel
implements PropertyChangeListener, // property changes from temperature source
ActionListener, // action events from buttons
ItemListener // item events choice controls
{
// the choice control for display units
protected Choice unitsChoice;
// the choice control for displaying ambient or comfort level temperature
protected Choice displayChoice;
// button for decrementing comfort level temperature
protected Button decButton;
// button for incrementing comfort level temperature
protected Button incButton;
// label for displaying temperatures
protected Label displayLabel;
// flags for the NeedsCooling and NeedsHeating state
protected boolean bNeedsCooling = false;
protected boolean bNeedsHeating = false;
// the comfort level temperature
protected double comfortTemp = 22.0;
// the ambient temperature from the temperature source
protected double ambientTemp;
// flag indicating if ambient temperature is being displayed
protected boolean bShowingAmbient = true;
// flag indicating if Celsius units are being displayed
protected boolean bShowingCelsius = true;
// support for the constrained properties
protected VetoableChangeSupport vetoSupport;
// cooling and heating request listeners
protected transient Vector coolingListeners;
protected transient Vector heatingListeners;
// constructor
public Thermostat()
{
// call superclass constructor
super();
// create the support object for constrained properties
vetoSupport = new VetoableChangeSupport(this);
// use a border layout for the constituents
setLayout(new BorderLayout());
// create the constituents
unitsChoice = new Choice();
displayChoice = new Choice();
decButton = new Button("<<");
incButton = new Button(">>");
displayLabel = new Label("**********");
// register as action listener for the buttons
decButton.addActionListener(this);
incButton.addActionListener(this);
// register as item listener for the choice controls
displayChoice.addItemListener(this);
unitsChoice.addItemListener(this);
// disable the comfort temperature buttons
decButton.setEnabled(false);
incButton.setEnabled(false);
// add the constituents in their appropriate locations
add(unitsChoice, BorderLayout.NORTH);
add(displayChoice, BorderLayout.SOUTH);
add(decButton, BorderLayout.WEST);
add(incButton, BorderLayout.EAST);
add(displayLabel, BorderLayout.CENTER);
// use center alignment for the temperature display
displayLabel.setAlignment(Label.CENTER);
// add the units to the choice control
unitsChoice.add("Celsius");
unitsChoice.add("Fahrenheit");
// add the display types to the choice control
displayChoice.add("Ambient");
displayChoice.add("Comfort");
}
// handle an action event
public void actionPerformed(ActionEvent evt)
{
// change in temperature
double tempDelta;
// delta value for rounding
double roundingDelta;
// it was the decrement button
if (evt.getSource() == decButton)
{
// reduce temp by 1
tempDelta = -1.0;
// delta is 0 for rounding down
roundingDelta = 0.0;
}
else // it was the increment button
{
// increase temp by 1
tempDelta = 1.0;
// delta is 1 for rounding up
roundingDelta = 1.0;
}
// the new proposed comfort temperature
double newValue;
// displaying temperatures in Celsius
if (bShowingCelsius)
{
// just add the delta
newValue = comfortTemp + tempDelta;
}
else // displaying in Fahrenheit
{
// convert to Fahrenheit, add the delta, and convert back
double t = 32.0 + ((comfortTemp * 9.0) / 5.0);
t += tempDelta;
newValue = (t - 32.0) * 5.0 / 9.0;
}
// the old value object for firing the vetoable change event
Double old = new Double(comfortTemp);
try
{
// fire the event
vetoSupport.fireVetoableChange("ComfortTemperature", old, new
Double(newValue));
// if we get this far we can make the change
synchronized (this)
{
comfortTemp = newValue;
}
}
catch (PropertyVetoException e)
{
// the change was vetoed by a listening object, but
// if we have a fractional part, we could try rounding the value
// to use a whole number
double wholePart = (double)old.longValue();
if ((old.doubleValue() - wholePart) == 0.0)
{
// we can't make a change
return;
}
// attempt to alter the comfort temperature using the whole part of the
// old value and the rounding delta
newValue = wholePart + roundingDelta;
try
{
// fire the event
vetoSupport.fireVetoableChange("ComfortTemperature", old,
new Double(newValue));
}
catch (PropertyVetoException ee)
{
// we couldn |