Skip to main content

rlvgl_ui/
progress.rs

1// SPDX-License-Identifier: MIT
2//! Linear progress component for rlvgl-ui.
3//!
4//! [`Progress`] wraps [`rlvgl_widgets::progress::ProgressBar`] with a concise
5//! app-facing name and fluent value/color setters.
6
7use rlvgl_core::{
8    event::Event,
9    renderer::Renderer,
10    widget::{Color, Rect, Widget},
11};
12use rlvgl_widgets::progress::ProgressBar;
13
14use crate::theme::{ColorScheme, ComponentSize, Theme, Variant};
15
16/// Linear progress indicator.
17pub struct Progress {
18    inner: ProgressBar,
19}
20
21impl Progress {
22    /// Create a progress indicator with an inclusive value range.
23    pub fn new(bounds: Rect, min: i32, max: i32) -> Self {
24        Self {
25            inner: ProgressBar::new(bounds, min, max),
26        }
27    }
28
29    /// Set the current value and return the widget.
30    pub fn with_value(mut self, value: i32) -> Self {
31        self.inner.set_value(value);
32        self
33    }
34
35    /// Return the current progress value.
36    pub fn value(&self) -> i32 {
37        self.inner.value()
38    }
39
40    /// Set the current progress value.
41    pub fn set_value(&mut self, value: i32) {
42        self.inner.set_value(value);
43    }
44
45    /// Set the filled-track color and return the widget.
46    pub fn fill_color(mut self, color: Color) -> Self {
47        self.inner.bar_color = color;
48        self
49    }
50
51    /// Return the filled-track color.
52    pub fn fill_color_value(&self) -> Color {
53        self.inner.bar_color
54    }
55
56    /// Set the filled-track color.
57    pub fn set_fill_color(&mut self, color: Color) {
58        self.inner.bar_color = color;
59    }
60
61    /// Apply a themed style and fill color.
62    pub fn themed(
63        mut self,
64        theme: &Theme,
65        scheme: ColorScheme,
66        variant: Variant,
67        size: ComponentSize,
68    ) -> Self {
69        let resolved = theme.component_style(scheme, variant, size);
70        self.inner.style = resolved.style;
71        self.inner.bar_color = resolved.accent_color;
72        self
73    }
74
75    /// Immutable access to the progress style.
76    pub fn style(&self) -> &rlvgl_core::style::Style {
77        &self.inner.style
78    }
79
80    /// Mutable access to the progress style.
81    pub fn style_mut(&mut self) -> &mut rlvgl_core::style::Style {
82        &mut self.inner.style
83    }
84}
85
86impl Widget for Progress {
87    fn bounds(&self) -> Rect {
88        self.inner.bounds()
89    }
90
91    fn draw(&self, renderer: &mut dyn Renderer) {
92        self.inner.draw(renderer);
93    }
94
95    fn handle_event(&mut self, event: &Event) -> bool {
96        self.inner.handle_event(event)
97    }
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103
104    #[test]
105    fn progress_sets_value_and_fill_color() {
106        let mut progress = Progress::new(rect(0, 0, 100, 8), 0, 100)
107            .with_value(40)
108            .fill_color(Color(1, 2, 3, 255));
109
110        assert_eq!(progress.value(), 40);
111        assert_eq!(progress.fill_color_value(), Color(1, 2, 3, 255));
112        progress.set_value(150);
113        assert_eq!(progress.value(), 100);
114    }
115
116    #[test]
117    fn progress_themed_sets_style_and_fill() {
118        let theme = Theme::material_light();
119        let progress = Progress::new(rect(0, 0, 100, 8), 0, 100).themed(
120            &theme,
121            ColorScheme::Success,
122            Variant::Subtle,
123            ComponentSize::Sm,
124        );
125
126        assert_eq!(
127            progress.fill_color_value(),
128            theme.scheme(ColorScheme::Success).solid
129        );
130        assert_eq!(progress.style().radius, theme.tokens.radii.sm);
131    }
132
133    fn rect(x: i32, y: i32, width: i32, height: i32) -> Rect {
134        Rect {
135            x,
136            y,
137            width,
138            height,
139        }
140    }
141}