use crate::{GetMemSize, TuiStyle, fg_magenta, ok};
use std::fmt::{self, Debug};
#[derive(Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum PixelChar {
Void,
#[default]
Spacer,
PlainText {
display_char: char,
style: TuiStyle,
},
}
pub const EMPTY_CHAR: char = '╳';
pub const VOID_CHAR: char = '❯';
impl GetMemSize for PixelChar {
fn get_mem_size(&self) -> usize {
std::mem::size_of::<PixelChar>()
}
}
impl Debug for PixelChar {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
const WIDTH: usize = 16;
match self {
PixelChar::Void => {
write!(f, " V {VOID_CHAR:░^WIDTH$}")?;
}
PixelChar::Spacer => {
write!(f, " S {EMPTY_CHAR:░^WIDTH$}")?;
}
PixelChar::PlainText {
display_char,
style,
} => {
if style == &TuiStyle::default() {
write!(f, " {} '{display_char}': ^WIDTH$", fg_magenta("P"))?;
} else {
write!(f, " {} '{display_char}'→{style: ^WIDTH$}", fg_magenta("P"))?;
}
}
}
ok!()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{height, new_style,
tui::terminal_lib_backends::offscreen_buffer::OffscreenBuffer,
tui_color, tui_style_attrib::Underline, tui_style_attribs, width};
fn create_test_buffer() -> OffscreenBuffer {
let window_size = width(4) + height(2);
OffscreenBuffer::new_empty(window_size)
}
#[test]
fn test_default_pixel_char() {
let default_char = PixelChar::default();
assert!(matches!(default_char, PixelChar::Spacer));
let window_size = width(1) + height(1);
let ofs_buf = OffscreenBuffer::new_empty(window_size);
assert!(matches!(ofs_buf.buffer[0][0], PixelChar::Spacer));
}
#[test]
fn test_pixel_char_variants() {
let mut ofs_buf = create_test_buffer();
assert!(matches!(ofs_buf.buffer[0][0], PixelChar::Spacer));
ofs_buf.buffer[0][1] = PixelChar::PlainText {
display_char: 'a',
style: TuiStyle::default(),
};
match &ofs_buf.buffer[0][1] {
PixelChar::PlainText {
display_char,
style,
} => {
assert_eq!(*display_char, 'a');
assert_eq!(*style, TuiStyle::default());
}
_ => panic!("Expected PlainText variant"),
}
ofs_buf.buffer[0][2] = PixelChar::PlainText {
display_char: 'b',
style: new_style!(underline color_fg: {tui_color!(red)}),
};
match &ofs_buf.buffer[0][2] {
PixelChar::PlainText {
display_char,
style,
} => {
assert_eq!(*display_char, 'b');
assert_eq!(style.attribs, tui_style_attribs(Underline));
assert_eq!(style.color_fg, Some(tui_color!(red)));
}
_ => panic!("Expected styled PlainText variant"),
}
ofs_buf.buffer[1][0] = PixelChar::Void;
assert!(matches!(ofs_buf.buffer[1][0], PixelChar::Void));
ofs_buf.buffer[1][1] = PixelChar::PlainText {
display_char: ' ',
style: TuiStyle::default(),
};
match &ofs_buf.buffer[1][1] {
PixelChar::PlainText {
display_char,
style,
} => {
assert_eq!(*display_char, ' ');
assert_eq!(*style, TuiStyle::default());
}
_ => panic!("Expected PlainText with space"),
}
ofs_buf.buffer[1][2] = PixelChar::PlainText {
display_char: ' ',
style: new_style!(color_bg: {tui_color!(blue)}),
};
match &ofs_buf.buffer[1][2] {
PixelChar::PlainText {
display_char,
style: actual_style,
} => {
assert_eq!(*display_char, ' ');
assert_eq!(actual_style.color_bg, Some(tui_color!(blue)));
}
_ => panic!("Expected styled space"),
}
}
#[test]
fn test_pixel_char_memory_size() {
let void_char = PixelChar::Void;
let spacer_char = PixelChar::Spacer;
let plain_char = PixelChar::PlainText {
display_char: 'x',
style: TuiStyle::default(),
};
let styled_char = PixelChar::PlainText {
display_char: 'y',
style: new_style!(color_fg: {tui_color!(green)}),
};
let void_size = void_char.get_mem_size();
let spacer_size = spacer_char.get_mem_size();
let plain_size = plain_char.get_mem_size();
let styled_size = styled_char.get_mem_size();
assert_eq!(void_size, spacer_size);
assert_eq!(spacer_size, plain_size);
assert_eq!(plain_size, styled_size);
assert_eq!(void_size, std::mem::size_of::<PixelChar>());
}
#[test]
fn test_pixel_char_equality() {
let char1 = PixelChar::PlainText {
display_char: 'a',
style: TuiStyle::default(),
};
let char2 = PixelChar::PlainText {
display_char: 'a',
style: TuiStyle::default(),
};
let char3 = PixelChar::PlainText {
display_char: 'b',
style: TuiStyle::default(),
};
let char4 = PixelChar::PlainText {
display_char: 'a',
style: new_style!(bold),
};
assert_eq!(char1, char2); assert_ne!(char1, char3); assert_ne!(char1, char4); assert_ne!(char1, PixelChar::Spacer); assert_ne!(char1, PixelChar::Void);
assert_eq!(PixelChar::Spacer, PixelChar::Spacer);
assert_eq!(PixelChar::Void, PixelChar::Void);
assert_ne!(PixelChar::Spacer, PixelChar::Void);
}
#[test]
fn test_pixel_char_copy_clone() {
let original = PixelChar::PlainText {
display_char: 'z',
style: new_style!(italic color_bg: {tui_color!(yellow)}),
};
let copied = original;
assert_eq!(original, copied);
let cloned = original;
assert_eq!(original, cloned);
let modified = PixelChar::Spacer;
assert_ne!(original, modified);
assert_eq!(original, copied); }
}