How to lay out submorphs
Please read first the well written dynamic essay on Bob's SuperSwiki which you
find under the name 'MorphLayoutArticle'.
More examples are needed -- add yours here!
Every Morph now has the capability to layout it's submorphs. Before that only
the AlignmentMorph could do this, which is now deprecated ( i.e., still in
place and functioning, but not recommended for use in new code.)
Each Morph can have now its own LayoutPolicy. The new TableLayout corresponds
to what AlignmentMorph used to do. There is also a ProportionalLayout, which I
haven't used much. You should also be able to make your own subclasses of
LayoutPolicy.
Here is some code to lay out some morphs in the new system. You can find other
layout methods under Morph->layout-properties. Also, play with them from the
red halo menu of a morph.
m := RectangleMorph new.
m layoutPolicy: TableLayout new.
m listDirection: #leftToRight.
m hResizing: #shrinkWrap; vResizing: #shrinkWrap.
m layoutInset: 20; cellInset: 10.
4 timesRepeat:[ m addMorph: (RectangleMorph new color: (Color red)) ].
m openInWorld.
Eddie Cottongim
The same example enlarged a bit and modeled after the example on the page
AlignmentMorph.
m := RectangleMorph new.
m layoutPolicy: TableLayout new.
m listDirection: #leftToRight. "If you omit this expression you get the default
"
"m listDirection: #topToBottom."
m hResizing: #shrinkWrap.
m vResizing: #shrinkWrap.
m addMorph: (EllipseMorph new extent: 40@40; color: Color red).
m addMorph: (EllipseMorph new extent: 50@50; color: Color yellow).
m addMorph: (EllipseMorph new extent: 60@60; color: Color green).
m addMorph: (EllipseMorph new extent: 70@70; color: Color blue).
m openInWorld.
You can change anytime between:
m listDirection: #leftToRight.
and
m listDirection: #topToBottom.
Just evaluate the expressions with do-it.
You may as well change attributes:
m borderWidth: 0
m color: Color transparent.
m layoutInset: 20; cellInset: 10.
Hannes Hirzel, February 2002
Here is a slightly more extensive example. I typed this in a workspace,
developing it bit by bit as I experimented trying to figure out what the
various methods were and what they did. I suggest that you copy it to a
workspace, and execute it a bit at a time, looking at the effects.
"Let's start by setting up a background Morph to play with.
(Select this code down to the next comment, and 'DoIt')"
r := RectangleMorph new.
r color: Color gray.
r position: 10@10.
r extent: 150@200.
r name: 'background'.
r openInWorld.
"OK, now set up our background so that we can put something inside"
r layoutPolicy: TableLayout new. "lay out contents as a table"
r listDirection: #topToBottom. "how we want to place the contents"
r listCentering: #topLeft. "start list at the top"
r wrapCentering: #center. "each item is in the center"
e := EllipseMorph new.
r addMorph: e.
"Now lets add a second item..."
s := RectangleMorph new.
s borderWidth: 1.
s color: Color blue twiceDarker.
r addMorph: s. "note that the new item goes at the top"
"and a third."
b := SimpleButtonMorph new.
b color: Color red;
label: 'remove';
target: r;
actionSelector: #delete;
setBalloonText: 'click to remove the background rectangle and contents'.
r addMorph: b.
"Now let's space things out a bit. Try these one at a time ..."
r cellInset: 2@5. "controls distance between content elements"
r hResizing: #shrinkWrap. "try it and see!"
r layoutInset: 4@8. "that was a bt too cramped"
r vResizing: #shrinkWrap. "Now we are done"
Andrew Black
The example above enlarged by using TextMorphs put into Morph instances. This
shows how a bullet list morph may be built.
r := RectangleMorph new.
r color: Color blue twiceLighter.
r position: 10@10.
r extent: 150@200.
r name: 'background2'.
"OK, now set up our background so that we can put something inside"
r layoutPolicy: TableLayout new. "lay out contents as a table"
r listDirection: #topToBottom. "how we want to place the contents"
r listCentering: #topLeft. "start list at the top"
r wrapCentering: #topLeft.
r hResizing: #rigid.
r addMorphBack: ((TTSampleStringMorph new
initializeToStandAlone; string: 'Change to title'; color: Color
white) openInWorld).
"bullet by Ned Konz"
bullet := TextMorph new.
bullet beAllFont: ((TextStyle default fontOfSize: 36) emphasized: 1).
bullet contentsAsIs: (Character value: 165) asString.
bullet color: Color blue.
item1 _ Morph new.
item1 layoutPolicy: TableLayout new.
item1 cellPositioning: #topLeft.
item1 cellInset: 4.
item1 color: Color blue twiceLighter twiceLighter.
item1 listDirection: #leftToRight.
item1 addMorph: bullet.
item1 hResizing: #spaceFill.
item1 vResizing: #shrinkWrap.
t1 := TextMorph new.
t1 layoutPolicy: TableLayout new.
t1 hResizing: #spaceFill.
t1 vResizing: #shrinkWrap.
t1 beAllFont: ((TextStyle default fontOfSize: 36) emphasized: 1).
t1 contentsWrapped: 'First list item - aTextMorph'.
t1 autoFit: true.
t1 width: 400.
item1 addMorphBack: t1.
r addMorphBack: item1.
item1 layoutChanged.
"Now lets add a second item..."
item2 _ Morph new.
item2 layoutPolicy: TableLayout new.
item2 cellPositioning: #topLeft.
item2 cellInset: 4.
item2 color: Color blue twiceLighter twiceLighter.
item2 listDirection: #leftToRight.
item2 addMorph: bullet duplicate.
item2 hResizing: #spaceFill.
item2 vResizing: #shrinkWrap.
t2 := TextMorph new.
t2 layoutPolicy: TableLayout new.
t2 hResizing: #spaceFill.
t2 vResizing: #shrinkWrap.
t2 beAllFont: ((TextStyle default fontOfSize: 36) emphasized: 1).
"t2 borderWidth: 1."
t2 color: Color blue twiceDarker.
t2 contentsWrapped: 'Second list item - text is editable; click and add
text. The box will grow'.
t2 autoFit: true.
item2 addMorphBack: t2.
r addMorphBack: item2.
"and a button bar ..."
bbar _ Morph new.
bbar layoutPolicy: TableLayout new.
bbar cellPositioning: #topLeft.
bbar cellInset: 4.
bbar color: Color blue twiceLighter.
bbar listDirection: #leftToRight.
bbar hResizing: #shrinkWrap.
bbar vResizing: #shrinkWrap.
b := SimpleButtonMorph new.
b color: Color yellow;
label: 'remove button bar';
target: bbar;
actionSelector: #delete;
setBalloonText: 'click to remove the button bar'.
bbar addMorph: b.
r addMorph: bbar.
block _ [ :r2 |
item _ Morph new.
item layoutPolicy: TableLayout new.
item cellPositioning: #topLeft.
item cellInset: 4.
item color: Color blue twiceLighter twiceLighter.
item listDirection: #leftToRight.
item addMorph: bullet duplicate.
item hResizing: #spaceFill.
item vResizing: #shrinkWrap.
t := TextMorph new.
t layoutPolicy: TableLayout new.
t hResizing: #spaceFill.
t vResizing: #shrinkWrap.
t beAllFont: ((TextStyle default fontOfSize: 36) emphasized: 1).
t contentsWrapped: 'A list item - aTextMorph'.
t autoFit: true.
t width: 400.
item addMorphBack: t.
r2 addMorphBack: item.
].
b := SimpleButtonMorph new.
b color: Color yellow;
label: 'add other item';
setBalloonText: 'click to add another bullet list item'.
bbar addMorph: b.
b target: block.
b actionSelector: #value:.
b arguments: (Array with: b owner owner).
r addMorph: bbar.
b := SimpleButtonMorph new.
b color: Color yellow;
label: 'X';
setBalloonText: 'click to delete bullet list completely'.
bbar addMorph: b.
b target: r.
b actionSelector: #delete.
r addMorph: bbar.
r cellInset: 3@5. "controls distance between content elements"
r openInWorld.
r hResizing: #shrinkWrap. "try it and see!"
r layoutInset: 4@8. "that was a bit too cramped"
r vResizing: #shrinkWrap. "Now we are done"
item1 layoutChanged.
item2 layoutChanged.
Hannes Hirzel, March 2002
Craig Latta asked Mon, 04 Feb 2002 on the mailing list:
I'd like to nest a proportional layout in a table layout.
Bob Arning gave an example:
Morph new
color: Color green;
extent: 300 @ 300;
layoutPolicy: ProportionalLayout new;
addMorph: (
Morph new color: (Color blue alpha: 0.5)
)
fullFrame: (
LayoutFrame fractions: (0@1 corner: 1 @ 1) offsets: (0@100 negated corner: 0@0)
);
addMorph: (
Morph new
color: (Color red alpha: 0.5);
layoutPolicy: ProportionalLayout new;
addMorph: (
Morph new
color: (Color yellow alpha: 0.5);
layoutPolicy: TableLayout new;
listDirection: #topToBottom;
listCentering: #center;
addMorph: (
Morph new extent: 100@2; color: Color black; hResizing: #spaceFill
)
)
fullFrame: (LayoutFrame fractions: (0@0 corner: 0.9 @ 0.9) offsets: nil)
)
fullFrame: (
LayoutFrame fractions: (0@0 corner: 1 @ 1) offsets: (0@0 corner: 0@100 negated)
);
openInWorld