package ui import ( "image" "gioui.org/layout" "gioui.org/op/clip" "gioui.org/text" "gioui.org/widget/material" ) // Renderer consumes a slice of elements and draws them. type Renderer struct { theme Theme shp *text.Shaper } // New creates a new Renderer. func New(th Theme, shp *text.Shaper) *Renderer { return &Renderer{theme: th, shp: shp} } // Draw iterates elements and draws each in slice order (back-to-front). func (r *Renderer) Draw(gtx layout.Context, elems []Element) { for _, e := range elems { if !e.Visible() { continue } switch v := e.(type) { case Label: r.drawLabel(gtx, v) case ListView: r.drawListView(gtx, v) default: // unknown element type, skip } } } func (r *Renderer) drawLabel(gtx layout.Context, l Label) { reg := l.Region() c := clip.Rect{ Min: image.Point{X: int(reg.X), Y: int(reg.Y)}, Max: image.Point{X: int(reg.X + reg.W), Y: int(reg.Y + reg.H)}, }.Push(gtx.Ops) th := material.NewTheme() th.Shaper = r.shp size := l.FontSize if size == 0 { size = r.theme.FontSize } material.Label(th, size, l.Text).Layout(gtx) c.Pop() } func (r *Renderer) drawListView(gtx layout.Context, lv ListView) { reg := lv.Region() c := clip.Rect{ Min: image.Point{X: int(reg.X), Y: int(reg.Y)}, Max: image.Point{X: int(reg.X + reg.W), Y: int(reg.Y + reg.H)}, }.Push(gtx.Ops) th := material.NewTheme() th.Shaper = r.shp for _, item := range lv.Items { material.Label(th, r.theme.FontSize, item.Text).Layout(gtx) } c.Pop() }