diff --git a/imgui-examples/examples/slider.rs b/imgui-examples/examples/slider.rs index 691a4fe..2b3698e 100644 --- a/imgui-examples/examples/slider.rs +++ b/imgui-examples/examples/slider.rs @@ -41,29 +41,27 @@ fn example_1(ui: &Ui, state: &mut State) { ui.text("Unsigned: u8 u16 u32 u64"); ui.text("Floats: f32 f64"); - Slider::new(im_str!("u8 value")) + Slider::new(im_str!("u8 value"), 0, 255) .build(ui, &mut state.u8_value); - Slider::new(im_str!("f32 value")) + Slider::new(im_str!("f32 value"), -f32::MIN, f32::MAX) .build(ui, &mut state.f32_value); ui.separator(); ui.text("Slider range can be limited:"); - Slider::new(im_str!("i32 value with range")) - .range(-999 ..= 999) + Slider::new(im_str!("i32 value with range"), -999, 999) .build(ui, &mut state.i32_value); ui.text("Note that for 32-bit/64-bit types, sliders are always limited to half of the natural type range!"); ui.separator(); ui.text("Value formatting can be customized with a C-style printf string:"); - Slider::new(im_str!("f64 value with custom formatting")) - .range(-999_999_999.0 ..= 999_999_999.0) + Slider::new(im_str!("f64 value with custom formatting"), -999_999_999.0, 999_999_999.0) .display_format(im_str!("%09.0f")) .build(ui, &mut state.f64_formatted); ui.separator(); ui.text("Vertical sliders require a size parameter but otherwise work in a similar way:"); - VerticalSlider::new(im_str!("vertical\nu8 value"), [50.0, 50.0]) + VerticalSlider::new(im_str!("vertical\nu8 value"), [50.0, 50.0], u8::MIN, u8::MAX) .build(ui, &mut state.u8_value); }); } @@ -74,11 +72,11 @@ fn example_2(ui: &Ui, state: &mut State) { .position([20.0, 120.0], Condition::Appearing); w.build(ui, || { ui.text("You can easily build a slider group from an array of values:"); - Slider::new(im_str!("[u8; 4]")).build_array(ui, &mut state.array); + Slider::new(im_str!("[u8; 4]"), 0, u8::MAX).build_array(ui, &mut state.array); ui.text("You don't need to use arrays with known length; arbitrary slices can be used:"); let slice: &mut [u8] = &mut state.array[1..=2]; - Slider::new(im_str!("subslice")).build_array(ui, slice); + Slider::new(im_str!("subslice"), 0, u8::MAX).build_array(ui, slice); }); } diff --git a/imgui-examples/examples/test_window_impl.rs b/imgui-examples/examples/test_window_impl.rs index 0704d68..867b848 100644 --- a/imgui-examples/examples/test_window_impl.rs +++ b/imgui-examples/examples/test_window_impl.rs @@ -448,7 +448,7 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) { )); ui.spacing(); - Slider::new(im_str!("Wrap width")).range(-20.0 ..= 600.0) + Slider::new(im_str!("Wrap width"), -20.0, 600.0) .display_format(im_str!("%.0f")) .build(ui, &mut state.wrap_width); @@ -545,7 +545,7 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) { .step(0.01) .step_fast(1.0) .build(); - Drag::new(im_str!("drag float")).range(-1.0..=1.0).speed(0.001).build(ui, &mut state.f0); + Drag::new(im_str!("drag float")).range(-1.0, 1.0).speed(0.001).build(ui, &mut state.f0); ui.input_float3(im_str!("input float3"), &mut state.vec3f) .build(); ColorEdit::new(im_str!("color 1"), &mut state.col1).build(ui); @@ -899,9 +899,7 @@ fn show_example_menu_file<'a>(ui: &Ui<'a>, state: &mut FileMenuState) { ui.text(format!("Scrolling Text {}", i)); } }); - Slider::new(im_str!("Value")) - .range(0.0..=1.0) - .build(ui, &mut state.f); + Slider::new(im_str!("Value"), 0.0, 1.0).build(ui, &mut state.f); ui.input_float(im_str!("Input"), &mut state.f) .step(0.1) @@ -936,9 +934,7 @@ fn show_example_app_auto_resize(ui: &Ui, state: &mut AutoResizeState, opened: &m Note that you probably don't want to query the window size to output your content because that would create a feedback loop.", ); - Slider::new(im_str!("Number of lines")) - .range(1..=20) - .build(ui, &mut state.lines); + Slider::new(im_str!("Number of lines"), 1, 20).build(ui, &mut state.lines); for i in 0..state.lines { ui.text(format!("{:2$}This is line {}", "", i, i as usize * 4)); } diff --git a/imgui/src/internal.rs b/imgui/src/internal.rs index d3d10d4..a34613e 100644 --- a/imgui/src/internal.rs +++ b/imgui/src/internal.rs @@ -1,6 +1,5 @@ //! Internal raw utilities (don't use unless you know what you're doing!) -use std::ops::{RangeFrom, RangeInclusive, RangeToInclusive}; use std::slice; /// A generic version of the raw imgui-sys ImVector struct types @@ -127,94 +126,34 @@ pub enum DataType { /// representation in memory as the primitive value described by the associated `KIND` constant. pub unsafe trait DataTypeKind: Copy { const KIND: DataType; - const SLIDER_MIN: Self; - const SLIDER_MAX: Self; } unsafe impl DataTypeKind for i8 { const KIND: DataType = DataType::I8; - const SLIDER_MIN: Self = std::i8::MIN; - const SLIDER_MAX: Self = std::i8::MAX; } unsafe impl DataTypeKind for u8 { const KIND: DataType = DataType::U8; - const SLIDER_MIN: Self = std::u8::MIN; - const SLIDER_MAX: Self = std::u8::MAX; } unsafe impl DataTypeKind for i16 { const KIND: DataType = DataType::I16; - const SLIDER_MIN: Self = std::i16::MIN; - const SLIDER_MAX: Self = std::i16::MAX; } unsafe impl DataTypeKind for u16 { const KIND: DataType = DataType::U16; - const SLIDER_MIN: Self = std::u16::MIN; - const SLIDER_MAX: Self = std::u16::MAX; } unsafe impl DataTypeKind for i32 { const KIND: DataType = DataType::I32; - const SLIDER_MIN: Self = std::i32::MIN / 2; - const SLIDER_MAX: Self = std::i32::MAX / 2; } unsafe impl DataTypeKind for u32 { const KIND: DataType = DataType::U32; - const SLIDER_MIN: Self = std::u32::MIN / 2; - const SLIDER_MAX: Self = std::u32::MAX / 2; } unsafe impl DataTypeKind for i64 { const KIND: DataType = DataType::I64; - const SLIDER_MIN: Self = std::i64::MIN / 2; - const SLIDER_MAX: Self = std::i64::MAX / 2; } unsafe impl DataTypeKind for u64 { const KIND: DataType = DataType::U64; - const SLIDER_MIN: Self = std::u64::MIN / 2; - const SLIDER_MAX: Self = std::u64::MAX / 2; } unsafe impl DataTypeKind for f32 { const KIND: DataType = DataType::F32; - const SLIDER_MIN: Self = std::f32::MIN / 2.0; - const SLIDER_MAX: Self = std::f32::MAX / 2.0; } unsafe impl DataTypeKind for f64 { const KIND: DataType = DataType::F64; - const SLIDER_MIN: Self = std::f64::MIN / 2.0; - const SLIDER_MAX: Self = std::f64::MAX / 2.0; -} - -pub trait InclusiveRangeBounds { - fn start_bound(&self) -> Option<&T>; - fn end_bound(&self) -> Option<&T>; -} - -impl InclusiveRangeBounds for RangeFrom { - #[inline] - fn start_bound(&self) -> Option<&T> { - Some(&self.start) - } - #[inline] - fn end_bound(&self) -> Option<&T> { - None - } -} - -impl InclusiveRangeBounds for RangeInclusive { - #[inline] - fn start_bound(&self) -> Option<&T> { - Some(self.start()) - } - #[inline] - fn end_bound(&self) -> Option<&T> { - Some(self.end()) - } -} - -impl InclusiveRangeBounds for RangeToInclusive { - #[inline] - fn start_bound(&self) -> Option<&T> { - None - } - #[inline] - fn end_bound(&self) -> Option<&T> { - Some(&self.end) - } } diff --git a/imgui/src/widget/drag.rs b/imgui/src/widget/drag.rs index 1b8539c..dd5cb43 100644 --- a/imgui/src/widget/drag.rs +++ b/imgui/src/widget/drag.rs @@ -1,7 +1,7 @@ use std::os::raw::c_void; use std::ptr; -use crate::internal::{DataTypeKind, InclusiveRangeBounds}; +use crate::internal::DataTypeKind; use crate::string::ImStr; use crate::sys; use crate::widget::slider::SliderFlags; @@ -34,9 +34,9 @@ impl<'a, T: DataTypeKind> Drag<'a, T> { } /// Sets the range (inclusive) #[inline] - pub fn range>(mut self, range: R) -> Self { - self.min = range.start_bound().copied(); - self.max = range.end_bound().copied(); + pub fn range(mut self, min: T, max: T) -> Self { + self.min = Some(min); + self.max = Some(max); self } /// Sets the value increment for a movement of one pixel. @@ -140,9 +140,9 @@ impl<'a, T: DataTypeKind> DragRange<'a, T> { } } #[inline] - pub fn range>(mut self, range: R) -> Self { - self.min = range.start_bound().copied(); - self.max = range.end_bound().copied(); + pub fn range(mut self, min: T, max: T) -> Self { + self.min = Some(min); + self.max = Some(max); self } /// Sets the value increment for a movement of one pixel. diff --git a/imgui/src/widget/slider.rs b/imgui/src/widget/slider.rs index 314eb76..37737f6 100644 --- a/imgui/src/widget/slider.rs +++ b/imgui/src/widget/slider.rs @@ -2,7 +2,7 @@ use bitflags::bitflags; use std::os::raw::c_void; use std::ptr; -use crate::internal::{DataTypeKind, InclusiveRangeBounds}; +use crate::internal::DataTypeKind; use crate::string::ImStr; use crate::sys; use crate::Ui; @@ -38,42 +38,32 @@ pub struct Slider<'a, T: DataTypeKind> { impl<'a, T: DataTypeKind> Slider<'a, T> { /// Constructs a new slider builder with the given range. #[doc(alias = "SliderScalar", alias = "SliderScalarN")] - pub fn new(label: &ImStr) -> Slider { + pub fn new(label: &ImStr, min: T, max: T) -> Slider { Slider { label, - min: T::SLIDER_MIN, - max: T::SLIDER_MAX, + min, + max, display_format: None, flags: SliderFlags::empty(), } } - /// Sets the range (inclusive) - /// - /// The argument uses the standard Rust [`std::ops::Range`] syntax. - /// - /// For example, to set both the min and max values: + /// Sets the range inclusively, such that both values given + /// are valid values which the slider can be dragged to. /// /// ```rust /// # use imgui::im_str; /// imgui::Slider::new(im_str!("Example")) - /// .range(1 ..= 10) + /// .range(i8::MIN, i8::MAX) /// // Remember to call .build(&ui) /// ; /// ``` /// - /// To set only the max value, using the default minimum value: - /// - /// ```rust - /// # use imgui::im_str; - /// imgui::Slider::new(im_str!("Example")) - /// .range(..= 10) - /// // 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, range: R) -> Self { - self.min = range.start_bound().copied().unwrap_or(T::SLIDER_MIN); - self.max = range.end_bound().copied().unwrap_or(T::SLIDER_MAX); + pub fn range(mut self, min: T, max: T) -> Self { + self.min = min; + self.max = max; self } /// Sets the display format using *a C-style printf string* @@ -142,21 +132,32 @@ pub struct VerticalSlider<'a, T: DataTypeKind + Copy> { impl<'a, T: DataTypeKind> VerticalSlider<'a, T> { /// Constructs a new vertical slider builder with the given size and range. #[doc(alias = "VSliderScalar")] - pub fn new(label: &ImStr, size: [f32; 2]) -> VerticalSlider { + pub fn new(label: &ImStr, size: [f32; 2], min: T, max: T) -> VerticalSlider { VerticalSlider { label, size, - min: T::SLIDER_MIN, - max: T::SLIDER_MAX, + min, + max, display_format: None, flags: SliderFlags::empty(), } } - /// Sets the range (inclusive) + + /// + /// ```rust + /// # use imgui::im_str; + /// imgui::VerticalSlider::new(im_str!("Example")) + /// .range(i8::MIN, i8::MAX) + /// // 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, range: R) -> Self { - self.min = range.start_bound().copied().unwrap_or(T::SLIDER_MIN); - self.max = range.end_bound().copied().unwrap_or(T::SLIDER_MAX); + pub fn range(mut self, min: T, max: T) -> Self { + self.min = min; + self.max = max; self } /// Sets the display format using *a C-style printf string* @@ -204,7 +205,8 @@ pub struct AngleSlider<'a> { } impl<'a> AngleSlider<'a> { - /// Constructs a new angle slider builder. + /// Constructs a new angle slider builder, where its minimum defaults to -360.0 and + /// maximum defaults to 360.0 #[doc(alias = "SliderAngle")] pub fn new(label: &ImStr) -> AngleSlider { AngleSlider { @@ -215,11 +217,21 @@ impl<'a> AngleSlider<'a> { flags: SliderFlags::empty(), } } - /// Sets the range (in degrees, inclusive) + /// Sets the range in degrees (inclusive) + /// ```rust + /// # use imgui::im_str; + /// imgui::AngleSlider::new(im_str!("Example")) + /// .range_degrees(-20.0, 20.0) + /// // 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_degrees>(mut self, range: R) -> Self { - self.min_degrees = range.start_bound().copied().unwrap_or(-360.0); - self.max_degrees = range.end_bound().copied().unwrap_or(360.0); + pub fn range_degrees(mut self, min_degrees: f32, max_degrees: f32) -> Self { + self.min_degrees = min_degrees; + self.max_degrees = max_degrees; self } /// Sets the minimum value (in degrees)