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 CLAMP_ON_INPUT = sys::ImGuiSliderFlags_ClampOnInput as i32;
388 const CLAMP_ZERO_RANGE = sys::ImGuiSliderFlags_ClampZeroRange as i32;
392 const NO_SPEED_TWEAKS = sys::ImGuiSliderFlags_NoSpeedTweaks as i32;
396 const ALWAYS_CLAMP = sys::ImGuiSliderFlags_AlwaysClamp as i32;
398 const LOGARITHMIC = sys::ImGuiSliderFlags_Logarithmic as i32;
400 const NO_ROUND_TO_FORMAT = sys::ImGuiSliderFlags_NoRoundToFormat as i32;
402 const NO_INPUT = sys::ImGuiSliderFlags_NoInput as i32;
404 }
405}
406
407impl Ui {
408 pub fn slider<T: AsRef<str>, K: DataTypeKind>(
410 &self,
411 label: T,
412 min: K,
413 max: K,
414 value: &mut K,
415 ) -> bool {
416 self.slider_config(label, min, max).build(value)
417 }
418
419 pub fn slider_config<T: AsRef<str>, K: DataTypeKind>(
421 &self,
422 label: T,
423 min: K,
424 max: K,
425 ) -> Slider<'_, T, K> {
426 Slider {
427 ui: self,
428 label,
429 min,
430 max,
431 display_format: Option::<&'static str>::None,
432 flags: SliderFlags::NONE,
433 }
434 }
435
436 #[doc(alias = "SliderFloat")]
438 pub fn slider_f32(&self, label: impl AsRef<str>, value: &mut f32, min: f32, max: f32) -> bool {
439 self.slider_config(label, min, max).build(value)
440 }
441
442 #[doc(alias = "SliderInt")]
444 pub fn slider_i32(&self, label: impl AsRef<str>, value: &mut i32, min: i32, max: i32) -> bool {
445 self.slider_config(label, min, max).build(value)
446 }
447
448 #[doc(alias = "SliderFloat2")]
450 pub fn slider_float2(
451 &self,
452 label: impl AsRef<str>,
453 value: &mut [f32; 2],
454 min: f32,
455 max: f32,
456 ) -> bool {
457 self.slider_config(label, min, max)
458 .build_array(value.as_mut_slice())
459 }
460
461 #[doc(alias = "SliderFloat3")]
463 pub fn slider_float3(
464 &self,
465 label: impl AsRef<str>,
466 value: &mut [f32; 3],
467 min: f32,
468 max: f32,
469 ) -> bool {
470 self.slider_config(label, min, max)
471 .build_array(value.as_mut_slice())
472 }
473
474 #[doc(alias = "SliderFloat4")]
476 pub fn slider_float4(
477 &self,
478 label: impl AsRef<str>,
479 value: &mut [f32; 4],
480 min: f32,
481 max: f32,
482 ) -> bool {
483 self.slider_config(label, min, max)
484 .build_array(value.as_mut_slice())
485 }
486
487 #[doc(alias = "SliderInt2")]
489 pub fn slider_int2(
490 &self,
491 label: impl AsRef<str>,
492 value: &mut [i32; 2],
493 min: i32,
494 max: i32,
495 ) -> bool {
496 self.slider_config(label, min, max)
497 .build_array(value.as_mut_slice())
498 }
499
500 #[doc(alias = "SliderInt3")]
502 pub fn slider_int3(
503 &self,
504 label: impl AsRef<str>,
505 value: &mut [i32; 3],
506 min: i32,
507 max: i32,
508 ) -> bool {
509 self.slider_config(label, min, max)
510 .build_array(value.as_mut_slice())
511 }
512
513 #[doc(alias = "SliderInt4")]
515 pub fn slider_int4(
516 &self,
517 label: impl AsRef<str>,
518 value: &mut [i32; 4],
519 min: i32,
520 max: i32,
521 ) -> bool {
522 self.slider_config(label, min, max)
523 .build_array(value.as_mut_slice())
524 }
525
526 #[doc(alias = "VSliderFloat")]
528 pub fn v_slider_f32(
529 &self,
530 label: impl AsRef<str>,
531 size: impl Into<[f32; 2]>,
532 value: &mut f32,
533 min: f32,
534 max: f32,
535 ) -> bool {
536 VerticalSlider::new(label, size, min, max).build(self, value)
537 }
538
539 #[doc(alias = "VSliderInt")]
541 pub fn v_slider_i32(
542 &self,
543 label: impl AsRef<str>,
544 size: impl Into<[f32; 2]>,
545 value: &mut i32,
546 min: i32,
547 max: i32,
548 ) -> bool {
549 VerticalSlider::new(label, size, min, max).build(self, value)
550 }
551
552 #[doc(alias = "SliderAngle")]
554 pub fn slider_angle(&self, label: impl AsRef<str>, value_rad: &mut f32) -> bool {
555 AngleSlider::new(label).build(self, value_rad)
556 }
557}