Skip to content
Jakub Sobon edited this page Nov 14, 2020 · 4 revisions

Doc Status

This page explains how to change the layout of the terminal dynamically at runtime. This can be done by updating the options at a specific container. The developer creates options that represent the new desired layout using one of the two available methods, i.e. the Binary tree layout or the Grid layout.

Dynamic layout changes are demonstrated in the termdashdemo, run it using the following command:

go run github.com/mum4k/termdash/termdashdemo/termdashdemo.go

Identifying containers

In order to update a container, the developer must provide its identifier. By default the created containers have no identifiers assigned and thus cannot be updated. Use the container.ID option to create a container with a custom identifier. This identifier is later used when updating the container.

The container.ID option sets the identifier on a container. This can be later used to update the container's options.

Changing the layout

Use the Container.Update method to specify new options for a container.

The Container.Update method applies the specified options to a container with the provided ID. This can be used to perform simple changes like adding a border or layout changes. When changing the layout, the developer can replace the widget with another one or define new splits for the container that effectively establish new layout on the screen.

Replacing widget in a container

The following code places a button widget inside a container and then updates the container by replacing the button with a text widget:

t, err := tcell.New()
if err != nil {
    panic(err)
}
defer t.Close()

b, err := button.New("hello world", func() error {
    return nil
},
)
if err != nil {
    return fmt.Errorf("button.New => %v", err)
}

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

c, err := container.New(
    t,
    container.PlaceWidget(b),
    container.ID("myID"),
)
if err != nil {
    return fmt.Errorf("container.New => %v", err)
}

if err := c.Update("myID", container.PlaceWidget(t)); err != nil {
    return fmt.Errorf("c.Update => %v", err)
}

Changing the layout by specifying new splits

When container is updated by adding a new split, any previously placed widgets or sub-containers are replaced with the new layout. This can be utilized to change the layout of the screen and display new grid and content.

The following code places a button widget inside a container and then updates the container by splitting it into two and placing a button and a text widget:

t, err := tcell.New()
if err != nil {
    panic(err)
}
defer t.Close()

b, err := button.New("hello world", func() error {
    return nil
},
)
if err != nil {
    return fmt.Errorf("button.New => %v", err)
}

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

c, err := container.New(
    t,
    container.PlaceWidget(b),
    container.ID("myID"),
)
if err != nil {
    return fmt.Errorf("container.New => %v", err)
}

if err := c.Update(
    "myID",
    container.SplitVertical(
         container.Left(
             container.PlaceWidget(b),
         ),
         container.Right(
             container.PlaceWidget(t),
         ),
    ),
); err != nil {
    return fmt.Errorf("c.Update => %v", err)
}