radiate-ui 1.2.22

A Rust library for genetic algorithms and artificial evolution.
Documentation
use ratatui::{
    buffer::Buffer,
    layout::{Constraint, Direction, Layout, Rect},
    style::Style,
    widgets::{Block, Clear, StatefulWidget, Widget},
};

pub struct ModalWidget<W> {
    title: Option<String>,
    width_pct: u16,
    height_pct: u16,
    block_style: Style,
    overlay_style: Style,
    child: W,
}

impl<W> ModalWidget<W> {
    pub fn new(child: W) -> Self {
        Self {
            title: None,
            width_pct: 70,
            height_pct: 80,
            block_style: Style::default().bg(crate::styles::ALT_BG_COLOR),
            overlay_style: Style::default().bg(crate::styles::OVERLAY_COLOR),
            child,
        }
    }
}

impl<W> ModalWidget<W> {
    fn centered_rect(r: Rect, height: u16, width: u16) -> Rect {
        let popup_layout = Layout::default()
            .direction(Direction::Vertical)
            .constraints([
                Constraint::Percentage((100 - height) / 2),
                Constraint::Percentage(height),
                Constraint::Percentage((100 - height) / 2),
            ])
            .split(r);

        Layout::default()
            .direction(Direction::Horizontal)
            .constraints([
                Constraint::Percentage((100 - width) / 2),
                Constraint::Percentage(width),
                Constraint::Percentage((100 - width) / 2),
            ])
            .split(popup_layout[1])[1]
    }
}

impl<W> Widget for ModalWidget<W>
where
    W: Widget,
{
    fn render(self, area: Rect, buf: &mut Buffer) {
        let popup_area = Self::centered_rect(area, self.height_pct, self.width_pct);

        Block::default().style(self.overlay_style).render(area, buf);

        Clear.render(popup_area, buf);

        let mut block = Block::default().style(self.block_style);
        if let Some(title) = self.title {
            block = block.title(title);
        }

        let inner = block.inner(popup_area);
        block.render(popup_area, buf);
        self.child.render(inner, buf);
    }
}

impl<W> StatefulWidget for ModalWidget<W>
where
    W: StatefulWidget,
{
    type State = W::State;

    fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
        let popup_area = Self::centered_rect(area, self.height_pct, self.width_pct);

        Block::default().style(self.overlay_style).render(area, buf);

        Clear.render(popup_area, buf);

        let mut block = Block::default().style(self.block_style);
        if let Some(title) = self.title {
            block = block.title(title);
        }

        let inner = block.inner(popup_area);
        block.render(popup_area, buf);
        self.child.render(inner, buf, state);
    }
}