Now we have a User Interface and we can give some feedback to the user when they click an operator button. Next we want to get our calculator doing some calculations.
Entering numbers
Similar to the operator buttons the number buttons, including ".", all do the same thing, only the number changes. We will implement a numberPressed command on the Card Script and call it from each of the number buttons, passing the number as a parameter.
Open the Card Script from the Object menu and add this custom command, all this command does is put the pressed number after what is already in the display field.
command numberPressed pNumber put pNumber after field "display" end numberPressed
You can also before a field or into a field, which replaces any text that is already in the field.
Now add a mouseUp handler which calls this custom command to each of the number buttons
on mouseUp numberPressed the short name of me end mouseUp
Testing the Calculator
Now seems like a good time to test your app. Make sure you have saved it first.
Now switch to Run mode(1) in the Tools Palette, this allows you to interact with your app as a user, rather than Edit mode(2), which allows to you edit and modify your app.
Try pressing some number and operator buttons to make sure everything is working as expected.
Once you are done testing switch back to Edit mode to carry on with development.
The Percentage button
The first operation we will implement is the percentage operation.
Select the "percentage" button, and open its Script Editor by pressing the Code button in the Menubar. Add the following code to the button and apply it, again the button will call a custom command that we will implement on the Card Script.
on mouseUp percentagePressed end mouseUp
Ensure the Card Script is open and add the percentagePressed command to the Card Script.
The percentagePressed command takes the number that is currently in the "display" field and calculates it as a percentage by dividing it by 100 and putting the result into the "display" field.
command percentagePressed put field "display" into tCurrentValue put tCurrentValue / 100 into field "display" end percentagePressed
The Toggle button
The Calculator uses the "toggle" button to toggle the number in the display between positive and negative.
Add the following code to the "toggle" button
on mouseUp togglePressed end mouseUp
To toggle the displayed number between positive and negative we can multiply the number in the "display" field by -1.
Add the following code to the Card Script
command togglePressed put field "display" into tCurrentValue put tCurrentValue * -1 into field "display" end togglePressed
The Clear button
Next we want to implement the "clear" button. Again we will add code to the button that will call a command on the Card Script.
Add the following code to the "clear" button
on mouseUp clearPressed end mouseUp
To clear the display we just need to put 0 into the "display" field.
Add the following code to the Card Script
command clearPressed put 0 into field "display" end clearPressed
Now seem like another good time to test the Calculator, save your stack and switch to Run mode.
- try entering some numbers
- try getting a percentage
- try toggling the number
- try clearing the display
Did you notice any problems?
Did you notice that if you clear the display and then click on more numbers the display always has a leading 0?
There is a simple way to fix this in the numberPressed command, but we need to use an if statement. An if statement allows you to check if a condition is true and then execute different code depending on the outcome.
Our if statement will check whether the "display" field only contains 0. If so it will overwrite the contents of the field, otherwise it will behave as it currently does and put the pressed number after the current contents of the field.
Update the numberPressed command in the Card Script to
command numberPressed pNumber if field "display" is 0 then put pNumber into field "display" else put pNumber after field "display" end if end numberPressed
The Equals button
The final, and most import stage of implementing the Calculator is to implement the "equals" button.
When the "equals" button is pressed the calculation the user has entered is processed and the final result is displayed. To get this working there are a number of features we need to add to the calculator
- when an operator is pressed the calculator need to know which operator has been chosen
- when an operator is pressed the calculator needs to store the number that is currently in the display so it can be used when "equals" is pressed
- when "equals" is pressed the stored number, current operator and value in the "display" field are used to do the calculation and the result is displayed
We also need to add some additional functionality to our "clear" button
- The "clear" button can dislay "C" or "AC"
- When "AC" is pressed we clear everything, the display, the selected operator and any stored values
- When "C" is pressed only the current value in the "display" field is cleared, any stored value or operator are saved
- The label of the "clear" button should change to "C" when a number is pressed
- The label of the "clear" button should change to "AC" when the "clear" button is pressed
Storing information
Sometimes you want to store information for later use. To do this we use variables.
A variable is a place to store data that you create, which has no on-screen representation. Variables can hold any data you want to put into them. One way to think of a variable is as a box with a name on it. You can put anything you want into the box, and take it out later, by simply providing
the variable’s name:
But unlike some other types of containers, fields for example, variables are non-permanent and aren’t saved with the stack. Instead, variables are automatically deleted either when their handler is finished running or when you quit the application (depending on the variable’s scope).
Variables can have different levels of scope, the scope of a variable describes where is can be used in your code. There are three main levels of variable scope
- local: A local variable can be used only in the handler that creates it. Once the handler finishes executing, the variable is deleted. The next time you execute the handler, the variable starts from scratch: it does not retain what you put into it the last time the handler was
executed.
- scriptlocal: A script local variable can be used in any handler in an object’s script. You cannot use a script local variable in handlers in other objects’ scripts. Unlike a local variable, a script local variable retains its value even after a handler finishes executing.
- global: A global variable can be used in any handler, anywhere in the application. Unlike a local variable, a global variable retains its value even after the handler that created it finishes executing. Unlike a script local variable, a global variable can be used by any
handler in any object’s script.
For more on variables see Chapter 5.5 Variables of the User Guide, which can be accessed from the Help menu.
Storing the operator
The first piece of information we want to store is the operator that has been pressed. We will use a script local variable, sCurrentOperator
to store the operator.
To create a script local variable we define it at the top of the script, but outside of any handlers. This makes it accessible to all handlers on that script.
Open the Card Script and add this line to the first line of the script.
local sCurrentOperator
This variable can now be referred to anywhere in the Card Script.
We will update our operatorPressed handler to store the chose operator in this script local variable. Add the line
put pOperator into sCurrentOperator
to the end of the operatorPressed handler, now the operator is stored in the variable, ready to be used later.
Storing the current value
When an operator is pressed we store the chosen operator, but we also want to store the current value in the display so that it can be used in the calculation later. We will use another script local variable, sCurrentTotal, to store this value. We also want to know when a new number has been
started, for example after an operator has been pressed, so we will use another script local variable to store whether a number is new or not, sNewNumber.
You can list all the variables you want to define by separating them with commas. Update the first line in your Card Script to
local sCurrentOperator, sCurrentTotal, sNewNumber
There are 3 places we need to record the current total
- operatorPressed
- percentagePressed
- togglePressed
There are 4 places we need to record whether a new number has been started
- operatorPressed
- numberPressed
- percentagePressed
- togglePressed
We need to update these 4 handlers to store our information in these variables.
command operatorPressed pOperator set the showBorder of button "divide" to false set the showBorder of button "multiply" to false set the showBorder of button "minus" to false set the showBorder of button "plus" to false set the borderColor of button pOperator to black set the showBorder of button pOperator to true ## Store the operator, current total and start a new number put pOperator into sCurrentOperator put field "display" into sCurrentTotal put true into sNewNumber end operatorPressed
command numberPressed pNumber ## Check if a new number is to start if sNewNumber is true then put pNumber into field "display" put false into sNewNumber else put pNumber after field "display" end if end numberPressed
command percentagePressed put field "display" into tCurrentValue put tCurrentValue / 100 into field "display" ## Store the current total put field "display" into sCurrentTotal end percentagePressed
command togglePressed put field "display" into tCurrentValue put tCurrentValue * -1 into field "display" ## Store the current total put field "display" into sCurrentTotal end togglePressed
These three variables will allow us to implement our "equals" button.
Adding code to the Equals button
Now we want to implement the "equals" button. Again we will add code to the button that will call a command on the Card Script.
Add the following code to the "equals" button
on mouseUp equalsPressed end mouseUp
And add a equalsPressed handler to the Card Script.
The equalsPressed command takes the stored total, operator and value in the display field, calculates the result and puts it in the "display" field. It also resets the variables and display ready for the next calculation.
Becase the contents of the "display" field are used as the current total strings of calculations can be done in this way.
command equalsPressed ## if no operator has been pressed there is no calculation to do if sCurrentOperator is empty then exit pressEquals ## store the value in the display field put field "display" into tCurrentValue ## check which operator was chosen ## perform the calculation using the stored total, stored operator and current value switch sCurrentOperator case "divide" put sCurrentTotal / tCurrentValue into sCurrentTotal break case "multiply" put sCurrentTotal * tCurrentValue into sCurrentTotal break case "minus" put sCurrentTotal - tCurrentValue into sCurrentTotal break case "plus" put sCurrentTotal + tCurrentValue into sCurrentTotal break end switch ## put the result into the "display" field put sCurrentTotal into field "display" ## clear the operator button and stored values set the ShowBorder of button sCurrentOperator to false put empty into sCurrentOperator put true into sNewNumber end equalsPressed
Now try it out! remember to switch to Run mode.
Updating the Clear button
The very last step is to update the "clear" button. At the moment it only puts 0 into the "display" field, but now it needs to do a bit more
- allow us to clear the current value but retain the stored total and operator
- allow us to clear everything
This is the difference between the 2 modes of the "clear" button in a calculator. C only clears the current value, AC clears the current value, total and operator.
The first step is to update out clearPressed handler on the Card Script to reflect these 2 modes.
on clearPressed ## Clear the current value put 0 into field "display" ## Start a new number put true into sNewNumber if the label of button "clear" is "AC" thencd .. ## Clear the stored total put 0 into sCurrentTotal ## Clear the current operator if sCurrentOperator is not empty then set the showBorder of button sCurrentOperator to false put empty into sCurrentOperator else ## Change the mode to "AC" set the label of button "clear" to "AC" end if end clearPressed
We also need to update the equalsPressed handler to set the mode to AC. Add a line to the end of your equalsPressed handler.
set the label of button "clear" to "AC"
The other time the mode changes is when a number is enetered, this requires an update to the numberPressed handler.
Add the following line to the end of your numberPressed handler.
set the label of button "clear" to "C"
The Completed Calculator
And that’s it, you should now have a fully functional Calculator app. Make sure you save your work and try it out in Run mode.
Adding Logic to the Calculator