Files
sointu/tracker/gioui/popup.go
2025-06-24 20:25:52 +03:00

100 lines
2.0 KiB
Go

package gioui
import (
"image"
"image/color"
"gioui.org/io/event"
"gioui.org/io/pointer"
"gioui.org/layout"
"gioui.org/op"
"gioui.org/op/clip"
"gioui.org/op/paint"
"gioui.org/unit"
)
type (
PopupStyle struct {
Color color.NRGBA
CornerRadii struct {
SE, SW, NW, NE unit.Dp
}
Shadow struct {
Color color.NRGBA
N, E, W, S unit.Dp
}
}
PopupWidget struct {
Style *PopupStyle
Visible *bool
}
)
func Popup(th *Theme, visible *bool) PopupWidget {
return PopupWidget{
Style: &th.Popup.Dialog,
Visible: visible,
}
}
func (s PopupWidget) Layout(gtx C, contents layout.Widget) D {
s.update(gtx)
if !*s.Visible {
return D{}
}
bg := func(gtx C) D {
rrect := clip.RRect{
Rect: image.Rectangle{Max: gtx.Constraints.Min},
SE: gtx.Dp(s.Style.CornerRadii.SE),
SW: gtx.Dp(s.Style.CornerRadii.SW),
NW: gtx.Dp(s.Style.CornerRadii.NW),
NE: gtx.Dp(s.Style.CornerRadii.NE),
}
rrect2 := rrect
rrect2.Rect.Min = rrect2.Rect.Min.Sub(image.Pt(gtx.Dp(s.Style.Shadow.W), gtx.Dp(s.Style.Shadow.N)))
rrect2.Rect.Max = rrect2.Rect.Max.Add(image.Pt(gtx.Dp(s.Style.Shadow.E), gtx.Dp(s.Style.Shadow.S)))
paint.FillShape(gtx.Ops, s.Style.Shadow.Color, rrect2.Op(gtx.Ops))
paint.FillShape(gtx.Ops, s.Style.Color, rrect.Op(gtx.Ops))
area := clip.Rect(image.Rect(-1e6, -1e6, 1e6, 1e6)).Push(gtx.Ops)
event.Op(gtx.Ops, s.Visible)
area.Pop()
area = clip.Rect(rrect2.Rect).Push(gtx.Ops)
event.Op(gtx.Ops, &dummyTag)
area.Pop()
return D{Size: gtx.Constraints.Min}
}
macro := op.Record(gtx.Ops)
dims := layout.Stack{}.Layout(gtx,
layout.Expanded(bg),
layout.Stacked(contents),
)
callop := macro.Stop()
op.Defer(gtx.Ops, callop)
return dims
}
func (s *PopupWidget) update(gtx C) {
for {
event, ok := gtx.Event(pointer.Filter{
Target: s.Visible,
Kinds: pointer.Press,
})
if !ok {
break
}
e, ok := event.(pointer.Event)
if !ok {
continue
}
switch e.Kind {
case pointer.Press:
*s.Visible = false
}
}
}
var dummyTag bool