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 let count = match i32::try_from(values.len()) {
130 Ok(n) => n,
131 Err(_) => return false,
132 };
133 unsafe {
134 let (label, display_format) = self
135 .ui
136 .scratch_txt_with_opt(self.label, self.display_format);
137
138 sys::igSliderScalarN(
139 label,
140 Data::KIND as i32,
141 values.as_mut_ptr() as *mut c_void,
142 count,
143 &self.min as *const Data as *const c_void,
144 &self.max as *const Data as *const c_void,
145 display_format,
146 self.flags.bits(),
147 )
148 }
149 }
150}
151
152#[derive(Clone, Debug)]
154#[must_use]
155pub struct VerticalSlider<Label, Data, Format = &'static str> {
156 label: Label,
157 size: [f32; 2],
158 min: Data,
159 max: Data,
160 display_format: Option<Format>,
161 flags: SliderFlags,
162}
163
164impl<Label, Data> VerticalSlider<Label, Data>
165where
166 Label: AsRef<str>,
167 Data: DataTypeKind,
168{
169 #[doc(alias = "VSliderScalar")]
184 pub fn new(label: Label, size: impl Into<[f32; 2]>, min: Data, max: Data) -> Self {
185 VerticalSlider {
186 label,
187 size: size.into(),
188 min,
189 max,
190 display_format: None,
191 flags: SliderFlags::NONE,
192 }
193 }
194}
195
196impl<Label, Data, Format> VerticalSlider<Label, Data, Format>
197where
198 Label: AsRef<str>,
199 Data: DataTypeKind,
200 Format: AsRef<str>,
201{
202 #[inline]
217 pub fn range(mut self, min: Data, max: Data) -> Self {
218 self.min = min;
219 self.max = max;
220 self
221 }
222
223 #[inline]
225 pub fn display_format<Format2: AsRef<str>>(
226 self,
227 display_format: Format2,
228 ) -> VerticalSlider<Label, Data, Format2> {
229 VerticalSlider {
230 label: self.label,
231 size: self.size,
232 min: self.min,
233 max: self.max,
234 display_format: Some(display_format),
235 flags: self.flags,
236 }
237 }
238
239 #[inline]
241 pub fn flags(mut self, flags: SliderFlags) -> Self {
242 self.flags = flags;
243 self
244 }
245
246 pub fn build(self, ui: &Ui, value: &mut Data) -> bool {
250 unsafe {
251 let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format);
252 let size = sys::ImVec2::new(self.size[0], self.size[1]);
253
254 sys::igVSliderScalar(
255 label,
256 size,
257 Data::KIND as i32,
258 value as *mut Data as *mut c_void,
259 &self.min as *const Data as *const c_void,
260 &self.max as *const Data as *const c_void,
261 display_format,
262 self.flags.bits(),
263 )
264 }
265 }
266}
267
268#[derive(Copy, Clone, Debug)]
270#[must_use]
271pub struct AngleSlider<Label, Format = &'static str> {
272 label: Label,
273 min_degrees: f32,
274 max_degrees: f32,
275 display_format: Format,
276 flags: SliderFlags,
277}
278
279impl<Label> AngleSlider<Label>
280where
281 Label: AsRef<str>,
282{
283 #[doc(alias = "SliderAngle")]
286 pub fn new(label: Label) -> Self {
287 AngleSlider {
288 label,
289 min_degrees: -360.0,
290 max_degrees: 360.0,
291 display_format: "%.0f deg",
292 flags: SliderFlags::NONE,
293 }
294 }
295}
296
297impl<Label, Format> AngleSlider<Label, Format>
298where
299 Label: AsRef<str>,
300 Format: AsRef<str>,
301{
302 #[inline]
316 pub fn range_degrees(mut self, min_degrees: f32, max_degrees: f32) -> Self {
317 self.min_degrees = min_degrees;
318 self.max_degrees = max_degrees;
319 self
320 }
321
322 #[inline]
324 pub fn min_degrees(mut self, min_degrees: f32) -> Self {
325 self.min_degrees = min_degrees;
326 self
327 }
328
329 #[inline]
331 pub fn max_degrees(mut self, max_degrees: f32) -> Self {
332 self.max_degrees = max_degrees;
333 self
334 }
335
336 #[inline]
338 pub fn display_format<Format2: AsRef<str>>(
339 self,
340 display_format: Format2,
341 ) -> AngleSlider<Label, Format2> {
342 AngleSlider {
343 label: self.label,
344 min_degrees: self.min_degrees,
345 max_degrees: self.max_degrees,
346 display_format,
347 flags: self.flags,
348 }
349 }
350
351 #[inline]
353 pub fn flags(mut self, flags: SliderFlags) -> Self {
354 self.flags = flags;
355 self
356 }
357
358 pub fn build(self, ui: &Ui, value_rad: &mut f32) -> bool {
362 unsafe {
363 let (label, display_format) = ui.scratch_txt_two(self.label, self.display_format);
364
365 sys::igSliderAngle(
366 label,
367 value_rad as *mut _,
368 self.min_degrees,
369 self.max_degrees,
370 display_format,
371 self.flags.bits(),
372 )
373 }
374 }
375}
376
377bitflags::bitflags! {
378 #[repr(transparent)]
380 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
381 pub struct SliderFlags: i32 {
382 const NONE = 0;
384 const WRAP_AROUND = sys::ImGuiSliderFlags_WrapAround as i32;
388 const CLAMP_ON_INPUT = sys::ImGuiSliderFlags_ClampOnInput as i32;
392 const CLAMP_ZERO_RANGE = sys::ImGuiSliderFlags_ClampZeroRange as i32;
396 const NO_SPEED_TWEAKS = sys::ImGuiSliderFlags_NoSpeedTweaks as i32;
400 const ALWAYS_CLAMP = sys::ImGuiSliderFlags_AlwaysClamp as i32;
402 const LOGARITHMIC = sys::ImGuiSliderFlags_Logarithmic as i32;
404 const NO_ROUND_TO_FORMAT = sys::ImGuiSliderFlags_NoRoundToFormat as i32;
406 const NO_INPUT = sys::ImGuiSliderFlags_NoInput as i32;
408 }
409}
410
411impl Ui {
412 pub fn slider<T: AsRef<str>, K: DataTypeKind>(
414 &self,
415 label: T,
416 min: K,
417 max: K,
418 value: &mut K,
419 ) -> bool {
420 self.slider_config(label, min, max).build(value)
421 }
422
423 pub fn slider_config<T: AsRef<str>, K: DataTypeKind>(
425 &self,
426 label: T,
427 min: K,
428 max: K,
429 ) -> Slider<'_, T, K> {
430 Slider {
431 ui: self,
432 label,
433 min,
434 max,
435 display_format: Option::<&'static str>::None,
436 flags: SliderFlags::NONE,
437 }
438 }
439
440 #[doc(alias = "SliderFloat")]
442 pub fn slider_f32(&self, label: impl AsRef<str>, value: &mut f32, min: f32, max: f32) -> bool {
443 self.slider_config(label, min, max).build(value)
444 }
445
446 #[doc(alias = "SliderInt")]
448 pub fn slider_i32(&self, label: impl AsRef<str>, value: &mut i32, min: i32, max: i32) -> bool {
449 self.slider_config(label, min, max).build(value)
450 }
451
452 #[doc(alias = "VSliderFloat")]
454 pub fn v_slider_f32(
455 &self,
456 label: impl AsRef<str>,
457 size: impl Into<[f32; 2]>,
458 value: &mut f32,
459 min: f32,
460 max: f32,
461 ) -> bool {
462 VerticalSlider::new(label, size, min, max).build(self, value)
463 }
464
465 #[doc(alias = "VSliderInt")]
467 pub fn v_slider_i32(
468 &self,
469 label: impl AsRef<str>,
470 size: impl Into<[f32; 2]>,
471 value: &mut i32,
472 min: i32,
473 max: i32,
474 ) -> bool {
475 VerticalSlider::new(label, size, min, max).build(self, value)
476 }
477
478 #[doc(alias = "SliderAngle")]
480 pub fn slider_angle(&self, label: impl AsRef<str>, value_rad: &mut f32) -> bool {
481 AngleSlider::new(label).build(self, value_rad)
482 }
483}