frozen_term/terminal/
style.rs

1use std::{cell::LazyCell, sync::Arc};
2
3use termwiz::color::ColorAttribute;
4use wezterm_term::color::ColorPalette;
5
6use iced::{Padding, Pixels};
7
8#[derive(Clone)]
9pub struct Style {
10    pub line_height: iced::widget::text::LineHeight,
11    pub text_size: Option<Pixels>,
12    pub padding: iced::Padding,
13    pub background_color: iced::Color,
14    pub foreground_color: iced::Color,
15    pub font: iced::Font,
16    pub cursor_shape: CursorShape,
17    /// This value is used to set the height of the background for the text.
18    /// If you use a custom font, you might have to experiment which value works best for your font.
19    // pub font_height_modifier: f32,
20    pub palette: Arc<Palette256>,
21}
22
23pub struct Palette256(pub [iced::Color; 256]);
24
25#[derive(Debug, Clone, Copy)]
26pub enum CursorShape {
27    Block,
28    Underline,
29    Bar,
30}
31
32impl Palette256 {
33    fn from_wezterm(palette: wezterm_term::color::Palette256) -> Self {
34        let mut iced_palette = [iced::Color::BLACK; 256];
35
36        for (wez_color, iced_color) in palette.0.into_iter().zip(iced_palette.iter_mut()) {
37            let (r, g, b, a) = wez_color.to_tuple_rgba();
38            *iced_color = iced::Color::from_rgba(r, g, b, a);
39        }
40
41        Self(iced_palette)
42    }
43}
44
45const DEFAULT_STYLE: LazyCell<Style> = LazyCell::new(|| {
46    let palette = ColorPalette::default();
47
48    let (r, g, b, a) = palette.background.to_tuple_rgba();
49    let background_color = iced::Color::from_rgba(r, g, b, a);
50
51    let (r, g, b, a) = palette.foreground.to_tuple_rgba();
52    let foreground_color = iced::Color::from_rgba(r, g, b, a);
53
54    Style {
55        line_height: iced::widget::text::LineHeight::default(),
56        text_size: None,
57        padding: Padding::new(10.0),
58        cursor_shape: CursorShape::Underline,
59        background_color,
60        foreground_color,
61        font: iced::Font::MONOSPACE,
62        // font_height_modifier: 1.0,
63        palette: Arc::new(Palette256::from_wezterm(palette.colors)),
64    }
65});
66
67impl Default for Style {
68    fn default() -> Self {
69        DEFAULT_STYLE.clone()
70    }
71}
72
73impl Style {
74    pub fn line_height(mut self, line_height: impl Into<iced::widget::text::LineHeight>) -> Self {
75        self.line_height = line_height.into();
76        self
77    }
78
79    pub fn text_size(mut self, size: impl Into<Pixels>) -> Self {
80        self.text_size = Some(size.into());
81        self
82    }
83
84    pub fn padding(mut self, padding: Padding) -> Self {
85        self.padding = padding;
86        self
87    }
88
89    pub fn foreground_color(mut self, color: impl Into<iced::Color>) -> Self {
90        self.foreground_color = color.into();
91        self
92    }
93
94    pub fn background_color(mut self, color: impl Into<iced::Color>) -> Self {
95        self.background_color = color.into();
96        self
97    }
98
99    pub fn font(mut self, font: iced::Font) -> Self {
100        self.font = font;
101        self
102    }
103
104    pub fn palette(mut self, palette: Arc<Palette256>) -> Self {
105        self.palette = palette;
106        self
107    }
108
109    pub fn cursor_shape(mut self, shape: CursorShape) -> Self {
110        self.cursor_shape = shape;
111        self
112    }
113
114    pub(crate) fn get_color(&self, color: ColorAttribute) -> Option<iced::Color> {
115        match color {
116            ColorAttribute::TrueColorWithPaletteFallback(srgba_tuple, _)
117            | ColorAttribute::TrueColorWithDefaultFallback(srgba_tuple) => {
118                let (r, g, b, a) = srgba_tuple.to_tuple_rgba();
119                Some(iced::Color::from_rgba(r, g, b, a))
120            }
121            ColorAttribute::PaletteIndex(index) => Some(self.palette.0[index as usize]),
122            ColorAttribute::Default => None,
123        }
124    }
125}