/* * Calculator State and Behavior * * Developed for "Rethinking CS101", a project of Lynn Andrea Stein's AP Group. * For more information, see the * CS101 homepage or email . * * Copyright (C) 1999 Massachusetts Institute of Technology. * Please do not redistribute without obtaining permission. */ package calculator; import cs101.util.Coerce; import cs101.io.Console; /** * This class provides the main functionality for a basic four-function * calculator. Adapted from the earlier ButtonHandler. * *

Copyright (c) 1999 Massachusetts Institute of Technology * * @author Todd C. Parnell, tparnell@ai.mit.edu * @author Emil Sit, sit@mit.edu * @author Lynn Andrea Stein, las@ai.mit.edu * @version $Id: CalculatorState.java,v 1.1.1.1 2002/06/05 21:56:27 root Exp $ * * @see Calculator */ public class CalculatorState extends Object { /** * The GUI for which this CalculatorState is providing behavior. */ private Calculator gui; // This variable represents whether the current number displayed on the // calculator contains a decimal. If it does, seenDecimal is true. // Otherwise, it's false. // protected boolean seenDecimal; // This variable represents whether the calculator is ready to accept a new // number as input. This happens // 1) When the calculator is just started // 2) Directly after the user performs an arithmetic operation // 3) Directly after the user resets the calculator // protected boolean readyForNewNumber; // This variable represents the last number that has been entered into the // calculator. A number is entered by typing a number to the screen, // and performing an arithmetic operation. The new value for previousNumber // will be calculated through the following equation: // // (new value of previous number) = // (old value of previousNumber) op (value shown on calculator) // // where "op" is the operation stored in this.operation. // protected double previousNumber; // This variable represents the last operation requested by the user. // It's value must be one of the symbolic constants defined in // the Calculator class. // protected int operation; /** * Class constructor. Makes a new Calculator object, and connects * it to "gui". This means that all user-visible output will be * displayed on "gui". */ protected CalculatorState ( Calculator gui ) { super(); // Redundant. Calls superclass constructor. this.gui = gui; // Store the gui we wish to write output to this.resetCalc(); // Reset the calculator -- it's just been created! } /** * Returns a human-readable representation of the state of this * CalculatorState object. */ public String toString() { return "CalculatorState: currentNumber is " + this.readScreen() + ",\n" + " seenDecimal is " + this.seenDecimal + ",\n" + " operation is " + this.operation + ",\n" + " previousNumber is " + this.previousNumber + ",\n" + " readyForNewNumber is " + this.readyForNewNumber ; } /** * Handles a numeric keypress. The parameter "num" must be a number * between 0-9, representing the number entered into the calculator. * If the calculator has just been reset, or if a computation has just * been completed, clears the display and writes "num" to the display. * Otherwise, concatenates "num" to the end of the current number shown * on the display. */ protected void handleNumKey( int num ) { if ( this.readyForNewNumber ) // Are we done with the current number? { this.clearScreen(); // If so, clear the screen. this.seenDecimal = false; // We've just reset, so we couldn't have seen a decimal yet. this.readyForNewNumber = false; // We're not done with the current number. } // Concatenate "num" to the current value displayed, and write it to the screen. this.writeScreen( this.readScreen() + String.valueOf(num) ); } /** * Handles a keypress of the decimal button. This method is broken. * (This was an acceptable answer. You did not have to describe * this broken method.) */ protected void handleDecimal () { if ( this.readyForNewNumber ) { this.handleNumKey( 0 ); } if ( this.seenDecimal ) { this.seenDecimal = false; this.writeScreen( this.readScreen() + "."); } } /** * Handles a keypress of one of the operation buttons * (+, -, /, *). Calculates a new value to display to the screen * using the following equation: * * value to display = operand1 operator operand2 * * where * operand2 is the last number entered into the calculator * operand1 is the number entered into the calculator previous to operand1 * operator is the operation entered into the calculator directly previous * to the one we are currently handling. * * "op" must be one of * * Calculator.OP_ADD * Calculator.OP_DIV * Calculator.OP_MUL * Calculator.OP_SUB */ protected void handleOperation( int op ) { this.handleEquals(); // Handle equals does all the work. this.operation = op; // Store "op" in operation. See description of the operation variable (above). // Store the value of the display in previousNumber. See descriptor of the previousNumber variable (above). this.previousNumber = Coerce.StringTodouble( this.readScreen() ); } /** * Handles a keypress of the "equals" button (=). Computes a value to display * by performing the last stored operation on last stored operand, and the value * currently on the display. Writes the value to this calculator's gui. * Also, sets the previous operation to be NO_OP (no operation). */ protected void handleEquals () { // Compute the value to display to the screen. double answer = this.doOperation ( Coerce.StringTodouble( this.readScreen() ) ); // Writes the computed value to the screen. this.writeScreen( answer ); // Who knows? seenDecimal is broken. this.seenDecimal = true; // Equals doesn't allow previous operations. this.operation = Calculator.NO_OP; // Ok, now we're ready to enter a new number. this.readyForNewNumber = true; } /** * Computes a value based on the currentNumber, and the * previous number and operand. Specifically, returns * * currentNumber this.operation this.previousNumber * * If the previous operation is not one of the symbolic operators * defined in the Calculator class, returns currentNumber. */ protected double doOperation ( double currentNumber ) { switch ( this.operation ) // Have to determine which operation to use { // If it's one of the four standard operations, perform it // and return. case Calculator.OP_MUL: return ( this.previousNumber * currentNumber ); case Calculator.OP_DIV: return ( this.previousNumber / currentNumber ); case Calculator.OP_SUB: return ( this.previousNumber - currentNumber ); case Calculator.OP_ADD: return ( this.previousNumber + currentNumber ); // Otherwise, return currentNumber case Calculator.NO_OP: // fall through.... default: return ( currentNumber ); } } /** * Sets all information regarding the decimal to a state consistent * with the calculator's initial state. */ protected void resetDecimal () { this.seenDecimal = false; } /** * Clears the display associated with this CalculatorState. */ protected void clearScreen() { this.writeScreen( "" ); } /** * Returns the current value shown on this CalculatorState's display. */ protected String readScreen() { return this.gui.getText(); } /** * Writes "s" to this CalculatorState's display. This first deletes * any text that was showing. */ protected void writeScreen( String s ) { this.gui.setText( s ); } /** * Converts "d" to a String, and writes it to this CalculatorState's display. * This first deletes any text that was showing. */ protected void writeScreen( double d ) { this.writeScreen( String.valueOf( d ) ); } /** * Converts "i" to a String, and writes it to this CalculatorState's display. * This first deletes any text that was showing. */ protected void writeScreen( int i ) { this.writeScreen( String.valueOf( i ) ); } /** * Returns this CalculatorState to its initial state. * This clears the screen and writes "0.0" to it, * sets 0 as the last number entered, and * sets the last operation performed to be a NO_OP. */ protected void resetCalc() { this.clearScreen(); // Clear the display. this.writeScreen( 0.0 ); // Write 0.0 to the display. this.previousNumber = 0.0; // Set the previous number to be 0.0 this.seenDecimal = true; // More seenDecimal weirdness this.readyForNewNumber = true; // We're ready for a new number. this.operation = Calculator.NO_OP; // Set the last operation performed to be NO_OP. } } /* Comments: * * History: * $Log: CalculatorState.java,v $ * Revision 1.1.1.1 2002/06/05 21:56:27 root * CS101 comes to Olin finally. * * Revision 1.1 1999/11/15 04:33:17 piano18 * Committed calculator solns * * Revision 1.1 1999/10/08 15:09:24 las * This pset replaces the old Calculator pset. However, not everything * has been transferred. At the moment, it's just java, doc, and index. * The rest are still in the repository under Calculator-Old. * */