freya_components/
progressbar.rs1use freya_animation::{
2 easing::Function,
3 hook::{
4 Ease,
5 use_animation_transition,
6 },
7 prelude::AnimNum,
8};
9use freya_core::prelude::*;
10use torin::{
11 prelude::Alignment,
12 size::Size,
13};
14
15use crate::{
16 define_theme,
17 get_theme,
18};
19
20define_theme! {
21 %[component]
22 pub ProgressBar {
23 %[fields]
24 color: Color,
25 background: Color,
26 progress_background: Color,
27 height: f32,
28 }
29}
30
31#[derive(Clone, PartialEq)]
44pub struct ProgressBar {
45 pub(crate) theme: Option<ProgressBarThemePartial>,
46 width: Size,
47 show_progress: bool,
48 progress: f32,
49 key: DiffKey,
50}
51
52impl KeyExt for ProgressBar {
53 fn key_mut(&mut self) -> &mut DiffKey {
54 &mut self.key
55 }
56}
57
58impl ProgressBar {
59 pub fn new(progress: f32) -> Self {
60 Self {
61 width: Size::fill(),
62 theme: None,
63 show_progress: true,
64 progress,
65 key: DiffKey::None,
66 }
67 }
68
69 pub fn width(mut self, width: impl Into<Size>) -> Self {
70 self.width = width.into();
71 self
72 }
73
74 pub fn show_progress(mut self, show_progress: bool) -> Self {
78 self.show_progress = show_progress;
79 self
80 }
81}
82
83impl Component for ProgressBar {
84 fn render(&self) -> impl IntoElement {
85 let progressbar_theme = get_theme!(&self.theme, ProgressBarThemePreference, "progressbar");
86
87 let progress = use_reactive(&self.progress.clamp(0., 100.));
88 let animation = use_animation_transition(progress, |from, to| {
89 AnimNum::new(from, to)
90 .time(500)
91 .ease(Ease::Out)
92 .function(Function::Expo)
93 });
94
95 rect()
96 .a11y_alt(format!("Progress {:.2}%", self.progress))
97 .a11y_focusable(true)
98 .a11y_role(AccessibilityRole::ProgressIndicator)
99 .horizontal()
100 .width(self.width.clone())
101 .height(Size::px(progressbar_theme.height))
102 .corner_radius(99.)
103 .overflow(Overflow::Clip)
104 .background(progressbar_theme.background)
105 .border(
106 Border::new()
107 .width(1.)
108 .alignment(BorderAlignment::Outer)
109 .fill(progressbar_theme.background),
110 )
111 .font_size(13.)
112 .child(
113 rect()
114 .horizontal()
115 .width(Size::percent(animation.read().value()))
116 .cross_align(Alignment::Center)
117 .height(Size::fill())
118 .corner_radius(99.)
119 .background(progressbar_theme.progress_background)
120 .maybe(self.show_progress, |el| {
121 el.child(
122 label()
123 .width(Size::fill())
124 .color(progressbar_theme.color)
125 .text_align(TextAlign::Center)
126 .text(format!("{:.2}%", self.progress))
127 .max_lines(1),
128 )
129 }),
130 )
131 }
132
133 fn render_key(&self) -> DiffKey {
134 self.key.clone().or(self.default_key())
135 }
136}