use crate::render::{Cell, Modifier};
use crate::style::Color;
use crate::utils::figlet::{figlet_with_font, font_height, FigletFont};
use crate::utils::text_sizing::{is_supported as text_sizing_supported, TextSizing};
use crate::widget::traits::{RenderContext, View, WidgetProps};
use crate::{impl_props_builders, impl_styled_view};
pub struct BigText {
text: String,
tier: u8,
fg: Option<Color>,
bg: Option<Color>,
figlet_font: FigletFont,
force_figlet: bool,
props: WidgetProps,
}
impl BigText {
pub fn new(text: impl Into<String>, tier: u8) -> Self {
Self {
text: text.into(),
tier: tier.clamp(1, 6),
fg: None,
bg: None,
figlet_font: FigletFont::Block,
force_figlet: false,
props: WidgetProps::new(),
}
}
pub fn h1(text: impl Into<String>) -> Self {
Self::new(text, 1)
}
pub fn h2(text: impl Into<String>) -> Self {
Self::new(text, 2)
}
pub fn h3(text: impl Into<String>) -> Self {
Self::new(text, 3)
}
pub fn h4(text: impl Into<String>) -> Self {
Self::new(text, 4)
}
pub fn h5(text: impl Into<String>) -> Self {
Self::new(text, 5)
}
pub fn h6(text: impl Into<String>) -> Self {
Self::new(text, 6)
}
pub fn tier(mut self, tier: u8) -> Self {
self.tier = tier.clamp(1, 6);
self
}
pub fn fg(mut self, color: Color) -> Self {
self.fg = Some(color);
self
}
pub fn bg(mut self, color: Color) -> Self {
self.bg = Some(color);
self
}
pub fn figlet_font(mut self, font: FigletFont) -> Self {
self.figlet_font = font;
self
}
pub fn force_figlet(mut self, force: bool) -> Self {
self.force_figlet = force;
self
}
pub fn height(&self) -> u16 {
if !self.force_figlet && text_sizing_supported() {
TextSizing::height()
} else {
self.figlet_height()
}
}
fn figlet_height(&self) -> u16 {
let font = self.font_for_tier();
font_height(font) as u16
}
fn font_for_tier(&self) -> FigletFont {
match self.tier {
1 => self.figlet_font, 2 => FigletFont::Slant, 3 => FigletFont::Small, 4..=6 => FigletFont::Mini, _ => FigletFont::Mini,
}
}
#[doc(hidden)]
pub fn get_text(&self) -> &str {
&self.text
}
#[doc(hidden)]
pub fn get_tier(&self) -> u8 {
self.tier
}
#[doc(hidden)]
pub fn get_fg(&self) -> Option<Color> {
self.fg
}
#[doc(hidden)]
pub fn get_bg(&self) -> Option<Color> {
self.bg
}
#[doc(hidden)]
pub fn get_figlet_font(&self) -> FigletFont {
self.figlet_font
}
#[doc(hidden)]
pub fn get_force_figlet(&self) -> bool {
self.force_figlet
}
#[doc(hidden)]
pub fn get_font_for_tier(&self) -> FigletFont {
self.font_for_tier()
}
#[doc(hidden)]
pub fn test_render_text_sizing(&self, ctx: &mut RenderContext) {
self.render_text_sizing(ctx)
}
fn render_figlet(&self, ctx: &mut RenderContext) {
let area = ctx.area;
let font = self.font_for_tier();
let figlet_text = figlet_with_font(&self.text, font);
let fg = self.fg.unwrap_or(Color::WHITE);
let modifier = Modifier::BOLD;
for (row, line) in figlet_text.lines().enumerate() {
if row as u16 >= area.height {
break;
}
for (col, ch) in line.chars().enumerate() {
if col as u16 >= area.width {
break;
}
let mut cell = Cell::new(ch);
cell.fg = Some(fg);
if let Some(bg) = self.bg {
cell.bg = Some(bg);
}
cell.modifier = modifier;
ctx.set(col as u16, row as u16, cell);
}
}
}
fn render_text_sizing(&self, ctx: &mut RenderContext) {
let area = ctx.area;
let seq = TextSizing::escape_sequence(&self.text, self.tier, area.width);
let height = TextSizing::height();
ctx.buffer
.put_sequence(area.x, area.y, &seq, area.width, height);
}
}
impl Default for BigText {
fn default() -> Self {
Self::new("", 1)
}
}
impl View for BigText {
crate::impl_view_meta!("BigText");
fn render(&self, ctx: &mut RenderContext) {
if ctx.area.width == 0 || ctx.area.height == 0 {
return;
}
if self.text.is_empty() {
return;
}
if !self.force_figlet && text_sizing_supported() {
self.render_text_sizing(ctx);
} else {
self.render_figlet(ctx);
}
}
}
impl_styled_view!(BigText);
impl_props_builders!(BigText);
pub fn bigtext(text: impl Into<String>, tier: u8) -> BigText {
BigText::new(text, tier)
}
pub fn h1(text: impl Into<String>) -> BigText {
BigText::h1(text)
}
pub fn h2(text: impl Into<String>) -> BigText {
BigText::h2(text)
}
pub fn h3(text: impl Into<String>) -> BigText {
BigText::h3(text)
}