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
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License in the LICENSE-APACHE file or at:
// https://www.apache.org/licenses/LICENSE-2.0
//! Progress bar
use kas::prelude::*;
use kas::theme::Feature;
impl_scope! {
/// A progress bar
///
/// The "progress" value may range from 0.0 to 1.0.
#[autoimpl(Debug ignore self.value_fn)]
#[widget]
pub struct ProgressBar<A, D: Directional = kas::dir::Right> {
core: widget_core!(),
align: AlignPair,
direction: D,
value: f32,
value_fn: Box<dyn Fn(&ConfigCx, &A) -> f32>,
}
impl Self
where
D: Default,
{
/// Construct a slider
///
/// Closure `value_fn` returns the current progress as a value between
/// 0.0 and 1.0.
#[inline]
pub fn new(value_fn: impl Fn(&ConfigCx, &A) -> f32 + 'static) -> Self {
Self::new_dir(value_fn, D::default())
}
}
impl<A> ProgressBar<A, kas::dir::Right> {
/// Construct a progress bar (horizontal)
///
/// Closure `value_fn` returns the current progress as a value between
/// 0.0 and 1.0.
#[inline]
pub fn right(value_fn: impl Fn(&ConfigCx, &A) -> f32 + 'static) -> Self {
ProgressBar::new(value_fn)
}
}
impl Self {
/// Construct a slider with the given `direction`
///
/// Closure `value_fn` returns the current progress as a value between
/// 0.0 and 1.0.
#[inline]
pub fn new_dir(value_fn: impl Fn(&ConfigCx, &A) -> f32 + 'static, direction: D) -> Self {
ProgressBar {
core: Default::default(),
align: Default::default(),
direction,
value: 0.0,
value_fn: Box::new(value_fn),
}
}
/// Get the progress bar's direction
#[inline]
pub fn direction(&self) -> Direction {
self.direction.as_direction()
}
}
impl Layout for Self {
fn size_rules(&mut self, sizer: SizeCx, axis: AxisInfo) -> SizeRules {
self.align.set_component(
axis,
match axis.is_vertical() == self.direction.is_vertical() {
false => axis.align_or_center(),
true => axis.align_or_stretch(),
},
);
sizer.feature(Feature::ProgressBar(self.direction()), axis)
}
fn set_rect(&mut self, cx: &mut ConfigCx, rect: Rect) {
let rect = cx.align_feature(Feature::ProgressBar(self.direction()), rect, self.align);
self.core.rect = rect;
}
fn draw(&mut self, mut draw: DrawCx) {
let dir = self.direction.as_direction();
draw.progress_bar(self.rect(), dir, self.value);
}
}
impl Events for Self {
type Data = A;
fn update(&mut self, cx: &mut ConfigCx, data: &A) {
let value = (self.value_fn)(cx, data);
self.value = value.clamp(0.0, 1.0);
}
}
}