arcdps_imgui/
style.rs

1use std::ops::{Index, IndexMut};
2
3use crate::internal::RawCast;
4use crate::sys;
5use crate::Direction;
6
7/// User interface style/colors
8#[repr(C)]
9#[derive(Debug, Copy, Clone)]
10pub struct Style {
11    /// Global alpha applies to everything
12    pub alpha: f32,
13    /// Padding within a window
14    pub window_padding: [f32; 2],
15    /// Rounding radius of window corners.
16    ///
17    /// Set to 0.0 to have rectangular windows.
18    /// Large values tend to lead to a variety of artifacts and are not recommended.
19    pub window_rounding: f32,
20    /// Thickness of border around windows.
21    ///
22    /// Generally set to 0.0 or 1.0 (other values are not well tested and cost more CPU/GPU).
23    pub window_border_size: f32,
24    /// Minimum window size
25    pub window_min_size: [f32; 2],
26    /// Alignment for title bar text.
27    ///
28    /// Defaults to [0.5, 0.5] for left-aligned, vertically centered.
29    pub window_title_align: [f32; 2],
30    /// Side of the collapsing/docking button in the title bar (left/right).
31    ///
32    /// Defaults to Direction::Left.
33    pub window_menu_button_position: Direction,
34    /// Rounding radius of child window corners.
35    ///
36    /// Set to 0.0 to have rectangular child windows.
37    pub child_rounding: f32,
38    /// Thickness of border around child windows.
39    ///
40    /// Generally set to 0.0 or 1.0 (other values are not well tested and cost more CPU/GPU).
41    pub child_border_size: f32,
42    /// Rounding radius of popup window corners.
43    ///
44    /// Note that tooltip windows use `window_rounding` instead.
45    pub popup_rounding: f32,
46    /// Thickness of border around popup/tooltip windows.
47    ///
48    /// Generally set to 0.0 or 1.0 (other values are not well tested and cost more CPU/GPU).
49    pub popup_border_size: f32,
50    /// Padding within a framed rectangle (used by most widgets)
51    pub frame_padding: [f32; 2],
52    /// Rounding radius of frame corners (used by most widgets).
53    ///
54    /// Set to 0.0 to have rectangular frames.
55    pub frame_rounding: f32,
56    /// Thickness of border around frames.
57    ///
58    /// Generally set to 0.0 or 1.0 (other values are not well tested and cost more CPU/GPU).
59    pub frame_border_size: f32,
60    /// Horizontal and vertical spacing between widgets/lines
61    pub item_spacing: [f32; 2],
62    /// Horizontal and vertical spacing between elements of a composed widget (e.g. a slider and
63    /// its label)
64    pub item_inner_spacing: [f32; 2],
65    /// Padding within a table cell.
66    pub cell_padding: [f32; 2],
67    /// Expand reactive bounding box for touch-based system where touch position is not accurate
68    /// enough.
69    ///
70    /// Unfortunately we don't sort widgets so priority on overlap will always be given to the
71    /// first widget, so don't grow this too much.
72    pub touch_extra_padding: [f32; 2],
73    /// Horizontal indentation when e.g. entering a tree node.
74    ///
75    /// Generally equal to (font size + horizontal frame padding * 2).
76    pub indent_spacing: f32,
77    /// Minimum horizontal spacing between two columns
78    pub columns_min_spacing: f32,
79    /// Width of the vertical scrollbar, height of the horizontal scrollbar
80    pub scrollbar_size: f32,
81    /// Rounding radius of scrollbar grab corners
82    pub scrollbar_rounding: f32,
83    /// Minimum width/height of a grab box for slider/scrollbar
84    pub grab_min_size: f32,
85    /// Rounding radius of grab corners.
86    ///
87    /// Set to 0.0 to have rectangular slider grabs.
88    pub grab_rounding: f32,
89    /// The size in pixels of the dead-zone around zero on logarithmic sliders that cross zero
90    pub log_slider_deadzone: f32,
91    /// Rounding radius of upper corners of tabs.
92    ///
93    /// Set to 0.0 to have rectangular tabs.
94    pub tab_rounding: f32,
95    /// Thickness of border around tabs
96    pub tab_border_size: f32,
97    /// Minimum width for close button to appear on an unselected tab when hovered.
98    ///
99    /// `= 0.0`: always show when hovering
100    /// `= f32::MAX`: never show close button unless selected
101    pub tab_min_width_for_close_button: f32,
102    /// Side of the color buttonton pubin color editor widgets (left/right).
103    pub color_button_position: Direction,
104    /// Alignment of button text when button is larger than text.
105    ///
106    /// Defaults to [0.5, 0.5] (centered).
107    pub button_text_align: [f32; 2],
108    /// Alignment of selectable text when selectable is larger than text.
109    ///
110    /// Defaults to [0.5, 0.5] (top-left aligned).
111    pub selectable_text_align: [f32; 2],
112    /// Window positions are clamped to be visible within the display area or monitors by at least
113    /// this amount.
114    ///
115    /// Only applies to regular windows.
116    pub display_window_padding: [f32; 2],
117    /// If you cannot see the edges of your screen (e.g. on a TV), increase the safe area padding.
118    ///
119    /// Also applies to popups/tooltips in addition to regular windows.
120    pub display_safe_area_padding: [f32; 2],
121    /// Scale software-rendered mouse cursor.
122    ///
123    /// May be removed later.
124    pub mouse_cursor_scale: f32,
125    /// Enable anti-aliased lines/borders.
126    ///
127    /// Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame.
128    pub anti_aliased_lines: bool,
129    /// Enable anti-aliased lines/borders using textures where possible.
130    ///
131    /// Require back-end to render with bilinear filtering. Latched at the beginning of the frame.
132    pub anti_aliased_lines_use_tex: bool,
133    /// Enable anti-aliased edges around filled shapes (rounded recatngles, circles, etc.).
134    ///
135    /// Disable if you are really tight on CPU/GPU. Latched at the beginning of the frame.
136    pub anti_aliased_fill: bool,
137    /// Tessellation tolerance when using path_bezier_curve_to without a specific number of
138    /// segments.
139    ///
140    /// Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce
141    /// quality.
142    pub curve_tessellation_tol: f32,
143    /// Maximum error (in pixels) allowed when drawing circles or rounded corner rectangles with no
144    /// explicit segment count specified.
145    ///
146    /// Decrease for higher quality but more geometry.
147    pub circle_tesselation_max_error: f32,
148    /// Style colors.
149    pub colors: [[f32; 4]; StyleColor::COUNT],
150}
151
152unsafe impl RawCast<sys::ImGuiStyle> for Style {}
153
154impl Style {
155    /// Scales all sizes in the style
156    #[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    /// Replaces current colors with classic Dear ImGui style
163    #[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    /// Replaces current colors with a new, recommended style
171    #[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    /// Replaces current colors with a light style. Best used with borders and a custom, thicker
179    /// font
180    #[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/// A color identifier for styling
205#[repr(u32)]
206#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
207pub enum StyleColor {
208    Text = sys::ImGuiCol_Text,
209    TextDisabled = sys::ImGuiCol_TextDisabled,
210    /// Background of normal windows
211    WindowBg = sys::ImGuiCol_WindowBg,
212    /// Background of child windows
213    ChildBg = sys::ImGuiCol_ChildBg,
214    /// Background of popups, menus, tooltips windows
215    PopupBg = sys::ImGuiCol_PopupBg,
216    Border = sys::ImGuiCol_Border,
217    BorderShadow = sys::ImGuiCol_BorderShadow,
218    /// Background of checkbox, radio button, plot, slider, text input
219    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    /// Gamepad/keyboard: current highlighted item
262    NavHighlight = sys::ImGuiCol_NavHighlight,
263    /// Highlight window when using CTRL+TAB
264    NavWindowingHighlight = sys::ImGuiCol_NavWindowingHighlight,
265    /// Darken/colorize entire screen behind the CTRL+TAB window list, when active
266    NavWindowingDimBg = sys::ImGuiCol_NavWindowingDimBg,
267    /// Darken/colorize entire screen behind a modal window, when one is active
268    ModalWindowDimBg = sys::ImGuiCol_ModalWindowDimBg,
269}
270
271impl StyleColor {
272    /// All possible `StyleColor` variants
273    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    /// Total count of `StyleColor` variants
329    pub const COUNT: usize = sys::ImGuiCol_COUNT as usize;
330}
331
332/// A temporary change in user interface style
333#[derive(Copy, Clone, Debug, PartialEq)]
334pub enum StyleVar {
335    /// Global alpha applies to everything
336    Alpha(f32),
337    /// Padding within a window
338    WindowPadding([f32; 2]),
339    /// Rounding radius of window corners
340    WindowRounding(f32),
341    /// Thickness of border around windows
342    WindowBorderSize(f32),
343    /// Minimum window size
344    WindowMinSize([f32; 2]),
345    /// Alignment for title bar text
346    WindowTitleAlign([f32; 2]),
347    /// Rounding radius of child window corners
348    ChildRounding(f32),
349    /// Thickness of border around child windows
350    ChildBorderSize(f32),
351    /// Rounding radius of popup window corners
352    PopupRounding(f32),
353    /// Thickness of border around popup/tooltip windows
354    PopupBorderSize(f32),
355    /// Padding within a framed rectangle (used by most widgets)
356    FramePadding([f32; 2]),
357    /// Rounding radius of frame corners (used by most widgets)
358    FrameRounding(f32),
359    /// Thickness of border around frames
360    FrameBorderSize(f32),
361    /// Horizontal and vertical spacing between widgets/lines
362    ItemSpacing([f32; 2]),
363    /// Horizontal and vertical spacing between elements of a composed widget (e.g. a slider and
364    /// its label)
365    ItemInnerSpacing([f32; 2]),
366    /// Horizontal indentation when e.g. entering a tree node
367    IndentSpacing(f32),
368    /// Width of the vertical scrollbar, height of the horizontal scrollbar
369    ScrollbarSize(f32),
370    /// Rounding radius of scrollbar grab corners
371    ScrollbarRounding(f32),
372    /// Minimum width/height of a grab box for slider/scrollbar
373    GrabMinSize(f32),
374    /// Rounding radius of grab corners
375    GrabRounding(f32),
376    /// Rounding radius of upper corners of tabs
377    TabRounding(f32),
378    /// Alignment of button text when button is larger than text
379    ButtonTextAlign([f32; 2]),
380    /// Alignment of selectable text when selectable is larger than text
381    SelectableTextAlign([f32; 2]),
382    /// Padding within a table cell
383    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}