## 4.2 The Packer

The packer supports simple arrangements of widgets in rows and columns. Arranging widgets nicely usually also means that some vertical and horizontal space has to be inserted, either designed to provide for additional space or to fill up space not occupied by the widget's original size.

The different ways how to affect the geometry we will study by means of examples. For this, let us assume we are dealing with three label widgets. The following function creates a toplevel widget with background color white for better visibility, and returns a list of three labels.

  `fun {NewLabels}
  W={New Tk.toplevel tkInit(background:white)}
  in
  {Map ['label' 'Second label widget' '3rd label']
  fun {$ A}
  {New Tk.label tkInit(parent:W text:A)}
  end}
  end`

To display the labels in the toplevel widget, the packer can be invoked as follows:

  `[L1 L2 L3] = {NewLabels}
  {Tk.send pack(L1 L2 L3)}`

This computes and displays a geometry for the toplevel widget as shown in Figure 4.1. Rather than giving a tickle which contains each of the labels as field we can give a batch tickle. A batch tickle is a tuple with label `b` where its single argument must be a list of tickles. By using a batch tickle, we can rewrite our example from above to

  `{Tk.send pack(b({NewLabels}))}`

where the list of tickles is the list of labels as returned by the function `NewLabels`.

Figure 4.1: Plain geometry computed by the packer.

### 4.2.1 Side Options

The label widgets in the previous examples were placed from the top to the bottom of the toplevel widget. The side where the widgets are packed against can be determined with the `side` option. The default value for this option is `top`. The examples in Figure 4.2 show the geometry which is computed when `left` and `bottom` are given as values for the side option. Valid values for the side option are `top`, `bottom`, `left`, and `right`.

  `{Tk.send pack(b({NewLabels}) side:left)}`

  `{Tk.send pack(b({NewLabels}) side:bottom)}`

Figure 4.2: Geometries computed by the packer according to `side` option.

### 4.2.2 Padding

The geometry computed for widgets by the packer can be given additional space in two different ways: either externally or internally. Additional external space can be specified with the options `padx` and `pady`. The values for these options must be valid screen distances (see Section 3.3.2), specifying how much additional space should be provided by the master widget around the packed widgets. The internal space can be specified by the `ipadx` and `ipady` options, where the values must be screen distances as well. These values determine by how much space the packed widgets are expanded in each of their four borders. The examples in Figure 4.3 show the effects on the geometries computed by the packer for both internal and external padding.

  `{Tk.send pack(b({NewLabels}) padx:1#m pady:1#m)}`

  `{Tk.send pack(b({NewLabels}) ipadx:2#m ipady:2#m)}`

Figure 4.3: Additional space provided by the packer.

### 4.2.3 Anchors

With the `anchor` option it can be specified where in a widget's parcel the packer places the widget. If no `anchor` option is given, the packer places the widget in the center of its parcel. Otherwise, the widget is placed according to the option's value, which can be one of `center`, `n`, `s`, `w`, `e`, `nw`, `ne`, `sw`, and `se`. The Figure 4.4 shows the geometry computed when `w` is used as anchor.

  `{Tk.send pack(b({NewLabels}) anchor:w padx:1#m pady:1#m)}`

Figure 4.4: Using the `anchor` option for packing.

### 4.2.4 Filling and Expansion

For pleasant overall geometry it is imported that widgets have similar geometries. The packer employs two different schemes how widgets can be arranged to have similar geometries. One is filling: the widget extends over its entire parcel. The other one is expansion: the widget's parcel is extended such that the parcels of all slaves in a master occupy the master's parcel entirely.

Figure 4.5 shows the geometry computed when the option `fill` with value `x` is used. Possible values for the `fill` option are `x`, `y`, `both`, and `none` (which is the default).

  `{Tk.send pack(b({NewLabels}) fill:x)}`

Figure 4.5: Using the `fill` option for packing.

Expansion is only significant when the parcels of the slave do not fill the master's parcel completely. In all our previous examples, the parcel of the master was computed by the packer to be just large enough to contain the slave's parcels. So there was no additional space in the master's parcel to be filled by expansion of slave parcels.

Figure 4.6 shows three toplevel widgets which have been resized manually by dragging with the mouse. The top most example shows that when the parcel of the toplevel widget grows, the remaining space is filled by the label widgets. In the example in the middle, only the parcels of the label widget's are expanded. At the bottom, the parcels are expanded and then filled up in both horizontal and vertical direction by the label widgets.

  `{Tk.send pack(b({NewLabels}) fill:x)}`

  `{Tk.send pack(b({NewLabels}) expand:true)}`

  `{Tk.send pack(b({NewLabels}) fill:both expand:true)}`

Figure 4.6: Resizing effects for filling and expansion.