Morphic Tutorial: Build a 4 digit LED counter -- 2nd approach
Last updated at 3:15 pm UTC on 2 March 2019
Continued from
Morphic Tutorial: Build a 4 digit LED counter

### Second approach

Here we will use Smalltalk code to construct the counter. The original description was prepared by Tim Olson.

Daniel McBrearty's comment:
I found Tim's example excellent - if you already know some Smalltalk but want to learn to build morphs from scratch, this is worth exploring. I added comments with a more detailed analysis showing how the LED counter works, step by step. (The only thing I couldn't track was the dependency mechanism - see the query in my code.)

Hannes Hirzel: I reedited the text and added a explanatory note on the 'changed' method.

Tutorial instruction:
Open a new project and then open a new workspace and place it at the right hand side of the screen. Copy all of the following text (until 'third approach') and paste it into the workspace. You can the directly execute the Smalltalk code by selecting it and choosing 'do-it'.

"The object pointed to by the variable frame will be holding the box containing the panel."

frame := AlignmentMorph newColumn."(for version 2.7 and 2.8) or"

frame := AlignmentMorph new listDirection: #topToBottom."(for version 3.0)"

"To make it visible we'll send it the message openInWorld... "

frame openInWorld.
"We now just see a dumb rectangle in the top left corner

We can reposition it by sending it the message position with two coordinate values given by a point:"

frame position: 30 @ 50.

"We now create an LED display for the count"
display := LedMorph new

digits: 4;

extent: (410@150).

" ... to make the display visible we send it as well the message openInWorld. It has all the behaviour of a 4 digit LED display"

display openInWorld.

"it opens on top of frame, but it is draggable ... try it"

"What is it made of? Do print-it on the next line"
display submorphs.

"you should have got something like this (the actual id numbers will be different, every morph get's an id number assigned by the system)

(a LedDigitMorph(2449) a LedDigitMorph(1990) a LedDigitMorph(1560) a LedDigitMorph(2460))"

"Browsing the protocol for LedDigitMorph shows that this is the bit that does the hard work. This class has class variables that define the positions of the segments and the state of each horizontal and vertical segment for each digit and the - sign. It also knows how to change colour and be highlighted or not. Do the following expressions one at a time ... "

(display submorphs at: 2) digit: 5.

(display submorphs at: 2) highlighted: true.

"Note that the second digit was only redrawn when the highlighted message was sent. This is because that method contains the 'self changed' message which causes a redraw.

To test this, modify the 'digit:' instance method. Open a system browser (green window), find the class 'LedDigitMorph' and change the method to look like this ...

digit: anInteger

digit := anInteger \\ 10. ""make sure it stays between 0 and 9""

self changed

.... we have made the individual digit change when its value changes. Test this:"

(display submorphs at: 2) digit: 7.

"A note: The message send 'changed' invokes a method which is implemented in class Morph. It reports that the area should be redrawn. It has nothing to do with the dependency mechanism implemented in class Object which also has a method 'changed'. In Smalltalk-80 this was a heavily used mechanism for building UIs"

"The value of the whole 4-digit array can be changed with the method value::"

display value: 2468.

"Again this uses 'self changed' "

"Now lets add control buttons in a row"

controls := AlignmentMorph newRow. "(for version 2.7 and 2.8) or"

controls := AlignmentMorph new listDirection: #leftToRight."(for version 3.0)"

"how does this look?"

controls openInWorld.

"Drag this away from the previous little rectangle so that the changes will be easy to see.

This is a nice bit. Let's add a quit button"

target: frame;

label: 'quit';

actionSelector: #delete).

"increment button"

target: display;

label: 'inc';

actionSelector: #increment).

target: display;

label: 'dec';

actionSelector: #decrement).

target: display;

label: 'clear';

actionSelector: #clear).

"We have now three morphs we will assemble

• frame (an AlignmentMorph)
• display (a LEDMorph)
• controls (another AlignmentMorph)
"

"add the controls to our frame"

"browsing the protocol for LedMorph again shows a couple of ways to change the appearance, straight away ... "

display color: Color red.

display highlighted: true.

We're not ready to run it yet. We have now built the user interface but we don't have the increment/decrement logic in place yet. To make this easy, we'll just add it to
the existing LedMorph class, which we are using for the display.

In the browser, find the LedMorph class, go to the method category pane and add a new category called 'counting'. We'll keep all of our new methods here.

• Add a message clear with the code self value: 0
• Accept your change: Hit command-s or select "accept" from the menu in the lower pane.
• Add a message increment with the code self value: self value + 1. Hit command-s as before.
• Now, select the newly created increment message again but this time simply change increment to decrement and change the plus sign in self value: self value + 1 to a minus sign. Then save the method again. Smalltalkers often use existing code snippets for creating new code.

Now we're ready to give it a try.

Morphic Tutorial: Build a 4 digit LED counter -- 3rd approach