1#![allow(
7 clippy::cast_possible_truncation,
8 clippy::cast_sign_loss,
9 clippy::as_conversions
10)]
11use crate::Ui;
12use crate::internal::DataTypeKind;
13use crate::sys;
14use std::ffi::c_void;
15
16#[derive(Clone, Debug)]
18#[must_use]
19pub struct Slider<'ui, Label, Data, Format = &'static str> {
20 ui: &'ui Ui,
21 label: Label,
22 min: Data,
23 max: Data,
24 display_format: Option<Format>,
25 flags: SliderFlags,
26}
27
28impl<'ui, Label, Data> Slider<'ui, Label, Data>
29where
30 Label: AsRef<str>,
31 Data: DataTypeKind,
32{
33 #[doc(alias = "SliderScalar", alias = "SliderScalarN")]
35 #[deprecated(note = "Use `Ui::slider` or `Ui::slider_config`.", since = "0.1.0")]
36 pub fn new(ui: &'ui Ui, label: Label, min: Data, max: Data) -> Self {
37 Self {
38 ui,
39 label,
40 min,
41 max,
42 display_format: None,
43 flags: SliderFlags::NONE,
44 }
45 }
46}
47
48impl<'ui, Label, Data, Format> Slider<'ui, Label, Data, Format>
49where
50 Label: AsRef<str>,
51 Data: DataTypeKind,
52 Format: AsRef<str>,
53{
54 #[inline]
75 pub fn range(mut self, min: Data, max: Data) -> Self {
76 self.min = min;
77 self.max = max;
78 self
79 }
80
81 #[inline]
83 pub fn display_format<Format2: AsRef<str>>(
84 self,
85 display_format: Format2,
86 ) -> Slider<'ui, Label, Data, Format2> {
87 Slider {
88 ui: self.ui,
89 label: self.label,
90 min: self.min,
91 max: self.max,
92 display_format: Some(display_format),
93 flags: self.flags,
94 }
95 }
96
97 #[inline]
99 pub fn flags(mut self, flags: SliderFlags) -> Self {
100 self.flags = flags;
101 self
102 }
103
104 pub fn build(self, value: &mut Data) -> bool {
108 unsafe {
109 let (label, display_format) = self
110 .ui
111 .scratch_txt_with_opt(self.label, self.display_format);
112
113 sys::igSliderScalar(
114 label,
115 Data::KIND as i32,
116 value as *mut Data as *mut c_void,
117 &self.min as *const Data as *const c_void,
118 &self.max as *const Data as *const c_void,
119 display_format,
120 self.flags.bits(),
121 )
122 }
123 }
124
125 pub fn build_array(self, values: &mut [Data]) -> bool {
129 unsafe {
130 let (label, display_format) = self
131 .ui
132 .scratch_txt_with_opt(self.label, self.display_format);
133
134 sys::igSliderScalarN(
135 label,
136 Data::KIND as i32,
137 values.as_mut_ptr() as *mut c_void,
138 values.len() as i32,
139 &self.min as *const Data as *const c_void,
140 &self.max as *const Data as *const c_void,
141 display_format,
142 self.flags.bits(),
143 )
144 }
145 }
146}
147
148#[derive(Clone, Debug)]
150#[must_use]
151pub struct VerticalSlider<Label, Data, Format = &'static str> {
152 label: Label,
153 size: [f32; 2],
154 min: Data,
155 max: Data,
156 display_format: Option<Format>,
157 flags: SliderFlags,
158}
159
160impl<Label, Data> VerticalSlider<Label, Data>
161where
162 Label: AsRef<str>,
163 Data: DataTypeKind,
164{
165 #[doc(alias = "VSliderScalar")]
180 pub fn new(label: Label, size: impl Into<[f32; 2]>, min: Data, max: Data) -> Self {
181 VerticalSlider {
182 label,
183 size: size.into(),
184 min,
185 max,
186 display_format: None,
187 flags: SliderFlags::NONE,
188 }
189 }
190}
191
192impl<Label, Data, Format> VerticalSlider<Label, Data, Format>
193where
194 Label: AsRef<str>,
195 Data: DataTypeKind,
196 Format: AsRef<str>,
197{
198 #[inline]
213 pub fn range(mut self, min: Data, max: Data) -> Self {
214 self.min = min;
215 self.max = max;
216 self
217 }
218
219 #[inline]
221 pub fn display_format<Format2: AsRef<str>>(
222 self,
223 display_format: Format2,
224 ) -> VerticalSlider<Label, Data, Format2> {
225 VerticalSlider {
226 label: self.label,
227 size: self.size,
228 min: self.min,
229 max: self.max,
230 display_format: Some(display_format),
231 flags: self.flags,
232 }
233 }
234
235 #[inline]
237 pub fn flags(mut self, flags: SliderFlags) -> Self {
238 self.flags = flags;
239 self
240 }
241
242 pub fn build(self, ui: &Ui, value: &mut Data) -> bool {
246 unsafe {
247 let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format);
248 let size = sys::ImVec2::new(self.size[0], self.size[1]);
249
250 sys::igVSliderScalar(
251 label,
252 size,
253 Data::KIND as i32,
254 value as *mut Data as *mut c_void,
255 &self.min as *const Data as *const c_void,
256 &self.max as *const Data as *const c_void,
257 display_format,
258 self.flags.bits(),
259 )
260 }
261 }
262}
263
264#[derive(Copy, Clone, Debug)]
266#[must_use]
267pub struct AngleSlider<Label, Format = &'static str> {
268 label: Label,
269 min_degrees: f32,
270 max_degrees: f32,
271 display_format: Format,
272 flags: SliderFlags,
273}
274
275impl<Label> AngleSlider<Label>
276where
277 Label: AsRef<str>,
278{
279 #[doc(alias = "SliderAngle")]
282 pub fn new(label: Label) -> Self {
283 AngleSlider {
284 label,
285 min_degrees: -360.0,
286 max_degrees: 360.0,
287 display_format: "%.0f deg",
288 flags: SliderFlags::NONE,
289 }
290 }
291}
292
293impl<Label, Format> AngleSlider<Label, Format>
294where
295 Label: AsRef<str>,
296 Format: AsRef<str>,
297{
298 #[inline]
312 pub fn range_degrees(mut self, min_degrees: f32, max_degrees: f32) -> Self {
313 self.min_degrees = min_degrees;
314 self.max_degrees = max_degrees;
315 self
316 }
317
318 #[inline]
320 pub fn min_degrees(mut self, min_degrees: f32) -> Self {
321 self.min_degrees = min_degrees;
322 self
323 }
324
325 #[inline]
327 pub fn max_degrees(mut self, max_degrees: f32) -> Self {
328 self.max_degrees = max_degrees;
329 self
330 }
331
332 #[inline]
334 pub fn display_format<Format2: AsRef<str>>(
335 self,
336 display_format: Format2,
337 ) -> AngleSlider<Label, Format2> {
338 AngleSlider {
339 label: self.label,
340 min_degrees: self.min_degrees,
341 max_degrees: self.max_degrees,
342 display_format,
343 flags: self.flags,
344 }
345 }
346
347 #[inline]
349 pub fn flags(mut self, flags: SliderFlags) -> Self {
350 self.flags = flags;
351 self
352 }
353
354 pub fn build(self, ui: &Ui, value_rad: &mut f32) -> bool {
358 unsafe {
359 let (label, display_format) = ui.scratch_txt_two(self.label, self.display_format);
360
361 sys::igSliderAngle(
362 label,
363 value_rad as *mut _,
364 self.min_degrees,
365 self.max_degrees,
366 display_format,
367 self.flags.bits(),
368 )
369 }
370 }
371}
372
373bitflags::bitflags! {
374 #[repr(transparent)]
376 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
377 pub struct SliderFlags: i32 {
378 const NONE = 0;
380 const ALWAYS_CLAMP = sys::ImGuiSliderFlags_AlwaysClamp as i32;
382 const LOGARITHMIC = sys::ImGuiSliderFlags_Logarithmic as i32;
384 const NO_ROUND_TO_FORMAT = sys::ImGuiSliderFlags_NoRoundToFormat as i32;
386 const NO_INPUT = sys::ImGuiSliderFlags_NoInput as i32;
388 }
389}
390
391impl Ui {
392 pub fn slider<T: AsRef<str>, K: DataTypeKind>(
394 &self,
395 label: T,
396 min: K,
397 max: K,
398 value: &mut K,
399 ) -> bool {
400 self.slider_config(label, min, max).build(value)
401 }
402
403 pub fn slider_config<T: AsRef<str>, K: DataTypeKind>(
405 &self,
406 label: T,
407 min: K,
408 max: K,
409 ) -> Slider<'_, T, K> {
410 Slider {
411 ui: self,
412 label,
413 min,
414 max,
415 display_format: Option::<&'static str>::None,
416 flags: SliderFlags::NONE,
417 }
418 }
419
420 #[doc(alias = "SliderFloat")]
422 pub fn slider_f32(&self, label: impl AsRef<str>, value: &mut f32, min: f32, max: f32) -> bool {
423 self.slider_config(label, min, max).build(value)
424 }
425
426 #[doc(alias = "SliderInt")]
428 pub fn slider_i32(&self, label: impl AsRef<str>, value: &mut i32, min: i32, max: i32) -> bool {
429 self.slider_config(label, min, max).build(value)
430 }
431
432 #[doc(alias = "VSliderFloat")]
434 pub fn v_slider_f32(
435 &self,
436 label: impl AsRef<str>,
437 size: impl Into<[f32; 2]>,
438 value: &mut f32,
439 min: f32,
440 max: f32,
441 ) -> bool {
442 VerticalSlider::new(label, size, min, max).build(self, value)
443 }
444
445 #[doc(alias = "VSliderInt")]
447 pub fn v_slider_i32(
448 &self,
449 label: impl AsRef<str>,
450 size: impl Into<[f32; 2]>,
451 value: &mut i32,
452 min: i32,
453 max: i32,
454 ) -> bool {
455 VerticalSlider::new(label, size, min, max).build(self, value)
456 }
457
458 #[doc(alias = "SliderAngle")]
460 pub fn slider_angle(&self, label: impl AsRef<str>, value_rad: &mut f32) -> bool {
461 AngleSlider::new(label).build(self, value_rad)
462 }
463}