90 lines
2.0 KiB
Go
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)
|
|
}
|