Created Binary tree layout (markdown)

Jakub Sobon 2019-03-10 23:43:46 -04:00
parent 388af4512f
commit 6f2619b644
1 changed files with 197 additions and 0 deletions

197
Binary-tree-layout.md Normal file

@ -0,0 +1,197 @@
[![Doc Status](https://godoc.org/github.com/mum4k/termdash/container?status.png)](https://godoc.org/github.com/mum4k/termdash/container)
This page explains how to setup the terminal layout using the [container](https://godoc.org/github.com/mum4k/termdash/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|grid-layout]].
Container organizes the terminal 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|container_splits]]
# Splitting a container
A container can either be split vertically or horizontally.
## [container.SplitHorizontal](https://godoc.org/github.com/mum4k/termdash/container#SplitHorizontal):
The **container.SplitHorizontal** option splits the current container into two sub-containers:
- Left sub-container, use [container.Left](https://godoc.org/github.com/mum4k/termdash/container#Left) to specify its options.
- Right sub-container, use [container.Right](https://godoc.org/github.com/mum4k/termdash/container#Right) to specify its options.
## [container.SplitVertical](https://godoc.org/github.com/mum4k/termdash/container#SplitVertical):
The **container.SplitVertical** option splits the current container into two sub-containers:
- Top sub-container, use [container.Top](https://godoc.org/github.com/mum4k/termdash/container#Top) to specify its options.
- Bottom sub-container, use [container.Bottom](https://godoc.org/github.com/mum4k/termdash/container#Bottom) to specify its options.
## [container.SplitPercent](https://godoc.org/github.com/mum4k/termdash/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](https://godoc.org/github.com/mum4k/termdash/container#pkg-constants).
# [container.New](https://godoc.org/github.com/mum4k/termdash/container#New):
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:
```go
tb, err := termbox.New()
if err != nil {
return fmt.Errorf("termbox.New => %v", err)
}
if _, err := container.New(
tb,
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|container_splits_actual]]
# Margin and padding
The terminal layout can be further adjusted by configuring margin and padding of containers. A **margin** is a cleared space on the outside of the container, i.e. between its border and whats beyond it. A **padding** is a cleared space on the inside of the container, i.e. between its border and its content.
The following diagram gives a visual explanation of where margin and padding apply:
[[/images/container-api/container_margin_padding.png|container_margin_padding]]
The margin or padding can be applied to a container by specifying absolute or relative values.
### Absolute values
Absolute margin or padding is specified as the amount of **cells** that should be cleared. When specifying absolute values, the padding remains unchanged even if the terminal and container size changes.
Use one of the following options to specify absolute margin:
- [container.MarginTop](https://godoc.org/github.com/mum4k/termdash/container/#MarginTop)
- [container.MarginRight](https://godoc.org/github.com/mum4k/termdash/container/#MarginRight)
- [container.MarginBottom](https://godoc.org/github.com/mum4k/termdash/container/#MarginBottom)
- [container.MarginLeft](https://godoc.org/github.com/mum4k/termdash/container/#MarginLeft)
Use one of the following options to specify absolute padding:
- [container.PaddingTop](https://godoc.org/github.com/mum4k/termdash/container/#PaddingTop)
- [container.PaddingRight](https://godoc.org/github.com/mum4k/termdash/container/#PaddingRight)
- [container.PaddingBottom](https://godoc.org/github.com/mum4k/termdash/container/#PaddingBottom)
- [container.PaddingLeft](https://godoc.org/github.com/mum4k/termdash/container/#PaddingLeft)
### Relative values
Relative margin or padding is specified as a percentage of the container's size. Specifying relative values is useful to accommodate terminal and container size changes. When the terminal size changes, so does the padding or margin.
Use one of the following options to specify relative margin. The **top** and **bottom** values are specified as percentage of the container's **height**.
- [container.MarginTopPercent](https://godoc.org/github.com/mum4k/termdash/container/#MarginTopPercent)
- [container.MarginBottomPercent](https://godoc.org/github.com/mum4k/termdash/container/#MarginBottomPercent)
The **right** and **left** values are specified as percentage of the container's **width**.
- [container.MarginRightPercent](https://godoc.org/github.com/mum4k/termdash/container/#MarginRightPercent)
- [container.MarginLeftPercent](https://godoc.org/github.com/mum4k/termdash/container/#MarginLeftPercent)
Use one of the following options to specify relative padding. The **top** and **bottom** values are specified as percentage of the container's **height**.
- [container.PaddingTopPercent](https://godoc.org/github.com/mum4k/termdash/container/#PaddingTopPercent)
- [container.PaddingBottomPercent](https://godoc.org/github.com/mum4k/termdash/container/#PaddingBottomPercent)
The **right** and **left** values are specified as percentage of the container's **width**.
- [container.PaddingRightPercent](https://godoc.org/github.com/mum4k/termdash/container/#PaddingRightPercent)
- [container.PaddingLeftPercent](https://godoc.org/github.com/mum4k/termdash/container/#PaddingLeftPercent)
## Applying margin and padding to containers
The following code snippet demonstrates application and effect of margin and padding. The left container has both margin and padding applied. The right container has none of these options. Both containers contain a single button and have a border.
```go
t, err := termbox.New()
if err != nil {
return fmt.Errorf("termbox.New => %v", err)
}
defer t.Close()
addB, err := button.New("(a)dd", func() error {
return nil
})
if err != nil {
return fmt.Errorf("button.New => %v", err)
}
subB, err := button.New("(s)ubtract", func() error {
return nil
})
if err != nil {
return fmt.Errorf("button.New => %v", err)
}
c, err := container.New(
t,
container.Border(linestyle.Light),
container.SplitHorizontal(
container.Top(),
container.Bottom(
container.SplitVertical(
container.Left(
container.PlaceWidget(addB),
container.AlignHorizontal(align.HorizontalRight),
container.Border(linestyle.Light),
container.MarginBottom(3),
container.MarginRight(1),
container.PaddingRight(3),
),
container.Right(
container.PlaceWidget(subB),
container.AlignHorizontal(align.HorizontalLeft),
container.Border(linestyle.Light),
),
),
),
container.SplitPercent(60),
),
)
if err != nil {
return fmt.Errorf("container.New => %v", err)
}
```
The code above results in the following layout:
[[/images/container-api/container_margin_padding_actual.png|container_margin_padding_actual]]