Files
prevara/gio/widget/float.go
2025-11-30 16:45:22 +00:00

72 lines
1.7 KiB
Go

// SPDX-License-Identifier: Unlicense OR MIT
package widget
import (
"image"
"github.com/p9c/p9/pkg/gel/gio/gesture"
"github.com/p9c/p9/pkg/gel/gio/io/pointer"
"github.com/p9c/p9/pkg/gel/gio/layout"
"github.com/p9c/p9/pkg/gel/gio/op/clip"
"github.com/p9c/p9/pkg/gel/gio/unit"
)
// Float is for selecting a value in a range.
type Float struct {
// Value is the value of the Float, in the [0; 1] range.
Value float32
drag gesture.Drag
axis layout.Axis
length float32
}
// Dragging returns whether the value is being interacted with.
func (f *Float) Dragging() bool { return f.drag.Dragging() }
func (f *Float) Layout(gtx layout.Context, axis layout.Axis, pointerMargin unit.Dp) layout.Dimensions {
f.Update(gtx)
size := gtx.Constraints.Min
f.length = float32(axis.Convert(size).X)
f.axis = axis
margin := axis.Convert(image.Pt(gtx.Dp(pointerMargin), 0))
rect := image.Rectangle{
Min: margin.Mul(-1),
Max: size.Add(margin),
}
defer clip.Rect(rect).Push(gtx.Ops).Pop()
f.drag.Add(gtx.Ops)
return layout.Dimensions{Size: size}
}
// Update the Value according to drag events along the f's main axis.
// The return value reports whether the value was changed.
//
// The range of f is set by the minimum constraints main axis value.
func (f *Float) Update(gtx layout.Context) bool {
changed := false
for {
e, ok := f.drag.Update(gtx.Metric, gtx.Source, gesture.Axis(f.axis))
if !ok {
break
}
if f.length > 0 && (e.Kind == pointer.Press || e.Kind == pointer.Drag) {
pos := e.Position.X
if f.axis == layout.Vertical {
pos = f.length - e.Position.Y
}
f.Value = pos / f.length
if f.Value < 0 {
f.Value = 0
} else if f.Value > 1 {
f.Value = 1
}
changed = true
}
}
return changed
}