dear_implot/
style.rs

1// Style and theming for plots
2
3use crate::sys;
4
5/// Style variables that can be modified
6#[repr(i32)]
7#[derive(Copy, Clone, Debug, PartialEq, Eq)]
8pub enum StyleVar {
9    LineWeight = sys::ImPlotStyleVar_LineWeight as i32,
10    Marker = sys::ImPlotStyleVar_Marker as i32,
11    MarkerSize = sys::ImPlotStyleVar_MarkerSize as i32,
12    MarkerWeight = sys::ImPlotStyleVar_MarkerWeight as i32,
13    FillAlpha = sys::ImPlotStyleVar_FillAlpha as i32,
14    ErrorBarSize = sys::ImPlotStyleVar_ErrorBarSize as i32,
15    ErrorBarWeight = sys::ImPlotStyleVar_ErrorBarWeight as i32,
16    DigitalBitHeight = sys::ImPlotStyleVar_DigitalBitHeight as i32,
17    DigitalBitGap = sys::ImPlotStyleVar_DigitalBitGap as i32,
18    PlotBorderSize = sys::ImPlotStyleVar_PlotBorderSize as i32,
19    MinorAlpha = sys::ImPlotStyleVar_MinorAlpha as i32,
20    MajorTickLen = sys::ImPlotStyleVar_MajorTickLen as i32,
21    MinorTickLen = sys::ImPlotStyleVar_MinorTickLen as i32,
22    MajorTickSize = sys::ImPlotStyleVar_MajorTickSize as i32,
23    MinorTickSize = sys::ImPlotStyleVar_MinorTickSize as i32,
24    MajorGridSize = sys::ImPlotStyleVar_MajorGridSize as i32,
25    MinorGridSize = sys::ImPlotStyleVar_MinorGridSize as i32,
26    PlotPadding = sys::ImPlotStyleVar_PlotPadding as i32,
27    LabelPadding = sys::ImPlotStyleVar_LabelPadding as i32,
28    LegendPadding = sys::ImPlotStyleVar_LegendPadding as i32,
29    LegendInnerPadding = sys::ImPlotStyleVar_LegendInnerPadding as i32,
30    LegendSpacing = sys::ImPlotStyleVar_LegendSpacing as i32,
31    MousePosPadding = sys::ImPlotStyleVar_MousePosPadding as i32,
32    AnnotationPadding = sys::ImPlotStyleVar_AnnotationPadding as i32,
33    FitPadding = sys::ImPlotStyleVar_FitPadding as i32,
34    PlotDefaultSize = sys::ImPlotStyleVar_PlotDefaultSize as i32,
35    PlotMinSize = sys::ImPlotStyleVar_PlotMinSize as i32,
36}
37
38/// Token for managing style variable changes
39pub struct StyleVarToken {
40    was_popped: bool,
41}
42
43impl StyleVarToken {
44    /// Pop this style variable from the stack
45    pub fn pop(mut self) {
46        if self.was_popped {
47            panic!("Attempted to pop a style var token twice.");
48        }
49        self.was_popped = true;
50        unsafe {
51            sys::ImPlot_PopStyleVar(1);
52        }
53    }
54}
55
56impl Drop for StyleVarToken {
57    fn drop(&mut self) {
58        if !self.was_popped {
59            unsafe {
60                sys::ImPlot_PopStyleVar(1);
61            }
62        }
63    }
64}
65
66/// Token for managing style color changes
67pub struct StyleColorToken {
68    was_popped: bool,
69}
70
71impl StyleColorToken {
72    /// Pop this style color from the stack
73    pub fn pop(mut self) {
74        if self.was_popped {
75            panic!("Attempted to pop a style color token twice.");
76        }
77        self.was_popped = true;
78        unsafe {
79            sys::ImPlot_PopStyleColor(1);
80        }
81    }
82}
83
84impl Drop for StyleColorToken {
85    fn drop(&mut self) {
86        if !self.was_popped {
87            unsafe {
88                sys::ImPlot_PopStyleColor(1);
89            }
90        }
91    }
92}
93
94/// Push a float style variable to the stack
95pub fn push_style_var_f32(var: StyleVar, value: f32) -> StyleVarToken {
96    unsafe {
97        sys::ImPlot_PushStyleVar_Float(var as sys::ImPlotStyleVar, value);
98    }
99    StyleVarToken { was_popped: false }
100}
101
102/// Push an integer style variable to the stack (converted to float)
103pub fn push_style_var_i32(var: StyleVar, value: i32) -> StyleVarToken {
104    unsafe {
105        sys::ImPlot_PushStyleVar_Int(var as sys::ImPlotStyleVar, value);
106    }
107    StyleVarToken { was_popped: false }
108}
109
110/// Push a Vec2 style variable to the stack
111pub fn push_style_var_vec2(var: StyleVar, value: [f32; 2]) -> StyleVarToken {
112    unsafe {
113        sys::ImPlot_PushStyleVar_Vec2(
114            var as sys::ImPlotStyleVar,
115            sys::ImVec2_c {
116                x: value[0],
117                y: value[1],
118            },
119        );
120    }
121    StyleVarToken { was_popped: false }
122}
123
124/// Push a style color to the stack
125pub fn push_style_color(element: crate::PlotColorElement, color: [f32; 4]) -> StyleColorToken {
126    unsafe {
127        // Convert color to ImU32 format (RGBA)
128        let r = (color[0] * 255.0) as u32;
129        let g = (color[1] * 255.0) as u32;
130        let b = (color[2] * 255.0) as u32;
131        let a = (color[3] * 255.0) as u32;
132        let color_u32 = (a << 24) | (b << 16) | (g << 8) | r;
133
134        sys::ImPlot_PushStyleColor_U32(element as sys::ImPlotCol, color_u32);
135    }
136    StyleColorToken { was_popped: false }
137}
138
139/// Push a colormap to the stack
140pub fn push_colormap(preset: crate::Colormap) {
141    unsafe {
142        sys::ImPlot_PushColormap_PlotColormap(preset as sys::ImPlotColormap);
143    }
144}
145
146/// Pop a colormap from the stack
147pub fn pop_colormap(count: i32) {
148    unsafe {
149        sys::ImPlot_PopColormap(count);
150    }
151}
152
153/// Add a custom colormap from a vector of colors
154pub fn add_colormap(name: &str, colors: &[sys::ImVec4], qualitative: bool) -> sys::ImPlotColormap {
155    let name_cstr = std::ffi::CString::new(name).unwrap();
156    unsafe {
157        sys::ImPlot_AddColormap_Vec4Ptr(
158            name_cstr.as_ptr(),
159            colors.as_ptr(),
160            colors.len() as i32,
161            qualitative,
162        ) as sys::ImPlotColormap
163    }
164}
165
166// Style editor / selectors and input-map helpers
167
168/// Show the ImPlot style editor window
169pub fn show_style_editor() {
170    unsafe { sys::ImPlot_ShowStyleEditor(std::ptr::null_mut()) }
171}
172
173/// Show the ImPlot style selector combo; returns true if selection changed
174pub fn show_style_selector(label: &str) -> bool {
175    let c = std::ffi::CString::new(label).unwrap_or_default();
176    unsafe { sys::ImPlot_ShowStyleSelector(c.as_ptr()) }
177}
178
179/// Show the ImPlot colormap selector combo; returns true if selection changed
180pub fn show_colormap_selector(label: &str) -> bool {
181    let c = std::ffi::CString::new(label).unwrap_or_default();
182    unsafe { sys::ImPlot_ShowColormapSelector(c.as_ptr()) }
183}
184
185/// Show the ImPlot input-map selector combo; returns true if selection changed
186pub fn show_input_map_selector(label: &str) -> bool {
187    let c = std::ffi::CString::new(label).unwrap_or_default();
188    unsafe { sys::ImPlot_ShowInputMapSelector(c.as_ptr()) }
189}
190
191/// Map input to defaults
192pub fn map_input_default() {
193    unsafe { sys::ImPlot_MapInputDefault(sys::ImPlot_GetInputMap()) }
194}
195
196/// Map input to reversed scheme
197pub fn map_input_reverse() {
198    unsafe { sys::ImPlot_MapInputReverse(sys::ImPlot_GetInputMap()) }
199}
200
201// Colormap widgets
202
203/// Draw a colormap scale widget
204pub fn colormap_scale(
205    label: &str,
206    scale_min: f64,
207    scale_max: f64,
208    height: f32,
209    cmap: Option<sys::ImPlotColormap>,
210) {
211    let c = std::ffi::CString::new(label).unwrap_or_default();
212    let size = sys::ImVec2_c { x: 0.0, y: height };
213    let fmt_ptr: *const i8 = std::ptr::null();
214    let flags: i32 = 0; // ImPlotColormapScaleFlags_None
215    unsafe {
216        sys::ImPlot_ColormapScale(
217            c.as_ptr(),
218            scale_min,
219            scale_max,
220            size,
221            fmt_ptr,
222            flags,
223            cmap.unwrap_or(0),
224        )
225    }
226}
227
228/// Draw a colormap slider; returns true if selection changed
229pub fn colormap_slider(
230    label: &str,
231    t: &mut f32,
232    out_color: &mut sys::ImVec4,
233    format: Option<&str>,
234    cmap: sys::ImPlotColormap,
235) -> bool {
236    let c = std::ffi::CString::new(label).unwrap_or_default();
237    let fmt_c = format.and_then(|s| std::ffi::CString::new(s).ok());
238    let fmt_ptr = fmt_c
239        .as_ref()
240        .map(|cs| cs.as_ptr())
241        .unwrap_or(std::ptr::null());
242    unsafe {
243        sys::ImPlot_ColormapSlider(
244            c.as_ptr(),
245            t as *mut f32,
246            out_color as *mut sys::ImVec4,
247            fmt_ptr,
248            cmap,
249        )
250    }
251}
252
253/// Draw a colormap picker button; returns true if clicked
254pub fn colormap_button(label: &str, size: [f32; 2], cmap: sys::ImPlotColormap) -> bool {
255    let c = std::ffi::CString::new(label).unwrap_or_default();
256    let sz = sys::ImVec2_c {
257        x: size[0],
258        y: size[1],
259    };
260    unsafe { sys::ImPlot_ColormapButton(c.as_ptr(), sz, cmap) }
261}