urushi/theme/
component_theme.rs1use crate::{
4 BlockStyle, Border, ListPresentation, ScrollbarPresentation, TablePresentation, TextStyle,
5 TreePresentation,
6};
7
8use super::{ComponentRole, ListRole, ScrollbarRole, SemanticTokens, TableRole, TreeRole};
9
10const COMPONENT_ROLE_COUNT: usize = 15;
11
12#[derive(Debug, Clone, PartialEq)]
14pub struct ComponentTheme {
15 text_styles: [TextStyle; COMPONENT_ROLE_COUNT],
16 panel: BlockStyle,
17 panel_focused: BlockStyle,
18 list: ListPresentation,
19 tree: TreePresentation,
20 table: TablePresentation,
21 scrollbar: ScrollbarPresentation,
22}
23
24impl ComponentTheme {
25 pub fn from_tokens(tokens: &SemanticTokens) -> Self {
27 let panel = BlockStyle::new()
28 .foreground(tokens.text)
29 .background(tokens.surface)
30 .border(Border::ROUNDED)
31 .border_foreground(tokens.border)
32 .padding((0, 1));
33
34 let text_styles = [
35 TextStyle::new().foreground(tokens.text),
36 TextStyle::new().foreground(tokens.text_muted).dim(),
37 TextStyle::new().foreground(tokens.accent).bold(),
38 TextStyle::new().foreground(tokens.success),
39 TextStyle::new().foreground(tokens.error).bold(),
40 TextStyle::new().foreground(tokens.accent).bold(),
41 TextStyle::new().foreground(tokens.text),
42 TextStyle::new().foreground(tokens.text_muted).italic(),
43 TextStyle::new().foreground(tokens.accent).bold(),
44 TextStyle::new().foreground(tokens.text),
45 TextStyle::new()
46 .foreground(tokens.accent_text)
47 .background(tokens.accent)
48 .bold(),
49 TextStyle::new()
50 .foreground(tokens.text)
51 .background(tokens.surface),
52 TextStyle::new()
53 .foreground(tokens.accent_text)
54 .background(tokens.accent)
55 .bold(),
56 TextStyle::new().foreground(tokens.text_muted).dim(),
57 TextStyle::new().foreground(tokens.error),
58 ];
59 Self {
60 text_styles,
61 panel: panel.clone(),
62 panel_focused: panel.border_foreground(tokens.accent),
63 list: ListPresentation::new(
64 TextStyle::new().foreground(tokens.text),
65 TextStyle::new().foreground(tokens.text_muted),
66 ),
67 tree: TreePresentation::new(
68 TextStyle::new().foreground(tokens.text).bold(),
69 TextStyle::new().foreground(tokens.text),
70 TextStyle::new().foreground(tokens.text_muted),
71 ),
72 table: TablePresentation::new(
73 BlockStyle::new().foreground(tokens.text).bold(),
74 BlockStyle::new().foreground(tokens.text),
75 TextStyle::new().foreground(tokens.border),
76 ),
77 scrollbar: ScrollbarPresentation::new(
78 TextStyle::new().foreground(tokens.accent),
79 TextStyle::new().foreground(tokens.border),
80 ),
81 }
82 }
83
84 pub fn get_text_style(&self, role: ComponentRole) -> &TextStyle {
85 &self.text_styles[role.index()]
86 }
87
88 pub const fn get_panel(&self) -> &BlockStyle {
90 &self.panel
91 }
92
93 pub const fn get_panel_focused(&self) -> &BlockStyle {
95 &self.panel_focused
96 }
97
98 pub fn get_list_style(&self, role: ListRole) -> &TextStyle {
100 self.list.get_style(role)
101 }
102
103 pub fn get_tree_style(&self, role: TreeRole) -> &TextStyle {
105 self.tree.get_style(role)
106 }
107
108 pub fn get_table_style(&self, role: TableRole) -> &BlockStyle {
110 self.table.get_style(role)
111 }
112
113 pub fn get_scrollbar_style(&self, role: ScrollbarRole) -> &TextStyle {
115 self.scrollbar.get_style(role)
116 }
117
118 pub fn list(&self) -> &ListPresentation {
120 &self.list
121 }
122
123 pub fn tree(&self) -> &TreePresentation {
125 &self.tree
126 }
127
128 pub fn table(&self) -> &TablePresentation {
130 &self.table
131 }
132
133 pub fn scrollbar(&self) -> &ScrollbarPresentation {
135 &self.scrollbar
136 }
137
138 #[must_use]
139 pub fn text_style(mut self, role: ComponentRole, style: TextStyle) -> Self {
140 self.text_styles[role.index()] = style;
141 self
142 }
143
144 #[must_use]
146 pub fn panel(mut self, panel: BlockStyle) -> Self {
147 self.panel = panel;
148 self
149 }
150
151 #[must_use]
153 pub fn panel_focused(mut self, panel: BlockStyle) -> Self {
154 self.panel_focused = panel;
155 self
156 }
157
158 #[must_use]
160 pub fn list_style(mut self, role: ListRole, style: TextStyle) -> Self {
161 self.list = self.list.style(role, style);
162 self
163 }
164
165 #[must_use]
167 pub fn tree_style(mut self, role: TreeRole, style: TextStyle) -> Self {
168 self.tree = self.tree.style(role, style);
169 self
170 }
171
172 #[must_use]
174 pub fn table_style(mut self, role: TableRole, style: BlockStyle) -> Self {
175 self.table = self.table.style(role, style);
176 self
177 }
178
179 #[must_use]
181 pub fn scrollbar_style(mut self, role: ScrollbarRole, style: TextStyle) -> Self {
182 self.scrollbar = self.scrollbar.style(role, style);
183 self
184 }
185}