PyGUI - Placement Methods

# Placement Methods

Class Frame provides three methods, `place`, `place_row` and `place_column`, for adding and laying out subcomponents. These methods accept a very flexible set of options for specifying the position and size of the subcomponents, adding scroll bars and borders to them, and controlling how they behave when the containing frame is resized.

## Common placement options

The following options are accepted by all three placement methods.

### Positioning options

> `left`
> `right`
> `top`
> `bottom`
>   These options specify the initial positions of the edges of a component. They may take one of four forms:

>   1. `None`

>   This is the default value, and it leaves the edge unspecified. The position of an unspecified edge is determined by the component's current size and the positioning of the opposite edge. If the opposite edge is unspecified as well, the positions of both edges are left as they are.

>   2. A distance

>   The edge is positioned at the specified distance from one of the edges of the containing frame. Which edge of the frame is used depends on the value of distance. Positive distances are measured from the left or top edge of the frame, whereas negative distances are measured from the right or bottom edge of the frame.

>   A distance of zero is measured from the corresponding edge to the one being specified -- for example, specifying `left` `=` `0` positions the left edge of the component at the left edge of the frame, and specifying `right` `=` `0` positions the right edge of the component at the right edge of the frame.

>   3. A component

>   The edge is aligned with the opposite edge of the specified component. For example, specifying `left` `=` `my_button` aligns the left edge of the component with the right edge of `my_button`.

>   4. An expression of the form component `+` distance or component `-` distance

>   The edge is positioned at the specified distance from the opposite edge of the specified component. For example, specifying `left` `=` `my_button` `+` `10` positions the left edge of the component 10 pixels to the right of the right edge of `my_button`, and specifying `bottom` `=` `my_label` `-` `20` positions the bottom edge of the component 20 pixels above the top edge of `my_label`.

>   It is important to understand that these options only control the initial position and size of the component. Specifying and edge relative to another component does not create any sort of connection or constraint between the two components. Whether the relationship will be maintained when the frame is subsequently resized depends entirely on the value of the `sticky` option (see below).

>   Note also that the `left`, `top`, `right`, and `bottom` options to the placement methods are quite different from the `left`, `top`, `right`, and `bottom` properties of components. The special forms described above can be used only with the former and not with the latter.

### Resizing options

> `sticky`
>   This option controls what happens to the position and size of the component when the frame is subsequently resized. It consists of a string made up of the letters '`n`', '`s`', '`e`' and '`w`' for north, south, east and west.
>   If `sticky` contains '`w`' but not '`e`', the component will "stick" to the left edge of the frame, meaning that its position and size in the horizontal direction will not change when the frame is resized. If it contains '`e`' but not '`w`', the component will stick to the right edge of the frame, meaning that it will move along with the right edge of the frame while retaining its size.
>   If `sticky` contains both '`e`' and '`w`', the component's left edge will stick to the left edge of the frame, and its right edge will stick to the right edge of the frame. The component will therefore stretch or shrink in the horizontal direction when the frame changes size.
>   Similar considerations apply to the letters '`n`' and '`s`' with regard to the vertical direction.
>   The default value of `sticky` is '`nw`', so that the component sticks to the top and left edges of the frame.

### Scrolling options

> `scrolling`
>   This option is a string made up of the letters '`h`' and '`v`' specifying horizontal and vertical scrolling, respectively. It should only be used when the component being placed is a subclass of View, or some other component that supports scrolling. The effect of using it on a component that does not support scrolling is undefined.
>   When scrolling is specified, the component is wrapped in a ScrollFrame before being added to the frame. The other placement options (for position, size, etc.) then apply to the ScrollFrame rather than the original component.

### Border options

> `border`
>   This is a boolean option requesting that the component be given a border. Whether a border is actually added, and if it is, its size and appearance, depends on the platform and on the type of component being placed. When a border is provided, it exists outside the bounds of the component, and is not included in the calculation of any component's position and size.

## Placing rows and columns

Whereas the `place` method places a single component at a time, the `place_row` and `place_column` methods can be used to lay out a list of components in a row or column. These two methods accept all of the placement options listed above, plus the following:

> `spacing`
>   The amount of space to leave between adjacent components. If unspecified, a platform-dependent default is used.

Placing a row or column is achieved by first placing one of the components as specified by the given options, and then placing each subsequent component relative to the previous one. All of the same placement options are applied to each subsequent component, except for one of its edges, which will be positioned at the specified `spacing` from the previous component.
Which component is placed first, and the direction of subsequent component placement, is determined by which edges are specified in the placement options. For example, if you specify the `left` edge when placing a row, the first component in the list will be placed first, with its left edge at the specified position. The second component will then be placed to the right of the first, with the left edge of the second component relative to the right edge of the first, and so forth.
On the other hand, if you specify the `right` edge (and not the left edge), then the last component in the list will be placed first, and then the second-to-last to the left of it, and so forth.
(It is currently illegal to specify both the left and right edges when placing a row, or both the top and bottom edges when placing a column. This restriction may be lifted in the future.)
If you're finding the above description too confusing, just think of the edge specifications as applying to the whole collection of components rather than to any individual component. For example, `my_frame.place_row([button1,` `button2,` `button3],` `top` `=` `42,` `right` `=` `-12,` `spacing` `=` `8)` means "place these buttons in a row 8 pixels apart, 42 pixels from the top of the frame and 12 pixels from the right."

##