dear_imgui/widget/
input.rs

1#![allow(
2    clippy::cast_possible_truncation,
3    clippy::cast_sign_loss,
4    clippy::as_conversions
5)]
6use crate::InputTextFlags;
7use crate::internal::DataTypeKind;
8use crate::string::ImString;
9use crate::sys;
10use crate::ui::Ui;
11use std::ffi::{c_int, c_void};
12use std::marker::PhantomData;
13use std::ptr;
14
15/// # Input Widgets
16impl Ui {
17    /// Creates a single-line text input widget builder.
18    ///
19    /// # Examples
20    ///
21    /// ```no_run
22    /// # use dear_imgui::*;
23    /// # let mut ctx = Context::create();
24    /// # let ui = ctx.frame();
25    /// let mut text = String::new();
26    /// if ui.input_text("Label", &mut text).build() {
27    ///     println!("Text changed: {}", text);
28    /// }
29    /// ```
30    #[doc(alias = "InputText", alias = "InputTextWithHint")]
31    pub fn input_text<'p>(
32        &self,
33        label: impl AsRef<str>,
34        buf: &'p mut String,
35    ) -> InputText<'_, 'p, String, String, PassthroughCallback> {
36        InputText::new(self, label, buf)
37    }
38
39    /// Creates a single-line text input backed by ImString (zero-copy)
40    pub fn input_text_imstr<'p>(
41        &self,
42        label: impl AsRef<str>,
43        buf: &'p mut ImString,
44    ) -> InputTextImStr<'_, 'p, String, String, PassthroughCallback> {
45        InputTextImStr::new(self, label, buf)
46    }
47
48    /// Creates a multi-line text input widget builder.
49    ///
50    /// # Examples
51    ///
52    /// ```no_run
53    /// # use dear_imgui::*;
54    /// # let mut ctx = Context::create();
55    /// # let ui = ctx.frame();
56    /// let mut text = String::new();
57    /// if ui.input_text_multiline("Label", &mut text, [200.0, 100.0]).build() {
58    ///     println!("Text changed: {}", text);
59    /// }
60    /// ```
61    #[doc(alias = "InputTextMultiline")]
62    pub fn input_text_multiline<'p>(
63        &self,
64        label: impl AsRef<str>,
65        buf: &'p mut String,
66        size: impl Into<[f32; 2]>,
67    ) -> InputTextMultiline<'_, 'p> {
68        InputTextMultiline::new(self, label, buf, size)
69    }
70
71    /// Creates a multi-line text input backed by ImString (zero-copy)
72    pub fn input_text_multiline_imstr<'p>(
73        &self,
74        label: impl AsRef<str>,
75        buf: &'p mut ImString,
76        size: impl Into<[f32; 2]>,
77    ) -> InputTextMultilineImStr<'_, 'p> {
78        InputTextMultilineImStr::new(self, label, buf, size)
79    }
80
81    /// Creates an integer input widget.
82    ///
83    /// Returns true if the value was edited.
84    #[doc(alias = "InputInt")]
85    pub fn input_int(&self, label: impl AsRef<str>, value: &mut i32) -> bool {
86        self.input_int_config(label).build(value)
87    }
88
89    /// Creates a float input widget.
90    ///
91    /// Returns true if the value was edited.
92    #[doc(alias = "InputFloat")]
93    pub fn input_float(&self, label: impl AsRef<str>, value: &mut f32) -> bool {
94        self.input_float_config(label).build(value)
95    }
96
97    /// Creates a double input widget.
98    ///
99    /// Returns true if the value was edited.
100    #[doc(alias = "InputDouble")]
101    pub fn input_double(&self, label: impl AsRef<str>, value: &mut f64) -> bool {
102        self.input_double_config(label).build(value)
103    }
104
105    /// Creates an integer input builder
106    pub fn input_int_config(&self, label: impl AsRef<str>) -> InputInt<'_> {
107        InputInt::new(self, label)
108    }
109
110    /// Creates a float input builder
111    pub fn input_float_config(&self, label: impl AsRef<str>) -> InputFloat<'_> {
112        InputFloat::new(self, label)
113    }
114
115    /// Creates a double input builder
116    pub fn input_double_config(&self, label: impl AsRef<str>) -> InputDouble<'_> {
117        InputDouble::new(self, label)
118    }
119
120    /// Shows an input field for a scalar value. This is not limited to `f32` and `i32` and can be used with
121    /// any primitive scalar type e.g. `u8` and `f64`.
122    #[doc(alias = "InputScalar")]
123    pub fn input_scalar<'p, L, T>(&self, label: L, value: &'p mut T) -> InputScalar<'_, 'p, T, L>
124    where
125        L: AsRef<str>,
126        T: DataTypeKind,
127    {
128        InputScalar::new(self, label, value)
129    }
130
131    /// Shows a horizontal array of scalar value input fields. See [`input_scalar`].
132    ///
133    /// [`input_scalar`]: Self::input_scalar
134    #[doc(alias = "InputScalarN")]
135    pub fn input_scalar_n<'p, L, T>(
136        &self,
137        label: L,
138        values: &'p mut [T],
139    ) -> InputScalarN<'_, 'p, T, L>
140    where
141        L: AsRef<str>,
142        T: DataTypeKind,
143    {
144        InputScalarN::new(self, label, values)
145    }
146
147    /// Widget to edit two floats
148    #[doc(alias = "InputFloat2")]
149    pub fn input_float2<'p, L>(&self, label: L, value: &'p mut [f32; 2]) -> InputFloat2<'_, 'p, L>
150    where
151        L: AsRef<str>,
152    {
153        InputFloat2::new(self, label, value)
154    }
155
156    /// Widget to edit three floats
157    #[doc(alias = "InputFloat3")]
158    pub fn input_float3<'p, L>(&self, label: L, value: &'p mut [f32; 3]) -> InputFloat3<'_, 'p, L>
159    where
160        L: AsRef<str>,
161    {
162        InputFloat3::new(self, label, value)
163    }
164
165    /// Widget to edit four floats
166    #[doc(alias = "InputFloat4")]
167    pub fn input_float4<'p, L>(&self, label: L, value: &'p mut [f32; 4]) -> InputFloat4<'_, 'p, L>
168    where
169        L: AsRef<str>,
170    {
171        InputFloat4::new(self, label, value)
172    }
173
174    /// Widget to edit two integers
175    #[doc(alias = "InputInt2")]
176    pub fn input_int2<'p, L>(&self, label: L, value: &'p mut [i32; 2]) -> InputInt2<'_, 'p, L>
177    where
178        L: AsRef<str>,
179    {
180        InputInt2::new(self, label, value)
181    }
182
183    /// Widget to edit three integers
184    #[doc(alias = "InputInt3")]
185    pub fn input_int3<'p, L>(&self, label: L, value: &'p mut [i32; 3]) -> InputInt3<'_, 'p, L>
186    where
187        L: AsRef<str>,
188    {
189        InputInt3::new(self, label, value)
190    }
191
192    /// Widget to edit four integers
193    #[doc(alias = "InputInt4")]
194    pub fn input_int4<'p, L>(&self, label: L, value: &'p mut [i32; 4]) -> InputInt4<'_, 'p, L>
195    where
196        L: AsRef<str>,
197    {
198        InputInt4::new(self, label, value)
199    }
200}
201
202/// Builder for a text input widget
203#[must_use]
204pub struct InputText<'ui, 'p, L = String, H = String, T = PassthroughCallback> {
205    ui: &'ui Ui,
206    label: L,
207    buf: &'p mut String,
208    flags: InputTextFlags,
209    capacity_hint: Option<usize>,
210    hint: Option<H>,
211    callback_handler: T,
212    _phantom: PhantomData<&'ui ()>,
213}
214
215/// Builder for a text input backed by ImString (zero-copy)
216#[must_use]
217pub struct InputTextImStr<'ui, 'p, L = String, H = String, T = PassthroughCallback> {
218    ui: &'ui Ui,
219    label: L,
220    buf: &'p mut ImString,
221    flags: InputTextFlags,
222    hint: Option<H>,
223    callback_handler: T,
224    _phantom: PhantomData<&'ui ()>,
225}
226
227impl<'ui, 'p> InputTextImStr<'ui, 'p, String, String, PassthroughCallback> {
228    pub fn new(ui: &'ui Ui, label: impl AsRef<str>, buf: &'p mut ImString) -> Self {
229        Self {
230            ui,
231            label: label.as_ref().to_string(),
232            buf,
233            flags: InputTextFlags::empty(),
234            hint: None,
235            callback_handler: PassthroughCallback,
236            _phantom: PhantomData,
237        }
238    }
239}
240
241impl<'ui, 'p, L: AsRef<str>, H: AsRef<str>, T> InputTextImStr<'ui, 'p, L, H, T> {
242    pub fn flags(mut self, flags: InputTextFlags) -> Self {
243        self.flags = flags;
244        self
245    }
246    pub fn hint<H2: AsRef<str>>(self, hint: H2) -> InputTextImStr<'ui, 'p, L, H2, T> {
247        InputTextImStr {
248            ui: self.ui,
249            label: self.label,
250            buf: self.buf,
251            flags: self.flags,
252            hint: Some(hint),
253            callback_handler: self.callback_handler,
254            _phantom: PhantomData,
255        }
256    }
257    pub fn read_only(mut self, ro: bool) -> Self {
258        self.flags.set(InputTextFlags::READ_ONLY, ro);
259        self
260    }
261    pub fn password(mut self, pw: bool) -> Self {
262        self.flags.set(InputTextFlags::PASSWORD, pw);
263        self
264    }
265    pub fn auto_select_all(mut self, v: bool) -> Self {
266        self.flags.set(InputTextFlags::AUTO_SELECT_ALL, v);
267        self
268    }
269    pub fn enter_returns_true(mut self, v: bool) -> Self {
270        self.flags.set(InputTextFlags::ENTER_RETURNS_TRUE, v);
271        self
272    }
273
274    pub fn build(self) -> bool {
275        let label_ptr = self.ui.scratch_txt(self.label.as_ref());
276        let hint_ptr = if let Some(ref hint) = self.hint {
277            self.ui.scratch_txt(hint.as_ref())
278        } else {
279            std::ptr::null()
280        };
281        let buf_ptr = self.buf.as_mut_ptr();
282        let buf_size = self.buf.capacity_with_nul();
283        let user_ptr = self.buf as *mut ImString as *mut c_void;
284
285        extern "C" fn resize_cb_imstr(data: *mut sys::ImGuiInputTextCallbackData) -> c_int {
286            unsafe {
287                if (*data).EventFlag == (sys::ImGuiInputTextFlags_CallbackResize as i32) {
288                    let im = &mut *((*data).UserData as *mut ImString);
289                    let requested = (*data).BufSize as usize;
290                    if im.0.len() < requested {
291                        im.0.resize(requested, 0);
292                    }
293                    (*data).Buf = im.as_mut_ptr();
294                    (*data).BufDirty = true;
295                }
296            }
297            0
298        }
299
300        let flags = self.flags | InputTextFlags::CALLBACK_RESIZE;
301        unsafe {
302            if hint_ptr.is_null() {
303                sys::igInputText(
304                    label_ptr,
305                    buf_ptr,
306                    buf_size,
307                    flags.bits(),
308                    Some(resize_cb_imstr),
309                    user_ptr,
310                )
311            } else {
312                sys::igInputTextWithHint(
313                    label_ptr,
314                    hint_ptr,
315                    buf_ptr,
316                    buf_size,
317                    flags.bits(),
318                    Some(resize_cb_imstr),
319                    user_ptr,
320                )
321            }
322        }
323    }
324}
325impl<'ui, 'p> InputText<'ui, 'p, String, String, PassthroughCallback> {
326    /// Creates a new text input builder
327    pub fn new(ui: &'ui Ui, label: impl AsRef<str>, buf: &'p mut String) -> Self {
328        Self {
329            ui,
330            label: label.as_ref().to_string(),
331            buf,
332            flags: InputTextFlags::NONE,
333            capacity_hint: None,
334            hint: None,
335            callback_handler: PassthroughCallback,
336            _phantom: PhantomData,
337        }
338    }
339}
340
341impl<'ui, 'p, L, H, T> InputText<'ui, 'p, L, H, T> {
342    /// Sets the flags for the input
343    pub fn flags(mut self, flags: InputTextFlags) -> Self {
344        self.flags = flags;
345        self
346    }
347
348    /// Hint a minimum buffer capacity to reduce reallocations for large fields
349    pub fn capacity_hint(mut self, cap: usize) -> Self {
350        self.capacity_hint = Some(cap);
351        self
352    }
353
354    /// Sets a hint text
355    pub fn hint<H2: AsRef<str>>(self, hint: H2) -> InputText<'ui, 'p, L, H2, T> {
356        InputText {
357            ui: self.ui,
358            label: self.label,
359            buf: self.buf,
360            flags: self.flags,
361            capacity_hint: self.capacity_hint,
362            hint: Some(hint),
363            callback_handler: self.callback_handler,
364            _phantom: PhantomData,
365        }
366    }
367
368    /// Sets a callback handler for the input text
369    pub fn callback<T2: InputTextCallbackHandler>(
370        self,
371        callback_handler: T2,
372    ) -> InputText<'ui, 'p, L, H, T2> {
373        InputText {
374            ui: self.ui,
375            label: self.label,
376            buf: self.buf,
377            flags: self.flags,
378            capacity_hint: self.capacity_hint,
379            hint: self.hint,
380            callback_handler,
381            _phantom: PhantomData,
382        }
383    }
384
385    /// Sets callback flags for the input text
386    pub fn callback_flags(mut self, callback_flags: InputTextCallback) -> Self {
387        self.flags |= InputTextFlags::from_bits_truncate(callback_flags.bits() as i32);
388        self
389    }
390
391    /// Makes the input read-only
392    pub fn read_only(mut self, read_only: bool) -> Self {
393        self.flags.set(InputTextFlags::READ_ONLY, read_only);
394        self
395    }
396
397    /// Enables password mode
398    pub fn password(mut self, password: bool) -> Self {
399        self.flags.set(InputTextFlags::PASSWORD, password);
400        self
401    }
402
403    /// Enables auto-select all when first taking focus
404    pub fn auto_select_all(mut self, auto_select: bool) -> Self {
405        self.flags.set(InputTextFlags::AUTO_SELECT_ALL, auto_select);
406        self
407    }
408
409    /// Makes Enter key return true instead of adding new line
410    pub fn enter_returns_true(mut self, enter_returns: bool) -> Self {
411        self.flags
412            .set(InputTextFlags::ENTER_RETURNS_TRUE, enter_returns);
413        self
414    }
415
416    /// Allows only decimal characters (0123456789.+-*/)
417    pub fn chars_decimal(mut self, decimal: bool) -> Self {
418        self.flags.set(InputTextFlags::CHARS_DECIMAL, decimal);
419        self
420    }
421
422    /// Allows only hexadecimal characters (0123456789ABCDEFabcdef)
423    pub fn chars_hexadecimal(mut self, hex: bool) -> Self {
424        self.flags.set(InputTextFlags::CHARS_HEXADECIMAL, hex);
425        self
426    }
427
428    /// Turns a..z into A..Z
429    pub fn chars_uppercase(mut self, uppercase: bool) -> Self {
430        self.flags.set(InputTextFlags::CHARS_UPPERCASE, uppercase);
431        self
432    }
433
434    /// Filters out spaces and tabs
435    pub fn chars_no_blank(mut self, no_blank: bool) -> Self {
436        self.flags.set(InputTextFlags::CHARS_NO_BLANK, no_blank);
437        self
438    }
439}
440
441// Implementation for all InputText types
442impl<'ui, 'p, L, H, T> InputText<'ui, 'p, L, H, T>
443where
444    L: AsRef<str>,
445    H: AsRef<str>,
446    T: InputTextCallbackHandler,
447{
448    /// Builds the text input widget
449    pub fn build(self) -> bool {
450        let label_ptr = self.ui.scratch_txt(self.label.as_ref());
451        let hint_ptr = if let Some(ref hint) = self.hint {
452            self.ui.scratch_txt(hint.as_ref())
453        } else {
454            std::ptr::null()
455        };
456
457        // Prepare an owned, growable buffer with trailing NUL and capacity headroom
458        let mut init = self.buf.as_bytes().to_vec();
459        if !init.ends_with(&[0]) {
460            init.push(0);
461        }
462        let user_cap = self.capacity_hint.unwrap_or(0);
463        let min_cap = (init.len() + 64).max(256).max(user_cap);
464        if init.len() < min_cap {
465            init.resize(min_cap, 0);
466        }
467        let mut owned = Box::new(init);
468        let buf_ptr = owned.as_mut_ptr() as *mut std::os::raw::c_char;
469        let buf_size = owned.len();
470        let user_ptr = (&mut *owned) as *mut Vec<u8> as *mut c_void;
471
472        extern "C" fn resize_callback_vec(data: *mut sys::ImGuiInputTextCallbackData) -> c_int {
473            unsafe {
474                if (*data).EventFlag == (sys::ImGuiInputTextFlags_CallbackResize as i32) {
475                    let vec_ptr = (*data).UserData as *mut Vec<u8>;
476                    if !vec_ptr.is_null() {
477                        let buf = &mut *vec_ptr;
478                        let requested = (*data).BufSize as usize;
479                        if buf.len() < requested {
480                            buf.resize(requested, 0);
481                        }
482                        (*data).Buf = buf.as_mut_ptr() as *mut _;
483                        (*data).BufDirty = true;
484                    }
485                }
486            }
487            0
488        }
489
490        let flags = self.flags | InputTextFlags::CALLBACK_RESIZE;
491
492        let result = unsafe {
493            if hint_ptr.is_null() {
494                sys::igInputText(
495                    label_ptr,
496                    buf_ptr,
497                    buf_size,
498                    flags.bits(),
499                    Some(resize_callback_vec),
500                    user_ptr,
501                )
502            } else {
503                sys::igInputTextWithHint(
504                    label_ptr,
505                    hint_ptr,
506                    buf_ptr,
507                    buf_size,
508                    flags.bits(),
509                    Some(resize_callback_vec),
510                    user_ptr,
511                )
512            }
513        };
514
515        // Update the string if changed
516        if result {
517            let slice: &[u8] = &owned;
518            let end = slice.iter().position(|&b| b == 0).unwrap_or(slice.len());
519            if let Ok(new_string) = String::from_utf8(slice[..end].to_vec()) {
520                *self.buf = new_string;
521            }
522        }
523
524        result
525    }
526}
527
528/// Builder for multiline text input widget
529#[derive(Debug)]
530#[must_use]
531pub struct InputTextMultiline<'ui, 'p> {
532    ui: &'ui Ui,
533    label: String,
534    buf: &'p mut String,
535    size: [f32; 2],
536    flags: InputTextFlags,
537    capacity_hint: Option<usize>,
538}
539
540/// Builder for multiline text input backed by ImString (zero-copy)
541#[derive(Debug)]
542#[must_use]
543pub struct InputTextMultilineImStr<'ui, 'p> {
544    ui: &'ui Ui,
545    label: String,
546    buf: &'p mut ImString,
547    size: [f32; 2],
548    flags: InputTextFlags,
549}
550
551impl<'ui, 'p> InputTextMultilineImStr<'ui, 'p> {
552    pub fn new(
553        ui: &'ui Ui,
554        label: impl AsRef<str>,
555        buf: &'p mut ImString,
556        size: impl Into<[f32; 2]>,
557    ) -> Self {
558        Self {
559            ui,
560            label: label.as_ref().to_string(),
561            buf,
562            size: size.into(),
563            flags: InputTextFlags::NONE,
564        }
565    }
566    pub fn flags(mut self, flags: InputTextFlags) -> Self {
567        self.flags = flags;
568        self
569    }
570    pub fn read_only(mut self, v: bool) -> Self {
571        self.flags.set(InputTextFlags::READ_ONLY, v);
572        self
573    }
574    pub fn build(self) -> bool {
575        let label_ptr = self.ui.scratch_txt(&self.label);
576        let buf_ptr = self.buf.as_mut_ptr();
577        let buf_size = self.buf.capacity_with_nul();
578        let user_ptr = self.buf as *mut ImString as *mut c_void;
579        let size_vec: sys::ImVec2 = self.size.into();
580
581        extern "C" fn resize_cb_imstr(data: *mut sys::ImGuiInputTextCallbackData) -> c_int {
582            unsafe {
583                if (*data).EventFlag == (sys::ImGuiInputTextFlags_CallbackResize as i32) {
584                    let im = &mut *((*data).UserData as *mut ImString);
585                    let requested = (*data).BufSize as usize;
586                    if im.0.len() < requested {
587                        im.0.resize(requested, 0);
588                    }
589                    (*data).Buf = im.as_mut_ptr();
590                    (*data).BufDirty = true;
591                }
592            }
593            0
594        }
595
596        let flags = self.flags | InputTextFlags::CALLBACK_RESIZE;
597        unsafe {
598            sys::igInputTextMultiline(
599                label_ptr,
600                buf_ptr,
601                buf_size,
602                size_vec,
603                flags.bits(),
604                Some(resize_cb_imstr),
605                user_ptr,
606            )
607        }
608    }
609}
610impl<'ui, 'p> InputTextMultiline<'ui, 'p> {
611    /// Creates a new multiline text input builder
612    pub fn new(
613        ui: &'ui Ui,
614        label: impl AsRef<str>,
615        buf: &'p mut String,
616        size: impl Into<[f32; 2]>,
617    ) -> Self {
618        Self {
619            ui,
620            label: label.as_ref().to_string(),
621            buf,
622            size: size.into(),
623            flags: InputTextFlags::NONE,
624            capacity_hint: None,
625        }
626    }
627
628    /// Sets the flags for the input
629    pub fn flags(mut self, flags: InputTextFlags) -> Self {
630        self.flags = flags;
631        self
632    }
633
634    /// Hint a minimum buffer capacity to reduce reallocations for large fields
635    pub fn capacity_hint(mut self, cap: usize) -> Self {
636        self.capacity_hint = Some(cap);
637        self
638    }
639
640    /// Makes the input read-only
641    pub fn read_only(mut self, read_only: bool) -> Self {
642        self.flags.set(InputTextFlags::READ_ONLY, read_only);
643        self
644    }
645
646    /// Builds the multiline text input widget
647    pub fn build(self) -> bool {
648        let label_ptr = self.ui.scratch_txt(&self.label);
649
650        // Prepare an owned, growable buffer with trailing NUL and capacity headroom
651        let mut init = self.buf.as_bytes().to_vec();
652        if !init.ends_with(&[0]) {
653            init.push(0);
654        }
655        let user_cap = self.capacity_hint.unwrap_or(0);
656        let min_cap = (init.len() + 128).max(1024).max(user_cap);
657        if init.len() < min_cap {
658            init.resize(min_cap, 0);
659        }
660        let mut owned = Box::new(init);
661        let buf_ptr = owned.as_mut_ptr() as *mut std::os::raw::c_char;
662        let buf_size = owned.len();
663        let user_ptr = (&mut *owned) as *mut Vec<u8> as *mut c_void;
664
665        extern "C" fn resize_callback_vec(data: *mut sys::ImGuiInputTextCallbackData) -> c_int {
666            unsafe {
667                if (*data).EventFlag == (sys::ImGuiInputTextFlags_CallbackResize as i32) {
668                    let vec_ptr = (*data).UserData as *mut Vec<u8>;
669                    if !vec_ptr.is_null() {
670                        let buf = &mut *vec_ptr;
671                        let requested = (*data).BufSize as usize;
672                        if buf.len() < requested {
673                            buf.resize(requested, 0);
674                        }
675                        (*data).Buf = buf.as_mut_ptr() as *mut _;
676                        (*data).BufDirty = true;
677                    }
678                }
679            }
680            0
681        }
682
683        let size_vec: sys::ImVec2 = self.size.into();
684        let flags = self.flags | InputTextFlags::CALLBACK_RESIZE;
685        let result = unsafe {
686            sys::igInputTextMultiline(
687                label_ptr,
688                buf_ptr,
689                buf_size,
690                size_vec,
691                flags.bits(),
692                Some(resize_callback_vec),
693                user_ptr,
694            )
695        };
696
697        if result {
698            let slice: &[u8] = &owned;
699            let end = slice.iter().position(|&b| b == 0).unwrap_or(slice.len());
700            if let Ok(s) = String::from_utf8(slice[..end].to_vec()) {
701                *self.buf = s;
702            }
703        }
704        result
705    }
706}
707
708/// Builder for integer input widget
709#[derive(Debug)]
710#[must_use]
711pub struct InputInt<'ui> {
712    ui: &'ui Ui,
713    label: String,
714    step: i32,
715    step_fast: i32,
716    flags: InputTextFlags,
717}
718
719impl<'ui> InputInt<'ui> {
720    /// Creates a new integer input builder
721    pub fn new(ui: &'ui Ui, label: impl AsRef<str>) -> Self {
722        Self {
723            ui,
724            label: label.as_ref().to_string(),
725            step: 1,
726            step_fast: 100,
727            flags: InputTextFlags::NONE,
728        }
729    }
730
731    /// Sets the step value
732    pub fn step(mut self, step: i32) -> Self {
733        self.step = step;
734        self
735    }
736
737    /// Sets the fast step value
738    pub fn step_fast(mut self, step_fast: i32) -> Self {
739        self.step_fast = step_fast;
740        self
741    }
742
743    /// Sets the flags for the input
744    pub fn flags(mut self, flags: InputTextFlags) -> Self {
745        self.flags = flags;
746        self
747    }
748
749    /// Builds the integer input widget
750    pub fn build(self, value: &mut i32) -> bool {
751        let label_ptr = self.ui.scratch_txt(&self.label);
752        unsafe {
753            sys::igInputInt(
754                label_ptr,
755                value as *mut i32,
756                self.step,
757                self.step_fast,
758                self.flags.bits(),
759            )
760        }
761    }
762}
763
764/// Builder for float input widget
765#[derive(Debug)]
766#[must_use]
767pub struct InputFloat<'ui> {
768    ui: &'ui Ui,
769    label: String,
770    step: f32,
771    step_fast: f32,
772    format: Option<String>,
773    flags: InputTextFlags,
774}
775
776impl<'ui> InputFloat<'ui> {
777    /// Creates a new float input builder
778    pub fn new(ui: &'ui Ui, label: impl AsRef<str>) -> Self {
779        Self {
780            ui,
781            label: label.as_ref().to_string(),
782            step: 0.0,
783            step_fast: 0.0,
784            format: None,
785            flags: InputTextFlags::NONE,
786        }
787    }
788
789    /// Sets the step value
790    pub fn step(mut self, step: f32) -> Self {
791        self.step = step;
792        self
793    }
794
795    /// Sets the fast step value
796    pub fn step_fast(mut self, step_fast: f32) -> Self {
797        self.step_fast = step_fast;
798        self
799    }
800
801    /// Sets the display format
802    pub fn format(mut self, format: impl AsRef<str>) -> Self {
803        self.format = Some(format.as_ref().to_string());
804        self
805    }
806
807    /// Sets the flags for the input
808    pub fn flags(mut self, flags: InputTextFlags) -> Self {
809        self.flags = flags;
810        self
811    }
812
813    /// Builds the float input widget
814    pub fn build(self, value: &mut f32) -> bool {
815        let label_ptr = self.ui.scratch_txt(&self.label);
816        let format_ptr = self.ui.scratch_txt_opt(self.format.as_ref());
817        let format_ptr = if format_ptr.is_null() {
818            self.ui.scratch_txt("%.3f")
819        } else {
820            format_ptr
821        };
822
823        unsafe {
824            sys::igInputFloat(
825                label_ptr,
826                value as *mut f32,
827                self.step,
828                self.step_fast,
829                format_ptr,
830                self.flags.bits(),
831            )
832        }
833    }
834}
835
836/// Builder for double input widget
837#[derive(Debug)]
838#[must_use]
839pub struct InputDouble<'ui> {
840    ui: &'ui Ui,
841    label: String,
842    step: f64,
843    step_fast: f64,
844    format: Option<String>,
845    flags: InputTextFlags,
846}
847
848impl<'ui> InputDouble<'ui> {
849    /// Creates a new double input builder
850    pub fn new(ui: &'ui Ui, label: impl AsRef<str>) -> Self {
851        Self {
852            ui,
853            label: label.as_ref().to_string(),
854            step: 0.0,
855            step_fast: 0.0,
856            format: None,
857            flags: InputTextFlags::NONE,
858        }
859    }
860
861    /// Sets the step value
862    pub fn step(mut self, step: f64) -> Self {
863        self.step = step;
864        self
865    }
866
867    /// Sets the fast step value
868    pub fn step_fast(mut self, step_fast: f64) -> Self {
869        self.step_fast = step_fast;
870        self
871    }
872
873    /// Sets the display format
874    pub fn format(mut self, format: impl AsRef<str>) -> Self {
875        self.format = Some(format.as_ref().to_string());
876        self
877    }
878
879    /// Sets the flags for the input
880    pub fn flags(mut self, flags: InputTextFlags) -> Self {
881        self.flags = flags;
882        self
883    }
884
885    /// Builds the double input widget
886    pub fn build(self, value: &mut f64) -> bool {
887        let label_ptr = self.ui.scratch_txt(&self.label);
888        let format_ptr = self.ui.scratch_txt_opt(self.format.as_ref());
889        let format_ptr = if format_ptr.is_null() {
890            self.ui.scratch_txt("%.6f")
891        } else {
892            format_ptr
893        };
894
895        unsafe {
896            sys::igInputDouble(
897                label_ptr,
898                value as *mut f64,
899                self.step,
900                self.step_fast,
901                format_ptr,
902                self.flags.bits(),
903            )
904        }
905    }
906}
907
908// InputText Callback System
909// =========================
910
911bitflags::bitflags! {
912    /// Callback flags for InputText widgets
913    #[repr(transparent)]
914    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
915    pub struct InputTextCallback: u32 {
916        /// Call user function on pressing TAB (for completion handling)
917        const COMPLETION = sys::ImGuiInputTextFlags_CallbackCompletion as u32;
918        /// Call user function on pressing Up/Down arrows (for history handling)
919        const HISTORY = sys::ImGuiInputTextFlags_CallbackHistory as u32;
920        /// Call user function every time. User code may query cursor position, modify text buffer.
921        const ALWAYS = sys::ImGuiInputTextFlags_CallbackAlways as u32;
922        /// Call user function to filter character.
923        const CHAR_FILTER = sys::ImGuiInputTextFlags_CallbackCharFilter as u32;
924        /// Callback on buffer edit (note that InputText already returns true on edit, the
925        /// callback is useful mainly to manipulate the underlying buffer while focus is active)
926        const EDIT = sys::ImGuiInputTextFlags_CallbackEdit as u32;
927    }
928}
929
930/// Direction for history navigation
931#[derive(Debug, Clone, Copy, PartialEq, Eq)]
932pub enum HistoryDirection {
933    /// Up arrow key pressed
934    Up,
935    /// Down arrow key pressed
936    Down,
937}
938
939/// This trait provides an interface which ImGui will call on InputText callbacks.
940///
941/// Each method is called *if and only if* the corresponding flag for each
942/// method is passed to ImGui in the `callback` builder.
943pub trait InputTextCallbackHandler {
944    /// Filters a char -- returning a `None` means that the char is removed,
945    /// and returning another char substitutes it out.
946    ///
947    /// To make ImGui run this callback, use [InputTextCallback::CHAR_FILTER].
948    fn char_filter(&mut self, _c: char) -> Option<char> {
949        None
950    }
951
952    /// Called when the user presses the completion key (TAB by default).
953    ///
954    /// To make ImGui run this callback, use [InputTextCallback::COMPLETION].
955    fn on_completion(&mut self, _data: TextCallbackData) {}
956
957    /// Called when the user presses Up/Down arrow keys for history navigation.
958    ///
959    /// To make ImGui run this callback, use [InputTextCallback::HISTORY].
960    fn on_history(&mut self, _direction: HistoryDirection, _data: TextCallbackData) {}
961
962    /// Called every frame when the input text is active.
963    ///
964    /// To make ImGui run this callback, use [InputTextCallback::ALWAYS].
965    fn on_always(&mut self, _data: TextCallbackData) {}
966
967    /// Called when the text buffer is edited.
968    ///
969    /// To make ImGui run this callback, use [InputTextCallback::EDIT].
970    fn on_edit(&mut self, _data: TextCallbackData) {}
971}
972
973/// This struct provides methods to edit the underlying text buffer that
974/// Dear ImGui manipulates. Primarily, it gives [remove_chars](Self::remove_chars),
975/// [insert_chars](Self::insert_chars), and mutable access to what text is selected.
976pub struct TextCallbackData(*mut sys::ImGuiInputTextCallbackData);
977
978impl TextCallbackData {
979    /// Creates the buffer.
980    unsafe fn new(data: *mut sys::ImGuiInputTextCallbackData) -> Self {
981        Self(data)
982    }
983
984    /// Get a reference to the text callback buffer's str.
985    pub fn str(&self) -> &str {
986        unsafe {
987            std::str::from_utf8(std::slice::from_raw_parts(
988                (*(self.0)).Buf as *const _,
989                (*(self.0)).BufTextLen as usize,
990            ))
991            .expect("internal imgui error -- it boofed a utf8")
992        }
993    }
994
995    /// Get the current cursor position
996    pub fn cursor_pos(&self) -> usize {
997        unsafe { (*(self.0)).CursorPos as usize }
998    }
999
1000    /// Set the cursor position
1001    pub fn set_cursor_pos(&mut self, pos: usize) {
1002        unsafe {
1003            (*(self.0)).CursorPos = pos as i32;
1004        }
1005    }
1006
1007    /// Get the selection start position
1008    pub fn selection_start(&self) -> usize {
1009        unsafe { (*(self.0)).SelectionStart as usize }
1010    }
1011
1012    /// Set the selection start position
1013    pub fn set_selection_start(&mut self, pos: usize) {
1014        unsafe {
1015            (*(self.0)).SelectionStart = pos as i32;
1016        }
1017    }
1018
1019    /// Get the selection end position
1020    pub fn selection_end(&self) -> usize {
1021        unsafe { (*(self.0)).SelectionEnd as usize }
1022    }
1023
1024    /// Set the selection end position
1025    pub fn set_selection_end(&mut self, pos: usize) {
1026        unsafe {
1027            (*(self.0)).SelectionEnd = pos as i32;
1028        }
1029    }
1030
1031    /// Select all text
1032    pub fn select_all(&mut self) {
1033        unsafe {
1034            (*(self.0)).SelectionStart = 0;
1035            (*(self.0)).SelectionEnd = (*(self.0)).BufTextLen;
1036        }
1037    }
1038
1039    /// Clear selection
1040    pub fn clear_selection(&mut self) {
1041        unsafe {
1042            (*(self.0)).SelectionStart = (*(self.0)).CursorPos;
1043            (*(self.0)).SelectionEnd = (*(self.0)).CursorPos;
1044        }
1045    }
1046
1047    /// Returns true if there is a selection
1048    pub fn has_selection(&self) -> bool {
1049        unsafe { (*(self.0)).SelectionStart != (*(self.0)).SelectionEnd }
1050    }
1051
1052    /// Delete characters in the range [pos, pos+bytes_count)
1053    pub fn remove_chars(&mut self, pos: usize, bytes_count: usize) {
1054        unsafe {
1055            sys::ImGuiInputTextCallbackData_DeleteChars(self.0, pos as i32, bytes_count as i32);
1056        }
1057    }
1058
1059    /// Insert text at the given position
1060    pub fn insert_chars(&mut self, pos: usize, text: &str) {
1061        let text_cstr = format!("{}\0", text);
1062        unsafe {
1063            sys::ImGuiInputTextCallbackData_InsertChars(
1064                self.0,
1065                pos as i32,
1066                text_cstr.as_ptr() as *const std::os::raw::c_char,
1067                text_cstr.as_ptr().add(text.len()) as *const std::os::raw::c_char,
1068            );
1069        }
1070    }
1071
1072    /// Gives access to the underlying byte array MUTABLY.
1073    ///
1074    /// ## Safety
1075    ///
1076    /// This is very unsafe, and the following invariants must be
1077    /// upheld:
1078    /// 1. Keep the data utf8 valid.
1079    /// 2. After editing the string, call [set_dirty].
1080    ///
1081    /// To truncate the string, please use [remove_chars]. To extend
1082    /// the string, please use [insert_chars] and [push_str].
1083    ///
1084    /// This function should have highly limited usage, but could be for
1085    /// editing certain characters in the buffer based on some external condition.
1086    ///
1087    /// [remove_chars]: Self::remove_chars
1088    /// [set_dirty]: Self::set_dirty
1089    /// [insert_chars]: Self::insert_chars
1090    /// [push_str]: Self::push_str
1091    pub unsafe fn str_as_bytes_mut(&mut self) -> &mut [u8] {
1092        unsafe {
1093            let str = std::str::from_utf8_mut(std::slice::from_raw_parts_mut(
1094                (*(self.0)).Buf as *const _ as *mut _,
1095                (*(self.0)).BufTextLen as usize,
1096            ))
1097            .expect("internal imgui error -- it boofed a utf8");
1098
1099            str.as_bytes_mut()
1100        }
1101    }
1102
1103    /// Sets the dirty flag on the text to imgui, indicating that
1104    /// it should reapply this string to its internal state.
1105    ///
1106    /// **NB:** You only need to use this method if you're using `[str_as_bytes_mut]`.
1107    /// If you use the helper methods [remove_chars] and [insert_chars],
1108    /// this will be set for you. However, this is no downside to setting
1109    /// the dirty flag spuriously except the minor CPU time imgui will spend.
1110    ///
1111    /// [str_as_bytes_mut]: Self::str_as_bytes_mut
1112    /// [remove_chars]: Self::remove_chars
1113    /// [insert_chars]: Self::insert_chars
1114    pub fn set_dirty(&mut self) {
1115        unsafe {
1116            (*(self.0)).BufDirty = true;
1117        }
1118    }
1119
1120    /// Returns the selected text directly. Note that if no text is selected,
1121    /// an empty str slice will be returned.
1122    pub fn selected(&self) -> &str {
1123        let start = self.selection_start().min(self.selection_end());
1124        let end = self.selection_start().max(self.selection_end());
1125        &self.str()[start..end]
1126    }
1127
1128    /// Pushes the given str to the end of this buffer. If this
1129    /// would require the String to resize, it will be resized.
1130    /// This is automatically handled.
1131    pub fn push_str(&mut self, text: &str) {
1132        let current_len = unsafe { (*(self.0)).BufTextLen as usize };
1133        self.insert_chars(current_len, text);
1134    }
1135}
1136
1137/// This is a ZST which implements InputTextCallbackHandler as a passthrough.
1138///
1139/// If you do not set a callback handler, this will be used (but will never
1140/// actually run, since you will not have passed imgui any flags).
1141pub struct PassthroughCallback;
1142impl InputTextCallbackHandler for PassthroughCallback {}
1143
1144/// This is our default callback function that routes ImGui callbacks to our trait methods.
1145extern "C" fn callback(data: *mut sys::ImGuiInputTextCallbackData) -> c_int {
1146    let event_flag = unsafe { InputTextFlags::from_bits_truncate((*data).EventFlag) };
1147    let buffer_ptr = unsafe { (*data).UserData as *mut String };
1148
1149    // Handle different callback types
1150    match event_flag {
1151        InputTextFlags::CALLBACK_RESIZE => {
1152            unsafe {
1153                let requested_size = (*data).BufSize as usize;
1154                let buffer = &mut *buffer_ptr;
1155
1156                // Confirm that we ARE working with our string
1157                debug_assert_eq!(buffer.as_ptr() as *const _, (*data).Buf);
1158
1159                if requested_size > buffer.capacity() {
1160                    let additional_bytes = requested_size - buffer.len();
1161
1162                    // Reserve more data
1163                    buffer.reserve(additional_bytes);
1164
1165                    (*data).Buf = buffer.as_mut_ptr() as *mut _;
1166                    (*data).BufDirty = true;
1167                }
1168            }
1169        }
1170        _ => {
1171            // For other callbacks, we need the actual callback handler
1172            // This will only work for non-PassthroughCallback types
1173            // PassthroughCallback should never trigger these callbacks
1174        }
1175    }
1176
1177    0
1178}
1179
1180/// Builder for an input scalar widget.
1181#[must_use]
1182pub struct InputScalar<'ui, 'p, T, L, F = &'static str> {
1183    value: &'p mut T,
1184    label: L,
1185    step: Option<T>,
1186    step_fast: Option<T>,
1187    display_format: Option<F>,
1188    flags: InputTextFlags,
1189    ui: &'ui Ui,
1190}
1191
1192impl<'ui, 'p, L: AsRef<str>, T: DataTypeKind> InputScalar<'ui, 'p, T, L> {
1193    /// Constructs a new input scalar builder.
1194    #[doc(alias = "InputScalar")]
1195    pub fn new(ui: &'ui Ui, label: L, value: &'p mut T) -> Self {
1196        InputScalar {
1197            value,
1198            label,
1199            step: None,
1200            step_fast: None,
1201            display_format: None,
1202            flags: InputTextFlags::empty(),
1203            ui,
1204        }
1205    }
1206}
1207
1208impl<'ui, 'p, L: AsRef<str>, T: DataTypeKind, F: AsRef<str>> InputScalar<'ui, 'p, T, L, F> {
1209    /// Sets the display format using *a C-style printf string*
1210    pub fn display_format<F2: AsRef<str>>(
1211        self,
1212        display_format: F2,
1213    ) -> InputScalar<'ui, 'p, T, L, F2> {
1214        InputScalar {
1215            value: self.value,
1216            label: self.label,
1217            step: self.step,
1218            step_fast: self.step_fast,
1219            display_format: Some(display_format),
1220            flags: self.flags,
1221            ui: self.ui,
1222        }
1223    }
1224
1225    /// Sets the step value for the input
1226    #[inline]
1227    pub fn step(mut self, value: T) -> Self {
1228        self.step = Some(value);
1229        self
1230    }
1231
1232    /// Sets the fast step value for the input
1233    #[inline]
1234    pub fn step_fast(mut self, value: T) -> Self {
1235        self.step_fast = Some(value);
1236        self
1237    }
1238
1239    /// Sets the input text flags
1240    #[inline]
1241    pub fn flags(mut self, flags: InputTextFlags) -> Self {
1242        self.flags = flags;
1243        self
1244    }
1245
1246    /// Builds an input scalar that is bound to the given value.
1247    ///
1248    /// Returns true if the value was changed.
1249    pub fn build(self) -> bool {
1250        unsafe {
1251            let (one, two) = self
1252                .ui
1253                .scratch_txt_with_opt(self.label, self.display_format);
1254
1255            sys::igInputScalar(
1256                one,
1257                T::KIND as i32,
1258                self.value as *mut T as *mut c_void,
1259                self.step
1260                    .as_ref()
1261                    .map(|step| step as *const T)
1262                    .unwrap_or(ptr::null()) as *const c_void,
1263                self.step_fast
1264                    .as_ref()
1265                    .map(|step| step as *const T)
1266                    .unwrap_or(ptr::null()) as *const c_void,
1267                two,
1268                self.flags.bits() as i32,
1269            )
1270        }
1271    }
1272}
1273
1274/// Builder for an input scalar array widget.
1275#[must_use]
1276pub struct InputScalarN<'ui, 'p, T, L, F = &'static str> {
1277    values: &'p mut [T],
1278    label: L,
1279    step: Option<T>,
1280    step_fast: Option<T>,
1281    display_format: Option<F>,
1282    flags: InputTextFlags,
1283    ui: &'ui Ui,
1284}
1285
1286impl<'ui, 'p, L: AsRef<str>, T: DataTypeKind> InputScalarN<'ui, 'p, T, L> {
1287    /// Constructs a new input scalar array builder.
1288    #[doc(alias = "InputScalarN")]
1289    pub fn new(ui: &'ui Ui, label: L, values: &'p mut [T]) -> Self {
1290        InputScalarN {
1291            values,
1292            label,
1293            step: None,
1294            step_fast: None,
1295            display_format: None,
1296            flags: InputTextFlags::empty(),
1297            ui,
1298        }
1299    }
1300}
1301
1302impl<'ui, 'p, L: AsRef<str>, T: DataTypeKind, F: AsRef<str>> InputScalarN<'ui, 'p, T, L, F> {
1303    /// Sets the display format using *a C-style printf string*
1304    pub fn display_format<F2: AsRef<str>>(
1305        self,
1306        display_format: F2,
1307    ) -> InputScalarN<'ui, 'p, T, L, F2> {
1308        InputScalarN {
1309            values: self.values,
1310            label: self.label,
1311            step: self.step,
1312            step_fast: self.step_fast,
1313            display_format: Some(display_format),
1314            flags: self.flags,
1315            ui: self.ui,
1316        }
1317    }
1318
1319    /// Sets the step value for the input
1320    #[inline]
1321    pub fn step(mut self, value: T) -> Self {
1322        self.step = Some(value);
1323        self
1324    }
1325
1326    /// Sets the fast step value for the input
1327    #[inline]
1328    pub fn step_fast(mut self, value: T) -> Self {
1329        self.step_fast = Some(value);
1330        self
1331    }
1332
1333    /// Sets the input text flags
1334    #[inline]
1335    pub fn flags(mut self, flags: InputTextFlags) -> Self {
1336        self.flags = flags;
1337        self
1338    }
1339
1340    /// Builds a horizontal array of multiple input scalars attached to the given slice.
1341    ///
1342    /// Returns true if any value was changed.
1343    pub fn build(self) -> bool {
1344        unsafe {
1345            let (one, two) = self
1346                .ui
1347                .scratch_txt_with_opt(self.label, self.display_format);
1348
1349            sys::igInputScalarN(
1350                one,
1351                T::KIND as i32,
1352                self.values.as_mut_ptr() as *mut c_void,
1353                self.values.len() as i32,
1354                self.step
1355                    .as_ref()
1356                    .map(|step| step as *const T)
1357                    .unwrap_or(ptr::null()) as *const c_void,
1358                self.step_fast
1359                    .as_ref()
1360                    .map(|step| step as *const T)
1361                    .unwrap_or(ptr::null()) as *const c_void,
1362                two,
1363                self.flags.bits() as i32,
1364            )
1365        }
1366    }
1367}
1368
1369/// Builder for a 2-component float input widget.
1370#[must_use]
1371pub struct InputFloat2<'ui, 'p, L, F = &'static str> {
1372    label: L,
1373    value: &'p mut [f32; 2],
1374    display_format: Option<F>,
1375    flags: InputTextFlags,
1376    ui: &'ui Ui,
1377}
1378
1379impl<'ui, 'p, L: AsRef<str>> InputFloat2<'ui, 'p, L> {
1380    /// Constructs a new input float2 builder.
1381    #[doc(alias = "InputFloat2")]
1382    pub fn new(ui: &'ui Ui, label: L, value: &'p mut [f32; 2]) -> Self {
1383        InputFloat2 {
1384            label,
1385            value,
1386            display_format: None,
1387            flags: InputTextFlags::empty(),
1388            ui,
1389        }
1390    }
1391}
1392
1393impl<'ui, 'p, L: AsRef<str>, F: AsRef<str>> InputFloat2<'ui, 'p, L, F> {
1394    /// Sets the display format using *a C-style printf string*
1395    pub fn display_format<F2: AsRef<str>>(self, display_format: F2) -> InputFloat2<'ui, 'p, L, F2> {
1396        InputFloat2 {
1397            label: self.label,
1398            value: self.value,
1399            display_format: Some(display_format),
1400            flags: self.flags,
1401            ui: self.ui,
1402        }
1403    }
1404
1405    /// Sets the input text flags
1406    #[inline]
1407    pub fn flags(mut self, flags: InputTextFlags) -> Self {
1408        self.flags = flags;
1409        self
1410    }
1411
1412    /// Builds the input float2 widget.
1413    ///
1414    /// Returns true if any value was changed.
1415    pub fn build(self) -> bool {
1416        unsafe {
1417            let (one, two) = self
1418                .ui
1419                .scratch_txt_with_opt(self.label, self.display_format);
1420
1421            sys::igInputFloat2(one, self.value.as_mut_ptr(), two, self.flags.bits() as i32)
1422        }
1423    }
1424}
1425
1426/// Builder for a 3-component float input widget.
1427#[must_use]
1428pub struct InputFloat3<'ui, 'p, L, F = &'static str> {
1429    label: L,
1430    value: &'p mut [f32; 3],
1431    display_format: Option<F>,
1432    flags: InputTextFlags,
1433    ui: &'ui Ui,
1434}
1435
1436impl<'ui, 'p, L: AsRef<str>> InputFloat3<'ui, 'p, L> {
1437    /// Constructs a new input float3 builder.
1438    #[doc(alias = "InputFloat3")]
1439    pub fn new(ui: &'ui Ui, label: L, value: &'p mut [f32; 3]) -> Self {
1440        InputFloat3 {
1441            label,
1442            value,
1443            display_format: None,
1444            flags: InputTextFlags::empty(),
1445            ui,
1446        }
1447    }
1448}
1449
1450impl<'ui, 'p, L: AsRef<str>, F: AsRef<str>> InputFloat3<'ui, 'p, L, F> {
1451    /// Sets the display format using *a C-style printf string*
1452    pub fn display_format<F2: AsRef<str>>(self, display_format: F2) -> InputFloat3<'ui, 'p, L, F2> {
1453        InputFloat3 {
1454            label: self.label,
1455            value: self.value,
1456            display_format: Some(display_format),
1457            flags: self.flags,
1458            ui: self.ui,
1459        }
1460    }
1461
1462    /// Sets the input text flags
1463    #[inline]
1464    pub fn flags(mut self, flags: InputTextFlags) -> Self {
1465        self.flags = flags;
1466        self
1467    }
1468
1469    /// Builds the input float3 widget.
1470    ///
1471    /// Returns true if any value was changed.
1472    pub fn build(self) -> bool {
1473        unsafe {
1474            let (one, two) = self
1475                .ui
1476                .scratch_txt_with_opt(self.label, self.display_format);
1477
1478            sys::igInputFloat3(one, self.value.as_mut_ptr(), two, self.flags.bits() as i32)
1479        }
1480    }
1481}
1482
1483/// Builder for a 4-component float input widget.
1484#[must_use]
1485pub struct InputFloat4<'ui, 'p, L, F = &'static str> {
1486    label: L,
1487    value: &'p mut [f32; 4],
1488    display_format: Option<F>,
1489    flags: InputTextFlags,
1490    ui: &'ui Ui,
1491}
1492
1493impl<'ui, 'p, L: AsRef<str>> InputFloat4<'ui, 'p, L> {
1494    /// Constructs a new input float4 builder.
1495    #[doc(alias = "InputFloat4")]
1496    pub fn new(ui: &'ui Ui, label: L, value: &'p mut [f32; 4]) -> Self {
1497        InputFloat4 {
1498            label,
1499            value,
1500            display_format: None,
1501            flags: InputTextFlags::empty(),
1502            ui,
1503        }
1504    }
1505}
1506
1507impl<'ui, 'p, L: AsRef<str>, F: AsRef<str>> InputFloat4<'ui, 'p, L, F> {
1508    /// Sets the display format using *a C-style printf string*
1509    pub fn display_format<F2: AsRef<str>>(self, display_format: F2) -> InputFloat4<'ui, 'p, L, F2> {
1510        InputFloat4 {
1511            label: self.label,
1512            value: self.value,
1513            display_format: Some(display_format),
1514            flags: self.flags,
1515            ui: self.ui,
1516        }
1517    }
1518
1519    /// Sets the input text flags
1520    #[inline]
1521    pub fn flags(mut self, flags: InputTextFlags) -> Self {
1522        self.flags = flags;
1523        self
1524    }
1525
1526    /// Builds the input float4 widget.
1527    ///
1528    /// Returns true if any value was changed.
1529    pub fn build(self) -> bool {
1530        unsafe {
1531            let (one, two) = self
1532                .ui
1533                .scratch_txt_with_opt(self.label, self.display_format);
1534
1535            sys::igInputFloat4(one, self.value.as_mut_ptr(), two, self.flags.bits() as i32)
1536        }
1537    }
1538}
1539
1540/// Builder for a 2-component int input widget.
1541#[must_use]
1542pub struct InputInt2<'ui, 'p, L> {
1543    label: L,
1544    value: &'p mut [i32; 2],
1545    flags: InputTextFlags,
1546    ui: &'ui Ui,
1547}
1548
1549impl<'ui, 'p, L: AsRef<str>> InputInt2<'ui, 'p, L> {
1550    /// Constructs a new input int2 builder.
1551    #[doc(alias = "InputInt2")]
1552    pub fn new(ui: &'ui Ui, label: L, value: &'p mut [i32; 2]) -> Self {
1553        InputInt2 {
1554            label,
1555            value,
1556            flags: InputTextFlags::empty(),
1557            ui,
1558        }
1559    }
1560
1561    /// Sets the input text flags
1562    #[inline]
1563    pub fn flags(mut self, flags: InputTextFlags) -> Self {
1564        self.flags = flags;
1565        self
1566    }
1567
1568    /// Builds the input int2 widget.
1569    ///
1570    /// Returns true if any value was changed.
1571    pub fn build(self) -> bool {
1572        unsafe {
1573            let label_cstr = self.ui.scratch_txt(self.label);
1574
1575            sys::igInputInt2(
1576                label_cstr,
1577                self.value.as_mut_ptr(),
1578                self.flags.bits() as i32,
1579            )
1580        }
1581    }
1582}
1583
1584/// Builder for a 3-component int input widget.
1585#[must_use]
1586pub struct InputInt3<'ui, 'p, L> {
1587    label: L,
1588    value: &'p mut [i32; 3],
1589    flags: InputTextFlags,
1590    ui: &'ui Ui,
1591}
1592
1593impl<'ui, 'p, L: AsRef<str>> InputInt3<'ui, 'p, L> {
1594    /// Constructs a new input int3 builder.
1595    #[doc(alias = "InputInt3")]
1596    pub fn new(ui: &'ui Ui, label: L, value: &'p mut [i32; 3]) -> Self {
1597        InputInt3 {
1598            label,
1599            value,
1600            flags: InputTextFlags::empty(),
1601            ui,
1602        }
1603    }
1604
1605    /// Sets the input text flags
1606    #[inline]
1607    pub fn flags(mut self, flags: InputTextFlags) -> Self {
1608        self.flags = flags;
1609        self
1610    }
1611
1612    /// Builds the input int3 widget.
1613    ///
1614    /// Returns true if any value was changed.
1615    pub fn build(self) -> bool {
1616        unsafe {
1617            let label_cstr = self.ui.scratch_txt(self.label);
1618
1619            sys::igInputInt3(
1620                label_cstr,
1621                self.value.as_mut_ptr(),
1622                self.flags.bits() as i32,
1623            )
1624        }
1625    }
1626}
1627
1628/// Builder for a 4-component int input widget.
1629#[must_use]
1630pub struct InputInt4<'ui, 'p, L> {
1631    label: L,
1632    value: &'p mut [i32; 4],
1633    flags: InputTextFlags,
1634    ui: &'ui Ui,
1635}
1636
1637impl<'ui, 'p, L: AsRef<str>> InputInt4<'ui, 'p, L> {
1638    /// Constructs a new input int4 builder.
1639    #[doc(alias = "InputInt4")]
1640    pub fn new(ui: &'ui Ui, label: L, value: &'p mut [i32; 4]) -> Self {
1641        InputInt4 {
1642            label,
1643            value,
1644            flags: InputTextFlags::empty(),
1645            ui,
1646        }
1647    }
1648
1649    /// Sets the input text flags
1650    #[inline]
1651    pub fn flags(mut self, flags: InputTextFlags) -> Self {
1652        self.flags = flags;
1653        self
1654    }
1655
1656    /// Builds the input int4 widget.
1657    ///
1658    /// Returns true if any value was changed.
1659    pub fn build(self) -> bool {
1660        unsafe {
1661            let label_cstr = self.ui.scratch_txt(self.label);
1662
1663            sys::igInputInt4(
1664                label_cstr,
1665                self.value.as_mut_ptr(),
1666                self.flags.bits() as i32,
1667            )
1668        }
1669    }
1670}