From 3a0d34c0240f4421737a6a08761f99d6f8140d02 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 4 Mar 2023 05:37:11 +0100 Subject: Create `iced_widget` subcrate and re-organize the whole codebase --- widget/src/progress_bar.rs | 172 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 widget/src/progress_bar.rs (limited to 'widget/src/progress_bar.rs') diff --git a/widget/src/progress_bar.rs b/widget/src/progress_bar.rs new file mode 100644 index 00000000..896d40fe --- /dev/null +++ b/widget/src/progress_bar.rs @@ -0,0 +1,172 @@ +//! Provide progress feedback to your users. +use crate::core::layout; +use crate::core::renderer; +use crate::core::widget::Tree; +use crate::core::{ + Color, Element, Layout, Length, Point, Rectangle, Size, Widget, +}; + +use std::ops::RangeInclusive; + +pub use iced_style::progress_bar::{Appearance, StyleSheet}; + +/// A bar that displays progress. +/// +/// # Example +/// ``` +/// # type ProgressBar = +/// # iced_widget::ProgressBar>; +/// # +/// 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 +where + Renderer: crate::core::Renderer, + Renderer::Theme: StyleSheet, +{ + range: RangeInclusive, + value: f32, + width: Length, + height: Option, + style: ::Style, +} + +impl ProgressBar +where + Renderer: crate::core::Renderer, + Renderer::Theme: StyleSheet, +{ + /// The default height of a [`ProgressBar`]. + pub const DEFAULT_HEIGHT: f32 = 30.0; + + /// Creates a new [`ProgressBar`]. + /// + /// It expects: + /// * an inclusive range of possible values + /// * the current value of the [`ProgressBar`] + pub fn new(range: RangeInclusive, value: f32) -> Self { + ProgressBar { + value: value.clamp(*range.start(), *range.end()), + range, + width: Length::Fill, + height: None, + style: Default::default(), + } + } + + /// Sets the width of the [`ProgressBar`]. + pub fn width(mut self, width: impl Into) -> Self { + self.width = width.into(); + self + } + + /// Sets the height of the [`ProgressBar`]. + pub fn height(mut self, height: impl Into) -> Self { + self.height = Some(height.into()); + self + } + + /// Sets the style of the [`ProgressBar`]. + pub fn style( + mut self, + style: impl Into<::Style>, + ) -> Self { + self.style = style.into(); + self + } +} + +impl Widget for ProgressBar +where + Renderer: crate::core::Renderer, + Renderer::Theme: StyleSheet, +{ + fn width(&self) -> Length { + self.width + } + + fn height(&self) -> Length { + self.height.unwrap_or(Length::Fixed(Self::DEFAULT_HEIGHT)) + } + + fn layout( + &self, + _renderer: &Renderer, + limits: &layout::Limits, + ) -> layout::Node { + let limits = limits + .width(self.width) + .height(self.height.unwrap_or(Length::Fixed(Self::DEFAULT_HEIGHT))); + + let size = limits.resolve(Size::ZERO); + + layout::Node::new(size) + } + + fn draw( + &self, + _state: &Tree, + renderer: &mut Renderer, + theme: &Renderer::Theme, + _style: &renderer::Style, + layout: Layout<'_>, + _cursor_position: Point, + _viewport: &Rectangle, + ) { + let bounds = layout.bounds(); + let (range_start, range_end) = self.range.clone().into_inner(); + + let active_progress_width = if range_start >= range_end { + 0.0 + } else { + bounds.width * (self.value - range_start) + / (range_end - range_start) + }; + + let style = theme.appearance(&self.style); + + renderer.fill_quad( + renderer::Quad { + bounds: Rectangle { ..bounds }, + border_radius: style.border_radius.into(), + border_width: 0.0, + border_color: Color::TRANSPARENT, + }, + style.background, + ); + + if active_progress_width > 0.0 { + renderer.fill_quad( + renderer::Quad { + bounds: Rectangle { + width: active_progress_width, + ..bounds + }, + border_radius: style.border_radius.into(), + border_width: 0.0, + border_color: Color::TRANSPARENT, + }, + style.bar, + ); + } + } +} + +impl<'a, Message, Renderer> From> + for Element<'a, Message, Renderer> +where + Message: 'a, + Renderer: 'a + crate::core::Renderer, + Renderer::Theme: StyleSheet, +{ + fn from( + progress_bar: ProgressBar, + ) -> Element<'a, Message, Renderer> { + Element::new(progress_bar) + } +} -- cgit