1use bitflags::bitflags;
2use std::os::raw::c_void;
3
4use crate::internal::DataTypeKind;
5use crate::sys;
6use crate::Ui;
7
8bitflags!(
9 #[repr(transparent)]
11 pub struct SliderFlags: u32 {
12 const ALWAYS_CLAMP = sys::ImGuiSliderFlags_AlwaysClamp;
16 const LOGARITHMIC = sys::ImGuiSliderFlags_Logarithmic;
18 const NO_ROUND_TO_FORMAT = sys::ImGuiSliderFlags_NoRoundToFormat;
20 const NO_INPUT = sys::ImGuiSliderFlags_NoInput;
22 }
23);
24
25#[derive(Copy, Clone, Debug)]
27#[must_use]
28pub struct Slider<Label, Data, Format = &'static str> {
29 label: Label,
30 min: Data,
31 max: Data,
32 display_format: Option<Format>,
33 flags: SliderFlags,
34}
35
36impl<T: AsRef<str>, K: DataTypeKind> Slider<T, K> {
37 #[doc(alias = "SliderScalar", alias = "SliderScalarN")]
39 pub fn new(label: T, min: K, max: K) -> Self {
40 Slider {
41 label,
42 min,
43 max,
44 display_format: None,
45 flags: SliderFlags::empty(),
46 }
47 }
48}
49
50impl<Label, Data, Format> Slider<Label, Data, Format>
51where
52 Label: AsRef<str>,
53 Data: DataTypeKind,
54 Format: AsRef<str>,
55{
56 #[inline]
70 pub fn range(mut self, min: Data, max: Data) -> Self {
71 self.min = min;
72 self.max = max;
73 self
74 }
75 #[inline]
77 pub fn display_format<Format2: AsRef<str>>(
78 self,
79 display_format: Format2,
80 ) -> Slider<Label, Data, Format2> {
81 Slider {
82 label: self.label,
83 min: self.min,
84 max: self.max,
85 display_format: Some(display_format),
86 flags: self.flags,
87 }
88 }
89 #[inline]
91 pub fn flags(mut self, flags: SliderFlags) -> Self {
92 self.flags = flags;
93 self
94 }
95 pub fn build(self, ui: &Ui<'_>, value: &mut Data) -> bool {
99 unsafe {
100 let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format);
101
102 sys::igSliderScalar(
103 label,
104 Data::KIND as i32,
105 value as *mut Data as *mut c_void,
106 &self.min as *const Data as *const c_void,
107 &self.max as *const Data as *const c_void,
108 display_format,
109 self.flags.bits() as i32,
110 )
111 }
112 }
113 pub fn build_array(self, ui: &Ui<'_>, values: &mut [Data]) -> bool {
117 unsafe {
118 let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format);
119
120 sys::igSliderScalarN(
121 label,
122 Data::KIND as i32,
123 values.as_mut_ptr() as *mut c_void,
124 values.len() as i32,
125 &self.min as *const Data as *const c_void,
126 &self.max as *const Data as *const c_void,
127 display_format,
128 self.flags.bits() as i32,
129 )
130 }
131 }
132}
133
134#[derive(Clone, Debug)]
136#[must_use]
137pub struct VerticalSlider<Label, Data, Format = &'static str> {
138 label: Label,
139 size: [f32; 2],
140 min: Data,
141 max: Data,
142 display_format: Option<Format>,
143 flags: SliderFlags,
144}
145
146impl<Label, Data> VerticalSlider<Label, Data>
147where
148 Label: AsRef<str>,
149 Data: DataTypeKind,
150{
151 #[doc(alias = "VSliderScalar")]
164 pub fn new(label: Label, size: [f32; 2], min: Data, max: Data) -> Self {
165 VerticalSlider {
166 label,
167 size,
168 min,
169 max,
170 display_format: None,
171 flags: SliderFlags::empty(),
172 }
173 }
174}
175
176impl<Label, Data, Format> VerticalSlider<Label, Data, Format>
177where
178 Label: AsRef<str>,
179 Data: DataTypeKind,
180 Format: AsRef<str>,
181{
182 #[inline]
195 pub fn range(mut self, min: Data, max: Data) -> Self {
196 self.min = min;
197 self.max = max;
198 self
199 }
200 #[inline]
202 pub fn display_format<Format2: AsRef<str>>(
203 self,
204 display_format: Format2,
205 ) -> VerticalSlider<Label, Data, Format2> {
206 VerticalSlider {
207 label: self.label,
208 size: self.size,
209 min: self.min,
210 max: self.max,
211 display_format: Some(display_format),
212 flags: self.flags,
213 }
214 }
215 #[inline]
217 pub fn flags(mut self, flags: SliderFlags) -> Self {
218 self.flags = flags;
219 self
220 }
221 pub fn build(self, ui: &Ui<'_>, value: &mut Data) -> bool {
225 unsafe {
226 let (label, display_format) = ui.scratch_txt_with_opt(self.label, self.display_format);
227
228 sys::igVSliderScalar(
229 label,
230 self.size.into(),
231 Data::KIND as i32,
232 value as *mut Data as *mut c_void,
233 &self.min as *const Data as *const c_void,
234 &self.max as *const Data as *const c_void,
235 display_format,
236 self.flags.bits() as i32,
237 )
238 }
239 }
240}
241
242#[derive(Copy, Clone, Debug)]
244#[must_use]
245pub struct AngleSlider<Label, Format = &'static str> {
246 label: Label,
247 min_degrees: f32,
248 max_degrees: f32,
249 display_format: Format,
250 flags: SliderFlags,
251}
252
253impl<Label> AngleSlider<Label>
254where
255 Label: AsRef<str>,
256{
257 #[doc(alias = "SliderAngle")]
260 pub fn new(label: Label) -> Self {
261 AngleSlider {
262 label,
263 min_degrees: -360.0,
264 max_degrees: 360.0,
265 display_format: "%.0f deg",
266 flags: SliderFlags::empty(),
267 }
268 }
269}
270
271impl<Label, Format> AngleSlider<Label, Format>
272where
273 Label: AsRef<str>,
274 Format: AsRef<str>,
275{
276 #[inline]
288 pub fn range_degrees(mut self, min_degrees: f32, max_degrees: f32) -> Self {
289 self.min_degrees = min_degrees;
290 self.max_degrees = max_degrees;
291 self
292 }
293 #[inline]
295 pub fn min_degrees(mut self, min_degrees: f32) -> Self {
296 self.min_degrees = min_degrees;
297 self
298 }
299 #[inline]
301 pub fn max_degrees(mut self, max_degrees: f32) -> Self {
302 self.max_degrees = max_degrees;
303 self
304 }
305 #[inline]
307 pub fn display_format<Format2: AsRef<str>>(
308 self,
309 display_format: Format2,
310 ) -> AngleSlider<Label, Format2> {
311 AngleSlider {
312 label: self.label,
313 min_degrees: self.min_degrees,
314 max_degrees: self.max_degrees,
315 display_format,
316 flags: self.flags,
317 }
318 }
319 #[inline]
321 pub fn flags(mut self, flags: SliderFlags) -> Self {
322 self.flags = flags;
323 self
324 }
325 pub fn build(self, ui: &Ui<'_>, value_rad: &mut f32) -> bool {
329 unsafe {
330 let (label, display_format) = ui.scratch_txt_two(self.label, self.display_format);
331
332 sys::igSliderAngle(
333 label,
334 value_rad as *mut _,
335 self.min_degrees,
336 self.max_degrees,
337 display_format,
338 self.flags.bits() as i32,
339 )
340 }
341 }
342}