Skip to content
Jakub Sobon edited this page Mar 3, 2019 · 22 revisions

Container API

Doc Status

The container package is used to establish and mutate the layout of the terminal. An instance of the container object is required to start the Termdash application, see the Termdash API for details.

The container splits the raw terminal into smaller portions (sub-containers). The developer decides how the splits are organized. Design of the container object is heavily inspired by the i3 window manager, specifically by how the i3 wm organizes the layout of application windows on the screen.

Developers can also use the container to customize the look of the Termdash application.

Apart from organising the terminal layout, the Termdash infrastructure uses the container to call the Draw method on all placed widgets and to map virtual canvases given to widgets onto the raw terminal. The container is also responsible for distributing events to individual widgets.

Terminal layout

Layout of the terminal is organized 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.

The container.New function is used to constract 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 call:

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

if _, err := container.New(
    tb,
    container.SplitVertical(
        container.Left(),                     // Container is empty.
        container.Right(
            container.SplitHorizontal(
                container.Top()               // Container is empty.
                container.Bottom(
                    container.SplitVertical(
                        container.Left(),     // Container is empty.
                        container.Right(),    // Container is empty.
                    ),
                ),
            ),
        ),
    ),
); err != nil {
    panic(err)
}

Keyboard focus

Containers track keyboard focus. By default, any keyboard events are only delivered to widget in the focused container. The user changes the focused container by clicking on any area within the container. If the focused container has a border, its color will change according to the value of the container.FocusedColor option.

Note that widgets can also register for global keyboard events, see the Widget API for more details.

Splitting a container

A container can either be split vertically or horizontally.

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

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

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.

Placing widgets

Apart from establishing the terminal layout, containers are meant to hold widgets. Each container can hold exactly one widget. Containers that have widgets cannot have sub-containers.

Container is responsible for allocating virtual canvas for the widget that is in accordance to the options the widget provided. See the Widget API for more details on widget options. If the widget specifies maximum canvas size or ratio, there might be an empty space left inside the container and around the widget. If that happens, the widget alignment options can help to visually align widgets inside a container. Widgets that don't specify these options automatically stretch to the full size of the container unless the container has padding specified.

The container.PlaceWidget option places the provided widget into the container.

Widget alignment options

The following options can be used to align a widget within the container both horizontally and vertically.

The container.AlignHorizontal option is used to specify horizontal alignment for the widget. Refer to the Align API for alignment options.

The container.AlignVertical option is used to specify vertical alignment for the widget. Refer to the Align API for alignment options.

Style options for containers

This section describes container options that specify its style or look.

Borders for containers

Containers don't have any borders by default, use one of the following options to instruct Termdash to draw a border around a container.

The container.Border option is used to enable the border and specify its line style. Refer to the Linestyle API for the available line styles.

The container.BorderColor option sets the color of the border. This option takes no effect when the container has no border.

The container.FocusedColor option sets the color of the border when the container is focused. This option takes no effect when the container has no border.

Titles for containers

Containers that have a border can also have a text title displayed in the border. The title isn't visible on a container without border.

The container.BorderTitle option sets the title to display on the container. The title is displayed above the container and aligned according to the following alignment options.

The container.BorderTitleAlignLeft option indicates that the container title should be aligned at the top left corner.

The container.BorderTitleAlignCenter option indicates that the container title should be aligned at the top and center above the container.

The container.BorderTitleAlignRight option indicates that the container title should be aligned at the top right corner.

Clone this wiki locally