1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use crate::*;
const SLIDER_WIDTH: f32 = 4.0;
const SLIDER_THUMB_RADIUS: f32 = 10.0;
#[derive(Clone, Copy)]
pub struct SliderOptions {
thumb: Color,
}
impl Default for SliderOptions {
fn default() -> Self {
Self {
thumb: AZURE_HIGHLIGHT,
}
}
}
pub trait SliderMods: View + Sized {
fn thumb_color(self, color: Color) -> Self;
}
pub fn hslider(value: impl Binding<f32>) -> impl SliderMods {
modview(move |opts: SliderOptions, _| {
state(
|| 0.0,
move |width, cx| {
let w = cx[width];
let v = value.get(cx);
let r = SLIDER_THUMB_RADIUS;
let start_x = r;
let end_x = w - r;
let x = (1.0 - v) * start_x + v * (end_x);
canvas(move |_, sz, vger| {
let c = sz.center();
let paint = vger.color_paint(BUTTON_BACKGROUND_COLOR);
vger.fill_rect(
euclid::rect(
start_x,
c.y - SLIDER_WIDTH / 2.0,
sz.size.width - 2.0 * r,
SLIDER_WIDTH,
),
0.0,
paint,
);
let paint = vger.color_paint(AZURE_HIGHLIGHT_BACKGROUND);
vger.fill_rect(
euclid::rect(start_x, c.y - SLIDER_WIDTH / 2.0, x, SLIDER_WIDTH),
0.0,
paint,
);
let paint = vger.color_paint(opts.thumb);
vger.fill_circle([x, c.y], r, paint);
})
.geom(move |cx, sz| {
if sz.width != w {
cx[width] = sz.width;
}
})
.drag(move |cx, off, _state, _mouse_button| {
value.with_mut(cx, |v| *v = (*v + off.x / w).clamp(0.0, 1.0));
})
},
)
.role(accesskit::Role::Slider)
})
}
impl<F> SliderMods for ModView<SliderOptions, F>
where
ModView<SliderOptions, F>: View,
{
fn thumb_color(self, color: Color) -> Self {
let mut opts = self.value;
opts.thumb = color;
ModView {
func: self.func,
value: opts,
}
}
}
pub fn vslider(
value: f32,
set_value: impl Fn(&mut Context, f32) + 'static + Copy,
) -> impl SliderMods {
modview(move |opts: SliderOptions, _| {
state(
|| 0.0,
move |height, cx| {
let h = cx[height];
let y = value * h;
canvas(move |_, sz, vger| {
let c = sz.center();
let paint = vger.color_paint(BUTTON_BACKGROUND_COLOR);
vger.fill_rect(
euclid::rect(c.x - SLIDER_WIDTH / 2.0, 0.0, SLIDER_WIDTH, sz.height()),
0.0,
paint,
);
let paint = vger.color_paint(opts.thumb);
vger.fill_circle([c.x, y], SLIDER_THUMB_RADIUS, paint);
})
.geom(move |cx, sz| {
if sz.height != h {
cx[height] = sz.height;
}
})
.drag(move |cx, off, _state, _mouse_button| {
(set_value)(cx, (value + off.y / h).clamp(0.0, 1.0));
})
},
)
})
}