1use std::ops::{Index, IndexMut};
2
3use crate::internal::RawCast;
4use crate::sys;
5use crate::Direction;
6
7#[repr(C)]
9#[derive(Debug, Copy, Clone)]
10pub struct Style {
11 pub alpha: f32,
13 pub window_padding: [f32; 2],
15 pub window_rounding: f32,
20 pub window_border_size: f32,
24 pub window_min_size: [f32; 2],
26 pub window_title_align: [f32; 2],
30 pub window_menu_button_position: Direction,
34 pub child_rounding: f32,
38 pub child_border_size: f32,
42 pub popup_rounding: f32,
46 pub popup_border_size: f32,
50 pub frame_padding: [f32; 2],
52 pub frame_rounding: f32,
56 pub frame_border_size: f32,
60 pub item_spacing: [f32; 2],
62 pub item_inner_spacing: [f32; 2],
65 pub cell_padding: [f32; 2],
67 pub touch_extra_padding: [f32; 2],
73 pub indent_spacing: f32,
77 pub columns_min_spacing: f32,
79 pub scrollbar_size: f32,
81 pub scrollbar_rounding: f32,
83 pub grab_min_size: f32,
85 pub grab_rounding: f32,
89 pub log_slider_deadzone: f32,
91 pub tab_rounding: f32,
95 pub tab_border_size: f32,
97 pub tab_min_width_for_close_button: f32,
102 pub color_button_position: Direction,
104 pub button_text_align: [f32; 2],
108 pub selectable_text_align: [f32; 2],
112 pub display_window_padding: [f32; 2],
117 pub display_safe_area_padding: [f32; 2],
121 pub mouse_cursor_scale: f32,
125 pub anti_aliased_lines: bool,
129 pub anti_aliased_lines_use_tex: bool,
133 pub anti_aliased_fill: bool,
137 pub curve_tessellation_tol: f32,
143 pub circle_tesselation_max_error: f32,
148 pub colors: [[f32; 4]; StyleColor::COUNT],
150}
151
152unsafe impl RawCast<sys::ImGuiStyle> for Style {}
153
154impl Style {
155 #[doc(alias = "ScaleAllSizes")]
157 pub fn scale_all_sizes(&mut self, scale_factor: f32) {
158 unsafe {
159 sys::ImGuiStyle_ScaleAllSizes(self.raw_mut(), scale_factor);
160 }
161 }
162 #[doc(alias = "StyleColors", alias = "StlyeColorsClassic")]
164 pub fn use_classic_colors(&mut self) -> &mut Self {
165 unsafe {
166 sys::igStyleColorsClassic(self.raw_mut());
167 }
168 self
169 }
170 #[doc(alias = "StyleColors", alias = "StyleColorsDark")]
172 pub fn use_dark_colors(&mut self) -> &mut Self {
173 unsafe {
174 sys::igStyleColorsDark(self.raw_mut());
175 }
176 self
177 }
178 #[doc(alias = "StyleColors", alias = "StyleColorsLight")]
181 pub fn use_light_colors(&mut self) -> &mut Self {
182 unsafe {
183 sys::igStyleColorsLight(self.raw_mut());
184 }
185 self
186 }
187}
188
189impl Index<StyleColor> for Style {
190 type Output = [f32; 4];
191 #[inline]
192 fn index(&self, index: StyleColor) -> &[f32; 4] {
193 &self.colors[index as usize]
194 }
195}
196
197impl IndexMut<StyleColor> for Style {
198 #[inline]
199 fn index_mut(&mut self, index: StyleColor) -> &mut [f32; 4] {
200 &mut self.colors[index as usize]
201 }
202}
203
204#[repr(u32)]
206#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
207pub enum StyleColor {
208 Text = sys::ImGuiCol_Text,
209 TextDisabled = sys::ImGuiCol_TextDisabled,
210 WindowBg = sys::ImGuiCol_WindowBg,
212 ChildBg = sys::ImGuiCol_ChildBg,
214 PopupBg = sys::ImGuiCol_PopupBg,
216 Border = sys::ImGuiCol_Border,
217 BorderShadow = sys::ImGuiCol_BorderShadow,
218 FrameBg = sys::ImGuiCol_FrameBg,
220 FrameBgHovered = sys::ImGuiCol_FrameBgHovered,
221 FrameBgActive = sys::ImGuiCol_FrameBgActive,
222 TitleBg = sys::ImGuiCol_TitleBg,
223 TitleBgActive = sys::ImGuiCol_TitleBgActive,
224 TitleBgCollapsed = sys::ImGuiCol_TitleBgCollapsed,
225 MenuBarBg = sys::ImGuiCol_MenuBarBg,
226 ScrollbarBg = sys::ImGuiCol_ScrollbarBg,
227 ScrollbarGrab = sys::ImGuiCol_ScrollbarGrab,
228 ScrollbarGrabHovered = sys::ImGuiCol_ScrollbarGrabHovered,
229 ScrollbarGrabActive = sys::ImGuiCol_ScrollbarGrabActive,
230 CheckMark = sys::ImGuiCol_CheckMark,
231 SliderGrab = sys::ImGuiCol_SliderGrab,
232 SliderGrabActive = sys::ImGuiCol_SliderGrabActive,
233 Button = sys::ImGuiCol_Button,
234 ButtonHovered = sys::ImGuiCol_ButtonHovered,
235 ButtonActive = sys::ImGuiCol_ButtonActive,
236 Header = sys::ImGuiCol_Header,
237 HeaderHovered = sys::ImGuiCol_HeaderHovered,
238 HeaderActive = sys::ImGuiCol_HeaderActive,
239 Separator = sys::ImGuiCol_Separator,
240 SeparatorHovered = sys::ImGuiCol_SeparatorHovered,
241 SeparatorActive = sys::ImGuiCol_SeparatorActive,
242 ResizeGrip = sys::ImGuiCol_ResizeGrip,
243 ResizeGripHovered = sys::ImGuiCol_ResizeGripHovered,
244 ResizeGripActive = sys::ImGuiCol_ResizeGripActive,
245 Tab = sys::ImGuiCol_Tab,
246 TabHovered = sys::ImGuiCol_TabHovered,
247 TabActive = sys::ImGuiCol_TabActive,
248 TabUnfocused = sys::ImGuiCol_TabUnfocused,
249 TabUnfocusedActive = sys::ImGuiCol_TabUnfocusedActive,
250 PlotLines = sys::ImGuiCol_PlotLines,
251 PlotLinesHovered = sys::ImGuiCol_PlotLinesHovered,
252 PlotHistogram = sys::ImGuiCol_PlotHistogram,
253 PlotHistogramHovered = sys::ImGuiCol_PlotHistogramHovered,
254 TableHeaderBg = sys::ImGuiCol_TableHeaderBg,
255 TableBorderStrong = sys::ImGuiCol_TableBorderStrong,
256 TableBorderLight = sys::ImGuiCol_TableBorderLight,
257 TableRowBg = sys::ImGuiCol_TableRowBg,
258 TableRowBgAlt = sys::ImGuiCol_TableRowBgAlt,
259 TextSelectedBg = sys::ImGuiCol_TextSelectedBg,
260 DragDropTarget = sys::ImGuiCol_DragDropTarget,
261 NavHighlight = sys::ImGuiCol_NavHighlight,
263 NavWindowingHighlight = sys::ImGuiCol_NavWindowingHighlight,
265 NavWindowingDimBg = sys::ImGuiCol_NavWindowingDimBg,
267 ModalWindowDimBg = sys::ImGuiCol_ModalWindowDimBg,
269}
270
271impl StyleColor {
272 pub const VARIANTS: [StyleColor; StyleColor::COUNT] = [
274 StyleColor::Text,
275 StyleColor::TextDisabled,
276 StyleColor::WindowBg,
277 StyleColor::ChildBg,
278 StyleColor::PopupBg,
279 StyleColor::Border,
280 StyleColor::BorderShadow,
281 StyleColor::FrameBg,
282 StyleColor::FrameBgHovered,
283 StyleColor::FrameBgActive,
284 StyleColor::TitleBg,
285 StyleColor::TitleBgActive,
286 StyleColor::TitleBgCollapsed,
287 StyleColor::MenuBarBg,
288 StyleColor::ScrollbarBg,
289 StyleColor::ScrollbarGrab,
290 StyleColor::ScrollbarGrabHovered,
291 StyleColor::ScrollbarGrabActive,
292 StyleColor::CheckMark,
293 StyleColor::SliderGrab,
294 StyleColor::SliderGrabActive,
295 StyleColor::Button,
296 StyleColor::ButtonHovered,
297 StyleColor::ButtonActive,
298 StyleColor::Header,
299 StyleColor::HeaderHovered,
300 StyleColor::HeaderActive,
301 StyleColor::Separator,
302 StyleColor::SeparatorHovered,
303 StyleColor::SeparatorActive,
304 StyleColor::ResizeGrip,
305 StyleColor::ResizeGripHovered,
306 StyleColor::ResizeGripActive,
307 StyleColor::Tab,
308 StyleColor::TabHovered,
309 StyleColor::TabActive,
310 StyleColor::TabUnfocused,
311 StyleColor::TabUnfocusedActive,
312 StyleColor::PlotLines,
313 StyleColor::PlotLinesHovered,
314 StyleColor::PlotHistogram,
315 StyleColor::PlotHistogramHovered,
316 StyleColor::TableHeaderBg,
317 StyleColor::TableBorderStrong,
318 StyleColor::TableBorderLight,
319 StyleColor::TableRowBg,
320 StyleColor::TableRowBgAlt,
321 StyleColor::TextSelectedBg,
322 StyleColor::DragDropTarget,
323 StyleColor::NavHighlight,
324 StyleColor::NavWindowingHighlight,
325 StyleColor::NavWindowingDimBg,
326 StyleColor::ModalWindowDimBg,
327 ];
328 pub const COUNT: usize = sys::ImGuiCol_COUNT as usize;
330}
331
332#[derive(Copy, Clone, Debug, PartialEq)]
334pub enum StyleVar {
335 Alpha(f32),
337 WindowPadding([f32; 2]),
339 WindowRounding(f32),
341 WindowBorderSize(f32),
343 WindowMinSize([f32; 2]),
345 WindowTitleAlign([f32; 2]),
347 ChildRounding(f32),
349 ChildBorderSize(f32),
351 PopupRounding(f32),
353 PopupBorderSize(f32),
355 FramePadding([f32; 2]),
357 FrameRounding(f32),
359 FrameBorderSize(f32),
361 ItemSpacing([f32; 2]),
363 ItemInnerSpacing([f32; 2]),
366 IndentSpacing(f32),
368 ScrollbarSize(f32),
370 ScrollbarRounding(f32),
372 GrabMinSize(f32),
374 GrabRounding(f32),
376 TabRounding(f32),
378 ButtonTextAlign([f32; 2]),
380 SelectableTextAlign([f32; 2]),
382 CellPadding([f32; 2]),
384}
385
386#[test]
387fn test_style_scaling() {
388 let (_guard, mut ctx) = crate::test::test_ctx();
389 let style = ctx.style_mut();
390 style.window_padding = [1.0, 2.0];
391 style.window_rounding = 3.0;
392 style.window_min_size = [4.0, 5.0];
393 style.child_rounding = 6.0;
394 style.popup_rounding = 7.0;
395 style.frame_padding = [8.0, 9.0];
396 style.frame_rounding = 10.0;
397 style.item_spacing = [11.0, 12.0];
398 style.item_inner_spacing = [13.0, 14.0];
399 style.touch_extra_padding = [15.0, 16.0];
400 style.indent_spacing = 17.0;
401 style.columns_min_spacing = 18.0;
402 style.scrollbar_size = 19.0;
403 style.scrollbar_rounding = 20.0;
404 style.grab_min_size = 21.0;
405 style.grab_rounding = 22.0;
406 style.log_slider_deadzone = 29.0;
407 style.tab_rounding = 23.0;
408 style.display_window_padding = [24.0, 25.0];
409 style.display_safe_area_padding = [26.0, 27.0];
410 style.mouse_cursor_scale = 28.0;
411 style.cell_padding = [29.0, 30.0];
412 style.scale_all_sizes(2.0);
413 assert_eq!(style.window_padding, [2.0, 4.0]);
414 assert_eq!(style.window_rounding, 6.0);
415 assert_eq!(style.window_min_size, [8.0, 10.0]);
416 assert_eq!(style.child_rounding, 12.0);
417 assert_eq!(style.popup_rounding, 14.0);
418 assert_eq!(style.frame_padding, [16.0, 18.0]);
419 assert_eq!(style.frame_rounding, 20.0);
420 assert_eq!(style.item_spacing, [22.0, 24.0]);
421 assert_eq!(style.item_inner_spacing, [26.0, 28.0]);
422 assert_eq!(style.touch_extra_padding, [30.0, 32.0]);
423 assert_eq!(style.indent_spacing, 34.0);
424 assert_eq!(style.columns_min_spacing, 36.0);
425 assert_eq!(style.scrollbar_size, 38.0);
426 assert_eq!(style.scrollbar_rounding, 40.0);
427 assert_eq!(style.grab_min_size, 42.0);
428 assert_eq!(style.grab_rounding, 44.0);
429 assert_eq!(style.log_slider_deadzone, 58.0);
430 assert_eq!(style.tab_rounding, 46.0);
431 assert_eq!(style.display_window_padding, [48.0, 50.0]);
432 assert_eq!(style.display_safe_area_padding, [52.0, 54.0]);
433 assert_eq!(style.mouse_cursor_scale, 56.0);
434 assert_eq!(style.cell_padding, [58.0, 60.0]);
435}
436
437#[test]
438fn test_style_color_indexing() {
439 let (_guard, mut ctx) = crate::test::test_ctx();
440 let style = ctx.style_mut();
441 let value = [0.1, 0.2, 0.3, 1.0];
442 style[StyleColor::Tab] = value;
443 assert_eq!(style[StyleColor::Tab], value);
444 assert_eq!(style.colors[StyleColor::Tab as usize], value);
445}
446
447#[test]
448#[cfg(test)]
449fn test_style_memory_layout() {
450 use std::mem;
451 assert_eq!(mem::size_of::<Style>(), mem::size_of::<sys::ImGuiStyle>());
452 assert_eq!(mem::align_of::<Style>(), mem::align_of::<sys::ImGuiStyle>());
453 use sys::ImGuiStyle;
454 macro_rules! assert_field_offset {
455 ($l:ident, $r:ident) => {
456 assert_eq!(
457 memoffset::offset_of!(Style, $l),
458 memoffset::offset_of!(ImGuiStyle, $r)
459 );
460 };
461 }
462 assert_field_offset!(alpha, Alpha);
463 assert_field_offset!(window_padding, WindowPadding);
464 assert_field_offset!(window_rounding, WindowRounding);
465 assert_field_offset!(window_border_size, WindowBorderSize);
466 assert_field_offset!(window_min_size, WindowMinSize);
467 assert_field_offset!(window_title_align, WindowTitleAlign);
468 assert_field_offset!(window_menu_button_position, WindowMenuButtonPosition);
469 assert_field_offset!(child_rounding, ChildRounding);
470 assert_field_offset!(child_border_size, ChildBorderSize);
471 assert_field_offset!(popup_rounding, PopupRounding);
472 assert_field_offset!(popup_border_size, PopupBorderSize);
473 assert_field_offset!(frame_padding, FramePadding);
474 assert_field_offset!(frame_rounding, FrameRounding);
475 assert_field_offset!(frame_border_size, FrameBorderSize);
476 assert_field_offset!(item_spacing, ItemSpacing);
477 assert_field_offset!(item_inner_spacing, ItemInnerSpacing);
478 assert_field_offset!(cell_padding, CellPadding);
479 assert_field_offset!(touch_extra_padding, TouchExtraPadding);
480 assert_field_offset!(indent_spacing, IndentSpacing);
481 assert_field_offset!(columns_min_spacing, ColumnsMinSpacing);
482 assert_field_offset!(scrollbar_size, ScrollbarSize);
483 assert_field_offset!(scrollbar_rounding, ScrollbarRounding);
484 assert_field_offset!(grab_min_size, GrabMinSize);
485 assert_field_offset!(grab_rounding, GrabRounding);
486 assert_field_offset!(log_slider_deadzone, LogSliderDeadzone);
487 assert_field_offset!(tab_rounding, TabRounding);
488 assert_field_offset!(tab_border_size, TabBorderSize);
489 assert_field_offset!(tab_min_width_for_close_button, TabMinWidthForCloseButton);
490 assert_field_offset!(color_button_position, ColorButtonPosition);
491 assert_field_offset!(button_text_align, ButtonTextAlign);
492 assert_field_offset!(selectable_text_align, SelectableTextAlign);
493 assert_field_offset!(display_window_padding, DisplayWindowPadding);
494 assert_field_offset!(display_safe_area_padding, DisplaySafeAreaPadding);
495 assert_field_offset!(mouse_cursor_scale, MouseCursorScale);
496 assert_field_offset!(anti_aliased_lines, AntiAliasedLines);
497 assert_field_offset!(anti_aliased_lines_use_tex, AntiAliasedLinesUseTex);
498 assert_field_offset!(anti_aliased_fill, AntiAliasedFill);
499 assert_field_offset!(curve_tessellation_tol, CurveTessellationTol);
500 assert_field_offset!(circle_tesselation_max_error, CircleSegmentMaxError);
501 assert_field_offset!(colors, Colors);
502}
503
504#[test]
505fn test_style_color_variants() {
506 for (idx, &value) in StyleColor::VARIANTS.iter().enumerate() {
507 assert_eq!(idx, value as usize);
508 }
509}