Skip to content
This repository has been archived by the owner on Oct 13, 2021. It is now read-only.

Patterns

Marcus Olsson edited this page Jan 5, 2018 · 1 revision

This page describes some of the patterns that have been emerging in the projects that are using tui-go.

Extending existing widgets

By embedding an existing widget, you can make it implement other interfaces, like the io.Writer in this example.

type labelWriter struct {
	buf bytes.Buffer

	ui tui.UI
	tui.Label
}

func (w *labelWriter) OnKeyEvent(ev tui.KeyEvent) {
	if ev.Key == tui.KeyCtrlL {
		w.buf.Reset()
		w.Label.SetText("")
		go w.ui.Update(func() {})
	}
}


func (w *labelWriter) Write(p []byte) (n int, err error) {
	n, err = w.buf.Write(p)
	w.Label.SetText(w.buf.String())
	go w.ui.Update(func() {})
	return
}

func main() {
	root := tui.NewVBox()

	ui := tui.New(root)
	ui.SetKeybinding("Esc", func() { ui.Quit() })

	w := &labelWriter{ui: ui}
	root.Append(w)

	fmt.Fprintln(w, "hej")

	if err := ui.Run(); err != nil {
		panic(err)
	}
}

Views

Views allow you to group multiple related widgets together.

type scorecardView struct {
	player *tui.Label
	score  *tui.Label

	*tui.Box
}

func newScorecardView(name string) *scorecardView {
	v := &scorecardView{
		player: tui.NewLabel(name),
		score:  tui.NewLabel("0"),
	}

	v.Box = tui.NewHBox(
		v.player,
		v.score,
	)

	return v
}

func (v *scorecardView) updateScore(s int) {
	v.score.SetText(fmt.Sprintf("%d", s))
}

func main() {
	var (
		playerName = "highlander56"
		score      = 0
	)

	v := newScorecardView(playerName)

	ui := tui.New(v)
	ui.SetKeybinding("Esc", func() { ui.Quit() })
	ui.SetKeybinding("Ctrl+A", func() {
		score++
		v.updateScore(score)
		go ui.Update(func() {})
	})

	if err := ui.Run(); err != nil {
		panic(err)
	}
}

Custom widgets

If none of the provided widgets suits your use case, you can implement you own by implementing the Widget interface. The easiest way is to embed WidgetBase that provides default functionality for you widget.

For most purposes, you'll only have to implement the Draw and SizeHint methods for your custom widget. In the Draw method, you have access to the Painter which lets you draw lines, text or runes within your widget. You'll also implement SizeHint that will return the preferred size of your widget.

type customWidget struct {
	text string

	tui.WidgetBase
}

func (w *customWidget) Draw(p *tui.Painter) {
	p.DrawText(0, 0, w.text)
}

func (w *customWidget) SizeHint() image.Point {
	return image.Pt(len(w.text), 1)
}
Clone this wiki locally