diff options
Diffstat (limited to 'web')
| -rw-r--r-- | web/src/widget.rs | 2 | ||||
| -rw-r--r-- | web/src/widget/progress_bar.rs | 125 | 
2 files changed, 127 insertions, 0 deletions
| diff --git a/web/src/widget.rs b/web/src/widget.rs index e5481243..025cf22f 100644 --- a/web/src/widget.rs +++ b/web/src/widget.rs @@ -21,6 +21,7 @@ pub mod button;  pub mod checkbox;  pub mod container;  pub mod image; +pub mod progress_bar;  pub mod radio;  pub mod scrollable;  pub mod slider; @@ -46,6 +47,7 @@ pub use checkbox::Checkbox;  pub use column::Column;  pub use container::Container;  pub use image::Image; +pub use progress_bar::ProgressBar;  pub use radio::Radio;  pub use row::Row;  pub use space::Space; diff --git a/web/src/widget/progress_bar.rs b/web/src/widget/progress_bar.rs new file mode 100644 index 00000000..b1fcb4d8 --- /dev/null +++ b/web/src/widget/progress_bar.rs @@ -0,0 +1,125 @@ +//! Provide progress feedback to your users. +use crate::{bumpalo, css, Bus, Css, Element, Length, Widget}; + +pub use iced_style::progress_bar::{Style, StyleSheet}; + +use std::ops::RangeInclusive; + +/// A bar that displays progress. +/// +/// # Example +/// ``` +/// # use iced_native::renderer::Null; +/// # +/// # pub type ProgressBar = iced_native::ProgressBar<Null>; +/// let value = 50.0; +/// +/// ProgressBar::new(0.0..=100.0, value); +/// ``` +/// +///  +#[allow(missing_debug_implementations)] +pub struct ProgressBar { +    range: RangeInclusive<f32>, +    value: f32, +    width: Length, +    height: Option<Length>, +    style: Box<dyn StyleSheet>, +} + +impl ProgressBar { +    /// Creates a new [`ProgressBar`]. +    /// +    /// It expects: +    ///   * an inclusive range of possible values +    ///   * the current value of the [`ProgressBar`] +    /// +    /// [`ProgressBar`]: struct.ProgressBar.html +    pub fn new(range: RangeInclusive<f32>, value: f32) -> Self { +        ProgressBar { +            value: value.max(*range.start()).min(*range.end()), +            range, +            width: Length::Fill, +            height: None, +            style: Default::default(), +        } +    } + +    /// Sets the width of the [`ProgressBar`]. +    /// +    /// [`ProgressBar`]: struct.ProgressBar.html +    pub fn width(mut self, width: Length) -> Self { +        self.width = width; +        self +    } + +    /// Sets the height of the [`ProgressBar`]. +    /// +    /// [`ProgressBar`]: struct.ProgressBar.html +    pub fn height(mut self, height: Length) -> Self { +        self.height = Some(height); +        self +    } + +    /// Sets the style of the [`ProgressBar`]. +    /// +    /// [`ProgressBar`]: struct.ProgressBar.html +    pub fn style(mut self, style: impl Into<Box<dyn StyleSheet>>) -> Self { +        self.style = style.into(); +        self +    } +} + +impl<Message> Widget<Message> for ProgressBar { +    fn node<'b>( +        &self, +        bump: &'b bumpalo::Bump, +        _bus: &Bus<Message>, +        _style_sheet: &mut Css<'b>, +    ) -> dodrio::Node<'b> { +        use dodrio::builder::*; + +        let (range_start, range_end) = self.range.clone().into_inner(); +        let amount_filled = +            (self.value - range_start) / (range_end - range_start).max(1.0); + +        let style = self.style.style(); + +        let bar = div(bump) +            .attr( +                "style", +                bumpalo::format!( +                    in bump, +                    "width: {}%; height: 100%; background: {}", +                    amount_filled * 100.0, +                    css::background(style.bar) +                ) +                .into_bump_str(), +            ) +            .finish(); + +        let node = div(bump).attr( +            "style", +            bumpalo::format!( +                in bump, +                "width: {}; height: {}; background: {}; border-radius: {}px; overflow: hidden;", +                css::length(self.width), +                css::length(self.height.unwrap_or(Length::Units(30))), +                css::background(style.background), +                style.border_radius +            ) +            .into_bump_str(), +        ).children(vec![bar]); + +        node.finish() +    } +} + +impl<'a, Message> From<ProgressBar> for Element<'a, Message> +where +    Message: 'static, +{ +    fn from(container: ProgressBar) -> Element<'a, Message> { +        Element::new(container) +    } +} | 
