1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
use compact_str::CompactString;
use crate::prelude::*;
/// A buffer cell
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Cell {
/// The string to be drawn in the cell.
///
/// This accepts unicode grapheme clusters which might take up more than one cell.
///
/// This is a [`CompactString`] which is a wrapper around [`String`] that uses a small inline
/// buffer for short strings.
///
/// See <https://github.com/ratatui-org/ratatui/pull/601> for more information.
symbol: CompactString,
/// The foreground color of the cell.
pub fg: Color,
/// The background color of the cell.
pub bg: Color,
/// The underline color of the cell.
#[cfg(feature = "underline-color")]
pub underline_color: Color,
/// The modifier of the cell.
pub modifier: Modifier,
/// Whether the cell should be skipped when copying (diffing) the buffer to the screen.
pub skip: bool,
}
impl Cell {
/// Gets the symbol of the cell.
pub fn symbol(&self) -> &str {
self.symbol.as_str()
}
/// Sets the symbol of the cell.
pub fn set_symbol(&mut self, symbol: &str) -> &mut Self {
self.symbol = CompactString::new(symbol);
self
}
/// Sets the symbol of the cell to a single character.
pub fn set_char(&mut self, ch: char) -> &mut Self {
let mut buf = [0; 4];
self.symbol = CompactString::new(ch.encode_utf8(&mut buf));
self
}
/// Sets the foreground color of the cell.
pub fn set_fg(&mut self, color: Color) -> &mut Self {
self.fg = color;
self
}
/// Sets the background color of the cell.
pub fn set_bg(&mut self, color: Color) -> &mut Self {
self.bg = color;
self
}
/// Sets the style of the cell.
///
/// `style` accepts any type that is convertible to [`Style`] (e.g. [`Style`], [`Color`], or
/// your own type that implements [`Into<Style>`]).
pub fn set_style<S: Into<Style>>(&mut self, style: S) -> &mut Self {
let style = style.into();
if let Some(c) = style.fg {
self.fg = c;
}
if let Some(c) = style.bg {
self.bg = c;
}
#[cfg(feature = "underline-color")]
if let Some(c) = style.underline_color {
self.underline_color = c;
}
self.modifier.insert(style.add_modifier);
self.modifier.remove(style.sub_modifier);
self
}
/// Returns the style of the cell.
pub fn style(&self) -> Style {
#[cfg(feature = "underline-color")]
return Style::default()
.fg(self.fg)
.bg(self.bg)
.underline_color(self.underline_color)
.add_modifier(self.modifier);
#[cfg(not(feature = "underline-color"))]
return Style::default()
.fg(self.fg)
.bg(self.bg)
.add_modifier(self.modifier);
}
/// Sets the cell to be skipped when copying (diffing) the buffer to the screen.
///
/// This is helpful when it is necessary to prevent the buffer from overwriting a cell that is
/// covered by an image from some terminal graphics protocol (Sixel / iTerm / Kitty ...).
pub fn set_skip(&mut self, skip: bool) -> &mut Self {
self.skip = skip;
self
}
/// Resets the cell to the default state.
pub fn reset(&mut self) {
self.symbol = CompactString::new_inline(" ");
self.fg = Color::Reset;
self.bg = Color::Reset;
#[cfg(feature = "underline-color")]
{
self.underline_color = Color::Reset;
}
self.modifier = Modifier::empty();
self.skip = false;
}
}
impl Default for Cell {
fn default() -> Self {
Self {
symbol: CompactString::new_inline(" "),
fg: Color::Reset,
bg: Color::Reset,
#[cfg(feature = "underline-color")]
underline_color: Color::Reset,
modifier: Modifier::empty(),
skip: false,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn symbol_field() {
let mut cell = Cell::default();
assert_eq!(cell.symbol(), " ");
cell.set_symbol("ใ"); // Multi-byte character
assert_eq!(cell.symbol(), "ใ");
cell.set_symbol("๐จโ๐ฉโ๐งโ๐ฆ"); // Multiple code units combined with ZWJ
assert_eq!(cell.symbol(), "๐จโ๐ฉโ๐งโ๐ฆ");
}
}