Skip to main content

egui_code_editor/themes/
mod.rs

1#![allow(dead_code)]
2pub mod ayu;
3pub mod github;
4pub mod gruvbox;
5pub mod sonokai;
6
7use super::syntax::TokenType;
8#[cfg(feature = "egui")]
9use egui::Color32;
10
11#[cfg(feature = "egui")]
12pub const ERROR_COLOR: Color32 = Color32::from_rgb(255, 0, 255);
13
14/// Array of default themes.
15pub const DEFAULT_THEMES: [ColorTheme; 8] = [
16    ColorTheme::AYU,
17    ColorTheme::AYU_MIRAGE,
18    ColorTheme::AYU_DARK,
19    ColorTheme::GITHUB_DARK,
20    ColorTheme::GITHUB_LIGHT,
21    ColorTheme::GRUVBOX,
22    ColorTheme::GRUVBOX_LIGHT,
23    ColorTheme::SONOKAI,
24];
25
26#[cfg(feature = "egui")]
27fn color_from_hex(hex: &str) -> Option<Color32> {
28    if hex == "none" {
29        return Some(Color32::from_rgba_premultiplied(255, 0, 255, 0));
30    }
31    let rgb = (1..hex.len())
32        .step_by(2)
33        .filter_map(|i| u8::from_str_radix(&hex[i..i + 2], 16).ok())
34        .collect::<Vec<u8>>();
35    let color = Color32::from_rgb(*rgb.first()?, *rgb.get(1)?, *rgb.get(2)?);
36    Some(color)
37}
38
39#[derive(Hash, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
40/// Colors in hexadecimal notation as used in HTML and CSS.
41pub struct ColorTheme {
42    pub name: &'static str,
43    pub dark: bool,
44    pub bg: &'static str,
45    pub cursor: &'static str,
46    pub selection: &'static str,
47    pub comments: &'static str,
48    pub functions: &'static str,
49    pub keywords: &'static str,
50    pub literals: &'static str,
51    pub numerics: &'static str,
52    pub punctuation: &'static str,
53    pub strs: &'static str,
54    pub types: &'static str,
55    pub special: &'static str,
56}
57impl Default for ColorTheme {
58    fn default() -> Self {
59        ColorTheme::GRUVBOX
60    }
61}
62impl ColorTheme {
63    pub fn name(&self) -> &str {
64        self.name
65    }
66
67    pub fn is_dark(&self) -> bool {
68        self.dark
69    }
70
71    #[cfg(feature = "egui")]
72    pub fn bg(&self) -> Color32 {
73        color_from_hex(self.bg).unwrap_or(ERROR_COLOR)
74    }
75
76    #[cfg(feature = "egui")]
77    pub fn cursor(&self) -> Color32 {
78        color_from_hex(self.cursor).unwrap_or(ERROR_COLOR)
79    }
80
81    #[cfg(feature = "egui")]
82    pub fn selection(&self) -> Color32 {
83        color_from_hex(self.selection).unwrap_or(ERROR_COLOR)
84    }
85
86    #[cfg(feature = "egui")]
87    pub fn modify_style(&self, ui: &mut egui::Ui, fontsize: f32) {
88        let style = ui.style_mut();
89        let bg = self.bg();
90        style.visuals.widgets.noninteractive.bg_fill = bg;
91        style.visuals.window_fill = bg;
92        style.visuals.panel_fill = bg;
93        style.visuals.faint_bg_color = bg;
94        style.visuals.extreme_bg_color = bg;
95        style.visuals.selection.stroke.color = self.cursor();
96        style.visuals.selection.bg_fill = self.selection();
97        style.override_font_id = Some(egui::FontId::monospace(fontsize));
98        style.visuals.text_cursor.stroke.width = fontsize * 0.1;
99    }
100
101    pub const fn type_color_str(&self, ty: TokenType) -> &'static str {
102        match ty {
103            TokenType::Comment(_) => self.comments,
104            TokenType::Function => self.functions,
105            TokenType::Keyword => self.keywords,
106            TokenType::Literal => self.literals,
107            TokenType::Hyperlink => self.special,
108            TokenType::Numeric(_) => self.numerics,
109            TokenType::Punctuation(_) => self.punctuation,
110            TokenType::Special => self.special,
111            TokenType::Str(_) => self.strs,
112            TokenType::Type => self.types,
113            TokenType::Whitespace(_) | TokenType::Unknown => self.comments,
114        }
115    }
116
117    #[cfg(feature = "egui")]
118    pub fn type_color(&self, ty: TokenType) -> Color32 {
119        match ty {
120            TokenType::Comment(_) => color_from_hex(self.comments),
121            TokenType::Function => color_from_hex(self.functions),
122            TokenType::Keyword => color_from_hex(self.keywords),
123            TokenType::Literal => color_from_hex(self.literals),
124            TokenType::Hyperlink => color_from_hex(self.special),
125            TokenType::Numeric(_) => color_from_hex(self.numerics),
126            TokenType::Punctuation(_) => color_from_hex(self.punctuation),
127            TokenType::Special => color_from_hex(self.special),
128            TokenType::Str(_) => color_from_hex(self.strs),
129            TokenType::Type => color_from_hex(self.types),
130            TokenType::Whitespace(_) | TokenType::Unknown => color_from_hex(self.comments),
131        }
132        .unwrap_or(ERROR_COLOR)
133    }
134
135    pub fn monocolor(
136        dark: bool,
137        bg: &'static str,
138        fg: &'static str,
139        cursor: &'static str,
140        selection: &'static str,
141    ) -> Self {
142        ColorTheme {
143            name: "monocolor",
144            dark,
145            bg,
146            cursor,
147            selection,
148            literals: fg,
149            numerics: fg,
150            keywords: fg,
151            functions: fg,
152            punctuation: fg,
153            types: fg,
154            strs: fg,
155            comments: fg,
156            special: fg,
157        }
158    }
159}