Skip to content
Split containers

Split containers

A split container divides its space between panes, with a divider the user drags to change the share. Bellui has two:

The gallery's Containment page: a tree on the left and scrolling cards on the right, divided by a draggable split bar The gallery's Containment page: a tree on the left and scrolling cards on the right, divided by a draggable split bar

Split

sidebar := widget.NewLabel("Sidebar")
editor := widget.NewMultiLineEntry()
editor.SetPlaceHolder("Editor")

// Two children with a draggable divider between them.
split := container.NewHSplit(sidebar, editor)
split.SetOffset(0.25) // the sidebar gets a quarter of the width

container.NewHSplit(leading, trailing) puts the panes side by side with a vertical divider. container.NewVSplit(top, bottom) stacks them with a horizontal divider.

SetOffset sets the divider position as a fraction of the space, from 0.0 to 1.0. A new split starts at 0.5, sharing the space equally. The offset is limited so that neither pane is smaller than its minimum size. If the user drags the divider, the Offset field follows.

If you hide one pane, the other one gets all the space and the divider is not shown.

Paned

// Any number of children. Weights set their share of the space.
panes := container.NewVPaned(
	split,
	widget.NewLabel("Output"),
	widget.NewLabel("Terminal"),
)
panes.SetWeight(0, 3) // the top pane gets 3 parts, the others 1 each

container.NewHPaned(panels...) arranges panes left to right; container.NewVPaned(panels...) top to bottom. Each pane has a weight, 1 by default, and gets a share of the space in proportion to its weight. SetWeight(i, w) changes one weight. AddPanel appends a pane and RemovePanel(i) removes one.

As with Split, no pane is made smaller than its minimum size.

Panes that shrink

A pane cannot be dragged smaller than its content’s minimum size. A long label or a wide form can make a pane hold more space than you want. Two ways around it:

  • Put the content in a scroll container, whose minimum size is small.
  • Wrap it in container.New(layout.NewShrinkLayout(), content). The shrink layout reports a minimum size of zero and always gives the content the pane’s full size, even when that is below the content’s minimum.

The whole program

The example nests a Split inside a Paned: a sidebar and editor on top, and two panels below.

// A three-pane editor shape: a sidebar split from an editor on top, with two
// more panes stacked below it in a vertical Paned.
package main

import (
	"github.com/belluikit/bellui"
	"github.com/belluikit/bellui/app"
	"github.com/belluikit/bellui/container"
	"github.com/belluikit/bellui/geo"
	"github.com/belluikit/bellui/widget"
)

func main() {
	a := app.NewWithID("com.example.split")
	w := a.NewWindow("Split containers")

	sidebar := widget.NewLabel("Sidebar")
	editor := widget.NewMultiLineEntry()
	editor.SetPlaceHolder("Editor")

	// Two children with a draggable divider between them.
	split := container.NewHSplit(sidebar, editor)
	split.SetOffset(0.25) // the sidebar gets a quarter of the width

	// Any number of children. Weights set their share of the space.
	panes := container.NewVPaned(
		split,
		widget.NewLabel("Output"),
		widget.NewLabel("Terminal"),
	)
	panes.SetWeight(0, 3) // the top pane gets 3 parts, the others 1 each

	w.SetContent(panes)
	w.Resize(geo.NewSize(700, 500))
	bellui.ShowAndRun(w)
}