Files
prevara/indefinite.go
2025-11-30 16:45:22 +00:00

90 lines
2.0 KiB
Go

package gel
import (
"image"
"image/color"
"math"
"time"
"github.com/p9c/p9/pkg/gel/gio/f32"
l "github.com/p9c/p9/pkg/gel/gio/layout"
"github.com/p9c/p9/pkg/gel/gio/op"
"github.com/p9c/p9/pkg/gel/gio/op/clip"
"github.com/p9c/p9/pkg/gel/gio/op/paint"
"github.com/p9c/p9/pkg/gel/gio/unit"
)
type Indefinite struct {
*Window
color color.NRGBA
scale float32
}
// Indefinite creates an indefinite loading animation icon
func (w *Window) Indefinite() *Indefinite {
return &Indefinite{
Window: w,
color: w.Colors.GetNRGBAFromName("Primary"),
}
}
// Scale sets the size of the spinner
func (lo *Indefinite) Scale(scale float32) *Indefinite {
lo.scale = scale
return lo
}
// Color sets the color of the spinner
func (lo *Indefinite) Color(color string) *Indefinite {
lo.color = lo.Theme.Colors.GetNRGBAFromName(color)
return lo
}
// Fn renders the loader
func (lo *Indefinite) Fn(gtx l.Context) l.Dimensions {
diam := gtx.Constraints.Min.X
if minY := gtx.Constraints.Min.Y; minY > diam {
diam = minY
}
if diam == 0 {
diam = gtx.Sp(lo.Theme.TextSize * unit.Sp(lo.scale))
}
sz := gtx.Constraints.Constrain(image.Pt(diam, diam))
radius := float64(sz.X) * .5
defer op.Offset(image.Pt(int(radius), int(radius))).Push(gtx.Ops).Pop()
dt := (time.Duration(gtx.Now.UnixNano()) % (time.Second)).Seconds()
startAngle := dt * math.Pi * 2
endAngle := startAngle + math.Pi*1.5
defer clipLoader(gtx.Ops, startAngle, endAngle, radius).Pop()
paint.ColorOp{
Color: lo.color,
}.Add(gtx.Ops)
paint.PaintOp{}.Add(gtx.Ops)
gtx.Execute(op.InvalidateCmd{})
return l.Dimensions{
Size: sz,
}
}
func clipLoader(ops *op.Ops, startAngle, endAngle, radius float64) clip.Stack {
const thickness = .25
var (
width = float32(radius * thickness)
delta = float32(endAngle - startAngle)
vy, vx = math.Sincos(startAngle)
pen = f32.Pt(float32(vx), float32(vy)).Mul(float32(radius))
center = f32.Pt(0, 0).Sub(pen)
p clip.Path
)
p.Begin(ops)
p.Move(pen)
p.Arc(center, center, delta)
return clip.Stroke{
Path: p.End(),
Width: width,
}.Op().Push(ops)
}