use bitflags::bitflags; use std::os::raw::c_void; use crate::internal::DataTypeKind; use crate::math::MintVec2; use crate::sys; use crate::Ui; bitflags!( /// Flags for sliders #[repr(transparent)] pub struct SliderFlags: u32 { /// Clamp value to min/max bounds when input manually with CTRL+Click. /// /// By default CTRL+click allows going out of bounds. const ALWAYS_CLAMP = sys::ImGuiSliderFlags_AlwaysClamp; /// Make the widget logarithmic instead of linear const LOGARITHMIC = sys::ImGuiSliderFlags_Logarithmic; /// Disable rounding underlying value to match precision of the display format string const NO_ROUND_TO_FORMAT = sys::ImGuiSliderFlags_NoRoundToFormat; /// Disable CTRL+Click or Enter key allowing to input text directly into the widget const NO_INPUT = sys::ImGuiSliderFlags_NoInput; } ); impl Ui { /// Creates a new slider widget. Returns true if the value has been edited. pub fn slider, K: DataTypeKind>( &self, label: T, min: K, max: K, value: &mut K, ) -> bool { self.slider_config(label, min, max).build(value) } /// Creates an new ubuilt Slider. pub fn slider_config, K: DataTypeKind>( &self, label: T, min: K, max: K, ) -> Slider<'_, T, K> { Slider { label, min, max, display_format: Option::<&'static str>::None, flags: SliderFlags::empty(), ui: self, } } } /// Builder for a slider widget. #[derive(Copy, Clone, Debug)] #[must_use] pub struct Slider<'ui, Label, Data, Format = &'static str> { label: Label, min: Data, max: Data, display_format: Option, flags: SliderFlags, ui: &'ui Ui, } impl<'ui, T: AsRef, K: DataTypeKind> Slider<'ui, T, K> { /// Constructs a new slider builder with the given range. #[doc(alias = "SliderScalar", alias = "SliderScalarN")] #[deprecated(note = "Use `Ui::slider` or `Ui::slider_config`.", since = "0.9.0")] pub fn new(ui: &'ui Ui, label: T, min: K, max: K) -> Self { Slider { label, min, max, display_format: None, flags: SliderFlags::empty(), ui, } } } impl<'ui, Label, Data, Format> Slider<'ui, Label, Data, Format> where Label: AsRef, Data: DataTypeKind, Format: AsRef, { /// Sets the range inclusively, such that both values given /// are valid values which the slider can be dragged to. /// /// ```no_run /// # let mut ctx = imgui::Context::create(); /// # let ui = ctx.frame(); /// ui.slider_config("Example", i8::MIN, i8::MAX) /// .range(4, 8) /// // Remember to call .build() /// ; /// ``` /// /// It is safe, though up to C++ Dear ImGui, on how to handle when /// `min > max`. /// /// Note for f32 and f64 sliders, Dear ImGui limits the available /// range to half their full range (e.g `f32::MIN/2.0 .. f32::MAX/2.0`) /// Specifying a value above this will cause an abort. /// For large ranged values, consider using [`Ui::input_scalar`] instead #[inline] pub fn range(mut self, min: Data, max: Data) -> Self { self.min = min; self.max = max; self } /// Sets the display format using *a C-style printf string* #[inline] pub fn display_format>( self, display_format: Format2, ) -> Slider<'ui, Label, Data, Format2> { Slider { label: self.label, min: self.min, max: self.max, display_format: Some(display_format), flags: self.flags, ui: self.ui, } } /// Replaces all current settings with the given flags #[inline] pub fn flags(mut self, flags: SliderFlags) -> Self { self.flags = flags; self } /// Builds a slider that is bound to the given value. /// /// Returns true if the slider value was changed. pub fn build(self, value: &mut Data) -> bool { unsafe { let (label, display_format) = self .ui .scratch_txt_with_opt(self.label, self.display_format); sys::igSliderScalar( label, Data::KIND as i32, value as *mut Data as *mut c_void, &self.min as *const Data as *const c_void, &self.max as *const Data as *const c_void, display_format, self.flags.bits() as i32, ) } } /// Builds a horizontal array of multiple sliders attached to the given slice. /// /// Returns true if any slider value was changed. pub fn build_array(self, values: &mut [Data]) -> bool { unsafe { let (label, display_format) = self .ui .scratch_txt_with_opt(self.label, self.display_format); sys::igSliderScalarN( label, Data::KIND as i32, values.as_mut_ptr() as *mut c_void, values.len() as i32, &self.min as *const Data as *const c_void, &self.max as *const Data as *const c_void, display_format, self.flags.bits() as i32, ) } } } /// Builder for a vertical slider widget. #[derive(Clone, Debug)] #[must_use] pub struct VerticalSlider { label: Label, size: [f32; 2], min: Data, max: Data, display_format: Option, flags: SliderFlags, } impl VerticalSlider where Label: AsRef, Data: DataTypeKind, { /// Constructs a new vertical slider builder with the given size and range. /// /// ```rust /// imgui::VerticalSlider::new("Example", [20.0, 20.0], i8::MIN, i8::MAX) /// .range(4, 8) /// // Remember to call .build(&ui) /// ; /// ``` /// /// It is safe, though up to C++ Dear ImGui, on how to handle when /// `min > max`. #[doc(alias = "VSliderScalar")] pub fn new(label: Label, size: impl Into, min: Data, max: Data) -> Self { VerticalSlider { label, size: size.into().into(), min, max, display_format: None, flags: SliderFlags::empty(), } } } impl VerticalSlider where Label: AsRef, Data: DataTypeKind, Format: AsRef, { /// Sets the range for the vertical slider. /// /// ```rust /// imgui::VerticalSlider::new("Example", [20.0, 20.0], i8::MIN, i8::MAX) /// .range(4, 8) /// // Remember to call .build(&ui) /// ; /// ``` /// /// It is safe, though up to C++ Dear ImGui, on how to handle when /// `min > max`. #[inline] pub fn range(mut self, min: Data, max: Data) -> Self { self.min = min; self.max = max; self } /// Sets the display format using *a C-style printf string* #[inline] pub fn display_format>( self, display_format: Format2, ) -> VerticalSlider { VerticalSlider { label: self.label, size: self.size, min: self.min, max: self.max, display_format: Some(display_format), flags: self.flags, } } /// Replaces all current settings with the given flags #[inline] pub fn flags(mut self, flags: SliderFlags) -> Self { self.flags = flags; self } /// Builds a vertical slider that is bound to the given value. /// /// Returns true if the slider value was changed. pub fn build(self, ui: &Ui, value: &mut Data) -> bool { unsafe { let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format); sys::igVSliderScalar( label, self.size.into(), Data::KIND as i32, value as *mut Data as *mut c_void, &self.min as *const Data as *const c_void, &self.max as *const Data as *const c_void, display_format, self.flags.bits() as i32, ) } } } /// Builder for an angle slider widget. #[derive(Copy, Clone, Debug)] #[must_use] pub struct AngleSlider { label: Label, min_degrees: f32, max_degrees: f32, display_format: Format, flags: SliderFlags, } impl