diff options
Diffstat (limited to 'widget/src/progress_bar.rs')
-rw-r--r-- | widget/src/progress_bar.rs | 103 |
1 files changed, 64 insertions, 39 deletions
diff --git a/widget/src/progress_bar.rs b/widget/src/progress_bar.rs index 38d8da85..e7821b43 100644 --- a/widget/src/progress_bar.rs +++ b/widget/src/progress_bar.rs @@ -4,7 +4,8 @@ use crate::core::mouse; use crate::core::renderer; use crate::core::widget::Tree; use crate::core::{ - Background, Border, Element, Layout, Length, Rectangle, Size, Theme, Widget, + self, Background, Border, Element, Layout, Length, Rectangle, Size, Theme, + Widget, }; use std::ops::RangeInclusive; @@ -22,15 +23,21 @@ use std::ops::RangeInclusive; /// ///  #[allow(missing_debug_implementations)] -pub struct ProgressBar<'a, Theme = crate::Theme> { +pub struct ProgressBar<'a, Theme = crate::Theme> +where + Theme: Catalog, +{ range: RangeInclusive<f32>, value: f32, width: Length, height: Option<Length>, - style: Style<'a, Theme>, + class: Theme::Class<'a>, } -impl<'a, Theme> ProgressBar<'a, Theme> { +impl<'a, Theme> ProgressBar<'a, Theme> +where + Theme: Catalog, +{ /// The default height of a [`ProgressBar`]. pub const DEFAULT_HEIGHT: f32 = 30.0; @@ -39,16 +46,13 @@ impl<'a, Theme> ProgressBar<'a, Theme> { /// It expects: /// * an inclusive range of possible values /// * the current value of the [`ProgressBar`] - pub fn new(range: RangeInclusive<f32>, value: f32) -> Self - where - Theme: DefaultStyle + 'a, - { + pub fn new(range: RangeInclusive<f32>, value: f32) -> Self { ProgressBar { value: value.clamp(*range.start(), *range.end()), range, width: Length::Fill, height: None, - style: Box::new(Theme::default_style), + class: Theme::default(), } } @@ -65,8 +69,20 @@ impl<'a, Theme> ProgressBar<'a, Theme> { } /// Sets the style of the [`ProgressBar`]. - pub fn style(mut self, style: impl Fn(&Theme) -> Appearance + 'a) -> Self { - self.style = Box::new(style); + #[must_use] + pub fn style(mut self, style: impl Fn(&Theme) -> Style + 'a) -> Self + where + Theme::Class<'a>: From<StyleFn<'a, Theme>>, + { + self.class = (Box::new(style) as StyleFn<'a, Theme>).into(); + self + } + + /// Sets the style class of the [`ProgressBar`]. + #[cfg(feature = "advanced")] + #[must_use] + pub fn class(mut self, class: impl Into<Theme::Class<'a>>) -> Self { + self.class = class.into(); self } } @@ -74,7 +90,8 @@ impl<'a, Theme> ProgressBar<'a, Theme> { impl<'a, Message, Theme, Renderer> Widget<Message, Theme, Renderer> for ProgressBar<'a, Theme> where - Renderer: crate::core::Renderer, + Theme: Catalog, + Renderer: core::Renderer, { fn size(&self) -> Size<Length> { Size { @@ -116,15 +133,15 @@ where / (range_end - range_start) }; - let appearance = (self.style)(theme); + let style = theme.style(&self.class); renderer.fill_quad( renderer::Quad { bounds: Rectangle { ..bounds }, - border: appearance.border, + border: style.border, ..renderer::Quad::default() }, - appearance.background, + style.background, ); if active_progress_width > 0.0 { @@ -134,10 +151,10 @@ where width: active_progress_width, ..bounds }, - border: Border::rounded(appearance.border.radius), + border: Border::rounded(style.border.radius), ..renderer::Quad::default() }, - appearance.bar, + style.bar, ); } } @@ -147,8 +164,8 @@ impl<'a, Message, Theme, Renderer> From<ProgressBar<'a, Theme>> for Element<'a, Message, Theme, Renderer> where Message: 'a, - Theme: 'a, - Renderer: 'a + crate::core::Renderer, + Theme: 'a + Catalog, + Renderer: 'a + core::Renderer, { fn from( progress_bar: ProgressBar<'a, Theme>, @@ -159,7 +176,7 @@ where /// The appearance of a progress bar. #[derive(Debug, Clone, Copy)] -pub struct Appearance { +pub struct Style { /// The [`Background`] of the progress bar. pub background: Background, /// The [`Background`] of the bar of the progress bar. @@ -168,29 +185,37 @@ pub struct Appearance { pub border: Border, } -/// The style of a [`ProgressBar`]. -pub type Style<'a, Theme> = Box<dyn Fn(&Theme) -> Appearance + 'a>; +/// The theme catalog of a [`ProgressBar`]. +pub trait Catalog: Sized { + /// The item class of the [`Catalog`]. + type Class<'a>; + + /// The default class produced by the [`Catalog`]. + fn default<'a>() -> Self::Class<'a>; -/// The default style of a [`ProgressBar`]. -pub trait DefaultStyle { - /// Returns the default style of a [`ProgressBar`]. - fn default_style(&self) -> Appearance; + /// The [`Style`] of a class with the given status. + fn style(&self, class: &Self::Class<'_>) -> Style; } -impl DefaultStyle for Theme { - fn default_style(&self) -> Appearance { - primary(self) +/// A styling function for a [`ProgressBar`]. +/// +/// This is just a boxed closure: `Fn(&Theme, Status) -> Style`. +pub type StyleFn<'a, Theme> = Box<dyn Fn(&Theme) -> Style + 'a>; + +impl Catalog for Theme { + type Class<'a> = StyleFn<'a, Self>; + + fn default<'a>() -> Self::Class<'a> { + Box::new(primary) } -} -impl DefaultStyle for Appearance { - fn default_style(&self) -> Appearance { - *self + fn style(&self, class: &Self::Class<'_>) -> Style { + class(self) } } /// The primary style of a [`ProgressBar`]. -pub fn primary(theme: &Theme) -> Appearance { +pub fn primary(theme: &Theme) -> Style { let palette = theme.extended_palette(); styled( @@ -200,7 +225,7 @@ pub fn primary(theme: &Theme) -> Appearance { } /// The secondary style of a [`ProgressBar`]. -pub fn secondary(theme: &Theme) -> Appearance { +pub fn secondary(theme: &Theme) -> Style { let palette = theme.extended_palette(); styled( @@ -210,14 +235,14 @@ pub fn secondary(theme: &Theme) -> Appearance { } /// The success style of a [`ProgressBar`]. -pub fn success(theme: &Theme) -> Appearance { +pub fn success(theme: &Theme) -> Style { let palette = theme.extended_palette(); styled(palette.background.strong.color, palette.success.base.color) } /// The danger style of a [`ProgressBar`]. -pub fn danger(theme: &Theme) -> Appearance { +pub fn danger(theme: &Theme) -> Style { let palette = theme.extended_palette(); styled(palette.background.strong.color, palette.danger.base.color) @@ -226,8 +251,8 @@ pub fn danger(theme: &Theme) -> Appearance { fn styled( background: impl Into<Background>, bar: impl Into<Background>, -) -> Appearance { - Appearance { +) -> Style { + Style { background: background.into(), bar: bar.into(), border: Border::rounded(2), |