#![allow(
clippy::cast_possible_truncation,
clippy::cast_sign_loss,
clippy::as_conversions
)]
use crate::Context;
use crate::internal::RawWrapper;
use crate::sys;
use crate::utils::{HoveredFlags, validate_tooltip_hovered_flags};
use crate::widget::TreeNodeFlags;
use crate::widget::{TableFlags, TableRowFlags};
use crate::window::WindowFlags;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::cell::UnsafeCell;
#[repr(transparent)]
#[derive(Debug)]
pub struct Style(pub(crate) UnsafeCell<sys::ImGuiStyle>);
const _: [(); std::mem::size_of::<sys::ImGuiStyle>()] = [(); std::mem::size_of::<Style>()];
const _: [(); std::mem::align_of::<sys::ImGuiStyle>()] = [(); std::mem::align_of::<Style>()];
const TABLE_ANGLED_HEADERS_MAX_ANGLE: f32 = 50.0 * std::f32::consts::PI / 180.0;
fn assert_finite_f32(caller: &str, name: &str, value: f32) {
assert!(value.is_finite(), "{caller} {name} must be finite");
}
fn assert_finite_vec2(caller: &str, name: &str, value: [f32; 2]) {
assert!(
value[0].is_finite() && value[1].is_finite(),
"{caller} {name} must contain finite values"
);
}
pub(crate) fn validate_style_color(caller: &str, name: &str, value: [f32; 4]) {
assert!(
value.iter().all(|component| component.is_finite()),
"{caller} {name} must contain finite values"
);
}
fn assert_positive_f32(caller: &str, name: &str, value: f32) {
assert_finite_f32(caller, name, value);
assert!(value > 0.0, "{caller} {name} must be positive");
}
fn assert_non_negative_f32(caller: &str, name: &str, value: f32) {
assert_finite_f32(caller, name, value);
assert!(value >= 0.0, "{caller} {name} must be non-negative");
}
fn assert_non_negative_vec2(caller: &str, name: &str, value: [f32; 2]) {
assert_finite_vec2(caller, name, value);
assert!(
value[0] >= 0.0 && value[1] >= 0.0,
"{caller} {name} must contain non-negative values"
);
}
fn assert_unit_f32(caller: &str, name: &str, value: f32) {
assert_finite_f32(caller, name, value);
assert!(
(0.0..=1.0).contains(&value),
"{caller} {name} must be between 0.0 and 1.0"
);
}
fn assert_unit_vec2(caller: &str, name: &str, value: [f32; 2]) {
assert_finite_vec2(caller, name, value);
assert!(
(0.0..=1.0).contains(&value[0]) && (0.0..=1.0).contains(&value[1]),
"{caller} {name} must contain values between 0.0 and 1.0"
);
}
fn assert_window_min_size(caller: &str, value: [f32; 2]) {
assert_finite_vec2(caller, "value", value);
assert!(
value[0] >= 1.0 && value[1] >= 1.0,
"{caller} value must contain values greater than or equal to 1.0"
);
}
fn assert_tab_close_button_min_width(caller: &str, value: f32) {
assert_finite_f32(caller, "value", value);
assert!(
value >= 0.0 || value == -1.0,
"{caller} value must be non-negative, or -1.0 to always show the close button"
);
}
fn assert_table_angled_headers_angle(caller: &str, value: f32) {
assert_finite_f32(caller, "value", value);
assert!(
(-TABLE_ANGLED_HEADERS_MAX_ANGLE..=TABLE_ANGLED_HEADERS_MAX_ANGLE).contains(&value),
"{caller} value must be between -50 and 50 degrees in radians"
);
}
fn validate_window_menu_button_position(caller: &str, direction: Direction) {
assert!(
matches!(
direction,
Direction::None | Direction::Left | Direction::Right
),
"{caller} accepts only Direction::None, Direction::Left, or Direction::Right"
);
}
fn validate_color_button_position(caller: &str, direction: Direction) {
assert!(
matches!(direction, Direction::Left | Direction::Right),
"{caller} accepts only Direction::Left or Direction::Right"
);
}
fn validate_tree_lines_flags(caller: &str, flags: TreeNodeFlags) {
assert!(
matches!(
flags,
TreeNodeFlags::DRAW_LINES_NONE
| TreeNodeFlags::DRAW_LINES_FULL
| TreeNodeFlags::DRAW_LINES_TO_NODES
),
"{caller} accepts only TreeNodeFlags::DRAW_LINES_NONE, DRAW_LINES_FULL, or DRAW_LINES_TO_NODES"
);
}
pub(crate) fn validate_style_var(caller: &str, style_var: StyleVar) {
use StyleVar::*;
match style_var {
Alpha(value) => assert_unit_f32(caller, "Alpha", value),
DisabledAlpha(value) => assert_unit_f32(caller, "DisabledAlpha", value),
WindowPadding(value) => assert_non_negative_vec2(caller, "WindowPadding", value),
WindowRounding(value) => assert_non_negative_f32(caller, "WindowRounding", value),
WindowBorderSize(value) => assert_non_negative_f32(caller, "WindowBorderSize", value),
WindowMinSize(value) => assert_non_negative_vec2(caller, "WindowMinSize", value),
WindowTitleAlign(value) => assert_unit_vec2(caller, "WindowTitleAlign", value),
ChildRounding(value) => assert_non_negative_f32(caller, "ChildRounding", value),
ChildBorderSize(value) => assert_non_negative_f32(caller, "ChildBorderSize", value),
PopupRounding(value) => assert_non_negative_f32(caller, "PopupRounding", value),
PopupBorderSize(value) => assert_non_negative_f32(caller, "PopupBorderSize", value),
FramePadding(value) => assert_non_negative_vec2(caller, "FramePadding", value),
FrameRounding(value) => assert_non_negative_f32(caller, "FrameRounding", value),
ImageRounding(value) => assert_non_negative_f32(caller, "ImageRounding", value),
ImageBorderSize(value) => assert_non_negative_f32(caller, "ImageBorderSize", value),
FrameBorderSize(value) => assert_non_negative_f32(caller, "FrameBorderSize", value),
ItemSpacing(value) => assert_non_negative_vec2(caller, "ItemSpacing", value),
ItemInnerSpacing(value) => assert_non_negative_vec2(caller, "ItemInnerSpacing", value),
IndentSpacing(value) => assert_non_negative_f32(caller, "IndentSpacing", value),
CellPadding(value) => assert_non_negative_vec2(caller, "CellPadding", value),
ScrollbarSize(value) => assert_non_negative_f32(caller, "ScrollbarSize", value),
ScrollbarRounding(value) => assert_non_negative_f32(caller, "ScrollbarRounding", value),
ScrollbarPadding(value) => assert_non_negative_f32(caller, "ScrollbarPadding", value),
GrabMinSize(value) => assert_non_negative_f32(caller, "GrabMinSize", value),
GrabRounding(value) => assert_non_negative_f32(caller, "GrabRounding", value),
TabRounding(value) => assert_non_negative_f32(caller, "TabRounding", value),
TabBorderSize(value) => assert_non_negative_f32(caller, "TabBorderSize", value),
TabMinWidthBase(value) => assert_non_negative_f32(caller, "TabMinWidthBase", value),
TabMinWidthShrink(value) => assert_non_negative_f32(caller, "TabMinWidthShrink", value),
TabBarBorderSize(value) => assert_non_negative_f32(caller, "TabBarBorderSize", value),
TabBarOverlineSize(value) => assert_non_negative_f32(caller, "TabBarOverlineSize", value),
TableAngledHeadersAngle(value) => assert_table_angled_headers_angle(caller, value),
TableAngledHeadersTextAlign(value) => {
assert_unit_vec2(caller, "TableAngledHeadersTextAlign", value);
}
TreeLinesSize(value) => assert_non_negative_f32(caller, "TreeLinesSize", value),
TreeLinesRounding(value) => assert_non_negative_f32(caller, "TreeLinesRounding", value),
DragDropTargetRounding(value) => assert_finite_f32(caller, "DragDropTargetRounding", value),
ButtonTextAlign(value) => assert_unit_vec2(caller, "ButtonTextAlign", value),
SelectableTextAlign(value) => assert_unit_vec2(caller, "SelectableTextAlign", value),
SeparatorSize(value) => assert_non_negative_f32(caller, "SeparatorSize", value),
SeparatorTextBorderSize(value) => {
assert_non_negative_f32(caller, "SeparatorTextBorderSize", value);
}
SeparatorTextAlign(value) => assert_unit_vec2(caller, "SeparatorTextAlign", value),
SeparatorTextPadding(value) => {
assert_non_negative_vec2(caller, "SeparatorTextPadding", value);
}
DockingSeparatorSize(value) => {
assert_non_negative_f32(caller, "DockingSeparatorSize", value);
}
}
}
impl Style {
#[inline]
fn inner(&self) -> &sys::ImGuiStyle {
unsafe { &*self.0.get() }
}
#[inline]
fn inner_mut(&mut self) -> &mut sys::ImGuiStyle {
unsafe { &mut *self.0.get() }
}
pub fn color(&self, color: StyleColor) -> [f32; 4] {
let c = self.inner().Colors[color as usize];
[c.x, c.y, c.z, c.w]
}
pub fn set_color(&mut self, color: StyleColor, value: [f32; 4]) {
validate_style_color("Style::set_color()", "value", value);
self.inner_mut().Colors[color as usize] = sys::ImVec4 {
x: value[0],
y: value[1],
z: value[2],
w: value[3],
};
}
pub fn font_scale_main(&self) -> f32 {
self.inner().FontScaleMain
}
pub fn set_font_scale_main(&mut self, scale: f32) {
assert_positive_f32("Style::set_font_scale_main()", "scale", scale);
self.inner_mut().FontScaleMain = scale;
}
pub fn font_scale_dpi(&self) -> f32 {
self.inner().FontScaleDpi
}
pub fn set_font_scale_dpi(&mut self, scale: f32) {
assert_positive_f32("Style::set_font_scale_dpi()", "scale", scale);
self.inner_mut().FontScaleDpi = scale;
}
pub fn font_size_base(&self) -> f32 {
self.inner().FontSizeBase
}
pub fn set_font_size_base(&mut self, sz: f32) {
assert_non_negative_f32("Style::set_font_size_base()", "sz", sz);
self.inner_mut().FontSizeBase = sz;
}
pub fn alpha(&self) -> f32 {
self.inner().Alpha
}
pub fn set_alpha(&mut self, v: f32) {
assert_unit_f32("Style::set_alpha()", "v", v);
self.inner_mut().Alpha = v;
}
pub fn disabled_alpha(&self) -> f32 {
self.inner().DisabledAlpha
}
pub fn set_disabled_alpha(&mut self, v: f32) {
assert_unit_f32("Style::set_disabled_alpha()", "v", v);
self.inner_mut().DisabledAlpha = v;
}
pub fn window_padding(&self) -> [f32; 2] {
[self.inner().WindowPadding.x, self.inner().WindowPadding.y]
}
pub fn set_window_padding(&mut self, v: [f32; 2]) {
assert_non_negative_vec2("Style::set_window_padding()", "v", v);
self.inner_mut().WindowPadding = sys::ImVec2 { x: v[0], y: v[1] };
}
pub fn window_rounding(&self) -> f32 {
self.inner().WindowRounding
}
pub fn set_window_rounding(&mut self, v: f32) {
assert_non_negative_f32("Style::set_window_rounding()", "v", v);
self.inner_mut().WindowRounding = v;
}
pub fn window_border_size(&self) -> f32 {
self.inner().WindowBorderSize
}
pub fn set_window_border_size(&mut self, v: f32) {
assert_non_negative_f32("Style::set_window_border_size()", "v", v);
self.inner_mut().WindowBorderSize = v;
}
pub fn window_min_size(&self) -> [f32; 2] {
[self.inner().WindowMinSize.x, self.inner().WindowMinSize.y]
}
pub fn set_window_min_size(&mut self, v: [f32; 2]) {
assert_window_min_size("Style::set_window_min_size()", v);
self.inner_mut().WindowMinSize = sys::ImVec2 { x: v[0], y: v[1] };
}
pub fn window_title_align(&self) -> [f32; 2] {
[
self.inner().WindowTitleAlign.x,
self.inner().WindowTitleAlign.y,
]
}
pub fn set_window_title_align(&mut self, v: [f32; 2]) {
assert_unit_vec2("Style::set_window_title_align()", "v", v);
self.inner_mut().WindowTitleAlign = sys::ImVec2 { x: v[0], y: v[1] };
}
pub fn window_menu_button_position(&self) -> Direction {
Direction::from(self.inner().WindowMenuButtonPosition)
}
pub fn set_window_menu_button_position(&mut self, d: Direction) {
validate_window_menu_button_position("Style::set_window_menu_button_position()", d);
self.inner_mut().WindowMenuButtonPosition = d.into();
}
pub fn child_rounding(&self) -> f32 {
self.inner().ChildRounding
}
pub fn set_child_rounding(&mut self, v: f32) {
assert_non_negative_f32("Style::set_child_rounding()", "v", v);
self.inner_mut().ChildRounding = v;
}
pub fn child_border_size(&self) -> f32 {
self.inner().ChildBorderSize
}
pub fn set_child_border_size(&mut self, v: f32) {
assert_non_negative_f32("Style::set_child_border_size()", "v", v);
self.inner_mut().ChildBorderSize = v;
}
pub fn popup_rounding(&self) -> f32 {
self.inner().PopupRounding
}
pub fn set_popup_rounding(&mut self, v: f32) {
assert_non_negative_f32("Style::set_popup_rounding()", "v", v);
self.inner_mut().PopupRounding = v;
}
pub fn popup_border_size(&self) -> f32 {
self.inner().PopupBorderSize
}
pub fn set_popup_border_size(&mut self, v: f32) {
assert_non_negative_f32("Style::set_popup_border_size()", "v", v);
self.inner_mut().PopupBorderSize = v;
}
pub fn frame_padding(&self) -> [f32; 2] {
[self.inner().FramePadding.x, self.inner().FramePadding.y]
}
pub fn set_frame_padding(&mut self, v: [f32; 2]) {
assert_non_negative_vec2("Style::set_frame_padding()", "v", v);
self.inner_mut().FramePadding = sys::ImVec2 { x: v[0], y: v[1] };
}
pub fn frame_rounding(&self) -> f32 {
self.inner().FrameRounding
}
pub fn set_frame_rounding(&mut self, v: f32) {
assert_non_negative_f32("Style::set_frame_rounding()", "v", v);
self.inner_mut().FrameRounding = v;
}
pub fn image_rounding(&self) -> f32 {
self.inner().ImageRounding
}
pub fn set_image_rounding(&mut self, v: f32) {
assert_non_negative_f32("Style::set_image_rounding()", "v", v);
self.inner_mut().ImageRounding = v;
}
pub fn frame_border_size(&self) -> f32 {
self.inner().FrameBorderSize
}
pub fn set_frame_border_size(&mut self, v: f32) {
assert_non_negative_f32("Style::set_frame_border_size()", "v", v);
self.inner_mut().FrameBorderSize = v;
}
pub fn item_spacing(&self) -> [f32; 2] {
[self.inner().ItemSpacing.x, self.inner().ItemSpacing.y]
}
pub fn set_item_spacing(&mut self, v: [f32; 2]) {
assert_non_negative_vec2("Style::set_item_spacing()", "v", v);
self.inner_mut().ItemSpacing = sys::ImVec2 { x: v[0], y: v[1] };
}
pub fn item_inner_spacing(&self) -> [f32; 2] {
[
self.inner().ItemInnerSpacing.x,
self.inner().ItemInnerSpacing.y,
]
}
pub fn set_item_inner_spacing(&mut self, v: [f32; 2]) {
assert_non_negative_vec2("Style::set_item_inner_spacing()", "v", v);
self.inner_mut().ItemInnerSpacing = sys::ImVec2 { x: v[0], y: v[1] };
}
pub fn cell_padding(&self) -> [f32; 2] {
[self.inner().CellPadding.x, self.inner().CellPadding.y]
}
pub fn set_cell_padding(&mut self, v: [f32; 2]) {
assert_non_negative_vec2("Style::set_cell_padding()", "v", v);
self.inner_mut().CellPadding = sys::ImVec2 { x: v[0], y: v[1] };
}
pub fn touch_extra_padding(&self) -> [f32; 2] {
[
self.inner().TouchExtraPadding.x,
self.inner().TouchExtraPadding.y,
]
}
pub fn set_touch_extra_padding(&mut self, v: [f32; 2]) {
assert_non_negative_vec2("Style::set_touch_extra_padding()", "v", v);
self.inner_mut().TouchExtraPadding = sys::ImVec2 { x: v[0], y: v[1] };
}
pub fn indent_spacing(&self) -> f32 {
self.inner().IndentSpacing
}
pub fn set_indent_spacing(&mut self, v: f32) {
assert_non_negative_f32("Style::set_indent_spacing()", "v", v);
self.inner_mut().IndentSpacing = v;
}
pub fn columns_min_spacing(&self) -> f32 {
self.inner().ColumnsMinSpacing
}
pub fn set_columns_min_spacing(&mut self, v: f32) {
assert_non_negative_f32("Style::set_columns_min_spacing()", "v", v);
self.inner_mut().ColumnsMinSpacing = v;
}
pub fn scrollbar_size(&self) -> f32 {
self.inner().ScrollbarSize
}
pub fn set_scrollbar_size(&mut self, v: f32) {
assert_non_negative_f32("Style::set_scrollbar_size()", "v", v);
self.inner_mut().ScrollbarSize = v;
}
pub fn scrollbar_rounding(&self) -> f32 {
self.inner().ScrollbarRounding
}
pub fn set_scrollbar_rounding(&mut self, v: f32) {
assert_non_negative_f32("Style::set_scrollbar_rounding()", "v", v);
self.inner_mut().ScrollbarRounding = v;
}
pub fn grab_min_size(&self) -> f32 {
self.inner().GrabMinSize
}
pub fn set_grab_min_size(&mut self, v: f32) {
assert_non_negative_f32("Style::set_grab_min_size()", "v", v);
self.inner_mut().GrabMinSize = v;
}
pub fn grab_rounding(&self) -> f32 {
self.inner().GrabRounding
}
pub fn set_grab_rounding(&mut self, v: f32) {
assert_non_negative_f32("Style::set_grab_rounding()", "v", v);
self.inner_mut().GrabRounding = v;
}
pub fn log_slider_deadzone(&self) -> f32 {
self.inner().LogSliderDeadzone
}
pub fn set_log_slider_deadzone(&mut self, v: f32) {
assert_non_negative_f32("Style::set_log_slider_deadzone()", "v", v);
self.inner_mut().LogSliderDeadzone = v;
}
pub fn tab_rounding(&self) -> f32 {
self.inner().TabRounding
}
pub fn set_tab_rounding(&mut self, v: f32) {
assert_non_negative_f32("Style::set_tab_rounding()", "v", v);
self.inner_mut().TabRounding = v;
}
pub fn tab_border_size(&self) -> f32 {
self.inner().TabBorderSize
}
pub fn set_tab_border_size(&mut self, v: f32) {
assert_non_negative_f32("Style::set_tab_border_size()", "v", v);
self.inner_mut().TabBorderSize = v;
}
pub fn color_button_position(&self) -> Direction {
Direction::from(self.inner().ColorButtonPosition)
}
pub fn set_color_button_position(&mut self, d: Direction) {
validate_color_button_position("Style::set_color_button_position()", d);
self.inner_mut().ColorButtonPosition = d.into();
}
pub fn button_text_align(&self) -> [f32; 2] {
[
self.inner().ButtonTextAlign.x,
self.inner().ButtonTextAlign.y,
]
}
pub fn set_button_text_align(&mut self, v: [f32; 2]) {
assert_unit_vec2("Style::set_button_text_align()", "v", v);
self.inner_mut().ButtonTextAlign = sys::ImVec2 { x: v[0], y: v[1] };
}
pub fn selectable_text_align(&self) -> [f32; 2] {
[
self.inner().SelectableTextAlign.x,
self.inner().SelectableTextAlign.y,
]
}
pub fn set_selectable_text_align(&mut self, v: [f32; 2]) {
assert_unit_vec2("Style::set_selectable_text_align()", "v", v);
self.inner_mut().SelectableTextAlign = sys::ImVec2 { x: v[0], y: v[1] };
}
pub fn display_window_padding(&self) -> [f32; 2] {
[
self.inner().DisplayWindowPadding.x,
self.inner().DisplayWindowPadding.y,
]
}
pub fn set_display_window_padding(&mut self, v: [f32; 2]) {
assert_non_negative_vec2("Style::set_display_window_padding()", "v", v);
self.inner_mut().DisplayWindowPadding = sys::ImVec2 { x: v[0], y: v[1] };
}
pub fn display_safe_area_padding(&self) -> [f32; 2] {
[
self.inner().DisplaySafeAreaPadding.x,
self.inner().DisplaySafeAreaPadding.y,
]
}
pub fn set_display_safe_area_padding(&mut self, v: [f32; 2]) {
assert_non_negative_vec2("Style::set_display_safe_area_padding()", "v", v);
self.inner_mut().DisplaySafeAreaPadding = sys::ImVec2 { x: v[0], y: v[1] };
}
pub fn mouse_cursor_scale(&self) -> f32 {
self.inner().MouseCursorScale
}
pub fn set_mouse_cursor_scale(&mut self, v: f32) {
assert_positive_f32("Style::set_mouse_cursor_scale()", "v", v);
self.inner_mut().MouseCursorScale = v;
}
pub fn anti_aliased_lines(&self) -> bool {
self.inner().AntiAliasedLines
}
pub fn set_anti_aliased_lines(&mut self, v: bool) {
self.inner_mut().AntiAliasedLines = v;
}
pub fn anti_aliased_lines_use_tex(&self) -> bool {
self.inner().AntiAliasedLinesUseTex
}
pub fn set_anti_aliased_lines_use_tex(&mut self, v: bool) {
self.inner_mut().AntiAliasedLinesUseTex = v;
}
pub fn anti_aliased_fill(&self) -> bool {
self.inner().AntiAliasedFill
}
pub fn set_anti_aliased_fill(&mut self, v: bool) {
self.inner_mut().AntiAliasedFill = v;
}
pub fn curve_tessellation_tol(&self) -> f32 {
self.inner().CurveTessellationTol
}
pub fn set_curve_tessellation_tol(&mut self, v: f32) {
assert_positive_f32("Style::set_curve_tessellation_tol()", "v", v);
self.inner_mut().CurveTessellationTol = v;
}
pub fn circle_tessellation_max_error(&self) -> f32 {
self.inner().CircleTessellationMaxError
}
pub fn set_circle_tessellation_max_error(&mut self, v: f32) {
assert_positive_f32("Style::set_circle_tessellation_max_error()", "v", v);
self.inner_mut().CircleTessellationMaxError = v;
}
pub fn window_border_hover_padding(&self) -> f32 {
self.inner().WindowBorderHoverPadding
}
pub fn set_window_border_hover_padding(&mut self, v: f32) {
assert_positive_f32("Style::set_window_border_hover_padding()", "v", v);
self.inner_mut().WindowBorderHoverPadding = v;
}
pub fn scrollbar_padding(&self) -> f32 {
self.inner().ScrollbarPadding
}
pub fn set_scrollbar_padding(&mut self, v: f32) {
assert_non_negative_f32("Style::set_scrollbar_padding()", "v", v);
self.inner_mut().ScrollbarPadding = v;
}
pub fn image_border_size(&self) -> f32 {
self.inner().ImageBorderSize
}
pub fn set_image_border_size(&mut self, v: f32) {
assert_non_negative_f32("Style::set_image_border_size()", "v", v);
self.inner_mut().ImageBorderSize = v;
}
pub fn tab_min_width_base(&self) -> f32 {
self.inner().TabMinWidthBase
}
pub fn set_tab_min_width_base(&mut self, v: f32) {
assert_non_negative_f32("Style::set_tab_min_width_base()", "v", v);
self.inner_mut().TabMinWidthBase = v;
}
pub fn tab_min_width_shrink(&self) -> f32 {
self.inner().TabMinWidthShrink
}
pub fn set_tab_min_width_shrink(&mut self, v: f32) {
assert_non_negative_f32("Style::set_tab_min_width_shrink()", "v", v);
self.inner_mut().TabMinWidthShrink = v;
}
pub fn tab_close_button_min_width_selected(&self) -> f32 {
self.inner().TabCloseButtonMinWidthSelected
}
pub fn set_tab_close_button_min_width_selected(&mut self, v: f32) {
assert_tab_close_button_min_width("Style::set_tab_close_button_min_width_selected()", v);
self.inner_mut().TabCloseButtonMinWidthSelected = v;
}
pub fn tab_close_button_min_width_unselected(&self) -> f32 {
self.inner().TabCloseButtonMinWidthUnselected
}
pub fn set_tab_close_button_min_width_unselected(&mut self, v: f32) {
assert_tab_close_button_min_width("Style::set_tab_close_button_min_width_unselected()", v);
self.inner_mut().TabCloseButtonMinWidthUnselected = v;
}
pub fn tab_bar_border_size(&self) -> f32 {
self.inner().TabBarBorderSize
}
pub fn set_tab_bar_border_size(&mut self, v: f32) {
assert_non_negative_f32("Style::set_tab_bar_border_size()", "v", v);
self.inner_mut().TabBarBorderSize = v;
}
pub fn tab_bar_overline_size(&self) -> f32 {
self.inner().TabBarOverlineSize
}
pub fn set_tab_bar_overline_size(&mut self, v: f32) {
assert_non_negative_f32("Style::set_tab_bar_overline_size()", "v", v);
self.inner_mut().TabBarOverlineSize = v;
}
pub fn table_angled_headers_angle(&self) -> f32 {
self.inner().TableAngledHeadersAngle
}
pub fn set_table_angled_headers_angle(&mut self, v: f32) {
assert_table_angled_headers_angle("Style::set_table_angled_headers_angle()", v);
self.inner_mut().TableAngledHeadersAngle = v;
}
pub fn table_angled_headers_text_align(&self) -> [f32; 2] {
[
self.inner().TableAngledHeadersTextAlign.x,
self.inner().TableAngledHeadersTextAlign.y,
]
}
pub fn set_table_angled_headers_text_align(&mut self, v: [f32; 2]) {
assert_unit_vec2("Style::set_table_angled_headers_text_align()", "v", v);
self.inner_mut().TableAngledHeadersTextAlign = sys::ImVec2 { x: v[0], y: v[1] };
}
pub fn tree_lines_flags(&self) -> TreeNodeFlags {
TreeNodeFlags::from_bits_truncate(self.inner().TreeLinesFlags as i32)
}
pub fn set_tree_lines_flags(&mut self, flags: TreeNodeFlags) {
validate_tree_lines_flags("Style::set_tree_lines_flags()", flags);
self.inner_mut().TreeLinesFlags = flags.bits() as sys::ImGuiTreeNodeFlags;
}
pub fn tree_lines_size(&self) -> f32 {
self.inner().TreeLinesSize
}
pub fn set_tree_lines_size(&mut self, v: f32) {
assert_non_negative_f32("Style::set_tree_lines_size()", "v", v);
self.inner_mut().TreeLinesSize = v;
}
pub fn tree_lines_rounding(&self) -> f32 {
self.inner().TreeLinesRounding
}
pub fn set_tree_lines_rounding(&mut self, v: f32) {
assert_non_negative_f32("Style::set_tree_lines_rounding()", "v", v);
self.inner_mut().TreeLinesRounding = v;
}
pub fn drag_drop_target_rounding(&self) -> f32 {
self.inner().DragDropTargetRounding
}
pub fn set_drag_drop_target_rounding(&mut self, v: f32) {
assert_finite_f32("Style::set_drag_drop_target_rounding()", "v", v);
self.inner_mut().DragDropTargetRounding = v;
}
pub fn drag_drop_target_border_size(&self) -> f32 {
self.inner().DragDropTargetBorderSize
}
pub fn set_drag_drop_target_border_size(&mut self, v: f32) {
assert_non_negative_f32("Style::set_drag_drop_target_border_size()", "v", v);
self.inner_mut().DragDropTargetBorderSize = v;
}
pub fn drag_drop_target_padding(&self) -> f32 {
self.inner().DragDropTargetPadding
}
pub fn set_drag_drop_target_padding(&mut self, v: f32) {
assert_non_negative_f32("Style::set_drag_drop_target_padding()", "v", v);
self.inner_mut().DragDropTargetPadding = v;
}
pub fn color_marker_size(&self) -> f32 {
self.inner().ColorMarkerSize
}
pub fn set_color_marker_size(&mut self, v: f32) {
assert_non_negative_f32("Style::set_color_marker_size()", "v", v);
self.inner_mut().ColorMarkerSize = v;
}
pub fn separator_size(&self) -> f32 {
self.inner().SeparatorSize
}
pub fn set_separator_size(&mut self, v: f32) {
assert_non_negative_f32("Style::set_separator_size()", "v", v);
self.inner_mut().SeparatorSize = v;
}
pub fn separator_text_border_size(&self) -> f32 {
self.inner().SeparatorTextBorderSize
}
pub fn set_separator_text_border_size(&mut self, v: f32) {
assert_non_negative_f32("Style::set_separator_text_border_size()", "v", v);
self.inner_mut().SeparatorTextBorderSize = v;
}
pub fn separator_text_align(&self) -> [f32; 2] {
[
self.inner().SeparatorTextAlign.x,
self.inner().SeparatorTextAlign.y,
]
}
pub fn set_separator_text_align(&mut self, v: [f32; 2]) {
assert_unit_vec2("Style::set_separator_text_align()", "v", v);
self.inner_mut().SeparatorTextAlign = sys::ImVec2 { x: v[0], y: v[1] };
}
pub fn separator_text_padding(&self) -> [f32; 2] {
[
self.inner().SeparatorTextPadding.x,
self.inner().SeparatorTextPadding.y,
]
}
pub fn set_separator_text_padding(&mut self, v: [f32; 2]) {
assert_non_negative_vec2("Style::set_separator_text_padding()", "v", v);
self.inner_mut().SeparatorTextPadding = sys::ImVec2 { x: v[0], y: v[1] };
}
pub fn docking_node_has_close_button(&self) -> bool {
self.inner().DockingNodeHasCloseButton
}
pub fn set_docking_node_has_close_button(&mut self, v: bool) {
self.inner_mut().DockingNodeHasCloseButton = v;
}
pub fn docking_separator_size(&self) -> f32 {
self.inner().DockingSeparatorSize
}
pub fn set_docking_separator_size(&mut self, v: f32) {
assert_non_negative_f32("Style::set_docking_separator_size()", "v", v);
self.inner_mut().DockingSeparatorSize = v;
}
pub fn hover_stationary_delay(&self) -> f32 {
self.inner().HoverStationaryDelay
}
pub fn set_hover_stationary_delay(&mut self, v: f32) {
assert_non_negative_f32("Style::set_hover_stationary_delay()", "v", v);
self.inner_mut().HoverStationaryDelay = v;
}
pub fn hover_delay_short(&self) -> f32 {
self.inner().HoverDelayShort
}
pub fn set_hover_delay_short(&mut self, v: f32) {
assert_non_negative_f32("Style::set_hover_delay_short()", "v", v);
self.inner_mut().HoverDelayShort = v;
}
pub fn hover_delay_normal(&self) -> f32 {
self.inner().HoverDelayNormal
}
pub fn set_hover_delay_normal(&mut self, v: f32) {
assert_non_negative_f32("Style::set_hover_delay_normal()", "v", v);
self.inner_mut().HoverDelayNormal = v;
}
pub fn hover_flags_for_tooltip_mouse(&self) -> HoveredFlags {
HoveredFlags::from_bits_truncate(self.inner().HoverFlagsForTooltipMouse as i32)
}
pub fn set_hover_flags_for_tooltip_mouse(&mut self, flags: HoveredFlags) {
validate_tooltip_hovered_flags("Style::set_hover_flags_for_tooltip_mouse()", flags);
self.inner_mut().HoverFlagsForTooltipMouse = flags.bits() as sys::ImGuiHoveredFlags;
}
pub fn hover_flags_for_tooltip_nav(&self) -> HoveredFlags {
HoveredFlags::from_bits_truncate(self.inner().HoverFlagsForTooltipNav as i32)
}
pub fn set_hover_flags_for_tooltip_nav(&mut self, flags: HoveredFlags) {
validate_tooltip_hovered_flags("Style::set_hover_flags_for_tooltip_nav()", flags);
self.inner_mut().HoverFlagsForTooltipNav = flags.bits() as sys::ImGuiHoveredFlags;
}
}
#[repr(i32)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum Direction {
None = sys::ImGuiDir_None as i32,
Left = sys::ImGuiDir_Left as i32,
Right = sys::ImGuiDir_Right as i32,
Up = sys::ImGuiDir_Up as i32,
Down = sys::ImGuiDir_Down as i32,
}
impl From<sys::ImGuiDir> for Direction {
fn from(d: sys::ImGuiDir) -> Self {
match d as i32 {
x if x == sys::ImGuiDir_Left as i32 => Direction::Left,
x if x == sys::ImGuiDir_Right as i32 => Direction::Right,
x if x == sys::ImGuiDir_Up as i32 => Direction::Up,
x if x == sys::ImGuiDir_Down as i32 => Direction::Down,
_ => Direction::None,
}
}
}
impl From<Direction> for sys::ImGuiDir {
fn from(d: Direction) -> Self {
match d {
Direction::None => sys::ImGuiDir_None,
Direction::Left => sys::ImGuiDir_Left,
Direction::Right => sys::ImGuiDir_Right,
Direction::Up => sys::ImGuiDir_Up,
Direction::Down => sys::ImGuiDir_Down,
}
}
}
#[repr(i32)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum StyleColor {
Text = sys::ImGuiCol_Text as i32,
TextDisabled = sys::ImGuiCol_TextDisabled as i32,
WindowBg = sys::ImGuiCol_WindowBg as i32,
ChildBg = sys::ImGuiCol_ChildBg as i32,
PopupBg = sys::ImGuiCol_PopupBg as i32,
Border = sys::ImGuiCol_Border as i32,
BorderShadow = sys::ImGuiCol_BorderShadow as i32,
FrameBg = sys::ImGuiCol_FrameBg as i32,
FrameBgHovered = sys::ImGuiCol_FrameBgHovered as i32,
FrameBgActive = sys::ImGuiCol_FrameBgActive as i32,
TitleBg = sys::ImGuiCol_TitleBg as i32,
TitleBgActive = sys::ImGuiCol_TitleBgActive as i32,
TitleBgCollapsed = sys::ImGuiCol_TitleBgCollapsed as i32,
MenuBarBg = sys::ImGuiCol_MenuBarBg as i32,
ScrollbarBg = sys::ImGuiCol_ScrollbarBg as i32,
ScrollbarGrab = sys::ImGuiCol_ScrollbarGrab as i32,
ScrollbarGrabHovered = sys::ImGuiCol_ScrollbarGrabHovered as i32,
ScrollbarGrabActive = sys::ImGuiCol_ScrollbarGrabActive as i32,
CheckMark = sys::ImGuiCol_CheckMark as i32,
CheckboxSelectedBg = sys::ImGuiCol_CheckboxSelectedBg as i32,
SliderGrab = sys::ImGuiCol_SliderGrab as i32,
SliderGrabActive = sys::ImGuiCol_SliderGrabActive as i32,
Button = sys::ImGuiCol_Button as i32,
ButtonHovered = sys::ImGuiCol_ButtonHovered as i32,
ButtonActive = sys::ImGuiCol_ButtonActive as i32,
Header = sys::ImGuiCol_Header as i32,
HeaderHovered = sys::ImGuiCol_HeaderHovered as i32,
HeaderActive = sys::ImGuiCol_HeaderActive as i32,
Separator = sys::ImGuiCol_Separator as i32,
SeparatorHovered = sys::ImGuiCol_SeparatorHovered as i32,
SeparatorActive = sys::ImGuiCol_SeparatorActive as i32,
ResizeGrip = sys::ImGuiCol_ResizeGrip as i32,
ResizeGripHovered = sys::ImGuiCol_ResizeGripHovered as i32,
ResizeGripActive = sys::ImGuiCol_ResizeGripActive as i32,
Tab = sys::ImGuiCol_Tab as i32,
TabHovered = sys::ImGuiCol_TabHovered as i32,
TabSelected = sys::ImGuiCol_TabSelected as i32,
TabSelectedOverline = sys::ImGuiCol_TabSelectedOverline as i32,
TabDimmed = sys::ImGuiCol_TabDimmed as i32,
TabDimmedSelected = sys::ImGuiCol_TabDimmedSelected as i32,
TabDimmedSelectedOverline = sys::ImGuiCol_TabDimmedSelectedOverline as i32,
DockingPreview = sys::ImGuiCol_DockingPreview as i32,
DockingEmptyBg = sys::ImGuiCol_DockingEmptyBg as i32,
PlotLines = sys::ImGuiCol_PlotLines as i32,
PlotLinesHovered = sys::ImGuiCol_PlotLinesHovered as i32,
PlotHistogram = sys::ImGuiCol_PlotHistogram as i32,
PlotHistogramHovered = sys::ImGuiCol_PlotHistogramHovered as i32,
TableHeaderBg = sys::ImGuiCol_TableHeaderBg as i32,
TableBorderStrong = sys::ImGuiCol_TableBorderStrong as i32,
TableBorderLight = sys::ImGuiCol_TableBorderLight as i32,
TableRowBg = sys::ImGuiCol_TableRowBg as i32,
TableRowBgAlt = sys::ImGuiCol_TableRowBgAlt as i32,
TextSelectedBg = sys::ImGuiCol_TextSelectedBg as i32,
TextLink = sys::ImGuiCol_TextLink as i32,
TreeLines = sys::ImGuiCol_TreeLines as i32,
InputTextCursor = sys::ImGuiCol_InputTextCursor as i32,
DragDropTarget = sys::ImGuiCol_DragDropTarget as i32,
DragDropTargetBg = sys::ImGuiCol_DragDropTargetBg as i32,
UnsavedMarker = sys::ImGuiCol_UnsavedMarker as i32,
NavCursor = sys::ImGuiCol_NavCursor as i32,
NavWindowingHighlight = sys::ImGuiCol_NavWindowingHighlight as i32,
NavWindowingDimBg = sys::ImGuiCol_NavWindowingDimBg as i32,
ModalWindowDimBg = sys::ImGuiCol_ModalWindowDimBg as i32,
}
impl StyleColor {
pub const COUNT: usize = sys::ImGuiCol_COUNT as usize;
}
impl Clone for Style {
fn clone(&self) -> Self {
Self(UnsafeCell::new(*self.inner()))
}
}
impl PartialEq for Style {
fn eq(&self, other: &Self) -> bool {
*self.inner() == *other.inner()
}
}
impl RawWrapper for Style {
type Raw = sys::ImGuiStyle;
unsafe fn raw(&self) -> &Self::Raw {
self.inner()
}
unsafe fn raw_mut(&mut self) -> &mut Self::Raw {
self.inner_mut()
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[non_exhaustive]
pub enum StyleVar {
Alpha(f32),
DisabledAlpha(f32),
WindowPadding([f32; 2]),
WindowRounding(f32),
WindowBorderSize(f32),
WindowMinSize([f32; 2]),
WindowTitleAlign([f32; 2]),
ChildRounding(f32),
ChildBorderSize(f32),
PopupRounding(f32),
PopupBorderSize(f32),
FramePadding([f32; 2]),
FrameRounding(f32),
ImageRounding(f32),
ImageBorderSize(f32),
FrameBorderSize(f32),
ItemSpacing([f32; 2]),
ItemInnerSpacing([f32; 2]),
IndentSpacing(f32),
CellPadding([f32; 2]),
ScrollbarSize(f32),
ScrollbarRounding(f32),
ScrollbarPadding(f32),
GrabMinSize(f32),
GrabRounding(f32),
TabRounding(f32),
TabBorderSize(f32),
TabMinWidthBase(f32),
TabMinWidthShrink(f32),
TabBarBorderSize(f32),
TabBarOverlineSize(f32),
TableAngledHeadersAngle(f32),
TableAngledHeadersTextAlign([f32; 2]),
TreeLinesSize(f32),
TreeLinesRounding(f32),
DragDropTargetRounding(f32),
ButtonTextAlign([f32; 2]),
SelectableTextAlign([f32; 2]),
SeparatorSize(f32),
SeparatorTextBorderSize(f32),
SeparatorTextAlign([f32; 2]),
SeparatorTextPadding([f32; 2]),
DockingSeparatorSize(f32),
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ThemePreset {
None,
Dark,
Light,
Classic,
}
impl Default for ThemePreset {
fn default() -> Self {
ThemePreset::None
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq)]
pub struct ColorOverride {
pub id: StyleColor,
pub rgba: [f32; 4],
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(default))]
pub struct StyleTweaks {
pub window_rounding: Option<f32>,
pub frame_rounding: Option<f32>,
pub tab_rounding: Option<f32>,
pub window_padding: Option<[f32; 2]>,
pub frame_padding: Option<[f32; 2]>,
pub cell_padding: Option<[f32; 2]>,
pub item_spacing: Option<[f32; 2]>,
pub item_inner_spacing: Option<[f32; 2]>,
pub scrollbar_size: Option<f32>,
pub grab_min_size: Option<f32>,
pub indent_spacing: Option<f32>,
pub separator_size: Option<f32>,
pub scrollbar_rounding: Option<f32>,
pub grab_rounding: Option<f32>,
pub window_border_size: Option<f32>,
pub child_border_size: Option<f32>,
pub popup_border_size: Option<f32>,
pub frame_border_size: Option<f32>,
pub tab_border_size: Option<f32>,
pub child_rounding: Option<f32>,
pub popup_rounding: Option<f32>,
pub anti_aliased_lines: Option<bool>,
pub anti_aliased_fill: Option<bool>,
}
impl Default for StyleTweaks {
fn default() -> Self {
Self {
window_rounding: None,
frame_rounding: None,
tab_rounding: None,
window_padding: None,
frame_padding: None,
cell_padding: None,
item_spacing: None,
item_inner_spacing: None,
scrollbar_size: None,
grab_min_size: None,
indent_spacing: None,
separator_size: None,
scrollbar_rounding: None,
grab_rounding: None,
window_border_size: None,
child_border_size: None,
popup_border_size: None,
frame_border_size: None,
tab_border_size: None,
child_rounding: None,
popup_rounding: None,
anti_aliased_lines: None,
anti_aliased_fill: None,
}
}
}
impl StyleTweaks {
pub fn apply(&self, style: &mut Style) {
if let Some(v) = self.window_rounding {
style.set_window_rounding(v);
}
if let Some(v) = self.frame_rounding {
style.set_frame_rounding(v);
}
if let Some(v) = self.tab_rounding {
style.set_tab_rounding(v);
}
if let Some(v) = self.window_padding {
style.set_window_padding(v);
}
if let Some(v) = self.frame_padding {
style.set_frame_padding(v);
}
if let Some(v) = self.cell_padding {
style.set_cell_padding(v);
}
if let Some(v) = self.item_spacing {
style.set_item_spacing(v);
}
if let Some(v) = self.item_inner_spacing {
style.set_item_inner_spacing(v);
}
if let Some(v) = self.scrollbar_size {
style.set_scrollbar_size(v);
}
if let Some(v) = self.grab_min_size {
style.set_grab_min_size(v);
}
if let Some(v) = self.indent_spacing {
style.set_indent_spacing(v);
}
if let Some(v) = self.separator_size {
style.set_separator_size(v);
}
if let Some(v) = self.scrollbar_rounding {
style.set_scrollbar_rounding(v);
}
if let Some(v) = self.grab_rounding {
style.set_grab_rounding(v);
}
if let Some(v) = self.window_border_size {
style.set_window_border_size(v);
}
if let Some(v) = self.child_border_size {
style.set_child_border_size(v);
}
if let Some(v) = self.popup_border_size {
style.set_popup_border_size(v);
}
if let Some(v) = self.frame_border_size {
style.set_frame_border_size(v);
}
if let Some(v) = self.tab_border_size {
style.set_tab_border_size(v);
}
if let Some(v) = self.child_rounding {
style.set_child_rounding(v);
}
if let Some(v) = self.popup_rounding {
style.set_popup_rounding(v);
}
if let Some(v) = self.anti_aliased_lines {
style.set_anti_aliased_lines(v);
}
if let Some(v) = self.anti_aliased_fill {
style.set_anti_aliased_fill(v);
}
}
}
#[derive(Clone, Debug, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct WindowTheme {
pub default_window_flags: Option<WindowFlags>,
pub popup_window_flags: Option<WindowFlags>,
}
#[derive(Clone, Debug, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct TableTheme {
pub default_table_flags: Option<TableFlags>,
pub default_row_flags: Option<TableRowFlags>,
}
#[derive(Clone, Debug, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Theme {
#[cfg_attr(feature = "serde", serde(default))]
pub preset: ThemePreset,
#[cfg_attr(feature = "serde", serde(default))]
pub colors: Vec<ColorOverride>,
#[cfg_attr(feature = "serde", serde(default))]
pub style: StyleTweaks,
#[cfg_attr(feature = "serde", serde(default))]
pub windows: WindowTheme,
#[cfg_attr(feature = "serde", serde(default))]
pub tables: TableTheme,
}
impl Theme {
pub fn apply_to_style(&self, style: &mut Style) {
match self.preset {
ThemePreset::None => {}
ThemePreset::Dark => unsafe {
sys::igStyleColorsDark(style.raw_mut());
},
ThemePreset::Light => unsafe {
sys::igStyleColorsLight(style.raw_mut());
},
ThemePreset::Classic => unsafe {
sys::igStyleColorsClassic(style.raw_mut());
},
}
for c in &self.colors {
style.set_color(c.id, c.rgba);
}
self.style.apply(style);
}
pub fn apply_to_context(&self, ctx: &mut Context) {
let style = ctx.style_mut();
self.apply_to_style(style);
}
}