ratatui_toolkit/vt100_term/
cell.rs

1//! Terminal cell representation
2
3use ratatui::style::{Color, Modifier, Style};
4use termwiz::cell::Intensity;
5use termwiz::color::ColorAttribute;
6
7/// Text attributes for a cell
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub struct Attrs {
10    pub fgcolor: ColorAttribute,
11    pub bgcolor: ColorAttribute,
12    pub intensity: Intensity,
13    pub underline: bool,
14    pub blink: bool,
15    pub reverse: bool,
16    pub strikethrough: bool,
17    pub italic: bool,
18}
19
20impl Default for Attrs {
21    fn default() -> Self {
22        Self {
23            fgcolor: ColorAttribute::Default,
24            bgcolor: ColorAttribute::Default,
25            intensity: Intensity::Normal,
26            underline: false,
27            blink: false,
28            reverse: false,
29            strikethrough: false,
30            italic: false,
31        }
32    }
33}
34
35impl Attrs {
36    /// Convert termwiz color to ratatui color
37    fn termwiz_to_ratatui_color(color: ColorAttribute) -> Color {
38        match color {
39            ColorAttribute::Default => Color::Reset,
40            ColorAttribute::PaletteIndex(idx) => {
41                // Standard 256 color palette
42                match idx {
43                    0 => Color::Black,
44                    1 => Color::Red,
45                    2 => Color::Green,
46                    3 => Color::Yellow,
47                    4 => Color::Blue,
48                    5 => Color::Magenta,
49                    6 => Color::Cyan,
50                    7 => Color::Gray,
51                    8 => Color::DarkGray,
52                    9 => Color::LightRed,
53                    10 => Color::LightGreen,
54                    11 => Color::LightYellow,
55                    12 => Color::LightBlue,
56                    13 => Color::LightMagenta,
57                    14 => Color::LightCyan,
58                    15 => Color::White,
59                    _ => Color::Indexed(idx),
60                }
61            }
62            ColorAttribute::TrueColorWithPaletteFallback(rgb, _)
63            | ColorAttribute::TrueColorWithDefaultFallback(rgb) => Color::Rgb(
64                (rgb.0 * 255.0) as u8,
65                (rgb.1 * 255.0) as u8,
66                (rgb.2 * 255.0) as u8,
67            ),
68        }
69    }
70
71    /// Convert attributes to ratatui modifiers
72    pub fn to_ratatui_modifier(&self) -> Modifier {
73        let mut modifier = Modifier::empty();
74
75        if self.intensity == Intensity::Bold {
76            modifier |= Modifier::BOLD;
77        }
78        if self.intensity == Intensity::Half {
79            modifier |= Modifier::DIM;
80        }
81        if self.underline {
82            modifier |= Modifier::UNDERLINED;
83        }
84        if self.blink {
85            modifier |= Modifier::SLOW_BLINK;
86        }
87        if self.reverse {
88            modifier |= Modifier::REVERSED;
89        }
90        if self.strikethrough {
91            modifier |= Modifier::CROSSED_OUT;
92        }
93        if self.italic {
94            modifier |= Modifier::ITALIC;
95        }
96
97        modifier
98    }
99
100    /// Convert to ratatui style
101    pub fn to_ratatui_style(&self) -> Style {
102        let fg = Self::termwiz_to_ratatui_color(self.fgcolor);
103        let bg = Self::termwiz_to_ratatui_color(self.bgcolor);
104
105        Style::default()
106            .fg(fg)
107            .bg(bg)
108            .add_modifier(self.to_ratatui_modifier())
109    }
110}
111
112/// A single terminal cell
113#[derive(Debug, Clone)]
114pub struct Cell {
115    /// The character in this cell
116    pub text: String,
117
118    /// Text attributes
119    pub attrs: Attrs,
120}
121
122impl Default for Cell {
123    fn default() -> Self {
124        Self {
125            text: " ".to_string(),
126            attrs: Attrs::default(),
127        }
128    }
129}
130
131impl Cell {
132    /// Create a new cell with a character
133    pub fn new(text: impl Into<String>) -> Self {
134        Self {
135            text: text.into(),
136            attrs: Attrs::default(),
137        }
138    }
139
140    /// Create a new cell with character and attributes
141    pub fn with_attrs(text: impl Into<String>, attrs: Attrs) -> Self {
142        Self {
143            text: text.into(),
144            attrs,
145        }
146    }
147
148    /// Check if cell has content (not just space)
149    pub fn has_contents(&self) -> bool {
150        !self.text.trim().is_empty()
151    }
152
153    /// Convert to ratatui cell
154    pub fn to_ratatui(&self) -> ratatui::buffer::Cell {
155        let mut cell = ratatui::buffer::Cell::default();
156        cell.set_symbol(&self.text);
157        cell.set_style(self.attrs.to_ratatui_style());
158        cell
159    }
160}