Skip to main content

itools_tui/
style.rs

1//! 样式系统模块
2//!
3//! 提供样式相关功能,包括颜色、字体样式和边框样式。
4
5use crossterm::style as crossterm_style;
6
7/// 颜色
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum Color {
10    /// 黑色
11    Black,
12    /// 红色
13    Red,
14    /// 绿色
15    Green,
16    /// 黄色
17    Yellow,
18    /// 蓝色
19    Blue,
20    /// 紫色
21    Magenta,
22    /// 青色
23    Cyan,
24    /// 白色
25    White,
26    /// 亮黑色
27    BrightBlack,
28    /// 亮红色
29    BrightRed,
30    /// 亮绿色
31    BrightGreen,
32    /// 亮黄色
33    BrightYellow,
34    /// 亮蓝色
35    BrightBlue,
36    /// 亮紫色
37    BrightMagenta,
38    /// 亮青色
39    BrightCyan,
40    /// 亮白色
41    BrightWhite,
42    /// RGB 颜色
43    Rgb(u8, u8, u8),
44}
45
46impl From<Color> for crossterm_style::Color {
47    fn from(color: Color) -> Self {
48        match color {
49            Color::Black => crossterm_style::Color::Black,
50            Color::Red => crossterm_style::Color::Red,
51            Color::Green => crossterm_style::Color::Green,
52            Color::Yellow => crossterm_style::Color::Yellow,
53            Color::Blue => crossterm_style::Color::Blue,
54            Color::Magenta => crossterm_style::Color::Magenta,
55            Color::Cyan => crossterm_style::Color::Cyan,
56            Color::White => crossterm_style::Color::White,
57            Color::BrightBlack => crossterm_style::Color::AnsiValue(8),
58            Color::BrightRed => crossterm_style::Color::AnsiValue(9),
59            Color::BrightGreen => crossterm_style::Color::AnsiValue(10),
60            Color::BrightYellow => crossterm_style::Color::AnsiValue(11),
61            Color::BrightBlue => crossterm_style::Color::AnsiValue(12),
62            Color::BrightMagenta => crossterm_style::Color::AnsiValue(13),
63            Color::BrightCyan => crossterm_style::Color::AnsiValue(14),
64            Color::BrightWhite => crossterm_style::Color::AnsiValue(15),
65            Color::Rgb(r, g, b) => crossterm_style::Color::Rgb { r, g, b },
66        }
67    }
68}
69
70/// 字体样式修饰符
71#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
72pub struct Modifier {
73    bits: u8,
74}
75
76impl Modifier {
77    /// 空修饰符
78    pub const NONE: Self = Self { bits: 0 };
79    /// 粗体
80    pub const BOLD: Self = Self { bits: 1 };
81    /// 斜体
82    pub const ITALIC: Self = Self { bits: 2 };
83    /// 下划线
84    pub const UNDERLINED: Self = Self { bits: 4 };
85    /// 反显
86    pub const REVERSED: Self = Self { bits: 8 };
87
88    /// 检查是否包含指定修饰符
89    pub fn contains(&self, other: Self) -> bool {
90        (self.bits & other.bits) == other.bits
91    }
92
93    /// 添加修饰符
94    pub fn insert(&mut self, other: Self) {
95        self.bits |= other.bits;
96    }
97
98    /// 移除修饰符
99    pub fn remove(&mut self, other: Self) {
100        self.bits &= !other.bits;
101    }
102}
103
104impl std::ops::BitOr for Modifier {
105    type Output = Self;
106
107    fn bitor(self, rhs: Self) -> Self {
108        Self { bits: self.bits | rhs.bits }
109    }
110}
111
112impl std::ops::BitOrAssign for Modifier {
113    fn bitor_assign(&mut self, rhs: Self) {
114        self.bits |= rhs.bits;
115    }
116}
117
118/// 样式
119#[derive(Debug, Clone, PartialEq, Eq)]
120pub struct Style {
121    /// 前景色
122    pub fg: Option<Color>,
123    /// 背景色
124    pub bg: Option<Color>,
125    /// 修饰符
126    pub modifiers: Modifier,
127}
128
129impl Default for Style {
130    fn default() -> Self {
131        Self { fg: None, bg: None, modifiers: Modifier::NONE }
132    }
133}
134
135impl Style {
136    /// 创建默认样式
137    pub fn new() -> Self {
138        Self::default()
139    }
140
141    /// 设置前景色
142    pub fn fg(mut self, color: Color) -> Self {
143        self.fg = Some(color);
144        self
145    }
146
147    /// 设置背景色
148    pub fn bg(mut self, color: Color) -> Self {
149        self.bg = Some(color);
150        self
151    }
152
153    /// 设置粗体
154    pub fn bold(mut self) -> Self {
155        self.modifiers.insert(Modifier::BOLD);
156        self
157    }
158
159    /// 设置斜体
160    pub fn italic(mut self) -> Self {
161        self.modifiers.insert(Modifier::ITALIC);
162        self
163    }
164
165    /// 设置下划线
166    pub fn underlined(mut self) -> Self {
167        self.modifiers.insert(Modifier::UNDERLINED);
168        self
169    }
170
171    /// 设置反显
172    pub fn reversed(mut self) -> Self {
173        self.modifiers.insert(Modifier::REVERSED);
174        self
175    }
176
177    /// 组合样式
178    pub fn combine(&mut self, other: &Style) {
179        if other.fg.is_some() {
180            self.fg = other.fg;
181        }
182        if other.bg.is_some() {
183            self.bg = other.bg;
184        }
185        self.modifiers |= other.modifiers;
186    }
187
188    /// 转换为 crossterm 样式
189    pub fn to_crossterm_style(&self) -> crossterm_style::ContentStyle {
190        let mut content_style = crossterm_style::ContentStyle::default();
191
192        // 直接设置前景色和背景色
193        if let Some(fg) = self.fg {
194            content_style.foreground_color = Some(crossterm_style::Color::from(fg));
195        }
196
197        if let Some(bg) = self.bg {
198            content_style.background_color = Some(crossterm_style::Color::from(bg));
199        }
200
201        // 设置修饰符
202        if self.modifiers.contains(Modifier::BOLD) {
203            content_style.attributes.set(crossterm_style::Attribute::Bold);
204        }
205
206        if self.modifiers.contains(Modifier::ITALIC) {
207            content_style.attributes.set(crossterm_style::Attribute::Italic);
208        }
209
210        if self.modifiers.contains(Modifier::UNDERLINED) {
211            content_style.attributes.set(crossterm_style::Attribute::Underlined);
212        }
213
214        if self.modifiers.contains(Modifier::REVERSED) {
215            content_style.attributes.set(crossterm_style::Attribute::Reverse);
216        }
217
218        content_style
219    }
220}