The radio button problem turns out to be a very educational one. Squeak has many of the traditional GUI widgets: lots of different kinds of buttons, lots of different kinds of menus, lots of different kinds of lists, lots of different kinds of text areas. This makes them not so good as educational examples, because you just use them. The fun of radio buttons is building them.
Poking around a bit more with Morphic, I've started to wonder whether the rather large size of Morph might actually be _justified_, because there seems to be a highly relevant slogan:
ANY MORPH CAN...
Let's consider the abstract needs of a radio button group. * "container" - holds buttons so they can be moved as a group * "button" 1..n - has visibly different ON and OFF states - tells the co-ordinator when it is pressed * "co-ordinator" - holds the state (1..n) - tells buttons when to turn ON and OFF
Now, ANY MORPH CAN... be a container. Just use addMorph{,Back}: or addAllMorphs: to add submorphs.
ANY MORPH CAN... be a button. The visibly different states could be colours (easy as easy) or borders (plain/raised/bevelled/thick/thin) or even costumes. More to the point, whatever kind of Morph we choose for our buttons, the co-ordinator can tell the (i)th button:
button on: #MouseDown send: #state:event:morph: to: self withValue: i
and then when you click on the button, it will send coordinator state: (i) event: (mouseDownEvent) morph: (thisButton) and the coordinator will know what to do.
We could say there's another Morphic slogan:
YOU DON'T HAVE TO INHERIT TO BE RICH.
After discovering on:send:to:withValue: last night, it took me another half hour to put together a three-class solution. RadioGroup, a new subclass of Object, acting as co-ordinator. EllipseMorph, the existing ellipse morph class, with no changes. I used the default yellow colour for off, red for on. AlignmentMorph, the existing alignment morph class, with no changes, as container. Unlike my previous example, this one could handle any number of buttons up to an arbitrary limit of 20, and could present them in a vertical or horizontal row.
The only real weakness in this new version is that it doesn't handle labels; I tried stuffing a StringMorph in one of the EllipseMorphs and the alignment went crazy. I have no idea why.
Doing it again, I might make RadioGroup a subclass of AlignmentMorph.
The thing I particularly like about this solution is that there isn't the slightest need for the various buttons to be the same shape. If you want to select between various nibs for a pen, for example, the morphs used as buttons can be images of the nib.
Then there are the Squeaky things you can do like indicate the active button by animating it, perhaps having it jog up and down gently, or rocking; and you can make the buttons make noises when they are pressed for audio feedback.
If anyone has suitable animal pictures and sounds, a neat Morphic tutorial would be an "AnimalChooser" that put up a radio-button-group-like list of animal pictures, letting you choose any one, and making the appropriate sounds.
Richard;
It's beginning to sound as though the difficulty Lily thought her instructor had in demonstrating the "button problem" may simply have been a way to encourage the students to explore what you've shown to be an amazingly rich set of possibilities and options.
I don't want to litter the list with "attaboys" but I really appreciate experts like yourself taking the time to explain, step by step, how and why you approach Squeak programming challenges in a particular way. Code fragments and completed solutions are useful and convenient, but walking in the footsteps of Alan Kay, Tim Rowledge, yourself and others who have talked the list through various problems (I've got Alan's "Tamika Knox" messages and Swiki pages permanently archived, for example) is truly and deeply helpful.
Thank you.
Gary
----- Original Message ----- From: Richard A. O'Keefe To: squeak-dev@lists.squeakfoundation.org Sent: Tuesday, July 30, 2002 10:12 PM Subject: Re: A problem hindering SmallTalk's popularity:
The radio button problem turns out to be a very educational one. Squeak has many of the traditional GUI widgets: lots of different kinds of buttons, lots of different kinds of menus, lots of different kinds of lists, lots of different kinds of text areas. This makes them not so good as educational examples, because you just use them. The fun of radio buttons is building them.
Poking around a bit more with Morphic, I've started to wonder whether the rather large size of Morph might actually be _justified_, because there seems to be a highly relevant slogan:
ANY MORPH CAN...
Let's consider the abstract needs of a radio button group. * "container" - holds buttons so they can be moved as a group * "button" 1..n - has visibly different ON and OFF states - tells the co-ordinator when it is pressed * "co-ordinator" - holds the state (1..n) - tells buttons when to turn ON and OFF
Now, ANY MORPH CAN... be a container. Just use addMorph{,Back}: or addAllMorphs: to add submorphs.
ANY MORPH CAN... be a button. The visibly different states could be colours (easy as easy) or borders (plain/raised/bevelled/thick/thin) or even costumes. More to the point, whatever kind of Morph we choose for our buttons, the co-ordinator can tell the (i)th button:
button on: #MouseDown send: #state:event:morph: to: self withValue: i
and then when you click on the button, it will send coordinator state: (i) event: (mouseDownEvent) morph: (thisButton) and the coordinator will know what to do.
We could say there's another Morphic slogan:
YOU DON'T HAVE TO INHERIT TO BE RICH.
After discovering on:send:to:withValue: last night, it took me another half hour to put together a three-class solution. RadioGroup, a new subclass of Object, acting as co-ordinator. EllipseMorph, the existing ellipse morph class, with no changes. I used the default yellow colour for off, red for on. AlignmentMorph, the existing alignment morph class, with no changes, as container. Unlike my previous example, this one could handle any number of buttons up to an arbitrary limit of 20, and could present them in a vertical or horizontal row.
The only real weakness in this new version is that it doesn't handle labels; I tried stuffing a StringMorph in one of the EllipseMorphs and the alignment went crazy. I have no idea why.
Doing it again, I might make RadioGroup a subclass of AlignmentMorph.
The thing I particularly like about this solution is that there isn't the slightest need for the various buttons to be the same shape. If you want to select between various nibs for a pen, for example, the morphs used as buttons can be images of the nib.
Then there are the Squeaky things you can do like indicate the active button by animating it, perhaps having it jog up and down gently, or rocking; and you can make the buttons make noises when they are pressed for audio feedback.
If anyone has suitable animal pictures and sounds, a neat Morphic tutorial would be an "AnimalChooser" that put up a radio-button-group-like list of animal pictures, letting you choose any one, and making the appropriate sounds.
On Tuesday 30 July 2002 07:12 pm, Richard A. O'Keefe wrote:
Doing it again, I might make RadioGroup a subclass of AlignmentMorph.
Good summary, Richard; thanks!
I might also add:
ANY MORPH CAN: be an AlignmentMorph.
Ever since Andreas moved the table alignment stuff down into Morph, AlignmentMorph has been just a convenient constructor for a BorderedMorph. It doesn't have any interesting behavior (other than a slightly different keyboard focus policy; I'm not sure how important that is).
You can lay out submorphs either by using the TableLayout (which is what AlignmentMorph uses), the ProportionalLayout (which is what the SystemWindows use), or by defining your own layoutInBounds:
The ProportionalLayout is often overlooked; it allows each submorph to have its own bounds rectangle computed separately based on a simple spec.
The spec computes the corners of the submorph bounds from a combination of a proportion of the owner bounds plus (or minus) a fixed pixel offset.
Of course, in the RadioButton case, you don't even need a layout policy, since the submorphs don't have to re-position themselves.
So you could have a structure (for 3 buttons with labels) that looks like this:
RadioButtonMorph EllipseMorph StringMorph EllipseMorph StringMorph EllipseMorph StringMorph
I've attached a little change set that adds the ability to add arbitrary labeled Morphs (including buttons) to any Morph.
squeak-dev@lists.squeakfoundation.org