Why Morphic is Way Cool
Last updated at 9:51 am UTC on 29 July 2020
A short essay by Jim Benson March, April 2000
Update note 2020: The AlignmentMorph may be replaced by any Morph class, however the exercises may be done with AlignmentMorph as it is still available.
So you want to learn more about Morphic. Do you know what a Morph is, where it lives, and how it relates to its environment? Do you know the meaning of life? Do you want to impress your friends and confuse your enemies? Well, this talk only covers Morphic, for the rest you'll have to look somewhere else.
This talk is geared towards the Morphic programmer. I expect you to be comfortable with loading changeset files, and looking at code through a code browser. You should also know a little bit about programming in Squeak. I won't hold the bar very high, but then again this isn't a limbo contest. [ Really, it get's better after he warms up. Ed.]
This material explains some of the basic concepts behind Morphic which includes this page, The AlignmentMorph, HandMorph, Why Morphic is Way Cool, and a three page series on Morphic Animation starting at the insightfully named Morphic Animation page. Next, a little bit of Eye Candy, which covers gradient buttons and backgrounds. We're just starting on Check Check Roger Roger on some basic controls.
With snappy titles like those, how can you resist? As an added bonus, there are even some examples!!!
If you haven't done so already, go through the tutorial at: http://static.squeak.org/tutorials/morphic-tutorial-1.html
This is the demo John Maloney gave in Santa Barbara at SqueakEnd 2000.
So why is this clever? You have a bouncing ball, and you've seen those before. Maybe not one so colorful, but ...
A few definitions:
A Morph (from the Greek for "shape" or "form") has several properties:
- A visual (graphical) representation. It shows up on the display.
- It may be a composite, which means it may contain other Morphs. These components are called subMorphs.
- They may exhibit behavior.
- They may respond to temporal information.
Them thar pretty fancy words, Tex. What do they mean? Well, a Morph is a visual interface object, which means you can see it on the display.
Because it is a displayable object, it also has some geometry associated with it, i.e., stuff like its bounding rectangle which is where it will draw on the screen and how to position it. And you can make a Morph look pretty much like you want it to (usually this is first attacked in #drawOn:).
You may see references to costumes sprinkled throughout the code. This refers to either what a Morph looks like, or how it behaves. So when a Morph looks like a rectangle, you can tell it things like "put this circle costume on, and look like a circle".
Now, Morphs may contain other Morphs. These subMorphs are just regular old Morphs, but when they are added to a Morph (#addMorph:) this composite object acts like a single unit for moving, copying, deleting, and the such. Because submorphs may contain other Morphs, you can see that it is possible to build quite a complex structure using just this one simple concept. Us computer geeks cleverly call the resulting structure a tree.
For example, when you bring up a code browser, the SystemWindow holding the browser is just one Morph with a whole bunch of subMorphs. So you can build a rich and complex visual object with just this one simple thing, the Morph.
Pretty straightforward so far. Here comes something a little more interesting. A Morph may exhibit behavior. This means that a Morph can be programmed to do things like respond to mouse downs or keyboard input (we call this event handling), or send/receive messages from other objects. Uh oh, here's one of those clever parts I warned you about. Let's take an example:
Execute this in a Morphic project:
IconicButton new openInWorld
A little Squeak button comes up. When you click the button, the borders invert. That's nice. This is what we call the default behavior of this particular Morph. There are many defaults assigned to a Morph when it is created, things such as its color, and how it responds to events. But remember, this isn't your dad's programming language (or maybe it is if he's really smart ;-) ) and once a Morph comes to life, you may still interact with it, and have the Morph change what it looks like and behaves.
Let's subclass IconicButton. Command click with the mouse to bring up the halo around the Squeak button. Click on the red halo (menu) button.
Select 'debug' then 'make own subclass'. Name the subclass 'MyIconButton'.
If you explore the Squeak button here, (red halo, 'debug'-'explore morph'), you can see that our Squeak button friend has changed classes to become an instance of MyIconicButton. [Wowie!!! - Ed.] OK, bring up a browser and open the MyIconicButton class
(, just created with the debugger in Morphic-Widgets, the home of IconicButton) in Create a method:
"do what we're supposed to do"
super mouseUp: evt.
" skootch over a bit "
self bounds: ( self bounds translateBy: ( 10 @ 10 )).
" and tell the world that we're important enough to print something ut"
Transcript show: 'My Squeak button did this!!' ; cr.
Make sure that your Transcript Window is open. Now press the Squeak button. The button hops a little, and something is printed in the Transcript window.
When we received a #mouseUp: event, we told the button to do everything it used to do, plus a little more. Now let's try something pretty wild. The bulk of this code is lifted out of CurveFitter #displayOn:at:clippingBox:rule:fillColor: I selected this code fragment because you'll see a lot of this type of code for the lowlevel drawing routines in the system. I added comments to the code so you might at least have a chance of figuring out what's going on.
Here's a filein for your convenience: myiconicbutton.st
By the way, is there a filein command for the built-in Webbrowser
Scamper? I didn't find it. So the filein on a Windows98 system was very imcomfortable.
1. browsing to the target
2. copying it into the clipboard
3. calling notepad
4. pasting it into notepad
5. saving it under MyIconicButton.st
6. going to the directory, where the file was saved
(unfortunately with a forced additional extension ".txt")
7. chopping off ".txt"
8. filing it in with Squeak. :-(
There must be a better way ... I certainly missed it ...
| p1 p2 p3 s pa pb k delay |
" do what we're supposed to do first "
super mouseDown: evt.
" We're going to drive ourselves around a little arc,
then come back. We put in a little delay so that we
can see our little friend on fast machines. Also, we
randomize the delay so it looks kind of herky jerky.
Just a little fun stuff "
" Prepare an arc for our friend to follow "
p1 _ bounds origin.
p2 _ bounds origin + ( 400 @ 0 ).
p3 _ bounds origin + ( 200 @ 200).
" Here's the Path we're going to travel "
s _ Path new.
s add: p1.
pa _ p2 - p1.
pb _ p3 - p2.
" Now some horrible math bits to figure out the points on the arc "
k _ 5 max: pa x abs + pa y abs + pb x abs + pb y abs // 20.
"k is a guess as to how many line segments to use to approximate
1 to: k do:
s add: pa * i // k + p1 * (k - i) + (pb * (i - 1) // k + p2 * (i - 1)) //
(k - 1)].
s add: p3.
1 to: ( s size - 1 ) do: [ :j | delay _ Delay forMilliseconds: ( 10 to: 50) atRandom.
" Move to the place on the arc that we want to display at"
self position: ( s at: j ).
" make sure that we display ourselves "
" and wait for some amount of time "
" Now it's time to go back "
( s size - 1 ) to: 1 by: -1 do: [ :j |
delay _ Delay forMilliseconds: ( 10 to: 30 ) atRandom.
self position: ( s at: j ).
delay wait. ].
"No Luke, it's a trap !!! ". He promised it was clever and simple, and then he throws a method like that out at me !!! This is one of those deals, "Pay no attention to the man behind the curtain..," The above method, like many others in graphics programming, look like they have to work pretty hard to do simple things. The above method is actually simple. First we calculate an arc that the button is going to follow and store that arc as an instance of Path. Then we display our button along the arc. Then we display him coming back in the opposite direction. No, really, it is simple ...
Import this method, and save it. Now, when we click on our little friend, he takes a little trip, comes back, and hops to a new position. This may not be very useful, but it sure is fun. Of course, we could program him to do lots of other things. That's one of the important points, if you're taking notes.
OK, so we coded up this animation thingie using our little Squeak friend. But that doesn't seem like a very good way to handle animation, does it? We'll talk about that later. Next, let's talk about