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 let count = match i32::try_from(values.len()) {
196 Ok(n) => n,
197 Err(_) => return false,
198 };
199 unsafe {
200 let (one, two) = ui.scratch_txt_with_opt(self.label, self.display_format);
201
202 sys::igDragScalarN(
203 one,
204 T::KIND as i32,
205 values.as_mut_ptr() as *mut c_void,
206 count,
207 self.speed,
208 self.min
209 .as_ref()
210 .map(|min| min as *const T)
211 .unwrap_or(ptr::null()) as *const c_void,
212 self.max
213 .as_ref()
214 .map(|max| max as *const T)
215 .unwrap_or(ptr::null()) as *const c_void,
216 two,
217 self.flags.bits(),
218 )
219 }
220 }
221}
222
223#[derive(Clone, Debug)]
225#[must_use]
226pub struct DragRange<T, L, F = &'static str, M = &'static str> {
227 label: L,
228 speed: f32,
229 min: Option<T>,
230 max: Option<T>,
231 display_format: Option<F>,
232 max_display_format: Option<M>,
233 flags: SliderFlags,
234}
235
236impl<T: DataTypeKind, L: AsRef<str>> DragRange<T, L> {
237 #[doc(alias = "DragIntRange2", alias = "DragFloatRange2")]
239 pub fn new(label: L) -> DragRange<T, L> {
240 DragRange {
241 label,
242 speed: 1.0,
243 min: None,
244 max: None,
245 display_format: None,
246 max_display_format: None,
247 flags: SliderFlags::NONE,
248 }
249 }
250}
251
252impl<T, L, F, M> DragRange<T, L, F, M>
253where
254 T: DataTypeKind,
255 L: AsRef<str>,
256 F: AsRef<str>,
257 M: AsRef<str>,
258{
259 pub fn range(mut self, min: T, max: T) -> Self {
261 self.min = Some(min);
262 self.max = Some(max);
263 self
264 }
265
266 pub fn speed(mut self, speed: f32) -> Self {
270 self.speed = speed;
271 self
272 }
273
274 pub fn display_format<F2: AsRef<str>>(self, display_format: F2) -> DragRange<T, L, F2, M> {
276 DragRange {
277 label: self.label,
278 speed: self.speed,
279 min: self.min,
280 max: self.max,
281 display_format: Some(display_format),
282 max_display_format: self.max_display_format,
283 flags: self.flags,
284 }
285 }
286
287 pub fn max_display_format<M2: AsRef<str>>(
289 self,
290 max_display_format: M2,
291 ) -> DragRange<T, L, F, M2> {
292 DragRange {
293 label: self.label,
294 speed: self.speed,
295 min: self.min,
296 max: self.max,
297 display_format: self.display_format,
298 max_display_format: Some(max_display_format),
299 flags: self.flags,
300 }
301 }
302
303 pub fn flags(mut self, flags: SliderFlags) -> Self {
305 self.flags = flags;
306 self
307 }
308}
309
310impl<L, F, M> DragRange<f32, L, F, M>
311where
312 L: AsRef<str>,
313 F: AsRef<str>,
314 M: AsRef<str>,
315{
316 #[doc(alias = "DragFloatRange2")]
320 pub fn build(self, ui: &Ui, min: &mut f32, max: &mut f32) -> bool {
321 unsafe {
322 let buffer = &mut *ui.scratch_buffer().get();
323 buffer.refresh_buffer();
324
325 let label_start = buffer.push(self.label);
326 let display_format = self.display_format.as_ref().map(|v| buffer.push(v));
327 let max_display_format = self.max_display_format.as_ref().map(|v| buffer.push(v));
328
329 let label = buffer.offset(label_start);
330 let display_format = display_format
331 .map(|v| buffer.offset(v))
332 .unwrap_or_else(std::ptr::null);
333 let max_display_format = max_display_format
334 .map(|v| buffer.offset(v))
335 .unwrap_or_else(std::ptr::null);
336
337 sys::igDragFloatRange2(
338 label,
339 min as *mut f32,
340 max as *mut f32,
341 self.speed,
342 self.min.unwrap_or(0.0),
343 self.max.unwrap_or(0.0),
344 display_format,
345 max_display_format,
346 self.flags.bits(),
347 )
348 }
349 }
350}
351
352impl<L, F, M> DragRange<i32, L, F, M>
353where
354 L: AsRef<str>,
355 F: AsRef<str>,
356 M: AsRef<str>,
357{
358 #[doc(alias = "DragIntRange2")]
362 pub fn build(self, ui: &Ui, min: &mut i32, max: &mut i32) -> bool {
363 unsafe {
364 let buffer = &mut *ui.scratch_buffer().get();
365 buffer.refresh_buffer();
366
367 let label_start = buffer.push(self.label);
368 let display_format = self.display_format.as_ref().map(|v| buffer.push(v));
369 let max_display_format = self.max_display_format.as_ref().map(|v| buffer.push(v));
370
371 let label = buffer.offset(label_start);
372 let display_format = display_format
373 .map(|v| buffer.offset(v))
374 .unwrap_or_else(std::ptr::null);
375 let max_display_format = max_display_format
376 .map(|v| buffer.offset(v))
377 .unwrap_or_else(std::ptr::null);
378
379 sys::igDragIntRange2(
380 label,
381 min as *mut i32,
382 max as *mut i32,
383 self.speed,
384 self.min.unwrap_or(0),
385 self.max.unwrap_or(0),
386 display_format,
387 max_display_format,
388 self.flags.bits(),
389 )
390 }
391 }
392}