use freya_animation::{
easing::Function,
hook::{
Ease,
use_animation_transition,
},
prelude::AnimNum,
};
use freya_core::prelude::*;
use torin::{
prelude::Alignment,
size::Size,
};
use crate::{
define_theme,
get_theme,
};
define_theme! {
%[component]
pub ProgressBar {
%[fields]
color: Color,
background: Color,
progress_background: Color,
height: f32,
}
}
#[cfg_attr(feature = "docs",
doc = embed_doc_image::embed_image!("progressbar", "images/gallery_progressbar.png")
)]
#[derive(Clone, PartialEq)]
pub struct ProgressBar {
pub(crate) theme: Option<ProgressBarThemePartial>,
width: Size,
show_progress: bool,
progress: f32,
key: DiffKey,
}
impl KeyExt for ProgressBar {
fn write_key(&mut self) -> &mut DiffKey {
&mut self.key
}
}
impl ProgressBar {
pub fn new(progress: impl Into<f32>) -> Self {
Self {
width: Size::fill(),
theme: None,
show_progress: true,
progress: progress.into(),
key: DiffKey::None,
}
}
pub fn width(mut self, width: impl Into<Size>) -> Self {
self.width = width.into();
self
}
pub fn show_progress(mut self, show_progress: bool) -> Self {
self.show_progress = show_progress;
self
}
}
impl Component for ProgressBar {
fn render(&self) -> impl IntoElement {
let progressbar_theme = get_theme!(&self.theme, ProgressBarThemePreference, "progressbar");
let progress = use_reactive(&self.progress.clamp(0., 100.));
let animation = use_animation_transition(progress, |from, to| {
AnimNum::new(from, to)
.time(500)
.ease(Ease::Out)
.function(Function::Expo)
});
rect()
.a11y_alt(format!("Progress {}%", progress()))
.a11y_focusable(true)
.a11y_role(AccessibilityRole::ProgressIndicator)
.horizontal()
.width(self.width.clone())
.height(Size::px(progressbar_theme.height))
.corner_radius(99.)
.overflow(Overflow::Clip)
.background(progressbar_theme.background)
.border(
Border::new()
.width(1.)
.alignment(BorderAlignment::Outer)
.fill(progressbar_theme.background),
)
.font_size(13.)
.child(
rect()
.horizontal()
.width(Size::percent(&*animation.read()))
.cross_align(Alignment::Center)
.height(Size::fill())
.corner_radius(99.)
.background(progressbar_theme.progress_background)
.maybe(self.show_progress, |el| {
el.child(
label()
.width(Size::fill())
.color(progressbar_theme.color)
.text_align(TextAlign::Center)
.text(format!("{}%", self.progress))
.max_lines(1),
)
}),
)
}
fn render_key(&self) -> DiffKey {
self.key.clone().or(self.default_key())
}
}