Add Padding widget

This commit is contained in:
Joscha 2023-02-16 14:30:12 +01:00
parent 964f3bf011
commit dbafc40700
3 changed files with 133 additions and 0 deletions

View file

@ -16,6 +16,20 @@ impl Size {
pub const fn new(width: u16, height: u16) -> Self { pub const fn new(width: u16, height: u16) -> Self {
Self { width, height } Self { width, height }
} }
pub const fn saturating_add(self, rhs: Self) -> Self {
Self::new(
self.width.saturating_add(rhs.width),
self.height.saturating_add(rhs.height),
)
}
pub const fn saturating_sub(self, rhs: Self) -> Self {
Self::new(
self.width.saturating_sub(rhs.width),
self.height.saturating_sub(rhs.height),
)
}
} }
impl Add for Size { impl Add for Size {

View file

@ -1,5 +1,7 @@
mod border; mod border;
mod padding;
mod text; mod text;
pub use border::*; pub use border::*;
pub use padding::*;
pub use text::*; pub use text::*;

117
src/widgets/padding.rs Normal file
View file

@ -0,0 +1,117 @@
use async_trait::async_trait;
use crate::{AsyncWidget, Frame, Pos, Size, Widget};
pub struct Padding<I> {
inner: I,
left: u16,
right: u16,
top: u16,
bottom: u16,
}
impl<I> Padding<I> {
pub fn new(inner: I) -> Self {
Self {
inner,
left: 0,
right: 0,
top: 0,
bottom: 0,
}
}
pub fn left(mut self, amount: u16) -> Self {
self.left = amount;
self
}
pub fn right(mut self, amount: u16) -> Self {
self.right = amount;
self
}
pub fn top(mut self, amount: u16) -> Self {
self.top = amount;
self
}
pub fn bottom(mut self, amount: u16) -> Self {
self.bottom = amount;
self
}
pub fn horizontal(self, amount: u16) -> Self {
self.left(amount).right(amount)
}
pub fn vertical(self, amount: u16) -> Self {
self.top(amount).bottom(amount)
}
pub fn all(self, amount: u16) -> Self {
self.horizontal(amount).vertical(amount)
}
fn pad_size(&self) -> Size {
Size::new(self.left + self.right, self.top + self.bottom)
}
fn push_inner(&self, frame: &mut Frame) {
let size = frame.size();
let pad_size = self.pad_size();
let inner_size = size.saturating_sub(pad_size);
frame.push(Pos::new(self.left.into(), self.top.into()), inner_size);
}
}
impl<E, I> Widget<E> for Padding<I>
where
I: Widget<E>,
{
fn size(
&self,
frame: &mut Frame,
max_width: Option<u16>,
max_height: Option<u16>,
) -> Result<Size, E> {
let pad_size = self.pad_size();
let max_width = max_width.map(|w| w.saturating_sub(pad_size.width));
let max_height = max_height.map(|h| h.saturating_sub(pad_size.height));
let size = self.inner.size(frame, max_width, max_height)?;
Ok(size + pad_size)
}
fn draw(self, frame: &mut Frame) -> Result<(), E> {
self.push_inner(frame);
self.inner.draw(frame)?;
frame.pop();
Ok(())
}
}
#[async_trait]
impl<E, I> AsyncWidget<E> for Padding<I>
where
I: AsyncWidget<E> + Send + Sync,
{
async fn size(
&self,
frame: &mut Frame,
max_width: Option<u16>,
max_height: Option<u16>,
) -> Result<Size, E> {
let pad_size = self.pad_size();
let max_width = max_width.map(|w| w.saturating_sub(pad_size.width));
let max_height = max_height.map(|h| h.saturating_sub(pad_size.height));
let size = self.inner.size(frame, max_width, max_height).await?;
Ok(size + pad_size)
}
async fn draw(self, frame: &mut Frame) -> Result<(), E> {
self.push_inner(frame);
self.inner.draw(frame).await?;
frame.pop();
Ok(())
}
}