use crossterm::{cursor, event::MouseEvent, Command as _};
use std::fmt::Write;
use super::Widget;
use crate::{Area, Message};
pub struct Text {
content: String,
on_mouse: Option<Box<dyn Fn(MouseEvent) -> Message>>,
}
impl Text {
pub fn new<S>(content: S) -> Box<Text>
where
S: AsRef<str>,
{
Box::new(Text {
content: content.as_ref().to_owned(),
on_mouse: None,
})
}
pub fn on_mouse<F>(mut self: Box<Text>, handler: F) -> Box<Text>
where
F: Fn(MouseEvent) -> Message + 'static,
{
self.on_mouse = Some(Box::new(handler));
self
}
}
impl Widget for Text {
fn get_width_hint(&self) -> u16 {
self.content
.lines()
.map(|s| s.chars().count())
.max()
.unwrap_or(0) as u16
}
fn get_height_hint(&self) -> u16 {
self.content.lines().count() as u16
}
#[allow(unused_must_use)]
fn render(&self, area: Area) -> String {
let mut out = String::new();
cursor::MoveTo(area.x, area.y).write_ansi(&mut out);
for line in self.content.lines().take(area.height as usize) {
out.write_str(line);
cursor::MoveToColumn(area.x).write_ansi(&mut out);
cursor::MoveDown(1).write_ansi(&mut out);
}
out
}
fn process_mouse(&self, event: MouseEvent, area: Area) -> Message {
let Some(ref on_click) = self.on_mouse else {
return Message::empty();
};
on_click(event)
}
}