rtlibs-tui 0.1.5

rtools library: ratatui widgets
Documentation
use ratatui::buffer::Buffer;
use ratatui::layout::Constraint;
use ratatui::layout::Layout;
use ratatui::layout::Rect;
use ratatui::style::Style;
use ratatui::style::Stylize;
use ratatui::text::Text;
use ratatui::widgets::Block;
use ratatui::widgets::BorderType;
use ratatui::widgets::Borders;
use ratatui::widgets::Clear;
use ratatui::widgets::StatefulWidget;
use ratatui::widgets::Widget;

use super::NotificationState;

#[derive(Debug, Default)]
pub struct NotificationWidgetStyle
{
    pub success: Style,
    pub warning: Style,
    pub error: Style,
    pub info: Style,
}

pub struct NotificationWidget
{
    style: NotificationWidgetStyle,
}

impl std::default::Default for NotificationWidget
{
    fn default() -> Self
    {
        Self::new()
    }
}

impl NotificationWidget
{
    pub fn new() -> Self
    {
        Self {
            style: NotificationWidgetStyle::default(),
        }
    }

    pub fn style(
        mut self,
        style: NotificationWidgetStyle,
    ) -> Self
    {
        self.style = style;
        self
    }
}

impl StatefulWidget for NotificationWidget
{
    type State = NotificationState;

    fn render(
        self,
        area: Rect,
        buf: &mut Buffer,
        state: &mut Self::State,
    )
    {
        let [_, n] =
            Layout::horizontal([Constraint::Fill(1), Constraint::Length(state.area_width)])
                .areas(area);

        let mut notification_area = n;
        notification_area.y = 1;

        for item in state
            .items
            .iter()
        {
            let lines = textwrap::wrap(
                &item.message,
                notification_area.width as usize,
            );

            notification_area.height = lines.len() as u16 + 2;

            Clear.render(
                notification_area,
                buf,
            );

            let (title, style) = item.get_color(&self.style);

            Block::bordered()
                .borders(Borders::LEFT | Borders::TOP | Borders::BOTTOM)
                .border_type(BorderType::Thick)
                .title(title)
                .fg(
                    style
                        .fg
                        .unwrap_or_default(),
                )
                .bg(
                    style
                        .bg
                        .unwrap_or_default(),
                )
                .render(
                    notification_area,
                    buf,
                );

            notification_area.y += 1;
            notification_area.x += 1;
            notification_area.width -= 2;

            for line in lines
            {
                Text::raw(line).render(
                    notification_area,
                    buf,
                );
                notification_area.y += 1;
            }

            notification_area.x -= 1;
            notification_area.width += 2;
            notification_area.y += 2;
        }
    }
}