package main import ( "image" "image/color" "gioui.org/gesture" "gioui.org/io/event" "gioui.org/layout" "gioui.org/op/clip" "gioui.org/op/paint" "gioui.org/text" "gioui.org/unit" "gioui.org/widget/material" ) var ( black = color.NRGBA{A: 0xff, R: 0, G: 0, B: 0} white = color.NRGBA{A: 0xff, R: 0xff, G: 0xff, B: 0xff} gray = color.NRGBA{A: 0xff, R: 0xf0, G: 0xf0, B: 0xf0} darkgray = color.NRGBA{A: 0xff, R: 0xa0, G: 0xa0, B: 0xa0} ) type Overlay struct { Size unit.Sp Text string Click gesture.Click Color color.NRGBA Background color.NRGBA Alignment text.Alignment } func (b *Overlay) Layout(gtx C) D { ins := layout.UniformInset(unit.Dp(1)) return ins.Layout(gtx, func(gtx C) D { st := layout.Stack{} c2 := layout.Stacked(func(gtx C) D { l := material.Label(th, b.Size, b.Text) ins := layout.UniformInset(unit.Dp(4)) l.Color = b.Color return ins.Layout(gtx, func(gtx C) D { return l.Layout(gtx) }) }) c1 := layout.Expanded(func(gtx C) D { return layoutRRect(b.Background, gtx) }) return st.Layout(gtx, c1, c2) }) } type SelButton struct { Button SelColor color.NRGBA Selected bool } type Button struct { Size unit.Sp Label string Click gesture.Click Color color.NRGBA Background color.NRGBA Alignment text.Alignment clicked bool } func layoutRRect(col color.NRGBA, gtx C) D { r := gtx.Dp(4) sz := image.Point{X: gtx.Constraints.Min.X, Y: gtx.Constraints.Min.Y} // Push the rounded-rect clip, paint, then restore the previous clip. stk := clip.UniformRRect(image.Rectangle{Max: sz}, r).Push(gtx.Ops) paint.ColorOp{Color: col}.Add(gtx.Ops) paint.PaintOp{}.Add(gtx.Ops) stk.Pop() return layout.Dimensions{Size: sz} } func (b *Button) Layout(gtx C) D { mwidth := gtx.Constraints.Min.X b.clicked = false ins := layout.UniformInset(unit.Dp(1)) return ins.Layout(gtx, func(gtx C) D { st := layout.Stack{} c2 := layout.Stacked(func(gtx C) D { l := material.Label(th, b.Size, b.Label) l.Color = b.Color ins := layout.UniformInset(unit.Dp(4)) ret := ins.Layout(gtx, func(gtx C) D { return l.Layout(gtx) }) // Register the click handler for the label area. stk := clip.Rect(image.Rectangle{Max: ret.Size}).Push(gtx.Ops) event.Op(gtx.Ops, b) b.Click.Add(gtx.Ops) stk.Pop() for { ev, ok := b.Click.Update(gtx.Source) if !ok { break } if ev.Kind == gesture.KindClick { b.clicked = true } } return ret }) c1 := layout.Expanded(func(gtx C) D { gtx.Constraints.Min.X = mwidth return layoutRRect(b.Background, gtx) }) return st.Layout(gtx, c1, c2) }) } func (b *Button) Clicked() bool { return b.clicked } func (b *SelButton) Toggle() { b.Selected = !b.Selected b.SelColor, b.Background = b.Background, b.SelColor } func (b *SelButton) Select() { if !b.Selected { b.Toggle() } } func (b *SelButton) Deselect() { if b.Selected { b.Toggle() } } func (b *SelButton) Clicked() bool { if b.clicked { b.Toggle() return true } else { return false } }