Add Text widget

This commit is contained in:
Joscha 2023-02-16 09:58:18 +01:00
parent 70d33d4d5d
commit f793ec79ac
3 changed files with 96 additions and 0 deletions

View file

@ -14,6 +14,7 @@ mod frame;
mod styled;
mod terminal;
mod widget;
pub mod widgets;
mod widthdb;
mod wrap;

3
src/widgets.rs Normal file
View file

@ -0,0 +1,3 @@
mod text;
pub use text::*;

92
src/widgets/text.rs Normal file
View file

@ -0,0 +1,92 @@
use async_trait::async_trait;
use crate::{AsyncWidget, Frame, Pos, Size, Styled, Widget, WidthDb};
pub struct Text {
styled: Styled,
wrap: bool,
}
impl Text {
pub fn new<S: Into<Styled>>(styled: S) -> Self {
Self {
styled: styled.into(),
wrap: true,
}
}
pub fn wrap(mut self, wrap: bool) -> Self {
self.wrap = wrap;
self
}
fn wrapped(&self, widthdb: &mut WidthDb, max_width: Option<u16>) -> Vec<Styled> {
let max_width = max_width
.filter(|_| self.wrap)
.map(|w| w as usize)
.unwrap_or(usize::MAX);
let indices = widthdb.wrap(self.styled.text(), max_width);
self.styled.clone().split_at_indices(&indices)
}
fn size(&self, widthdb: &mut WidthDb, max_width: Option<u16>) -> Size {
let lines = self.wrapped(widthdb, max_width);
let min_width = lines
.iter()
.map(|l| widthdb.width(l.text().trim_end()))
.max()
.unwrap_or(0);
let min_height = lines.len();
let min_width: u16 = min_width.try_into().unwrap_or(u16::MAX);
let min_height: u16 = min_height.try_into().unwrap_or(u16::MAX);
Size::new(min_width, min_height)
}
fn draw(self, frame: &mut Frame) {
let size = frame.size();
for (i, line) in self
.wrapped(frame.widthdb(), Some(size.width))
.into_iter()
.enumerate()
{
let i: i32 = i.try_into().unwrap_or(i32::MAX);
frame.write(Pos::new(0, i), line);
}
}
}
impl<E> Widget<E> for Text {
fn size(
&self,
frame: &mut Frame,
max_width: Option<u16>,
_max_height: Option<u16>,
) -> Result<Size, E> {
Ok(self.size(frame.widthdb(), max_width))
}
fn draw(self, frame: &mut Frame) -> Result<(), E> {
self.draw(frame);
Ok(())
}
}
#[async_trait]
impl<E> AsyncWidget<E> for Text {
async fn size(
&self,
frame: &mut Frame,
max_width: Option<u16>,
_max_height: Option<u16>,
) -> Result<Size, E> {
Ok(self.size(frame.widthdb(), max_width))
}
async fn draw(self, frame: &mut Frame) -> Result<(), E> {
self.draw(frame);
Ok(())
}
}