1use super::{Style, StyleColor};
2use crate::Context;
3use crate::internal::RawWrapper;
4use crate::sys;
5use crate::widget::{TableFlags, TableRowFlags};
6use crate::window::WindowFlags;
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9
10#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
15#[derive(Copy, Clone, Debug, PartialEq, Eq)]
16pub enum ThemePreset {
17 None,
19 Dark,
21 Light,
23 Classic,
25}
26
27impl Default for ThemePreset {
28 fn default() -> Self {
29 ThemePreset::None
30 }
31}
32
33#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
35#[derive(Clone, Debug, PartialEq)]
36pub struct ColorOverride {
37 pub id: StyleColor,
39 pub rgba: [f32; 4],
41}
42
43#[derive(Clone, Debug)]
48#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
49#[cfg_attr(feature = "serde", serde(default))]
50pub struct StyleTweaks {
51 pub window_rounding: Option<f32>,
52 pub frame_rounding: Option<f32>,
53 pub tab_rounding: Option<f32>,
54
55 pub window_padding: Option<[f32; 2]>,
56 pub frame_padding: Option<[f32; 2]>,
57 pub cell_padding: Option<[f32; 2]>,
58 pub item_spacing: Option<[f32; 2]>,
59 pub item_inner_spacing: Option<[f32; 2]>,
60
61 pub scrollbar_size: Option<f32>,
62 pub grab_min_size: Option<f32>,
63
64 pub indent_spacing: Option<f32>,
65 pub separator_size: Option<f32>,
66 pub scrollbar_rounding: Option<f32>,
67 pub grab_rounding: Option<f32>,
68 pub window_border_size: Option<f32>,
69 pub child_border_size: Option<f32>,
70 pub popup_border_size: Option<f32>,
71 pub frame_border_size: Option<f32>,
72 pub tab_border_size: Option<f32>,
73 pub child_rounding: Option<f32>,
74 pub popup_rounding: Option<f32>,
75
76 pub anti_aliased_lines: Option<bool>,
77 pub anti_aliased_fill: Option<bool>,
78}
79
80impl Default for StyleTweaks {
81 fn default() -> Self {
82 Self {
83 window_rounding: None,
84 frame_rounding: None,
85 tab_rounding: None,
86 window_padding: None,
87 frame_padding: None,
88 cell_padding: None,
89 item_spacing: None,
90 item_inner_spacing: None,
91 scrollbar_size: None,
92 grab_min_size: None,
93 indent_spacing: None,
94 separator_size: None,
95 scrollbar_rounding: None,
96 grab_rounding: None,
97 window_border_size: None,
98 child_border_size: None,
99 popup_border_size: None,
100 frame_border_size: None,
101 tab_border_size: None,
102 child_rounding: None,
103 popup_rounding: None,
104 anti_aliased_lines: None,
105 anti_aliased_fill: None,
106 }
107 }
108}
109
110impl StyleTweaks {
111 pub fn apply(&self, style: &mut Style) {
113 if let Some(v) = self.window_rounding {
114 style.set_window_rounding(v);
115 }
116 if let Some(v) = self.frame_rounding {
117 style.set_frame_rounding(v);
118 }
119 if let Some(v) = self.tab_rounding {
120 style.set_tab_rounding(v);
121 }
122
123 if let Some(v) = self.window_padding {
124 style.set_window_padding(v);
125 }
126 if let Some(v) = self.frame_padding {
127 style.set_frame_padding(v);
128 }
129 if let Some(v) = self.cell_padding {
130 style.set_cell_padding(v);
131 }
132 if let Some(v) = self.item_spacing {
133 style.set_item_spacing(v);
134 }
135 if let Some(v) = self.item_inner_spacing {
136 style.set_item_inner_spacing(v);
137 }
138
139 if let Some(v) = self.scrollbar_size {
140 style.set_scrollbar_size(v);
141 }
142 if let Some(v) = self.grab_min_size {
143 style.set_grab_min_size(v);
144 }
145
146 if let Some(v) = self.indent_spacing {
147 style.set_indent_spacing(v);
148 }
149 if let Some(v) = self.separator_size {
150 style.set_separator_size(v);
151 }
152 if let Some(v) = self.scrollbar_rounding {
153 style.set_scrollbar_rounding(v);
154 }
155 if let Some(v) = self.grab_rounding {
156 style.set_grab_rounding(v);
157 }
158 if let Some(v) = self.window_border_size {
159 style.set_window_border_size(v);
160 }
161 if let Some(v) = self.child_border_size {
162 style.set_child_border_size(v);
163 }
164 if let Some(v) = self.popup_border_size {
165 style.set_popup_border_size(v);
166 }
167 if let Some(v) = self.frame_border_size {
168 style.set_frame_border_size(v);
169 }
170 if let Some(v) = self.tab_border_size {
171 style.set_tab_border_size(v);
172 }
173 if let Some(v) = self.child_rounding {
174 style.set_child_rounding(v);
175 }
176 if let Some(v) = self.popup_rounding {
177 style.set_popup_rounding(v);
178 }
179
180 if let Some(v) = self.anti_aliased_lines {
181 style.set_anti_aliased_lines(v);
182 }
183 if let Some(v) = self.anti_aliased_fill {
184 style.set_anti_aliased_fill(v);
185 }
186 }
187}
188
189#[derive(Clone, Debug, Default)]
191#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
192pub struct WindowTheme {
193 pub default_window_flags: Option<WindowFlags>,
195 pub popup_window_flags: Option<WindowFlags>,
197}
198
199#[derive(Clone, Debug, Default)]
201#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
202pub struct TableTheme {
203 pub default_table_flags: Option<TableFlags>,
205 pub default_row_flags: Option<TableRowFlags>,
207}
208
209#[derive(Clone, Debug, Default)]
219#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
220pub struct Theme {
221 #[cfg_attr(feature = "serde", serde(default))]
223 pub preset: ThemePreset,
224
225 #[cfg_attr(feature = "serde", serde(default))]
227 pub colors: Vec<ColorOverride>,
228
229 #[cfg_attr(feature = "serde", serde(default))]
231 pub style: StyleTweaks,
232
233 #[cfg_attr(feature = "serde", serde(default))]
235 pub windows: WindowTheme,
236
237 #[cfg_attr(feature = "serde", serde(default))]
239 pub tables: TableTheme,
240}
241
242impl Theme {
243 pub fn apply_to_style(&self, style: &mut Style) {
247 match self.preset {
249 ThemePreset::None => {}
250 ThemePreset::Dark => unsafe {
251 sys::igStyleColorsDark(style.raw_mut());
252 },
253 ThemePreset::Light => unsafe {
254 sys::igStyleColorsLight(style.raw_mut());
255 },
256 ThemePreset::Classic => unsafe {
257 sys::igStyleColorsClassic(style.raw_mut());
258 },
259 }
260
261 for c in &self.colors {
263 style.set_color(c.id, c.rgba);
264 }
265
266 self.style.apply(style);
268 }
269
270 pub fn apply_to_context(&self, ctx: &mut Context) {
272 let style = ctx.style_mut();
273 self.apply_to_style(style);
274 }
275}