use crate::FormatError;
use toolstr_colored::{Color, Colorize};
#[derive(Clone)]
pub struct Theme {
pub border_chars: BorderChars,
pub border_style: FontStyle,
pub title_style: FontStyle,
}
impl Default for Theme {
fn default() -> Theme {
Theme {
border_chars: BorderChars::default(),
border_style: FontStyle::default(),
title_style: FontStyle("".bold()),
}
}
}
impl Theme {
pub fn with_border_chars(mut self, border_chars: BorderChars) -> Theme {
self.border_chars = border_chars;
self
}
pub fn with_border_style(mut self, border_style: FontStyle) -> Theme {
self.border_style = border_style;
self
}
pub fn with_title_style(mut self, title_style: FontStyle) -> Theme {
self.title_style = title_style;
self
}
}
#[derive(Clone)]
pub struct BorderChars {
pub vertical: String,
pub horizontal: String,
pub top_left: String,
pub top_right: String,
pub bottom_left: String,
pub bottom_right: String,
pub cross: String,
pub top_cross: String,
pub bottom_cross: String,
pub left_cross: String,
pub right_cross: String,
}
impl Default for BorderChars {
fn default() -> BorderChars {
BorderChars {
vertical: "│".to_string(),
horizontal: "─".to_string(),
top_left: "┌".to_string(),
top_right: "┐".to_string(),
bottom_left: "└".to_string(),
bottom_right: "┘".to_string(),
cross: "┼".to_string(),
top_cross: "┬".to_string(),
bottom_cross: "┴".to_string(),
left_cross: "├".to_string(),
right_cross: "┤".to_string(),
}
}
}
#[derive(Default, Clone, Debug)]
pub struct FontStyle(pub toolstr_colored::ColoredString);
impl From<toolstr_colored::ColoredString> for FontStyle {
fn from(value: toolstr_colored::ColoredString) -> FontStyle {
FontStyle(value)
}
}
impl From<toolstr_colored::Color> for FontStyle {
fn from(value: toolstr_colored::Color) -> FontStyle {
FontStyle("".color(value))
}
}
impl FontStyle {
pub fn format<T: AsRef<str>>(&self, text: T) -> String {
let FontStyle(style) = self;
let mut s = style.clone();
s.input = text.as_ref().to_string();
s.to_string()
}
pub fn println<T: AsRef<str>>(&self, text: T) {
println!("{}", self.format(text))
}
pub fn bold(&mut self) {
self.0 = self.0.clone().bold();
}
}
pub fn hex_to_color(hex: &str) -> Result<Color, FormatError> {
let hex = hex.strip_prefix('#').unwrap_or(hex);
if hex.len() != 6 {
return Err(FormatError::InvalidFormat(
"Invalid length for a hex color string".to_string(),
));
}
let r = u8::from_str_radix(&hex[0..2], 16)
.map_err(|_| FormatError::InvalidFormat("Invalid hex value for red".to_string()))?;
let g = u8::from_str_radix(&hex[2..4], 16)
.map_err(|_| FormatError::InvalidFormat("Invalid hex value for green".to_string()))?;
let b = u8::from_str_radix(&hex[4..6], 16)
.map_err(|_| FormatError::InvalidFormat("Invalid hex value for blue".to_string()))?;
Ok(Color::TrueColor { r, g, b })
}
pub trait ToTheme {
fn to_theme(&self) -> Theme;
}
impl<T: ToTheme> ToTheme for Option<T> {
fn to_theme(&self) -> Theme {
match self {
Some(value) => value.to_theme(),
None => Theme::default(),
}
}
}
impl<T: ToTheme> ToTheme for &Option<T> {
fn to_theme(&self) -> Theme {
match self {
Some(value) => value.to_theme(),
None => Theme::default(),
}
}
}
impl ToTheme for Theme {
fn to_theme(&self) -> Theme {
self.clone()
}
}
impl ToTheme for &Theme {
fn to_theme(&self) -> Theme {
(*self).clone()
}
}
pub fn print_text_box<A: AsRef<str>, T: ToTheme>(text: A, style: T) {
let text = text.as_ref();
let theme = style.to_theme();
let top = format!(
"{}{}{}",
theme.border_chars.top_left,
theme.border_chars.horizontal.repeat(text.len() + 2),
theme.border_chars.top_right
);
theme.border_style.println(top);
println!(
"{} {} {}",
theme.border_style.format(&theme.border_chars.vertical),
theme.title_style.format(text),
theme.border_style.format(&theme.border_chars.vertical),
);
let bottom = format!(
"{}{}{}",
theme.border_chars.bottom_left,
theme.border_chars.horizontal.repeat(text.len() + 2),
theme.border_chars.bottom_right
);
theme.border_style.println(bottom);
}
pub fn print_header<A: AsRef<str>, T: ToTheme>(text: A, style: T) {
let text = text.as_ref();
let theme = style.to_theme();
let underline = theme.border_chars.horizontal.repeat(text.len());
theme.title_style.println(text);
theme.border_style.println(underline);
}