1#![allow(
2 clippy::cast_possible_truncation,
3 clippy::cast_sign_loss,
4 clippy::as_conversions
5)]
6use crate::Ui;
7use crate::internal::DataTypeKind;
8use crate::sys;
9use std::ffi::c_void;
10
11#[derive(Clone, Debug)]
13#[must_use]
14pub struct Slider<'ui, Label, Data, Format = &'static str> {
15 ui: &'ui Ui,
16 label: Label,
17 min: Data,
18 max: Data,
19 display_format: Option<Format>,
20 flags: SliderFlags,
21}
22
23impl<'ui, Label, Data> Slider<'ui, Label, Data>
24where
25 Label: AsRef<str>,
26 Data: DataTypeKind,
27{
28 #[doc(alias = "SliderScalar", alias = "SliderScalarN")]
30 #[deprecated(note = "Use `Ui::slider` or `Ui::slider_config`.", since = "0.1.0")]
31 pub fn new(ui: &'ui Ui, label: Label, min: Data, max: Data) -> Self {
32 Self {
33 ui,
34 label,
35 min,
36 max,
37 display_format: None,
38 flags: SliderFlags::NONE,
39 }
40 }
41}
42
43impl<'ui, Label, Data, Format> Slider<'ui, Label, Data, Format>
44where
45 Label: AsRef<str>,
46 Data: DataTypeKind,
47 Format: AsRef<str>,
48{
49 #[inline]
70 pub fn range(mut self, min: Data, max: Data) -> Self {
71 self.min = min;
72 self.max = max;
73 self
74 }
75
76 #[inline]
78 pub fn display_format<Format2: AsRef<str>>(
79 self,
80 display_format: Format2,
81 ) -> Slider<'ui, Label, Data, Format2> {
82 Slider {
83 ui: self.ui,
84 label: self.label,
85 min: self.min,
86 max: self.max,
87 display_format: Some(display_format),
88 flags: self.flags,
89 }
90 }
91
92 #[inline]
94 pub fn flags(mut self, flags: SliderFlags) -> Self {
95 self.flags = flags;
96 self
97 }
98
99 pub fn build(self, value: &mut Data) -> bool {
103 unsafe {
104 let (label, display_format) = self
105 .ui
106 .scratch_txt_with_opt(self.label, self.display_format);
107
108 sys::igSliderScalar(
109 label,
110 Data::KIND as i32,
111 value as *mut Data as *mut c_void,
112 &self.min as *const Data as *const c_void,
113 &self.max as *const Data as *const c_void,
114 display_format,
115 self.flags.bits(),
116 )
117 }
118 }
119
120 pub fn build_array(self, values: &mut [Data]) -> bool {
124 unsafe {
125 let (label, display_format) = self
126 .ui
127 .scratch_txt_with_opt(self.label, self.display_format);
128
129 sys::igSliderScalarN(
130 label,
131 Data::KIND as i32,
132 values.as_mut_ptr() as *mut c_void,
133 values.len() as i32,
134 &self.min as *const Data as *const c_void,
135 &self.max as *const Data as *const c_void,
136 display_format,
137 self.flags.bits(),
138 )
139 }
140 }
141}
142
143#[derive(Clone, Debug)]
145#[must_use]
146pub struct VerticalSlider<Label, Data, Format = &'static str> {
147 label: Label,
148 size: [f32; 2],
149 min: Data,
150 max: Data,
151 display_format: Option<Format>,
152 flags: SliderFlags,
153}
154
155impl<Label, Data> VerticalSlider<Label, Data>
156where
157 Label: AsRef<str>,
158 Data: DataTypeKind,
159{
160 #[doc(alias = "VSliderScalar")]
175 pub fn new(label: Label, size: impl Into<[f32; 2]>, min: Data, max: Data) -> Self {
176 VerticalSlider {
177 label,
178 size: size.into(),
179 min,
180 max,
181 display_format: None,
182 flags: SliderFlags::NONE,
183 }
184 }
185}
186
187impl<Label, Data, Format> VerticalSlider<Label, Data, Format>
188where
189 Label: AsRef<str>,
190 Data: DataTypeKind,
191 Format: AsRef<str>,
192{
193 #[inline]
208 pub fn range(mut self, min: Data, max: Data) -> Self {
209 self.min = min;
210 self.max = max;
211 self
212 }
213
214 #[inline]
216 pub fn display_format<Format2: AsRef<str>>(
217 self,
218 display_format: Format2,
219 ) -> VerticalSlider<Label, Data, Format2> {
220 VerticalSlider {
221 label: self.label,
222 size: self.size,
223 min: self.min,
224 max: self.max,
225 display_format: Some(display_format),
226 flags: self.flags,
227 }
228 }
229
230 #[inline]
232 pub fn flags(mut self, flags: SliderFlags) -> Self {
233 self.flags = flags;
234 self
235 }
236
237 pub fn build(self, ui: &Ui, value: &mut Data) -> bool {
241 unsafe {
242 let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format);
243 let size = sys::ImVec2::new(self.size[0], self.size[1]);
244
245 sys::igVSliderScalar(
246 label,
247 size,
248 Data::KIND as i32,
249 value as *mut Data as *mut c_void,
250 &self.min as *const Data as *const c_void,
251 &self.max as *const Data as *const c_void,
252 display_format,
253 self.flags.bits(),
254 )
255 }
256 }
257}
258
259#[derive(Copy, Clone, Debug)]
261#[must_use]
262pub struct AngleSlider<Label, Format = &'static str> {
263 label: Label,
264 min_degrees: f32,
265 max_degrees: f32,
266 display_format: Format,
267 flags: SliderFlags,
268}
269
270impl<Label> AngleSlider<Label>
271where
272 Label: AsRef<str>,
273{
274 #[doc(alias = "SliderAngle")]
277 pub fn new(label: Label) -> Self {
278 AngleSlider {
279 label,
280 min_degrees: -360.0,
281 max_degrees: 360.0,
282 display_format: "%.0f deg",
283 flags: SliderFlags::NONE,
284 }
285 }
286}
287
288impl<Label, Format> AngleSlider<Label, Format>
289where
290 Label: AsRef<str>,
291 Format: AsRef<str>,
292{
293 #[inline]
307 pub fn range_degrees(mut self, min_degrees: f32, max_degrees: f32) -> Self {
308 self.min_degrees = min_degrees;
309 self.max_degrees = max_degrees;
310 self
311 }
312
313 #[inline]
315 pub fn min_degrees(mut self, min_degrees: f32) -> Self {
316 self.min_degrees = min_degrees;
317 self
318 }
319
320 #[inline]
322 pub fn max_degrees(mut self, max_degrees: f32) -> Self {
323 self.max_degrees = max_degrees;
324 self
325 }
326
327 #[inline]
329 pub fn display_format<Format2: AsRef<str>>(
330 self,
331 display_format: Format2,
332 ) -> AngleSlider<Label, Format2> {
333 AngleSlider {
334 label: self.label,
335 min_degrees: self.min_degrees,
336 max_degrees: self.max_degrees,
337 display_format,
338 flags: self.flags,
339 }
340 }
341
342 #[inline]
344 pub fn flags(mut self, flags: SliderFlags) -> Self {
345 self.flags = flags;
346 self
347 }
348
349 pub fn build(self, ui: &Ui, value_rad: &mut f32) -> bool {
353 unsafe {
354 let (label, display_format) = ui.scratch_txt_two(self.label, self.display_format);
355
356 sys::igSliderAngle(
357 label,
358 value_rad as *mut _,
359 self.min_degrees,
360 self.max_degrees,
361 display_format,
362 self.flags.bits(),
363 )
364 }
365 }
366}
367
368bitflags::bitflags! {
369 #[repr(transparent)]
371 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
372 pub struct SliderFlags: i32 {
373 const NONE = 0;
375 const ALWAYS_CLAMP = sys::ImGuiSliderFlags_AlwaysClamp as i32;
377 const LOGARITHMIC = sys::ImGuiSliderFlags_Logarithmic as i32;
379 const NO_ROUND_TO_FORMAT = sys::ImGuiSliderFlags_NoRoundToFormat as i32;
381 const NO_INPUT = sys::ImGuiSliderFlags_NoInput as i32;
383 }
384}
385
386impl Ui {
387 pub fn slider<T: AsRef<str>, K: DataTypeKind>(
389 &self,
390 label: T,
391 min: K,
392 max: K,
393 value: &mut K,
394 ) -> bool {
395 self.slider_config(label, min, max).build(value)
396 }
397
398 pub fn slider_config<T: AsRef<str>, K: DataTypeKind>(
400 &self,
401 label: T,
402 min: K,
403 max: K,
404 ) -> Slider<'_, T, K> {
405 Slider {
406 ui: self,
407 label,
408 min,
409 max,
410 display_format: Option::<&'static str>::None,
411 flags: SliderFlags::NONE,
412 }
413 }
414
415 #[doc(alias = "SliderFloat")]
417 pub fn slider_f32(&self, label: impl AsRef<str>, value: &mut f32, min: f32, max: f32) -> bool {
418 self.slider_config(label, min, max).build(value)
419 }
420
421 #[doc(alias = "SliderInt")]
423 pub fn slider_i32(&self, label: impl AsRef<str>, value: &mut i32, min: i32, max: i32) -> bool {
424 self.slider_config(label, min, max).build(value)
425 }
426
427 #[doc(alias = "VSliderFloat")]
429 pub fn v_slider_f32(
430 &self,
431 label: impl AsRef<str>,
432 size: impl Into<[f32; 2]>,
433 value: &mut f32,
434 min: f32,
435 max: f32,
436 ) -> bool {
437 VerticalSlider::new(label, size, min, max).build(self, value)
438 }
439
440 #[doc(alias = "VSliderInt")]
442 pub fn v_slider_i32(
443 &self,
444 label: impl AsRef<str>,
445 size: impl Into<[f32; 2]>,
446 value: &mut i32,
447 min: i32,
448 max: i32,
449 ) -> bool {
450 VerticalSlider::new(label, size, min, max).build(self, value)
451 }
452
453 #[doc(alias = "SliderAngle")]
455 pub fn slider_angle(&self, label: impl AsRef<str>, value_rad: &mut f32) -> bool {
456 AngleSlider::new(label).build(self, value_rad)
457 }
458}