1use std::os::raw::c_void;
7use std::ptr;
8
9use crate::Ui;
10use crate::internal::DataTypeKind;
11use crate::sys;
12use crate::widget::slider::SliderFlags;
13
14impl Ui {
15 pub fn drag<T: AsRef<str>, K: DataTypeKind>(&self, label: T, value: &mut K) -> bool {
17 Drag::new(label).build(self, value)
18 }
19
20 pub fn drag_config<T: AsRef<str>, K: DataTypeKind>(&self, label: T) -> Drag<K, T> {
22 Drag::new(label)
23 }
24
25 #[doc(alias = "DragFloat2")]
27 pub fn drag_float2(&self, label: impl AsRef<str>, values: &mut [f32; 2]) -> bool {
28 unsafe {
29 let label_cstr = self.scratch_txt(label);
30 sys::igDragFloat2(
31 label_cstr,
32 values.as_mut_ptr(),
33 1.0,
34 0.0,
35 0.0,
36 ptr::null(),
37 0,
38 )
39 }
40 }
41
42 #[doc(alias = "DragFloat3")]
44 pub fn drag_float3(&self, label: impl AsRef<str>, values: &mut [f32; 3]) -> bool {
45 unsafe {
46 let label_cstr = self.scratch_txt(label);
47 sys::igDragFloat3(
48 label_cstr,
49 values.as_mut_ptr(),
50 1.0,
51 0.0,
52 0.0,
53 ptr::null(),
54 0,
55 )
56 }
57 }
58
59 #[doc(alias = "DragFloat4")]
61 pub fn drag_float4(&self, label: impl AsRef<str>, values: &mut [f32; 4]) -> bool {
62 unsafe {
63 let label_cstr = self.scratch_txt(label);
64 sys::igDragFloat4(
65 label_cstr,
66 values.as_mut_ptr(),
67 1.0,
68 0.0,
69 0.0,
70 ptr::null(),
71 0,
72 )
73 }
74 }
75
76 #[doc(alias = "DragInt2")]
78 pub fn drag_int2(&self, label: impl AsRef<str>, values: &mut [i32; 2]) -> bool {
79 unsafe {
80 let label_cstr = self.scratch_txt(label);
81 sys::igDragInt2(label_cstr, values.as_mut_ptr(), 1.0, 0, 0, ptr::null(), 0)
82 }
83 }
84
85 #[doc(alias = "DragInt3")]
87 pub fn drag_int3(&self, label: impl AsRef<str>, values: &mut [i32; 3]) -> bool {
88 unsafe {
89 let label_cstr = self.scratch_txt(label);
90 sys::igDragInt3(label_cstr, values.as_mut_ptr(), 1.0, 0, 0, ptr::null(), 0)
91 }
92 }
93
94 #[doc(alias = "DragInt4")]
96 pub fn drag_int4(&self, label: impl AsRef<str>, values: &mut [i32; 4]) -> bool {
97 unsafe {
98 let label_cstr = self.scratch_txt(label);
99 sys::igDragInt4(label_cstr, values.as_mut_ptr(), 1.0, 0, 0, ptr::null(), 0)
100 }
101 }
102}
103
104#[derive(Clone, Debug)]
106#[must_use]
107pub struct Drag<T, L, F = &'static str> {
108 label: L,
109 speed: f32,
110 min: Option<T>,
111 max: Option<T>,
112 display_format: Option<F>,
113 flags: SliderFlags,
114}
115
116impl<L: AsRef<str>, T: DataTypeKind> Drag<T, L> {
117 #[doc(alias = "DragScalar", alias = "DragScalarN")]
119 pub fn new(label: L) -> Self {
120 Drag {
121 label,
122 speed: 1.0,
123 min: None,
124 max: None,
125 display_format: None,
126 flags: SliderFlags::empty(),
127 }
128 }
129}
130
131impl<L: AsRef<str>, T: DataTypeKind, F: AsRef<str>> Drag<T, L, F> {
132 pub fn range(mut self, min: T, max: T) -> Self {
134 self.min = Some(min);
135 self.max = Some(max);
136 self
137 }
138
139 pub fn speed(mut self, speed: f32) -> Self {
143 self.speed = speed;
144 self
145 }
146
147 pub fn display_format<F2: AsRef<str>>(self, display_format: F2) -> Drag<T, L, F2> {
149 Drag {
150 label: self.label,
151 speed: self.speed,
152 min: self.min,
153 max: self.max,
154 display_format: Some(display_format),
155 flags: self.flags,
156 }
157 }
158
159 pub fn flags(mut self, flags: SliderFlags) -> Self {
161 self.flags = flags;
162 self
163 }
164
165 pub fn build(self, ui: &Ui, value: &mut T) -> bool {
169 unsafe {
170 let (one, two) = ui.scratch_txt_with_opt(self.label, self.display_format);
171
172 sys::igDragScalar(
173 one,
174 T::KIND as i32,
175 value as *mut T as *mut c_void,
176 self.speed,
177 self.min
178 .as_ref()
179 .map(|min| min as *const T)
180 .unwrap_or(ptr::null()) as *const c_void,
181 self.max
182 .as_ref()
183 .map(|max| max as *const T)
184 .unwrap_or(ptr::null()) as *const c_void,
185 two,
186 self.flags.bits(),
187 )
188 }
189 }
190
191 pub fn build_array(self, ui: &Ui, values: &mut [T]) -> bool {
195 unsafe {
196 let (one, two) = ui.scratch_txt_with_opt(self.label, self.display_format);
197
198 sys::igDragScalarN(
199 one,
200 T::KIND as i32,
201 values.as_mut_ptr() as *mut c_void,
202 values.len() as i32,
203 self.speed,
204 self.min
205 .as_ref()
206 .map(|min| min as *const T)
207 .unwrap_or(ptr::null()) as *const c_void,
208 self.max
209 .as_ref()
210 .map(|max| max as *const T)
211 .unwrap_or(ptr::null()) as *const c_void,
212 two,
213 self.flags.bits(),
214 )
215 }
216 }
217}
218
219#[derive(Clone, Debug)]
221#[must_use]
222pub struct DragRange<T, L, F = &'static str, M = &'static str> {
223 label: L,
224 speed: f32,
225 min: Option<T>,
226 max: Option<T>,
227 display_format: Option<F>,
228 max_display_format: Option<M>,
229 flags: SliderFlags,
230}
231
232impl<T: DataTypeKind, L: AsRef<str>> DragRange<T, L> {
233 #[doc(alias = "DragIntRange2", alias = "DragFloatRange2")]
235 pub fn new(label: L) -> DragRange<T, L> {
236 DragRange {
237 label,
238 speed: 1.0,
239 min: None,
240 max: None,
241 display_format: None,
242 max_display_format: None,
243 flags: SliderFlags::NONE,
244 }
245 }
246}
247
248impl<T, L, F, M> DragRange<T, L, F, M>
249where
250 T: DataTypeKind,
251 L: AsRef<str>,
252 F: AsRef<str>,
253 M: AsRef<str>,
254{
255 pub fn range(mut self, min: T, max: T) -> Self {
257 self.min = Some(min);
258 self.max = Some(max);
259 self
260 }
261
262 pub fn speed(mut self, speed: f32) -> Self {
266 self.speed = speed;
267 self
268 }
269
270 pub fn display_format<F2: AsRef<str>>(self, display_format: F2) -> DragRange<T, L, F2, M> {
272 DragRange {
273 label: self.label,
274 speed: self.speed,
275 min: self.min,
276 max: self.max,
277 display_format: Some(display_format),
278 max_display_format: self.max_display_format,
279 flags: self.flags,
280 }
281 }
282
283 pub fn max_display_format<M2: AsRef<str>>(
285 self,
286 max_display_format: M2,
287 ) -> DragRange<T, L, F, M2> {
288 DragRange {
289 label: self.label,
290 speed: self.speed,
291 min: self.min,
292 max: self.max,
293 display_format: self.display_format,
294 max_display_format: Some(max_display_format),
295 flags: self.flags,
296 }
297 }
298
299 pub fn flags(mut self, flags: SliderFlags) -> Self {
301 self.flags = flags;
302 self
303 }
304}
305
306impl<L, F, M> DragRange<f32, L, F, M>
307where
308 L: AsRef<str>,
309 F: AsRef<str>,
310 M: AsRef<str>,
311{
312 #[doc(alias = "DragFloatRange2")]
316 pub fn build(self, ui: &Ui, min: &mut f32, max: &mut f32) -> bool {
317 unsafe {
318 let buffer = &mut *ui.scratch_buffer().get();
319 buffer.refresh_buffer();
320
321 let label_start = buffer.push(self.label);
322 let display_format = self.display_format.as_ref().map(|v| buffer.push(v));
323 let max_display_format = self.max_display_format.as_ref().map(|v| buffer.push(v));
324
325 let label = buffer.offset(label_start);
326 let display_format = display_format
327 .map(|v| buffer.offset(v))
328 .unwrap_or_else(std::ptr::null);
329 let max_display_format = max_display_format
330 .map(|v| buffer.offset(v))
331 .unwrap_or_else(std::ptr::null);
332
333 sys::igDragFloatRange2(
334 label,
335 min as *mut f32,
336 max as *mut f32,
337 self.speed,
338 self.min.unwrap_or(0.0),
339 self.max.unwrap_or(0.0),
340 display_format,
341 max_display_format,
342 self.flags.bits(),
343 )
344 }
345 }
346}
347
348impl<L, F, M> DragRange<i32, L, F, M>
349where
350 L: AsRef<str>,
351 F: AsRef<str>,
352 M: AsRef<str>,
353{
354 #[doc(alias = "DragIntRange2")]
358 pub fn build(self, ui: &Ui, min: &mut i32, max: &mut i32) -> bool {
359 unsafe {
360 let buffer = &mut *ui.scratch_buffer().get();
361 buffer.refresh_buffer();
362
363 let label_start = buffer.push(self.label);
364 let display_format = self.display_format.as_ref().map(|v| buffer.push(v));
365 let max_display_format = self.max_display_format.as_ref().map(|v| buffer.push(v));
366
367 let label = buffer.offset(label_start);
368 let display_format = display_format
369 .map(|v| buffer.offset(v))
370 .unwrap_or_else(std::ptr::null);
371 let max_display_format = max_display_format
372 .map(|v| buffer.offset(v))
373 .unwrap_or_else(std::ptr::null);
374
375 sys::igDragIntRange2(
376 label,
377 min as *mut i32,
378 max as *mut i32,
379 self.speed,
380 self.min.unwrap_or(0),
381 self.max.unwrap_or(0),
382 display_format,
383 max_display_format,
384 self.flags.bits(),
385 )
386 }
387 }
388}