slider.go raw
1 package gel
2
3 import (
4 "image"
5 "image/color"
6
7 "github.com/p9c/gio/f32"
8 l "github.com/p9c/gio/layout"
9 "github.com/p9c/gio/op"
10 "github.com/p9c/gio/op/clip"
11 "github.com/p9c/gio/op/paint"
12 "github.com/p9c/gio/unit"
13
14 "github.com/p9c/gel/f32color"
15 )
16
17 type Slider struct {
18 *Window
19 min, max float32
20 color color.NRGBA
21 float *Float
22 }
23
24 // Slider is for selecting a value in a range.
25 func (w *Window) Slider() *Slider {
26 return &Slider{
27 Window: w,
28 color: w.Colors.GetNRGBAFromName("Primary"),
29 }
30 }
31
32 // Min sets the value at the left hand side
33 func (s *Slider) Min(min float32) *Slider {
34 s.min = min
35 return s
36 }
37
38 // Max sets the value at the right hand side
39 func (s *Slider) Max(max float32) *Slider {
40 s.max = max
41 return s
42 }
43
44 // Color sets the color to draw the slider in
45 func (s *Slider) Color(color string) *Slider {
46 s.color = s.Theme.Colors.GetNRGBAFromName(color)
47 return s
48 }
49
50 // Float sets the initial value
51 func (s *Slider) Float(f *Float) *Slider {
52 s.float = f
53 return s
54 }
55
56 // Fn renders the slider
57 func (s *Slider) Fn(gtx l.Context) l.Dimensions {
58 thumbRadiusInt := gtx.Px(unit.Dp(6))
59 trackWidth := float32(gtx.Px(unit.Dp(2)))
60 thumbRadius := float32(thumbRadiusInt)
61 halfWidthInt := 2 * thumbRadiusInt
62 halfWidth := float32(halfWidthInt)
63
64 size := gtx.Constraints.Min
65 // Keep a minimum length so that the track is always visible.
66 minLength := halfWidthInt + 3*thumbRadiusInt + halfWidthInt
67 if size.X < minLength {
68 size.X = minLength
69 }
70 size.Y = 2 * halfWidthInt
71
72 st := op.Save(gtx.Ops)
73 op.Offset(f32.Pt(halfWidth, 0)).Add(gtx.Ops)
74 gtx.Constraints.Min = image.Pt(size.X-2*halfWidthInt, size.Y)
75 s.float.Fn(gtx, halfWidthInt, s.min, s.max)
76 thumbPos := halfWidth + s.float.Pos()
77 st.Load()
78
79 col := s.color
80 if gtx.Queue == nil {
81 col = f32color.MulAlpha(col, 150)
82 }
83
84 // Draw track before thumb.
85 st = op.Save(gtx.Ops)
86 track := f32.Rectangle{
87 Min: f32.Point{
88 X: halfWidth,
89 Y: halfWidth - trackWidth/2,
90 },
91 Max: f32.Point{
92 X: thumbPos,
93 Y: halfWidth + trackWidth/2,
94 },
95 }
96 clip.RRect{Rect: track}.Add(gtx.Ops)
97 paint.ColorOp{Color: col}.Add(gtx.Ops)
98 paint.PaintOp{}.Add(gtx.Ops)
99 st.Load()
100
101 // Draw track after thumb.
102 st = op.Save(gtx.Ops)
103 track.Min.X = thumbPos
104 track.Max.X = float32(size.X) - halfWidth
105 clip.RRect{Rect: track}.Add(gtx.Ops)
106 paint.ColorOp{Color: f32color.MulAlpha(col, 96)}.Add(gtx.Ops)
107 paint.PaintOp{}.Add(gtx.Ops)
108 st.Load()
109
110 // Draw thumb.
111 st = op.Save(gtx.Ops)
112 thumb := f32.Rectangle{
113 Min: f32.Point{
114 X: thumbPos - thumbRadius,
115 Y: halfWidth - thumbRadius,
116 },
117 Max: f32.Point{
118 X: thumbPos + thumbRadius,
119 Y: halfWidth + thumbRadius,
120 },
121 }
122 rr := thumbRadius
123 clip.RRect{
124 Rect: thumb,
125 NE: rr, NW: rr, SE: rr, SW: rr,
126 }.Add(gtx.Ops)
127 paint.ColorOp{Color: col}.Add(gtx.Ops)
128 paint.PaintOp{}.Add(gtx.Ops)
129 st.Load()
130
131 return l.Dimensions{Size: size}
132 }
133