package variableEditorComponents; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.util.Observable; import java.util.Observer; import javax.swing.JCheckBox; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import valueTypes.BooleanValue; import variableEditorUI.VariableEditorUIUpdateThread; import variables.Variable; import expressionConsole.ExpressionConsoleModel; /** * A JCheckBox which is bound to a Variable. When the user checks or unchecks * the box, the content of the Variable is updated. When the Variable is changed * from another source, the state of the box is updated with the new contents of * the Variable. * * @author Curran Kelleher * */ public class VariableBoundCheckBox extends JCheckBox implements Observer, ItemListener, VariableEditorComponent { private static final long serialVersionUID = -7777499408692975081L; /** * The Variable to which this VariableBoundCheckBox is bound. */ Variable variable; /** * The Value that is currently being displayed. This is checked against the * actual value of the Variable periodically to decide whether or not to * update the display. This String is parseable into the actual value. It is * generated by the method Value.toParseableString() */ String displayedValue = ""; /** * set true to ignore self-generated checkbox events */ boolean ignoreUpdates = false; /** * Construct a VariableBoundCheckBox which is bound to the specified Variable. * * @param variable * the variable to edit */ public VariableBoundCheckBox(Variable variable) { super(variable.toString()); this.variable = variable; // get notifications every second. VariableEditorUIUpdateThread.getInstance().addObserver(this); // initialize the check box updateWithCurrentVariableValue(); // listen for slider movements addItemListener(this); } /** * Updates the content of the check box to reflect the current value of the * variable. * */ public void updateWithCurrentVariableValue() { ignoreUpdates = true; setSelected(BooleanValue.extractBooleanValue(variable.evaluate())); displayedValue = variable.evaluate().toParseableString(); ignoreUpdates = false; } /** * Get the update from the VariableEditorUIUpdateThread */ public void update(Observable o, Object arg) { if (o == VariableEditorUIUpdateThread.getInstance()) // if this component is no longer usable, remove it as an Observer. if (!isDisplayable()) VariableEditorUIUpdateThread.getInstance().deleteObserver(this); else if (!variable.evaluate().toParseableString().equals( displayedValue)) updateWithCurrentVariableValue(); } /** * Respond to check box changes */ public void itemStateChanged(ItemEvent e) { if (!ignoreUpdates) { variable.set(new BooleanValue( e.getStateChange() == ItemEvent.SELECTED)); // log the change for correct replay displayedValue = variable.evaluate().toParseableString(); ExpressionConsoleModel.getInstance().enterExpression( variable.toString() + " = " + displayedValue); } } /** * Sets up a VariableEditorComponent such that * updateWithCurrentVariableValue() will be called in it whenever the * checkbox is checked or unchecked. * * @param componentToUpdate * the VariableEditorComponent to update. */ public void bindToVariableEditorComponent( VariableEditorComponent componentToUpdate) { class ComponentChangeListener implements ChangeListener { VariableEditorComponent componentToUpdate; public ComponentChangeListener( VariableEditorComponent componentToUpdate) { this.componentToUpdate = componentToUpdate; } public void stateChanged(ChangeEvent e) { componentToUpdate.updateWithCurrentVariableValue(); } } addChangeListener(new ComponentChangeListener(componentToUpdate)); } }