use std::fmt::Display;
use crossterm::style::{Attribute, Color, ContentStyle, StyledContent};
use crate::color::OpalineColor;
#[cfg(feature = "gradients")]
use crate::gradient::Gradient;
use crate::style::OpalineStyle;
use crate::theme::Theme;
#[cfg(feature = "gradients")]
use unicode_segmentation::UnicodeSegmentation;
impl From<OpalineColor> for Color {
fn from(c: OpalineColor) -> Self {
Color::Rgb {
r: c.r,
g: c.g,
b: c.b,
}
}
}
impl From<&OpalineColor> for Color {
fn from(c: &OpalineColor) -> Self {
Color::Rgb {
r: c.r,
g: c.g,
b: c.b,
}
}
}
impl From<OpalineStyle> for ContentStyle {
fn from(s: OpalineStyle) -> Self {
let mut style = Self::new();
style.foreground_color = s.fg.map(Into::into);
style.background_color = s.bg.map(Into::into);
if s.bold {
style.attributes.set(Attribute::Bold);
}
if s.dim {
style.attributes.set(Attribute::Dim);
}
if s.italic {
style.attributes.set(Attribute::Italic);
}
if s.underline {
style.attributes.set(Attribute::Underlined);
}
if s.slow_blink {
style.attributes.set(Attribute::SlowBlink);
}
if s.rapid_blink {
style.attributes.set(Attribute::RapidBlink);
}
if s.reversed {
style.attributes.set(Attribute::Reverse);
}
if s.hidden {
style.attributes.set(Attribute::Hidden);
}
if s.crossed_out {
style.attributes.set(Attribute::CrossedOut);
}
style
}
}
impl From<&OpalineStyle> for ContentStyle {
fn from(s: &OpalineStyle) -> Self {
s.clone().into()
}
}
impl Theme {
pub fn crossterm_styled<D: Display>(&self, style_name: &str, content: D) -> StyledContent<D> {
ContentStyle::from(self.style(style_name)).apply(content)
}
}
#[cfg(feature = "gradients")]
pub fn gradient_styled(text: &str, gradient: &Gradient) -> Vec<StyledContent<String>> {
let graphemes: Vec<&str> = text.graphemes(true).collect();
if graphemes.is_empty() {
return vec![];
}
let colors = gradient.generate(graphemes.len());
graphemes
.into_iter()
.zip(colors)
.map(|(grapheme, color)| {
let style = ContentStyle {
foreground_color: Some(color.into()),
..ContentStyle::new()
};
style.apply(grapheme.to_string())
})
.collect()
}
#[cfg(feature = "gradients")]
pub fn gradient_bar(width: usize, ch: char, gradient: &Gradient) -> Vec<StyledContent<String>> {
if width == 0 {
return vec![];
}
let colors = gradient.generate(width);
colors
.into_iter()
.map(|color| {
let style = ContentStyle {
foreground_color: Some(color.into()),
..ContentStyle::new()
};
style.apply(ch.to_string())
})
.collect()
}