From b27cb816422abe093faf06887b30c44cddbf0c2d Mon Sep 17 00:00:00 2001 From: Joscha Date: Sat, 18 Feb 2023 20:24:56 +0100 Subject: [PATCH] Add Resize widget --- src/widget.rs | 8 +++- src/widgets.rs | 2 + src/widgets/resize.rs | 103 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 src/widgets/resize.rs diff --git a/src/widget.rs b/src/widget.rs index ef575cd..d2ae61e 100644 --- a/src/widget.rs +++ b/src/widget.rs @@ -1,6 +1,8 @@ use async_trait::async_trait; -use crate::widgets::{Background, Border, Either, Either3, Float, JoinSegment, Layer, Padding}; +use crate::widgets::{ + Background, Border, Either, Either3, Float, JoinSegment, Layer, Padding, Resize, +}; use crate::{Frame, Size}; // TODO Feature-gate these traits @@ -76,6 +78,10 @@ pub trait WidgetExt: Sized { fn padding(self) -> Padding { Padding::new(self) } + + fn resize(self) -> Resize { + Resize::new(self) + } } // It would be nice if this could be restricted to types implementing Widget. diff --git a/src/widgets.rs b/src/widgets.rs index f2fe1d7..608f50e 100644 --- a/src/widgets.rs +++ b/src/widgets.rs @@ -7,6 +7,7 @@ mod float; mod join; mod layer; mod padding; +mod resize; mod text; pub use background::*; @@ -18,4 +19,5 @@ pub use float::*; pub use join::*; pub use layer::*; pub use padding::*; +pub use resize::*; pub use text::*; diff --git a/src/widgets/resize.rs b/src/widgets/resize.rs new file mode 100644 index 0000000..bf80801 --- /dev/null +++ b/src/widgets/resize.rs @@ -0,0 +1,103 @@ +use async_trait::async_trait; + +use crate::{AsyncWidget, Frame, Size, Widget}; + +pub struct Resize { + inner: I, + min_width: Option, + min_height: Option, + max_width: Option, + max_height: Option, +} + +impl Resize { + pub fn new(inner: I) -> Self { + Self { + inner, + min_width: None, + min_height: None, + max_width: None, + max_height: None, + } + } + + pub fn min_width(mut self, width: u16) -> Self { + self.min_width = Some(width); + self + } + + pub fn min_height(mut self, height: u16) -> Self { + self.min_height = Some(height); + self + } + + pub fn max_width(mut self, width: u16) -> Self { + self.max_width = Some(width); + self + } + + pub fn max_height(mut self, height: u16) -> Self { + self.max_height = Some(height); + self + } + + fn resize(&self, size: Size) -> Size { + let mut width = size.width; + let mut height = size.height; + + if let Some(min_width) = self.min_width { + width = width.max(min_width); + } + if let Some(min_height) = self.min_height { + height = height.max(min_height); + } + + if let Some(max_width) = self.max_width { + width = width.min(max_width); + } + if let Some(max_height) = self.max_height { + height = height.min(max_height); + } + + Size::new(width, height) + } +} + +impl Widget for Resize +where + I: Widget, +{ + fn size( + &self, + frame: &mut Frame, + max_width: Option, + max_height: Option, + ) -> Result { + let size = self.inner.size(frame, max_width, max_height)?; + Ok(self.resize(size)) + } + + fn draw(self, frame: &mut Frame) -> Result<(), E> { + self.inner.draw(frame) + } +} + +#[async_trait] +impl AsyncWidget for Resize +where + I: AsyncWidget + Send + Sync, +{ + async fn size( + &self, + frame: &mut Frame, + max_width: Option, + max_height: Option, + ) -> Result { + let size = self.inner.size(frame, max_width, max_height).await?; + Ok(self.resize(size)) + } + + async fn draw(self, frame: &mut Frame) -> Result<(), E> { + self.inner.draw(frame).await + } +}