gioui.org@v0.6.1-0.20240506124620-7a9ce51988ce/widget/float.go (about) 1 // SPDX-License-Identifier: Unlicense OR MIT 2 3 package widget 4 5 import ( 6 "image" 7 8 "gioui.org/gesture" 9 "gioui.org/io/pointer" 10 "gioui.org/layout" 11 "gioui.org/op/clip" 12 "gioui.org/unit" 13 ) 14 15 // Float is for selecting a value in a range. 16 type Float struct { 17 // Value is the value of the Float, in the [0; 1] range. 18 Value float32 19 20 drag gesture.Drag 21 axis layout.Axis 22 length float32 23 } 24 25 // Dragging returns whether the value is being interacted with. 26 func (f *Float) Dragging() bool { return f.drag.Dragging() } 27 28 func (f *Float) Layout(gtx layout.Context, axis layout.Axis, pointerMargin unit.Dp) layout.Dimensions { 29 f.Update(gtx) 30 size := gtx.Constraints.Min 31 f.length = float32(axis.Convert(size).X) 32 f.axis = axis 33 34 margin := axis.Convert(image.Pt(gtx.Dp(pointerMargin), 0)) 35 rect := image.Rectangle{ 36 Min: margin.Mul(-1), 37 Max: size.Add(margin), 38 } 39 defer clip.Rect(rect).Push(gtx.Ops).Pop() 40 f.drag.Add(gtx.Ops) 41 42 return layout.Dimensions{Size: size} 43 } 44 45 // Update the Value according to drag events along the f's main axis. 46 // The return value reports whether the value was changed. 47 // 48 // The range of f is set by the minimum constraints main axis value. 49 func (f *Float) Update(gtx layout.Context) bool { 50 changed := false 51 for { 52 e, ok := f.drag.Update(gtx.Metric, gtx.Source, gesture.Axis(f.axis)) 53 if !ok { 54 break 55 } 56 if f.length > 0 && (e.Kind == pointer.Press || e.Kind == pointer.Drag) { 57 pos := e.Position.X 58 if f.axis == layout.Vertical { 59 pos = f.length - e.Position.Y 60 } 61 f.Value = pos / f.length 62 if f.Value < 0 { 63 f.Value = 0 64 } else if f.Value > 1 { 65 f.Value = 1 66 } 67 changed = true 68 } 69 } 70 return changed 71 }