use ratatui::{
buffer::Buffer,
layout::Rect,
text::Line,
style::{Color, Style},
widgets::Widget,
};
use crate::{BadgeStack, BorderType, ConfirmationPopup, DotGridConfig, DotPattern, 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>,
no_dot_grid: bool,
dot_grid: Option<DotGridConfig>,
badges: Option<BadgeStack<'a>>,
}
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);
}
if self.no_dot_grid {
popup = popup.no_background();
}
if let Some(ref dg) = self.dot_grid {
popup = popup
.background_dots(dg.color, &dg.symbol, dg.density_x)
.background_spacing(dg.density_x, dg.density_y);
}
if let Some(ref badges) = self.badges {
popup = popup.badges(badges.clone());
}
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,
no_dot_grid: false,
dot_grid: None,
badges: 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
}
pub fn no_background(mut self) -> Self {
self.no_dot_grid = true;
self
}
pub fn background_dots(mut self, color: Color, symbol: &str, density: u16) -> Self {
self.dot_grid = Some(DotGridConfig { color, symbol: symbol.to_string(), density_x: density, density_y: density, pattern: DotPattern::default() });
self
}
pub fn background_pattern(mut self, pattern: DotPattern) -> Self {
if let Some(ref mut dg) = self.dot_grid {
dg.pattern = pattern;
} else {
self.no_dot_grid = false;
self.dot_grid = Some(DotGridConfig { pattern, ..DotGridConfig::default() });
}
self
}
pub fn background_spacing(mut self, density_x: u16, density_y: u16) -> Self {
if let Some(ref mut dg) = self.dot_grid {
dg.density_x = density_x;
dg.density_y = density_y;
} else {
self.no_dot_grid = false;
self.dot_grid = Some(DotGridConfig {
density_x,
density_y,
..DotGridConfig::default()
});
}
self
}
pub fn badges(mut self, badges: BadgeStack<'a>) -> Self {
self.badges = Some(badges);
self
}
}
impl Widget for ThemedConfirmationPopup<'_> {
fn render(self, area: Rect, buf: &mut Buffer) {
self.build_inner().render(area, buf);
}
}
#[cfg(test)]
mod tests;