mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
a63e0cb44a
op.Offset is a convenience function most often used by layouts. Layouts usually operate in integer coordinates, and the float32 version of op.Offset needlessly force conversions from int to float32. This change makes op.Offset take integer coordinates, to better match its intended use. Signed-off-by: Elias Naur <mail@eliasnaur.com>
81 lines
1.6 KiB
Go
81 lines
1.6 KiB
Go
// SPDX-License-Identifier: Unlicense OR MIT
|
|
|
|
package material
|
|
|
|
import (
|
|
"image"
|
|
"image/color"
|
|
"math"
|
|
"time"
|
|
|
|
"gioui.org/f32"
|
|
"gioui.org/layout"
|
|
"gioui.org/op"
|
|
"gioui.org/op/clip"
|
|
"gioui.org/op/paint"
|
|
"gioui.org/unit"
|
|
)
|
|
|
|
type LoaderStyle struct {
|
|
Color color.NRGBA
|
|
}
|
|
|
|
func Loader(th *Theme) LoaderStyle {
|
|
return LoaderStyle{
|
|
Color: th.Palette.ContrastBg,
|
|
}
|
|
}
|
|
|
|
func (l LoaderStyle) Layout(gtx layout.Context) layout.Dimensions {
|
|
diam := gtx.Constraints.Min.X
|
|
if minY := gtx.Constraints.Min.Y; minY > diam {
|
|
diam = minY
|
|
}
|
|
if diam == 0 {
|
|
diam = gtx.Px(unit.Dp(24))
|
|
}
|
|
sz := gtx.Constraints.Constrain(image.Pt(diam, diam))
|
|
radius := sz.X / 2
|
|
defer op.Offset(image.Pt(radius, radius)).Push(gtx.Ops).Pop()
|
|
|
|
dt := float32((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, float32(radius)).Push(gtx.Ops).Pop()
|
|
paint.ColorOp{
|
|
Color: l.Color,
|
|
}.Add(gtx.Ops)
|
|
defer op.Offset(image.Pt(-radius, -radius)).Push(gtx.Ops).Pop()
|
|
paint.PaintOp{}.Add(gtx.Ops)
|
|
op.InvalidateOp{}.Add(gtx.Ops)
|
|
return layout.Dimensions{
|
|
Size: sz,
|
|
}
|
|
}
|
|
|
|
func clipLoader(ops *op.Ops, startAngle, endAngle, radius float32) clip.Op {
|
|
const thickness = .25
|
|
|
|
var (
|
|
width = radius * thickness
|
|
delta = endAngle - startAngle
|
|
|
|
vy, vx = math.Sincos(float64(startAngle))
|
|
|
|
inner = radius * (1. - thickness*.5)
|
|
pen = f32.Pt(float32(vx), float32(vy)).Mul(inner)
|
|
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()
|
|
}
|