# Layout Library

The `layout` package contains a library for specifying the layout of a set of rectangles (for example, UI components in a window). By itself, the library is not very useful, but it requires a small bit of code to integrate it with another library. This is provided for the UI library and the presentation library for example.

The layout library does not introduce additional coordinate systems. That is, all coordinates produced by the library are in the same coordinate system as those provided to the layout system. Coordinates are never relative to the root container or similarly.

## Core Concepts

The library is centered around the class `layout.Component`, which represents a rectangle on the screen. A `Component` itself does not actually store a position, but it rather provides callbacks to retrieve and set the position. The `Component` provides the following members:

- `core.geometry.Size minSize()`

  Get the minimum size of this component.

- `void findAll(core.Fn<void, layout.Component> fn)`

  Traverse the hierarchy to find all components.

The second important class is `layout.Layout`. It represents a collection of `Component`s that it is responsible to assign positions to. The `Layout` class extends `Component` which means that it is possible to nest layout logic to create more complex layout rules.

The `Layout` class introduces the following members in addition to the ones in `Component`:

- `core.geometry.Rect space`

  Our allotted space. Updated in the default implementation of `pos(Rect)`.

- `void layout()`

  Re-compute the layout here. Called automatically when the position is updated.

- `layout.Layout.Info add(layout.Component child)`

  Add a child to this layout. Returns a class that contains information about the child added. The caller is expected to be able to modify this information to alter the layout.

As noted above, the `add` function returns a `layout.Layout.Info` class that contains layout-specific information about the child. The `Info` class in `Layout` is empty, but other layout managers subclass the `Info` class in `Layout` to add custom data there. For example, the `Grid` layout stores the row and column that the child should be placed in inside the `Info` class. This information lets the DSL (see below) access the properties conveniently.

## Cardinal Directions

The layout library provides a set of cardinal directions to specify relative directions. These directions are described by the `layout.Cardinal` class and subclasses that implement some common directions. The `Cardinal` class has the following members:

- `layout.Cardinal opposite()`

  Get the opposite direction.

- `core.geometry.Point direction()`

  Get a direction vector.

The following cardinal directions are available:

- `layout.center`
- `layout.north`
- `layout.northEast`
- `layout.east`
- `layout.southEast`
- `layout.south`
- `layout.southWest`
- `layout.west`
- `layout.northWest`

## Layout Managers

The library provides the following layout managers. Of course it is possible to create custom layout managers by subclassing the `Layout` class.

- `layout.Border`

  A simple layout manager that adds a border around a single child within. If multiple children are added, all but the last one is discarded. The border size is set using the `border` member.

- `layout.Stack`

  This layout manager simply stacks components on top of each other. Essentially, it is an adapter that allows placing multiple components in the space where a single component would ordinarily fit.

- `layout.Anchor`

  This layout manager aligns its contents (a single component) to the specified cardinal direction. This is useful in situations where a small component should be placed in a large location, but the component should not be stretched. The `Anchor` layout thus uses the `minSize` of the component, and places it along the edge or in the center of the allocated space.

  It is also possible to modify the placement of the contained component using `xShift` and `yShift`.

- `layout.Grid`

  Layout for putting components in a grid-like pattern.

  The grid is automatically sized to fit the constraints dictated by the contained components. Each row and column will have their own size. To fill all available space, specify which rows and columns are allowed to grow using `expandRow` or `expandCol`. A weight may additionally be specified to allow different rows/columns to grow at different ratios with respect to each other. There are two modes that can be applied to the expansion. The default is to assign any extra space (according to the weights) to the expandable rows and columns. This means that they will have different sizes based on the minimum size, but the additional space is allocated fairly. The second mode (enabled using `normalizeRows`/`normalizeCols`) is to base the extra assignment based on the total size of the elements. That way, given equal weights, the layout will keep them at equal size. This means that the minimum size of some components might be enlarged to keep the distribution.

  Elements may also be positioned at absolute grid coordinates by specifying `row` and `col`, starting at index 0. Additional rows and columns are then created to accomodate all components. Elements may span multiple rows and column, as dictated by `rowspan` and `colspan`.

  Elements are added row by row, wrapping if a maximum number of columns have been specified using `wrapCols`, or if `nextLine` is called.

  Elements are spaced according to `border`. There is no space around the outer edge of the layout.

Finally, the library provides a single component that is useful in some cases:

- `layout.FillBox`

  A simple component that simply takes up space. Can be used in conjunction with the `Grid` layout for example to create extra spacing.

## Integrating the Layout Library

To use the layout library elsewhere, it is necessary to create a custom `Component` that overloads the `pos(Rect)` member and assigns the position to whatever should be laid out. It is also useful to implement the `minSize` member in order to provide the layout library with information about the minimum size of components.

When using the domain specific language, it is often inconvenient to have to create the custom component manually. For this reason, the domain specific language will automatically call the `component()` function on all objects that do not already inherit from `Component`. The `component()` function is expected to return a `Component` that corresponds to the parameter type.

## Domain Specific Language

The layout library provides a small domain specific language so that layouts can be specified more conveniently. The DSL is designed to be extended by other libraries to suit their needs. As such, the syntax provided here is quite simple.

The syntax consists of a tree of layout declarations. Each such declaration has the following form:

    <type-or-name>(<parameters>) {
        <body>
    }

Here the sequence `<type-or-name>(<parameters>)` is a call to a constructor, or a function. The result of evaluating this call will be inserted in the layout. The parentheses can be omitted if no parameters are required. As such, `<type-or-name>` may also be the name of a variable in the surrounding context. As mentioned above, if the type specified does not inherit from `Component`, then the language will attempt to call the `component()` function to create a component. The function is found using the standard Basic Storm lookup rules.

The `<body>` may consist of zero or more nested layout declarations or property assignments. Nested layout declarations are like regular layout declarations. Such objects will be added using the `add` member of the outer layout object. As such, nesting declarations in this way assumes that the parent declaration refers to a `Layout`.

Property assignments modify the behavior of the layout element. A property assignment has the following form:

    <identifier>: <parameters>;

or

    <identifier>;

Where `<identifier>` is an identifier, and the optional `<parameters>` is a comma-separated list of expressions. A property assignment attempts to call the function `<identifier>(<parameters>)` on the layout element for the current block. These functions are typically designed to modify the behavior of the element, which is why they are written in a different form from regular function calls. If no parameters are required, the second form can be used. The same syntax can also be used to assign values to member variables.

If `<identifier>` with suitable parameters is not found in the layout element, the language looks for a suitable function or member in the `Info` class that was returned when the element was added to its parent. This means that it is also possible to specify child-specific properties related to the parent layout inside the block used for the child.

To start a layout declaration in Basic Storm, the keyword `layout` is used. The example below uses the layout syntax to create a simple layout of a few components:

    use layout;

    Layout createLayout(Component a, Component b) {
        var x = layout Grid {
            wrapCols: 2;      // Executes: Grid.wrapCols(2)
            expandCol: 0, 1;  // Executes: Grid.expandCol(0, 1)

            a {}
            FillBox(1, 1) {}

            b {
                row: 3;     // Executes: Grid.Info.row = 3
                col: 3;     // Executes: Grid.Info.col = 3
            }
        };
        return x;
    }

The code above is roughly equivalent to the following:

    use layout;

    Layout createLayout(Component a, Component b) {
        Grid x;
        x.wrapCols(2);
        x.expandCol(0, 1);

        x.add(a);

        x.add(FillBox(1, 1));

        var cInfo = x.add(b);
        cInfo.row = 3;
        cInfo.col = 3;

        return x;
    }