We will not examine the code for the remaining methods. Instead, go ahead and add the following instance methods to STCalculator:
Method calculateAnswer:
calculateAnswer: aFunction "Private - Calculate the answer based on lastValue, aFunction, and the current value. Answer a String." | answer last current realFunction | last := self convertToNumber: lastValue. current := self convertToNumber: (textWidget value). aFunction = '=' ifTrue: [ realFunction := operation ] ifFalse: [ realFunction := aFunction ].
state = #equals ifTrue: [ answer := current perform: (realFunction asSymbol) with: last ] ifFalse: [ answer := last perform: (realFunction asSymbol) with: current ].
answer class = Fraction ifTrue: [ answer := answer asFloat ]. ^answer printString
Method clear
clear "Private - Clear the display and lastValue." textWidget setString: ''. "No space between single quotes" lastValue := nil.
Method close
close "Shut down the calculator. Just for fun, use a pop-up confirmation dialog." (CwMessagePrompter confirm: 'Really exit?' title: 'Confirmation') ifTrue: [ textWidget shell destroyWidget ]
Method convertToNumber:
convertToNumber: aString "Convert aString to a number. Answer either an Integer or a Float." | subStrings whole decimal exponent | subStrings := aString subStrings: $. . whole := (subStrings at: 1) asNumber. subStrings size = 1 ifTrue: [ ^whole ] ifFalse: [ decimal := subStrings at: 2. (decimal includes: $e) ifTrue: [ subStrings := decimal subStrings: $e. exponent := (subStrings at: 2) asNumber. decimal := subStrings at: 1 ] ifFalse: [ exponent := 0 ]. ^(whole + (decimal asNumber / (10 raisedTo: (decimal size)))) * (10 raisedTo: exponent) asFloat ].
Method doFunction:
doFunction: aFunction "Private - The user has pressed a function button." | temp | aFunction = '+/-' ifTrue: [ ^self negate ]. aFunction = 'Clr' ifTrue: [ ^self clear ]. aFunction = 'Pi' ifTrue: [ ^self pi ]. aFunction = 'Off' ifTrue: [ ^self close ].
aFunction = '=' ifTrue: [ temp := textWidget value. textWidget setString: (self calculateAnswer: aFunction). state = #equals ifFalse: [ lastValue := temp ]. state := #equals ] ifFalse: [ lastValue = nil ifTrue: [ lastValue := textWidget value. operation := aFunction ] ifFalse: [ state = #equals ifFalse: [ textWidget setString: (self calculateAnswer: operation)]. operation := aFunction. lastValue := textWidget value ].
textWidget setSelection: (0 @ (textWidget value size)). textWidget setHighlight: (0 @ (textWidget value size)) mode: XmHIGHLIGHTSELECTED. state := #function].
Method negate
negate "Private - The +/- button has been pressed. Change the sign of the current number." | string newString | string := textWidget value. string size > 0 ifTrue: [ string first = $- "Minus sign" ifTrue: [ string size > 1 ifTrue: [ newString := string copyFrom: 2 to: string size ]
ifFalse: [ newString := '' ]] ifFalse: [ newString := '-' , string ]] ifFalse: [ newString := '-' ]. textWidget setString: newString. textWidget cursorPosition: (textWidget value size).
Method pi
pi "The pi button has been pressed. Display its value." self insert: (Float pi)