Morphic Animation II

Steve Wessels stephan.wessels at
Mon Mar 20 19:32:04 UTC 2000

I must be missing something.  The e-mail message does not contain the class
definition for LaunchAlignmentMorph but the swiki does, so that's not too bad.

However, I have had no luck finding the class method
    LaunchAlignmentMorph openLauncher

  - Steve

Jim Benson wrote:

> Folks,
> Here is my Morphic Animation example. Please read through it and comment.
> These are also available on the Swiki in what I think is an easier to read
> format.
> Jim Benson
> When we last left our hero, PathRectangleMorph was busily fighting the
> forces of evil, preparing the way for all that is good. He had fought
> himself into a corner and was waiting to be rescued. Here comes the
> LaunchAlignmentMorph to the rescue.
> LaunchAlignmentMorph instance methods:
> animateWindowOpening: theWindow inWorld: theWorld
> | topWindow anime |
>  topWindow _ theWorld firstSubmorph.
>  topWindow ifNotNil: [
>   anime _ PathRectangleMorph beginPoint: ( topWindow bounds center )
> finishRectangle: ( theWindow bounds).
>   anime setProperty: #sender toValue: self.
>   anime startStepping.
>   ]
>  ifNil: [ self doneAnimation ].
> doneAnimation
>  " add the world to the window "
>  world addMorph: window.
>  " and make the window the frontmost one "
>  window activate.
>  " Make sure that the submorphs are happening "
>  world startSteppingSubmorphsOf: window.
>  ^window
> openInWindowLabeled: aString inWorld: theWorld
>  | extent |
>  inset _ 0.
>  world _ theWorld.
>  window _ (SystemWindow labelled: aString) model: nil.
>  window
>   " guess at initial extent"
>   bounds:  (RealEstateAgent initialFrameFor: window initialExtent: self
> fullBounds extent);
>   addMorph: self frame: (0 at 0 extent: 1 at 1);
>   updatePaneColors.
>  " calculate extent after adding in case any size related attributes were
> changed.  Use
>  fullBounds in order to trigger re-layout of layout morphs"
>  extent _ self fullBounds extent +
>    (window borderWidth at window labelHeight) + window borderWidth.
>  window extent: extent.
>  self animateWindowOpening: window inWorld: theWorld.
> So here it is. I've been talking all along about cool this, cool that, blah
> blah blah blah blah.
> Execute this in a Workspace:
> LaunchAlignmentMorph openLauncher
> I've tried to tell you, but you wouldn't listen. "He's on drugs, he doesn't
> know what's up!" Now you've seen it. That's way cool stuff. You open a
> window, and it just doesn't leap up on the screen. Instead the window
> appears to actually appear from somewhere. You can do this three or four
> times, and the windows show up in different places. Execute the same
> statement from another location on the screen. Play around with it some and
> see what it does. You can change the location that the animation starts at
> in the method #animateWindowOpening:inWorld: For example, you could start at
> the center of the screen by changing: anime _ PathRectangleMorph beginPoint:
> ( World bounds center ) finishRectangle: ( theWindow bounds).
> This technique is called temporal aliasing. For those interested in this
> kind of stuff, there is an excellent article called "Animation: From
> Cartoons to the User Interface" by Bay-Wei Chang and David Ungar. Ungar was
> one of the creators of the language Self, the environment where Morphic was
> first implemented. This article can be found in the "Proceedings of the ACM
> Symposium on User Interface software and Technology,[UIST] 1993, pg. 45".
> Hey, I don't name these things, I just read 'em. When I first read that
> article I remember thinking, "Who are those guys?" and, "Why can't I do
> things like that?". Well, they had Morphic even back then. That made them
> all powerful. They also had real machines, I had toys in comparison. Those
> guys also told me I needed to use an arc to animate this correctly. They're
> smart, I believe them. That's why you've had to put up with all that
> Arc/Path nonsense.
> -
> There is one tricky part I'd like to talk about. Remember, I'm telling you
> right up front, this is tricky. But if you can master the following, you're
> well on your way to being the master of all you survey.
> When we're getting ready to start the animation we:
> anime setProperty: #sender toValue: self.
> It's not immediately obvious what this does. Morphs have something called
> properties You can think of properties (some people call them slots) as
> extra pockets that a Morph has to carry stuff around in. So we tell the
> Morph that we're calling anime to put 'self' (which is a
> LaunchAlignmentMorph) into a pocket named #sender. #sender is an instance of
> Symbol, which is a fancy kind of String.
> You're thinking, "I know this trick. This dude starts talking like this
> right before he hits me on the side of the head with more of that high
> falutin' computer jock junk". You know me all too well. Except I'm going to
> beat you upside the head a couple of times. I can control the power of
> Morphic, that gives me unbelievable strength and power.
> If we look at the code for PathRectangleMorph #stopStepping, towards the end
> we see:
>   sender _ self valueOfProperty: #sender.
>  sender ifNotNil: [ sender doneAnimation].
> We read this code as, "If I have a property called sender, send the message
> #doneAnimation to the value of the property named sender". After reading
> that last sentence, you can understand why people came up with programming
> languages. English just doesn't cut it. The code is easier to read than the
> description. I guess that's why we don't comment the code either.
> So why would we do something silly like that? Here's what we want to happen.
> The LaunchAlignmentMorph gets ready to open a window. It tells the
> PathRectangleMorph to show it's animation starting from the center of the
> window where we're currently at to the top left hand corner of the window
> that we want to open. When the animation is over, we open the
> LaunchAlignmentMorph window.
> 'All good and well', you say. 'Simple'. 'Straight forward'. 'Why is he going
> to mess with something as simple as that?' The simple answer is that now we
> can harness the power of Morphic for all that is good. Right here, right
> now.
> We coded our example to do this: When it is ready to open a window, the
> LaunchAlignmentMorph tells the PathRectangleMorph to start animating. Then
> the LaunchAlignmentMorph is out of it. Doesn't care about life anymore.
> Then, when the PathRectangleMorph ends its animation sequence, it sends
> #doneAnimation to the LaunchAlignmentMorph. So during the animation
> sequence, LaunchAlignmentMorph was free to go about its business, and do
> whatever it wanted to. This process is called by computer nerds, now get
> this, an asynchrounous callback. Catchy huh? These are the same people who
> brought you "http://". Do you find it surprising that they are the hit of
> every party?
> I'll give you an analogy. Let's say you want a pizza. You go to the pizza
> place, order a pizza, sit around 20 minutes, get the pizza, and take it
> home. Computer idiots call this a synchronous process. You start a task and
> follow through with it until the task ends.
> You could have done it differently. You could have called the pizza place on
> the phone, and ordered the pizza for delivery. Then you could have played
> your guitar, washed the car, and scared the neighbors cat before the
> delivery guy brought the pizza to your door. You had the amount of time
> between when you ordered and when the pizza was delivered free to do
> whatever you wanted. That's an asynchronous process.
> As you have figured out by now, that's how we can all sorts of animations
> going on at once. We basically just start 'em up and let 'em rip. Plus, they
> have a way to tell someone who is interested that they are done.

More information about the Squeak-dev mailing list