Files
prevara/toast/toast.go_

147 lines
3.9 KiB
Plaintext

package toast
import (
"image"
"image/color"
"git.mleku.dev/mleku/prevara/gio/f32"
l "git.mleku.dev/mleku/prevara/gio/layout"
"git.mleku.dev/mleku/prevara/gio/op"
"git.mleku.dev/mleku/prevara/gio/op/clip"
"git.mleku.dev/mleku/prevara/gio/op/paint"
"git.mleku.dev/mleku/prevara/gio/unit"
icons2 "golang.org/x/exp/shiny/materialdesign/icons"
"github.com/p9c/p9/pkg/gui"
"github.com/p9c/p9/pkg/gui/shadow"
)
type Toasts struct {
toasts []toast
layout *gui.List
theme *gui.Theme
offset image.Point
duration int
singleSize image.Point
singleCornerRadius unit.Value
singleElevation unit.Value
}
type toast struct {
title, content, level string
headerBackground color.NRGBA
bodyBackground color.NRGBA
icon *[]byte
ticker float32
close gui.Clickable
cornerRadius unit.Value
elevation unit.Value
}
func New(th *gui.Theme) *Toasts {
return &Toasts{
layout: th.List(),
theme: th,
duration: 100,
singleSize: image.Pt(300, 80),
singleCornerRadius: unit.Dp(5),
singleElevation: unit.Dp(5),
}
}
func (t *Toasts) AddToast(title, content, level string) {
ic := &icons2.ActionInfo
switch level {
case "Warning":
ic = &icons2.AlertWarning
case "Success":
ic = &icons2.NavigationCheck
case "Danger":
ic = &icons2.AlertError
case "Info":
ic = &icons2.ActionInfo
}
t.toasts = append(
t.toasts, toast{
title: title,
content: content,
level: level,
ticker: 0,
headerBackground: gui.HexNRGB(t.theme.Colors[level]),
bodyBackground: gui.HexNRGB(t.theme.Colors["PanelBg"]),
cornerRadius: t.singleCornerRadius,
elevation: t.singleElevation,
icon: ic,
},
)
}
func (t *Toasts) DrawToasts() func(gtx l.Context) {
return func(gtx l.Context) {
defer op.Push(gtx.Ops).Pop()
op.Offset(f32.Pt(float32(gtx.Constraints.Max.X)-310, 0)).Add(gtx.Ops)
gtx.Constraints.Min = image.Pt(250, gtx.Constraints.Min.Y)
gtx.Constraints.Max.X = 250
// paint.Fill(gtx.Ops, helper.HexARGB("ff559988"))
t.theme.Inset(
0,
t.layout.Vertical().ScrollToEnd().Length(len(t.toasts)).ListElement(t.singleToast).Fn,
).Fn(gtx)
}
}
func (t *Toasts) singleToast(gtx l.Context, index int) l.Dimensions {
if t.toasts[index].ticker < float32(t.duration) {
t.toasts[index].ticker += 1
gtx.Constraints.Min = t.singleSize
// gtx.Constraints.Max = t.singleSize
gtx.Constraints.Max.X = t.singleSize.X
sz := gtx.Constraints.Min
rr := float32(gtx.Px(t.singleCornerRadius))
r := f32.Rect(0, 0, float32(sz.X), float32(sz.Y))
return t.theme.Inset(
0.05, func(gtx l.Context) l.Dimensions {
return shadow.Shadow(
gtx, unit.Dp(3), unit.Dp(1), gui.HexNRGB("ee000000"), t.theme.Flex().Flexed(
1,
func(gtx l.Context) l.Dimensions {
clip.UniformRRect(r, rr).Add(gtx.Ops)
paint.Fill(gtx.Ops, t.toasts[index].bodyBackground)
return t.theme.Inset(
0.25,
t.theme.VFlex().
Rigid(
t.theme.Inset(
0.1,
t.theme.Fill(t.toasts[index].level, t.theme.Flex().
Rigid(
func(gtx l.Context) l.Dimensions {
return t.theme.Icon().Color("DocText").Scale(1).Src(t.toasts[index].icon).Fn(gtx)
},
).
Flexed(
1,
t.theme.H6(t.toasts[index].title).Color("PanelBg").Fn,
).Fn, l.Center).Fn,
).Fn,
).
Rigid(
t.theme.Body1(t.toasts[index].content).Color("PanelText").Fn,
).Fn,
).Fn(gtx)
},
).Fn,
)
},
).Fn(gtx)
} else {
t.toasts = remove(t.toasts, index)
return gui.EmptySpace(0, 0)(gtx)
}
}
func remove(slice []toast, s int) []toast {
return append(slice[:s], slice[s+1:]...)
}