7 The Packer

7.1  The Packer

This section describes the geometry manager in GS.

When the user resizes a window, the application normally has to resize and move the graphical objects in the window to fit its new size. This can be handled by a so called packer or geometry manager. In GS, the packer functionality is a property of the frame object. A frame with the packer property may control the size and position of its children.

A packer frame organises its children according to a grid pattern of rows and columns. Each row or column has a stretching property associated to it. Some columns may expand more than others and some may have a fixed size. The grid pattern is in itself invisible, but the objects contained by it snap to fit the grid.

The packer controlled by the following options:

Frame options:
{packer_x,Packlist} where Packlist is list() of PackOption, and
{packer_y,Packlist} where Packlist is list() of PackOption.

PackOption is:
{stretch, Weight} where Weight is integer() > 0, or
{stretch, Weight, MinPixelSize, or}
{stretch, Weight, MinPixelSize, MaxPixelSize}, or
{fixed, PixelSize}

A Weight is a relative number that specifies how much of the total space of the frame a row or column will get. If the frame has three columns with the weights 2, 1, 3 it tells the geometry manager that the first column should have 2/6, the second 1/6 and the third 3/6 of the space.

Note that giving a minimum or maximum width of one or more columns will change the relation and the way the space is divided.

Then the objects contained by the frame use the following options to position themselves in the grid:
{pack_x,Column} where Column is integer(), or
{pack_x,{StartColumn,EndColumn}}

and
{pack_y,row} where row is integer(), or
{pack_y,{Startrow,Endrow}}

or, the the following option is a convenient shorthand:
{pack_xy,{Column,row}}

Consider the following example.


-module(ex17).
-copyright('Copyright (c) 1991-97 Ericsson Telecom AB').
-vsn('$Revision: /main/release/1 $ ').

-export([start/0,init/0]).

start() -> spawn(ex17, init, []).

init() ->
    WH = [{width,200},{height,300}],
    Win = gs:window(gs:start(),[{map,true},{configure,true},
				{title,"Packer Demo"}|WH]),
    gs:frame(packer,Win,[{packer_x,[{stretch,1,50},{stretch,2,50},
				    {stretch,1,50}]},
			 {packer_y,[{fixed,30},{stretch,1}]}]),
    gs:button(packer,[{label,{text,"left"}},{pack_xy,{1,1}}]),
    gs:button(packer,[{label,{text,"middle"}},{pack_xy,{2,1}}]),
    gs:button(packer,[{label,{text,"right"}},{pack_xy,{3,1}}]),
    gs:editor(packer,[{pack_xy,{{1,3},2}},{vscroll,true},{hscroll,true}]),
    gs:config(packer,WH), % refresh to initial size
    loop().

loop() ->
    receive
	{gs,_Id,destroy,_Data,_Arg} -> bye;
	{gs,_Id,configure,_Data,[W,H|_]} ->
	    gs:config(packer,[{width,W},{height,H}]), % repack
	    loop();
	Other ->
	    io:format("loop got: ~p~n",[Other]),
	    loop()
    end.

It defines a frame with three columns where the second should be twice as wide as the other but no column should be smaller than 50 pixels wide. The frame has two rows where the first has a fixed height of 30 pixels and the last row is totally flexible. Three buttons are placed next to each other on the first row, and below them an editor. The editor covers all three columns.

IMAGE MISSING
Figure 7.1:   Frame with three columns

The picture below illustrates what happens when the window is resized.

IMAGE MISSING
Figure 7.2:   Resized Frame

To repack the objects, the size of the packer frame has to be set explicitly. This is done by using the height and width options as usual. Since the packer frame controls the size of its children, using the standard x, y, width, height options, packer frames may be nested recursively.

The packer is very useful since it simplifies the programming. The programmer will not have to spend time fine tuning x, y, width, height of each object, since these options are handled by the frame.