kas_widgets/
progress.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License in the LICENSE-APACHE file or at:
4//     https://www.apache.org/licenses/LICENSE-2.0
5
6//! Progress bar
7
8use kas::prelude::*;
9use kas::theme::Feature;
10
11impl_scope! {
12    /// A progress bar
13    ///
14    /// The "progress" value may range from 0.0 to 1.0.
15    #[autoimpl(Debug ignore self.value_fn)]
16    #[widget]
17    pub struct ProgressBar<A, D: Directional = kas::dir::Right> {
18        core: widget_core!(),
19        direction: D,
20        value: f32,
21        value_fn: Box<dyn Fn(&ConfigCx, &A) -> f32>,
22    }
23
24    impl Self
25    where
26        D: Default,
27    {
28        /// Construct a slider
29        ///
30        /// Closure `value_fn` returns the current progress as a value between
31        /// 0.0 and 1.0.
32        #[inline]
33        pub fn new(value_fn: impl Fn(&ConfigCx, &A) -> f32 + 'static) -> Self {
34            Self::new_dir(value_fn, D::default())
35        }
36    }
37    impl<A> ProgressBar<A, kas::dir::Right> {
38        /// Construct a progress bar (horizontal)
39        ///
40        /// Closure `value_fn` returns the current progress as a value between
41        /// 0.0 and 1.0.
42        #[inline]
43        pub fn right(value_fn: impl Fn(&ConfigCx, &A) -> f32 + 'static) -> Self {
44            ProgressBar::new(value_fn)
45        }
46    }
47
48    impl Self {
49        /// Construct a slider with the given `direction`
50        ///
51        /// Closure `value_fn` returns the current progress as a value between
52        /// 0.0 and 1.0.
53        #[inline]
54        pub fn new_dir(value_fn: impl Fn(&ConfigCx, &A) -> f32 + 'static, direction: D) -> Self {
55            ProgressBar {
56                core: Default::default(),
57                direction,
58                value: 0.0,
59                value_fn: Box::new(value_fn),
60            }
61        }
62
63        /// Get the progress bar's direction
64        #[inline]
65        pub fn direction(&self) -> Direction {
66            self.direction.as_direction()
67        }
68    }
69
70    impl Layout for Self {
71        fn size_rules(&mut self, sizer: SizeCx, axis: AxisInfo) -> SizeRules {
72            sizer.feature(Feature::ProgressBar(self.direction()), axis)
73        }
74
75        fn set_rect(&mut self, cx: &mut ConfigCx, rect: Rect, hints: AlignHints) {
76            let align = match self.direction.is_vertical() {
77                false => AlignPair::new(Align::Stretch, hints.vert.unwrap_or(Align::Center)),
78                true => AlignPair::new(hints.horiz.unwrap_or(Align::Center), Align::Stretch),
79            };
80            let rect = cx.align_feature(Feature::ProgressBar(self.direction()), rect, align);
81            self.core.rect = rect;
82        }
83
84        fn draw(&mut self, mut draw: DrawCx) {
85            let dir = self.direction.as_direction();
86            draw.progress_bar(self.rect(), dir, self.value);
87        }
88    }
89
90    impl Events for Self {
91        type Data = A;
92
93        fn update(&mut self, cx: &mut ConfigCx, data: &A) {
94            let value = (self.value_fn)(cx, data);
95            self.value = value.clamp(0.0, 1.0);
96        }
97    }
98}