use ratatui::{
buffer::Buffer,
layout::{Alignment, Constraint, Layout, Rect},
text::{Line, Span},
style::{Color, Style},
prelude::Stylize,
widgets::{
Block, Borders, Padding, Paragraph, Widget, Wrap,
},
};
use crate::popup::Popup;
use crate::{BadgeStack, BorderType, DotPattern, PopupSize};
#[derive(Clone)]
pub struct ConfirmationPopup<'a> {
popup: Popup<'a>,
body: Vec<Line<'a>>,
confirm_style: Style,
cancel_style: Style,
confirm_label: &'a str,
cancel_label: &'a str,
}
impl<'a> ConfirmationPopup<'a> {
pub fn new() -> Self {
Self {
popup: Popup::new(Color::White).padding(0).header(),
body: vec![],
confirm_style: Style::new().bg(Color::Green).fg(Color::Black),
cancel_style: Style::new().bg(Color::Gray).fg(Color::Black),
confirm_label: "Confirmar",
cancel_label: "Cancelar",
}
}
pub fn title(mut self, title: &'a str) -> Self {
self.popup = self.popup.title(title);
self
}
pub fn body(mut self, body: Vec<Line<'a>>) -> Self {
self.body = body;
self
}
pub fn border_color(mut self, color: Color) -> Self {
self.popup = self.popup.border_color(color);
self
}
pub fn bg_color(mut self, color: Color) -> Self {
self.popup = self.popup.bg_color(color);
self
}
pub fn confirm_style(mut self, style: Style) -> Self {
self.confirm_style = style;
self
}
pub fn cancel_style(mut self, style: Style) -> Self {
self.cancel_style = style;
self
}
pub fn options(mut self, confirm_label: &'a str, cancel_label: &'a str) -> Self {
self.confirm_label = confirm_label;
self.cancel_label = cancel_label;
self
}
pub fn border_type(mut self, border_type: BorderType) -> Self {
self.popup = self.popup.border_type(border_type);
self
}
pub fn padding(mut self, padding: u16) -> Self {
self.popup = self.popup.padding(padding);
self
}
pub fn position(mut self, x: u16, y: u16) -> Self {
self.popup = self.popup.position(x, y);
self
}
pub fn width(mut self, width: PopupSize) -> Self {
self.popup = self.popup.width(width);
self
}
pub fn height(mut self, height: PopupSize) -> Self {
self.popup = self.popup.height(height);
self
}
pub fn origin(mut self, x: u16, y: u16) -> Self {
self.popup = self.popup.origin(x, y);
self
}
pub fn header(mut self) -> Self {
self.popup = self.popup.header();
self
}
pub fn resolve_rect(&self, area: Rect) -> Rect {
self.popup.resolve_rect(area)
}
pub fn no_background(mut self) -> Self {
self.popup = self.popup.no_background();
self
}
pub fn background_dots(mut self, color: Color, symbol: &str, density: u16) -> Self {
self.popup = self.popup.background_dots(color, symbol, density);
self
}
pub fn background_pattern(mut self, pattern: DotPattern) -> Self {
self.popup = self.popup.background_pattern(pattern);
self
}
pub fn background_spacing(mut self, density_x: u16, density_y: u16) -> Self {
self.popup = self.popup.background_spacing(density_x, density_y);
self
}
pub fn badges(mut self, badges: BadgeStack<'a>) -> Self {
self.popup = self.popup.badges(badges);
self
}
}
impl Default for ConfirmationPopup<'_> {
fn default() -> Self {
Self::new()
}
}
impl Widget for ConfirmationPopup<'_> {
fn render(self, area: Rect, buf: &mut Buffer) {
let Self { popup, body, confirm_style, cancel_style, confirm_label, cancel_label } = self;
let border_color = popup.get_border_color();
let inner = popup.render_inner(area, buf);
let chunks = Layout::vertical([
Constraint::Min(0),
Constraint::Length(2),
]).split(inner);
let body_para = Paragraph::new(body)
.block(Block::new().padding(Padding::new(1, 1, 0, 0)))
.wrap(Wrap { trim: false });
body_para.render(chunks[0], buf);
let border_style = Style::new().bold();
let options_block = Block::new()
.borders(Borders::TOP)
.border_style(border_style.fg(border_color))
.padding(Padding::new(1, 1, 0, 0));
let options_inner = options_block.inner(chunks[1]);
let option_chunks = Layout::horizontal([
Constraint::Percentage(48),
Constraint::Length(1),
Constraint::Percentage(48),
]).split(options_inner);
let confirm_para = Paragraph::new(Span::from(confirm_label).dim())
.alignment(Alignment::Center)
.style(confirm_style)
.block(Block::new().padding(Padding::new(1, 1, 0, 0)));
confirm_para.render(option_chunks[0], buf);
let cancel_para = Paragraph::new(Span::from(cancel_label).dim())
.alignment(Alignment::Center)
.style(cancel_style)
.block(Block::new().padding(Padding::new(1, 1, 0, 0)));
cancel_para.render(option_chunks[2], buf);
options_block.render(chunks[1], buf);
}
}
#[cfg(test)]
mod tests;