refactored Slider to match the new Ui based architecture

This commit is contained in:
Gabe Weiner 2022-01-28 11:36:22 -05:00 committed by Jonathan Spira
parent 18ded1a58a
commit d05827258f
3 changed files with 66 additions and 36 deletions

View File

@ -44,13 +44,11 @@ fn example_1(ui: &Ui, state: &mut State) {
ui.text("Floats: f32 f64"); ui.text("Floats: f32 f64");
// Full ranges can be specified with Rust's `::MIN/MAX` constants // Full ranges can be specified with Rust's `::MIN/MAX` constants
Slider::new("u8 value", u8::MIN, u8::MAX) ui.slider("u8 value", u8::MIN, u8::MAX, &mut state.u8_value);
.build(ui, &mut state.u8_value);
// However for larger data-types, it's usually best to specify // However for larger data-types, it's usually best to specify
// a much smaller range. The following slider is hard to use. // a much smaller range. The following slider is hard to use.
Slider::new("Full range f32 value", f32::MIN/2.0, f32::MAX/2.0) ui.slider("Full range f32 value", f32::MIN/2.0, f32::MAX/2.0, &mut state.f32_value);
.build(ui, &mut state.f32_value);
// Note the `... / 2.0` - anything larger is not supported by // Note the `... / 2.0` - anything larger is not supported by
// the upstream C++ library // the upstream C++ library
ui.text("Note that for 32-bit/64-bit types, sliders are always limited to half of the natural type range!"); ui.text("Note that for 32-bit/64-bit types, sliders are always limited to half of the natural type range!");
@ -58,24 +56,16 @@ fn example_1(ui: &Ui, state: &mut State) {
// Most of the time, it's best to specify the range // Most of the time, it's best to specify the range
ui.separator(); ui.separator();
ui.text("Slider range can be limited:"); ui.text("Slider range can be limited:");
Slider::new("i32 value with range", -999, 999) ui.slider("i32 value with range", -999, 999, &mut state.i32_value);
.build(ui, &mut state.i32_value); ui.slider("f32 value", -10.0, 10.0, &mut state.f32_value);
Slider::new("f32 value", -10.0, 10.0)
.build(ui, &mut state.f32_value);
ui.separator(); ui.separator();
ui.text("Value formatting can be customized with a C-style printf string:"); ui.text("Value formatting can be customized with a C-style printf string:");
Slider::new("f64 value with custom formatting", -999_999_999.0, 999_999_999.0) ui.slider_config("f64 value with custom formatting", -999_999_999.0, 999_999_999.0).display_format("%09.0f").build(&mut state.f64_formatted);
.display_format("%09.0f")
.build(ui, &mut state.f64_formatted);
// The display format changes the increments the slider operates in: // The display format changes the increments the slider operates in:
Slider::new("f32 with %.01f", 0.0, 1.0) ui.slider_config("f32 with %.01f", 0.0, 1.0).display_format("%.01f").build(&mut state.f32_value);
.display_format("%.01f") ui.slider_config("Same f32 with %.05f", 0.0, 1.0).display_format("%.05f").build(&mut state.f32_value);
.build(ui, &mut state.f32_value);
Slider::new("Same f32 with %.05f", 0.0, 1.0)
.display_format("%.05f")
.build(ui, &mut state.f32_value);
ui.separator(); ui.separator();
ui.text("Vertical sliders require a size parameter but otherwise work in a similar way:"); ui.text("Vertical sliders require a size parameter but otherwise work in a similar way:");
@ -91,11 +81,12 @@ fn example_2(ui: &Ui, state: &mut State) {
.position([20.0, 120.0], Condition::Appearing); .position([20.0, 120.0], Condition::Appearing);
w.build(|| { w.build(|| {
ui.text("You can easily build a slider group from an array of values:"); ui.text("You can easily build a slider group from an array of values:");
Slider::new("[u8; 4]", 0, u8::MAX).build_array(ui, &mut state.array); ui.slider_config("[u8; 4]", 0, u8::MAX)
.build_array(&mut state.array);
ui.text("You don't need to use arrays with known length; arbitrary slices can be used:"); 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]; let slice: &mut [u8] = &mut state.array[1..=2];
Slider::new("subslice", 0, u8::MAX).build_array(ui, slice); ui.slider_config("subslice", 0, u8::MAX).build_array(slice);
}); });
} }

View File

@ -433,9 +433,9 @@ fn show_test_window(ui: &Ui, state: &mut State, opened: &mut bool) {
); );
ui.spacing(); ui.spacing();
Slider::new("Wrap width", -20.0, 600.0) ui.slider_config("Wrap width", -20.0, 600.0)
.display_format("%.0f") .display_format("%.0f")
.build(ui, &mut state.wrap_width); .build(&mut state.wrap_width);
ui.text("Test paragraph 1:"); ui.text("Test paragraph 1:");
// TODO // TODO
@ -877,7 +877,7 @@ fn show_example_menu_file(ui: &Ui, state: &mut FileMenuState) {
ui.text(format!("Scrolling Text {}", i)); ui.text(format!("Scrolling Text {}", i));
} }
}); });
Slider::new("Value", 0.0, 1.0).build(ui, &mut state.f); ui.slider("Value", 0.0, 1.0, &mut state.f);
ui.input_float("Input", &mut state.f).step(0.1).build(); ui.input_float("Input", &mut state.f).step(0.1).build();
let items = ["Yes", "No", "Maybe"]; let items = ["Yes", "No", "Maybe"];
@ -904,7 +904,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 Note that you probably don't want to query the window size to
output your content because that would create a feedback loop.", output your content because that would create a feedback loop.",
); );
Slider::new("Number of lines", 1, 20).build(ui, &mut state.lines); ui.slider("Number of lines", 1, 20, &mut state.lines);
for i in 0..state.lines { for i in 0..state.lines {
ui.text(format!("{:2$}This is line {}", "", i, i as usize * 4)); ui.text(format!("{:2$}This is line {}", "", i, i as usize * 4));
} }

View File

@ -23,32 +23,65 @@ bitflags!(
} }
); );
impl Ui {
/// Creates a new slider widget. Returns true if the value has been edited.
pub fn slider<T: AsRef<str>, 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<T: AsRef<str>, 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. /// Builder for a slider widget.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
#[must_use] #[must_use]
pub struct Slider<Label, Data, Format = &'static str> { pub struct Slider<'ui, Label, Data, Format = &'static str> {
label: Label, label: Label,
min: Data, min: Data,
max: Data, max: Data,
display_format: Option<Format>, display_format: Option<Format>,
flags: SliderFlags, flags: SliderFlags,
ui: &'ui Ui,
} }
impl<T: AsRef<str>, K: DataTypeKind> Slider<T, K> { impl<'ui, T: AsRef<str>, K: DataTypeKind> Slider<'ui, T, K> {
/// Constructs a new slider builder with the given range. /// Constructs a new slider builder with the given range.
#[doc(alias = "SliderScalar", alias = "SliderScalarN")] #[doc(alias = "SliderScalar", alias = "SliderScalarN")]
pub fn new(label: T, min: K, max: K) -> Self { #[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 { Slider {
label, label,
min, min,
max, max,
display_format: None, display_format: None,
flags: SliderFlags::empty(), flags: SliderFlags::empty(),
ui,
} }
} }
} }
impl<Label, Data, Format> Slider<Label, Data, Format> impl<'ui, Label, Data, Format> Slider<'ui, Label, Data, Format>
where where
Label: AsRef<str>, Label: AsRef<str>,
Data: DataTypeKind, Data: DataTypeKind,
@ -57,11 +90,12 @@ where
/// Sets the range inclusively, such that both values given /// Sets the range inclusively, such that both values given
/// are valid values which the slider can be dragged to. /// are valid values which the slider can be dragged to.
/// ///
/// ```rust /// ```no_run
/// # use imgui::im_str; /// # let mut ctx = imgui::Context::create();
/// imgui::Slider::new(im_str!("Example"), i8::MIN, i8::MAX) /// # let ui = ctx.frame();
/// ui.slider_config("Example", i8::MIN, i8::MAX)
/// .range(4, 8) /// .range(4, 8)
/// // Remember to call .build(&ui) /// // Remember to call .build()
/// ; /// ;
/// ``` /// ```
/// ///
@ -83,13 +117,14 @@ where
pub fn display_format<Format2: AsRef<str>>( pub fn display_format<Format2: AsRef<str>>(
self, self,
display_format: Format2, display_format: Format2,
) -> Slider<Label, Data, Format2> { ) -> Slider<'ui, Label, Data, Format2> {
Slider { Slider {
label: self.label, label: self.label,
min: self.min, min: self.min,
max: self.max, max: self.max,
display_format: Some(display_format), display_format: Some(display_format),
flags: self.flags, flags: self.flags,
ui: self.ui,
} }
} }
/// Replaces all current settings with the given flags /// Replaces all current settings with the given flags
@ -101,9 +136,11 @@ where
/// Builds a slider that is bound to the given value. /// Builds a slider that is bound to the given value.
/// ///
/// Returns true if the slider value was changed. /// Returns true if the slider value was changed.
pub fn build(self, ui: &Ui, value: &mut Data) -> bool { pub fn build(self, value: &mut Data) -> bool {
unsafe { unsafe {
let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format); let (label, display_format) = self
.ui
.scratch_txt_with_opt(self.label, self.display_format);
sys::igSliderScalar( sys::igSliderScalar(
label, label,
@ -119,9 +156,11 @@ where
/// Builds a horizontal array of multiple sliders attached to the given slice. /// Builds a horizontal array of multiple sliders attached to the given slice.
/// ///
/// Returns true if any slider value was changed. /// Returns true if any slider value was changed.
pub fn build_array(self, ui: &Ui, values: &mut [Data]) -> bool { pub fn build_array(self, values: &mut [Data]) -> bool {
unsafe { unsafe {
let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format); let (label, display_format) = self
.ui
.scratch_txt_with_opt(self.label, self.display_format);
sys::igSliderScalarN( sys::igSliderScalarN(
label, label,