Implement ProgressBar widget in iced_web

This commit is contained in:
Héctor Ramón Jiménez 2020-02-06 01:24:40 +01:00
parent acfc815e1d
commit f5228695a2
2 changed files with 127 additions and 0 deletions

View File

@ -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;

View File

@ -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);
/// ```
///
/// ![Progress bar drawn with `iced_wgpu`](https://user-images.githubusercontent.com/18618951/71662391-a316c200-2d51-11ea-9cef-52758cab85e3.png)
#[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)
}
}