freya_components/
progressbar.rs

1use freya_core::prelude::*;
2use torin::size::Size;
3
4use crate::{
5    get_theme,
6    theming::component_themes::ProgressBarThemePartial,
7};
8
9/// ProgressBar component.
10///
11/// # Example
12///
13/// ```rust
14/// # use freya::prelude::*;
15/// fn app() -> impl IntoElement {
16///     ProgressBar::new(50.)
17/// }
18///
19/// # use freya_testing::prelude::*;
20/// # launch_doc(|| {
21/// #   rect().padding(8.).center().expanded().child(app())
22/// # }, "./images/gallery_progressbar.png").render();
23/// ```
24///
25/// # Preview
26/// ![Progressbar Preview][progressbar]
27#[cfg_attr(feature = "docs",
28    doc = embed_doc_image::embed_image!("progressbar", "images/gallery_progressbar.png")
29)]
30#[derive(Clone, PartialEq)]
31pub struct ProgressBar {
32    pub(crate) theme: Option<ProgressBarThemePartial>,
33    width: Size,
34    show_progress: bool,
35    progress: f32,
36    key: DiffKey,
37}
38
39impl KeyExt for ProgressBar {
40    fn write_key(&mut self) -> &mut DiffKey {
41        &mut self.key
42    }
43}
44
45impl ProgressBar {
46    pub fn new(progress: impl Into<f32>) -> Self {
47        Self {
48            width: Size::fill(),
49            theme: None,
50            show_progress: true,
51            progress: progress.into(),
52            key: DiffKey::None,
53        }
54    }
55
56    pub fn width(mut self, width: impl Into<Size>) -> Self {
57        self.width = width.into();
58        self
59    }
60
61    pub fn show_progress(mut self, show_progress: bool) -> Self {
62        self.show_progress = show_progress;
63        self
64    }
65}
66
67impl Component for ProgressBar {
68    fn render(&self) -> impl IntoElement {
69        let progressbar_theme = get_theme!(&self.theme, progressbar);
70
71        let progress = self.progress.clamp(0., 100.);
72
73        rect()
74            .a11y_alt(format!("Progress {progress}%"))
75            .a11y_focusable(true)
76            .a11y_role(AccessibilityRole::ProgressIndicator)
77            .horizontal()
78            .width(self.width.clone())
79            .height(Size::px(progressbar_theme.height))
80            .corner_radius(99.)
81            .background(progressbar_theme.background)
82            .border(
83                Border::new()
84                    .width(1.)
85                    .alignment(BorderAlignment::Outer)
86                    .fill(progressbar_theme.background),
87            )
88            .font_size(13.)
89            .child(
90                rect()
91                    .horizontal()
92                    .width(Size::percent(progress))
93                    .height(Size::fill())
94                    .corner_radius(99.)
95                    .background(progressbar_theme.progress_background)
96                    .child(
97                        label()
98                            .width(Size::fill())
99                            .color(progressbar_theme.color)
100                            .text_align(TextAlign::Center)
101                            .text(format!("{}%", self.progress))
102                            .max_lines(1),
103                    ),
104            )
105    }
106
107    fn render_key(&self) -> DiffKey {
108        self.key.clone().or(self.default_key())
109    }
110}