use ratatui::{
buffer::Buffer,
layout::Rect,
text::Line,
style::{Color, Style},
widgets::Widget,
};
use crate::{BorderType, ConfirmationPopup, PopupSize};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ConfirmationVariant {
Success,
Warning,
Danger,
None,
}
#[derive(Clone)]
pub struct ThemedConfirmationPopup<'a> {
title: &'a str,
body: Vec<Line<'a>>,
variant: ConfirmationVariant,
confirm_label: &'a str,
cancel_label: &'a str,
border_type: BorderType,
position: Option<(u16, u16)>,
origin: Option<(u16, u16)>,
width: Option<PopupSize>,
height: Option<PopupSize>,
header: bool,
padding: u16,
bg_color: Option<Color>,
}
impl<'a> ThemedConfirmationPopup<'a> {
fn border_color(variant: ConfirmationVariant) -> Color {
match variant {
ConfirmationVariant::Success => Color::Green,
ConfirmationVariant::Warning => Color::Yellow,
ConfirmationVariant::Danger => Color::Red,
ConfirmationVariant::None => Color::Gray,
}
}
fn confirm_color(variant: ConfirmationVariant) -> Color {
match variant {
ConfirmationVariant::Success => Color::Green,
ConfirmationVariant::Warning => Color::Yellow,
ConfirmationVariant::Danger => Color::Red,
ConfirmationVariant::None => Color::Blue,
}
}
fn build_inner(&self) -> ConfirmationPopup<'a> {
let mut popup = ConfirmationPopup::new()
.title(self.title)
.body(self.body.clone())
.border_color(Self::border_color(self.variant))
.confirm_style(Style::new().bg(Self::confirm_color(self.variant)).fg(Color::Black))
.cancel_style(Style::new().bg(Color::Gray).fg(Color::Black))
.border_type(self.border_type)
.options(self.confirm_label, self.cancel_label)
.padding(self.padding);
if let Some((x, y)) = self.position {
popup = popup.position(x, y);
}
if let Some((x, y)) = self.origin {
popup = popup.origin(x, y);
}
if let Some(w) = self.width {
popup = popup.width(w);
}
if let Some(h) = self.height {
popup = popup.height(h);
}
if self.header {
popup = popup.header();
}
if let Some(bg) = self.bg_color {
popup = popup.bg_color(bg);
}
popup
}
pub fn new(title: &'a str, body: Vec<Line<'a>>, variant: ConfirmationVariant) -> Self {
Self {
title,
body,
variant,
confirm_label: "Confirmar",
cancel_label: "Cancelar",
border_type: BorderType::Rounded,
position: None,
origin: None,
width: None,
height: None,
header: false,
padding: 0,
bg_color: None,
}
}
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.border_type = border_type;
self
}
pub fn position(mut self, x: u16, y: u16) -> Self {
self.position = Some((x, y));
self
}
pub fn origin(mut self, x: u16, y: u16) -> Self {
self.origin = Some((x, y));
self
}
pub fn width(mut self, width: PopupSize) -> Self {
self.width = Some(width);
self
}
pub fn height(mut self, height: PopupSize) -> Self {
self.height = Some(height);
self
}
pub fn header(mut self) -> Self {
self.header = true;
self
}
pub fn padding(mut self, padding: u16) -> Self {
self.padding = padding;
self
}
pub fn resolve_rect(&self, area: Rect) -> Rect {
self.build_inner().resolve_rect(area)
}
pub fn bg_color(mut self, color: Color) -> Self {
self.bg_color = Some(color);
self
}
}
impl Widget for ThemedConfirmationPopup<'_> {
fn render(self, area: Rect, buf: &mut Buffer) {
self.build_inner().render(area, buf);
}
}
#[cfg(test)]
mod tests;