arcdps_imgui\widget/
drag.rs

1use std::os::raw::c_void;
2use std::ptr;
3
4use crate::internal::DataTypeKind;
5use crate::sys;
6use crate::widget::slider::SliderFlags;
7use crate::Ui;
8
9/// Builder for a drag slider widget.
10#[derive(Copy, Clone, Debug)]
11#[must_use]
12pub struct Drag<T, L, F = &'static str> {
13    label: L,
14    speed: f32,
15    min: Option<T>,
16    max: Option<T>,
17    display_format: Option<F>,
18    flags: SliderFlags,
19}
20
21impl<L: AsRef<str>, T: DataTypeKind> Drag<T, L> {
22    /// Constructs a new drag slider builder.
23    #[doc(alias = "DragScalar", alias = "DragScalarN")]
24    pub fn new(label: L) -> Self {
25        Drag {
26            label,
27            speed: 1.0,
28            min: None,
29            max: None,
30            display_format: None,
31            flags: SliderFlags::empty(),
32        }
33    }
34}
35
36impl<L: AsRef<str>, T: DataTypeKind, F: AsRef<str>> Drag<T, L, F> {
37    /// Sets the range (inclusive)
38    pub fn range(mut self, min: T, max: T) -> Self {
39        self.min = Some(min);
40        self.max = Some(max);
41        self
42    }
43    /// Sets the value increment for a movement of one pixel.
44    ///
45    /// Example: speed=0.2 means mouse needs to move 5 pixels to increase the slider value by 1
46    pub fn speed(mut self, speed: f32) -> Self {
47        self.speed = speed;
48        self
49    }
50    /// Sets the display format using *a C-style printf string*
51    pub fn display_format<F2: AsRef<str>>(self, display_format: F2) -> Drag<T, L, F2> {
52        Drag {
53            label: self.label,
54            speed: self.speed,
55            min: self.min,
56            max: self.max,
57            display_format: Some(display_format),
58            flags: self.flags,
59        }
60    }
61    /// Replaces all current settings with the given flags
62    pub fn flags(mut self, flags: SliderFlags) -> Self {
63        self.flags = flags;
64        self
65    }
66    /// Builds a drag slider that is bound to the given value.
67    ///
68    /// Returns true if the slider value was changed.
69    pub fn build(self, ui: &Ui<'_>, value: &mut T) -> bool {
70        unsafe {
71            let (one, two) = ui.scratch_txt_with_opt(self.label, self.display_format);
72
73            sys::igDragScalar(
74                one,
75                T::KIND as i32,
76                value as *mut T as *mut c_void,
77                self.speed,
78                self.min
79                    .as_ref()
80                    .map(|min| min as *const T)
81                    .unwrap_or(ptr::null()) as *const c_void,
82                self.max
83                    .as_ref()
84                    .map(|max| max as *const T)
85                    .unwrap_or(ptr::null()) as *const c_void,
86                two,
87                self.flags.bits() as i32,
88            )
89        }
90    }
91    /// Builds a horizontal array of multiple drag sliders attached to the given slice.
92    ///
93    /// Returns true if any slider value was changed.
94    pub fn build_array(self, ui: &Ui<'_>, values: &mut [T]) -> bool {
95        unsafe {
96            let (one, two) = ui.scratch_txt_with_opt(self.label, self.display_format);
97
98            sys::igDragScalarN(
99                one,
100                T::KIND as i32,
101                values.as_mut_ptr() as *mut c_void,
102                values.len() as i32,
103                self.speed,
104                self.min
105                    .as_ref()
106                    .map(|min| min as *const T)
107                    .unwrap_or(ptr::null()) as *const c_void,
108                self.max
109                    .as_ref()
110                    .map(|max| max as *const T)
111                    .unwrap_or(ptr::null()) as *const c_void,
112                two,
113                self.flags.bits() as i32,
114            )
115        }
116    }
117}
118
119/// Builder for a drag slider widget.
120#[derive(Copy, Clone, Debug)]
121#[must_use]
122pub struct DragRange<T, L, F = &'static str, M = &'static str> {
123    label: L,
124    speed: f32,
125    min: Option<T>,
126    max: Option<T>,
127    display_format: Option<F>,
128    max_display_format: Option<M>,
129    flags: SliderFlags,
130}
131
132impl<T: DataTypeKind, L: AsRef<str>> DragRange<T, L> {
133    /// Constructs a new drag slider builder.
134    #[doc(alias = "DragIntRange2", alias = "DragFloatRange2")]
135    pub fn new(label: L) -> DragRange<T, L> {
136        DragRange {
137            label,
138            speed: 1.0,
139            min: None,
140            max: None,
141            display_format: None,
142            max_display_format: None,
143            flags: SliderFlags::empty(),
144        }
145    }
146}
147
148impl<T, L, F, M> DragRange<T, L, F, M>
149where
150    T: DataTypeKind,
151    L: AsRef<str>,
152    F: AsRef<str>,
153    M: AsRef<str>,
154{
155    pub fn range(mut self, min: T, max: T) -> Self {
156        self.min = Some(min);
157        self.max = Some(max);
158        self
159    }
160    /// Sets the value increment for a movement of one pixel.
161    ///
162    /// Example: speed=0.2 means mouse needs to move 5 pixels to increase the slider value by 1
163    pub fn speed(mut self, speed: f32) -> Self {
164        self.speed = speed;
165        self
166    }
167    /// Sets the display format using *a C-style printf string*
168    pub fn display_format<F2: AsRef<str>>(self, display_format: F2) -> DragRange<T, L, F2, M> {
169        DragRange {
170            label: self.label,
171            speed: self.speed,
172            min: self.min,
173            max: self.max,
174            display_format: Some(display_format),
175            max_display_format: self.max_display_format,
176            flags: self.flags,
177        }
178    }
179    /// Sets the display format for the max value using *a C-style printf string*
180    pub fn max_display_format<M2: AsRef<str>>(
181        self,
182        max_display_format: M2,
183    ) -> DragRange<T, L, F, M2> {
184        DragRange {
185            label: self.label,
186            speed: self.speed,
187            min: self.min,
188            max: self.max,
189            display_format: self.display_format,
190            max_display_format: Some(max_display_format),
191            flags: self.flags,
192        }
193    }
194    /// Replaces all current settings with the given flags
195    pub fn flags(mut self, flags: SliderFlags) -> Self {
196        self.flags = flags;
197        self
198    }
199}
200
201impl<L, F, M> DragRange<f32, L, F, M>
202where
203    L: AsRef<str>,
204    F: AsRef<str>,
205    M: AsRef<str>,
206{
207    /// Builds a drag range slider that is bound to the given min/max values.
208    ///
209    /// Returns true if the slider value was changed.
210    #[doc(alias = "DragFloatRange2")]
211    pub fn build(self, ui: &Ui<'_>, min: &mut f32, max: &mut f32) -> bool {
212        let label;
213        let mut display_format = std::ptr::null();
214        let mut max_display_format = std::ptr::null();
215
216        // we do this ourselves the long way...
217        unsafe {
218            let buffer = &mut *ui.buffer.get();
219            buffer.refresh_buffer();
220
221            label = buffer.push(self.label);
222            if let Some(v) = self.display_format {
223                display_format = buffer.push(v);
224            }
225            if let Some(v) = self.max_display_format {
226                max_display_format = buffer.push(v);
227            }
228
229            sys::igDragFloatRange2(
230                label,
231                min as *mut f32,
232                max as *mut f32,
233                self.speed,
234                self.min.unwrap_or(0.0),
235                self.max.unwrap_or(0.0),
236                display_format,
237                max_display_format,
238                self.flags.bits() as i32,
239            )
240        }
241    }
242}
243
244impl<L, F, M> DragRange<i32, L, F, M>
245where
246    L: AsRef<str>,
247    F: AsRef<str>,
248    M: AsRef<str>,
249{
250    /// Builds a drag range slider that is bound to the given min/max values.
251    ///
252    /// Returns true if the slider value was changed.
253    #[doc(alias = "DragIntRange2")]
254    pub fn build(self, ui: &Ui<'_>, min: &mut i32, max: &mut i32) -> bool {
255        unsafe {
256            let label;
257            let mut display_format = std::ptr::null();
258            let mut max_display_format = std::ptr::null();
259
260            // we do this ourselves the long way...
261            let buffer = &mut *ui.buffer.get();
262            buffer.refresh_buffer();
263
264            label = buffer.push(self.label);
265            if let Some(v) = self.display_format {
266                display_format = buffer.push(v);
267            }
268            if let Some(v) = self.max_display_format {
269                max_display_format = buffer.push(v);
270            }
271
272            sys::igDragIntRange2(
273                label,
274                min as *mut i32,
275                max as *mut i32,
276                self.speed,
277                self.min.unwrap_or(0),
278                self.max.unwrap_or(0),
279                display_format,
280                max_display_format,
281                self.flags.bits() as i32,
282            )
283        }
284    }
285}