Logo-small

3.7.1.2 Proportional Layout

Let's consider an example to talk about layouts. Evaluate:

window:= StandardWindow labelled: 'Painter'.
aMorph := Morph new.
window addMorph: aMorph frame: (0@0 corner: 0.5@1).
window openInWorld. 

Here we use addMorph:frame: to add the morph. The second argument is the fraction of the window's area covered by the morph given as first argument - here 50% horizontally and 100% vertically.

Basic layout

You can change it to 70% horizontally and 30% vertically.

window addMorph: aMorph frame: (0@0 corner: 0.7@0.3).

Basic layout continued

Note that when you resize the window, the ratio is kept.

You can put the morph in the center of the window:

window addMorph: aMorph frame: (0.2@0.2 corner: 0.8@0.8).

Basic layout, morph at center

If we put two morphs side by side, SystemWindow automatically adds a splitter to resize them. Evaluate:

window := StandardWindow labelled: 'Painter'.

aMorph := Morph new.
window addMorph: aMorph frame: (0@0 corner: 1.0@0.5).
aMorph color: Color paleMagenta.
aMorph := Morph new.
window addMorph: aMorph frame: (0@0.5 corner: 1.0@1.0).
aMorph color: Color lightCyan.

window openInWorld.

Automatic splitters

We needed to set the colors of the Morphs after they were added to the window because SystemWindow>>addMorph:frame: automatically forces the color of added Morphs to match the colors of the current theme.

To position a morph in a proportional layout, SystemWindow uses a LayoutFrame object. This is the code for SystemWindow>>addMorph:frame:

addMorph: aMorph frame: relFrame
| frame |
frame := LayoutFrame new.
frame
leftFraction: relFrame left;
rightFraction: relFrame right;
topFraction: relFrame top;
bottomFraction: relFrame bottom.
self addMorph: aMorph fullFrame: frame.

We can specify the LayoutFrame object using StandardWindow >>addMorph:fullFrame:. So

window addMorph: aMorph frame: (0@0 corner: 0.5@1).

can be written

window 
addMorph: aMorph
fullFrame: (LayoutFrame
fractions: (0@0 corner: 0.5@1)).

Fractions are used to specify a proportional layout. If you want to specify a fixed layout, you have to use offsets instead. Consider the following example:

window:= StandardWindow labelled: 'Painter'.

aMorph := Morph new.
window
addMorph: aMorph
fullFrame: (LayoutFrame offsets: (0@0 corner: 100@50)).

window openInWorld.

Fixed layout

So when you resize the window, the Morph size stays the same. Note that offsets are in pixels, so the Morph size remains 100px wide by 50px high.

But how it works is more subtle. See:

LayoutFrame>>offsets: offsetsOrNil
^self fractions: nil offsets: offsetsOrNil

and

LayoutFrame>>fractions: fractionsOrNil offsets: offsetsOrNil
| fractions offsets |
fractions := fractionsOrNil ifNil: [0@0 extent: 0@0].
....

This means that the proportional layout is set to 0% horizontally and 0% vertically when fractions are not specified. Then offsets move the top-left and bottom-right corners inward a specified number of pixels.

 LayoutFrame offsets: (0@0 corner: 100@50).

really means:

  • keep the morph 0% wide and 0% high
  • translate the top-left corner 0 pixels horizontally, and 0 pixels vertically
  • translate the bottom-right corner 100 pixels horizontally (to the right), and 50 pixels vertically (to the bottom).

Now let's lay out a Morph that stays a fixed distance from the bottom of the window.

window:=StandardWindow labelled: 'Painter'.

aMorph := Morph new.
window
addMorph: aMorph
fullFrame: (LayoutFrame
fractions: (0@0 corner: 1@1)
offsets: (0@0 corner: 0@50 negated)).

window openInWorld.

This means:

  • the morph is 100% wide and 100% high
  • translate the bottom-right corner -50 pixels vertically (to the top)

Fixed bottom layout

If you want a fixed-height morph at the bottom (like a status bar), you can say:

window:=StandardWindow labelled: 'Painter'.

aMorph := Morph new.
window
addMorph: aMorph
fullFrame: (LayoutFrame
fractions: (0@1 corner: 1@1)
offsets: (0@50 negated corner: 0@0)).

window openInWorld.
  • the morph is 100% wide and 0% high
  • translate the bottom-right corner -50 pixels vertically (to the top)

Gui_fixed_size_bottom.png

Knowing all this, you can create a layout with:

  • an horizontally-fixed panel on the right
  • a vertically-fixed panel at the bottom
  • a proportional panel in the center
window:=StandardWindow labelled: 'Painter'.
redMorph := Morph new.
window
addMorph: redMorph
fullFrame: (LayoutFrame
fractions: (0@0 corner: 1@1)
offsets: (100@0 corner: 0@50 negated)).
redMorph color: Color red.

greenMorph := Morph new.
window
addMorph: greenMorph
fullFrame: (LayoutFrame
fractions: (0@0 corner: 0@1)
offsets: (0@0 corner: 100@50 negated)).
greenMorph color: Color green.


yellowMorph := Morph new.
window
addMorph: yellowMorph
fullFrame: (LayoutFrame
fractions: (0@1 corner: 1@1)
offsets: (0@50 negated corner: 0@0)).
yellowMorph color: Color yellow.

window openInWorld.

Proportional and fixed layout

User Contributed Notes

dougedmunds (2 March 2011, 10:13 am)

Look at the Pharocast on

   http://www.pharocasts.com/2010/06/proportional-layout.html

which covers this section

Add a Note

Licensed under Creative Commons BY-NC-SA | Published using Pier |