6 Binary tree layout
Jakub Sobon edited this page 2020-11-14 01:29:24 -05:00

Doc Status

This page explains how to setup the terminal layout using the container package directly which organizes the layout in a binary tree structure. This is one of the two available methods, see also the Grid layout.

Container organizes the terminal in a binary tree structure. Each container is a node in this tree. Unless the node was created empty, it contains one of the following:

  • two sub-containers; OR
  • a widget.

Given a container, developers can create sub-containers by splitting the container. There are two kinds of splits:

  • horizontal split, which creates top and bottom sub-containers.
  • vertical split, which creates left and right sub-containers.

This property is recursive, meaning developers can further split the sub-containers using the same rules. The following diagram demonstrates how splits are utilized to create a layout.

/images/container-api/container_splits.png

Splitting a container

A container can either be split vertically or horizontally.

container.SplitHorizontal:

The container.SplitHorizontal option splits the current container into two sub-containers:

container.SplitVertical:

The container.SplitVertical option splits the current container into two sub-containers:

container.SplitPercent:

The container.SplitPercent option is used to specify at what percentage to perform the split. I.e. the percentage of the containers width (when splitting vertically) or height (when splitting horizontally).

The default value of the split is defined as a package constant.

container.New:

The container.New function is used to construct a container. The API of this function uses a recursive builder patters, the complete layout of all the containers in the tree is established in a single call.

To create the terminal layout indicated in the diagram above, the developer can use the following code:

t, err := tcell.New()
if err != nil {
  return fmt.Errorf("tcell.New => %v", err)
}

if _, err := container.New(
    t,
    container.SplitVertical(
        container.Left(
            container.Border(linestyle.Light),
        ),
        container.Right(
            container.SplitHorizontal(
                container.Top(
                    container.Border(linestyle.Light),
                ),
                container.Bottom(
                    container.SplitVertical(
                        container.Left(
                            container.Border(linestyle.Light),
                        ),
                        container.Right(
                            container.Border(linestyle.Light),
                        ),
                    ),
                ),
            ),
        ),
    ),
); err != nil {
    return fmt.Errorf("container.New => %v", err)
}

When executed, this results in the following terminal layout:

/images/container-api/container_splits_actual.png