rtlibs-tui 0.1.4

rtools library: ratatui widgets
Documentation
use std::marker::PhantomData;

use crossterm::event::KeyCode;
use crossterm::event::KeyModifiers;
use ratatui::buffer::Buffer;
use ratatui::layout::Alignment;
use ratatui::layout::Position;
use ratatui::layout::Rect;
use ratatui::widgets::Paragraph;
use ratatui::widgets::Widget;
use ratatui::widgets::Wrap;

use crate::widgets::Modal;
use crate::widgets::ModalConfig;
use crate::Result;

pub trait ModalConfirmResponse<EVENT>
{
    fn bool(
        event: EVENT,
        value: bool,
    ) -> Self;
    fn waiting_input() -> Self;
}

#[derive(Debug)]
pub struct ModalConfirm<RESPONSE, EVENT>
{
    pub message: String,
    phantom_r: PhantomData<RESPONSE>,
    phantom_e: PhantomData<EVENT>,
}

impl<RESPONSE, EVENT> ModalConfirm<RESPONSE, EVENT>
{
    pub fn new<S>(message: S) -> Self
    where
        S: AsRef<str>,
    {
        Self {
            message: message
                .as_ref()
                .to_string(),
            phantom_r: PhantomData,
            phantom_e: PhantomData,
        }
    }
}

impl<RESPONSE, EVENT> Modal<RESPONSE, EVENT> for ModalConfirm<RESPONSE, EVENT>
where
    EVENT: std::fmt::Debug,
    RESPONSE: std::fmt::Debug + ModalConfirmResponse<EVENT>,
{
    fn config(&self) -> ModalConfig
    {
        ModalConfig::new().title(" CONFIRM ")
    }

    fn render(
        &mut self,
        area: Rect,
        buf: &mut Buffer,
    )
    {
        let mut area = area;
        area.y += 1;
        area.height -= 1;

        Paragraph::new(
            self.message
                .as_str(),
        )
        .alignment(Alignment::Center)
        .wrap(Wrap { trim: true })
        .render(
            area, buf,
        );

        let mut commands_area = area;
        commands_area.y = commands_area.y + commands_area.height - 2;
        commands_area.height = 1;

        Paragraph::new("[Y]es   [N]o")
            .alignment(Alignment::Center)
            .render(
                commands_area,
                buf,
            );
    }

    fn handle_key_event(
        &mut self,
        code: KeyCode,
        _modifiers: KeyModifiers,
        event: EVENT,
    ) -> Result<RESPONSE>
    {
        let response = match code
        {
            KeyCode::Char('n') | KeyCode::Esc => RESPONSE::bool(
                event, false,
            ),
            KeyCode::Char('y') | KeyCode::Enter => RESPONSE::bool(
                event, true,
            ),
            _ => RESPONSE::waiting_input(),
        };

        Ok(response)
    }

    fn cursor(&self) -> Option<Position>
    {
        None
    }
}