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
15impl Ui {
17 #[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 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 #[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 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 #[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 #[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 #[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 pub fn input_int_config(&self, label: impl AsRef<str>) -> InputInt<'_> {
107 InputInt::new(self, label)
108 }
109
110 pub fn input_float_config(&self, label: impl AsRef<str>) -> InputFloat<'_> {
112 InputFloat::new(self, label)
113 }
114
115 pub fn input_double_config(&self, label: impl AsRef<str>) -> InputDouble<'_> {
117 InputDouble::new(self, label)
118 }
119
120 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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#[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#[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 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 pub fn flags(mut self, flags: InputTextFlags) -> Self {
344 self.flags = flags;
345 self
346 }
347
348 pub fn capacity_hint(mut self, cap: usize) -> Self {
350 self.capacity_hint = Some(cap);
351 self
352 }
353
354 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 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 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 pub fn read_only(mut self, read_only: bool) -> Self {
393 self.flags.set(InputTextFlags::READ_ONLY, read_only);
394 self
395 }
396
397 pub fn password(mut self, password: bool) -> Self {
399 self.flags.set(InputTextFlags::PASSWORD, password);
400 self
401 }
402
403 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 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 pub fn chars_decimal(mut self, decimal: bool) -> Self {
418 self.flags.set(InputTextFlags::CHARS_DECIMAL, decimal);
419 self
420 }
421
422 pub fn chars_hexadecimal(mut self, hex: bool) -> Self {
424 self.flags.set(InputTextFlags::CHARS_HEXADECIMAL, hex);
425 self
426 }
427
428 pub fn chars_uppercase(mut self, uppercase: bool) -> Self {
430 self.flags.set(InputTextFlags::CHARS_UPPERCASE, uppercase);
431 self
432 }
433
434 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
441impl<'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 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 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 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#[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#[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 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 pub fn flags(mut self, flags: InputTextFlags) -> Self {
630 self.flags = flags;
631 self
632 }
633
634 pub fn capacity_hint(mut self, cap: usize) -> Self {
636 self.capacity_hint = Some(cap);
637 self
638 }
639
640 pub fn read_only(mut self, read_only: bool) -> Self {
642 self.flags.set(InputTextFlags::READ_ONLY, read_only);
643 self
644 }
645
646 pub fn build(self) -> bool {
648 let label_ptr = self.ui.scratch_txt(&self.label);
649
650 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#[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 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 pub fn step(mut self, step: i32) -> Self {
733 self.step = step;
734 self
735 }
736
737 pub fn step_fast(mut self, step_fast: i32) -> Self {
739 self.step_fast = step_fast;
740 self
741 }
742
743 pub fn flags(mut self, flags: InputTextFlags) -> Self {
745 self.flags = flags;
746 self
747 }
748
749 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#[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 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 pub fn step(mut self, step: f32) -> Self {
791 self.step = step;
792 self
793 }
794
795 pub fn step_fast(mut self, step_fast: f32) -> Self {
797 self.step_fast = step_fast;
798 self
799 }
800
801 pub fn format(mut self, format: impl AsRef<str>) -> Self {
803 self.format = Some(format.as_ref().to_string());
804 self
805 }
806
807 pub fn flags(mut self, flags: InputTextFlags) -> Self {
809 self.flags = flags;
810 self
811 }
812
813 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#[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 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 pub fn step(mut self, step: f64) -> Self {
863 self.step = step;
864 self
865 }
866
867 pub fn step_fast(mut self, step_fast: f64) -> Self {
869 self.step_fast = step_fast;
870 self
871 }
872
873 pub fn format(mut self, format: impl AsRef<str>) -> Self {
875 self.format = Some(format.as_ref().to_string());
876 self
877 }
878
879 pub fn flags(mut self, flags: InputTextFlags) -> Self {
881 self.flags = flags;
882 self
883 }
884
885 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
908bitflags::bitflags! {
912 #[repr(transparent)]
914 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
915 pub struct InputTextCallback: u32 {
916 const COMPLETION = sys::ImGuiInputTextFlags_CallbackCompletion as u32;
918 const HISTORY = sys::ImGuiInputTextFlags_CallbackHistory as u32;
920 const ALWAYS = sys::ImGuiInputTextFlags_CallbackAlways as u32;
922 const CHAR_FILTER = sys::ImGuiInputTextFlags_CallbackCharFilter as u32;
924 const EDIT = sys::ImGuiInputTextFlags_CallbackEdit as u32;
927 }
928}
929
930#[derive(Debug, Clone, Copy, PartialEq, Eq)]
932pub enum HistoryDirection {
933 Up,
935 Down,
937}
938
939pub trait InputTextCallbackHandler {
944 fn char_filter(&mut self, _c: char) -> Option<char> {
949 None
950 }
951
952 fn on_completion(&mut self, _data: TextCallbackData) {}
956
957 fn on_history(&mut self, _direction: HistoryDirection, _data: TextCallbackData) {}
961
962 fn on_always(&mut self, _data: TextCallbackData) {}
966
967 fn on_edit(&mut self, _data: TextCallbackData) {}
971}
972
973pub struct TextCallbackData(*mut sys::ImGuiInputTextCallbackData);
977
978impl TextCallbackData {
979 unsafe fn new(data: *mut sys::ImGuiInputTextCallbackData) -> Self {
981 Self(data)
982 }
983
984 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 pub fn cursor_pos(&self) -> usize {
997 unsafe { (*(self.0)).CursorPos as usize }
998 }
999
1000 pub fn set_cursor_pos(&mut self, pos: usize) {
1002 unsafe {
1003 (*(self.0)).CursorPos = pos as i32;
1004 }
1005 }
1006
1007 pub fn selection_start(&self) -> usize {
1009 unsafe { (*(self.0)).SelectionStart as usize }
1010 }
1011
1012 pub fn set_selection_start(&mut self, pos: usize) {
1014 unsafe {
1015 (*(self.0)).SelectionStart = pos as i32;
1016 }
1017 }
1018
1019 pub fn selection_end(&self) -> usize {
1021 unsafe { (*(self.0)).SelectionEnd as usize }
1022 }
1023
1024 pub fn set_selection_end(&mut self, pos: usize) {
1026 unsafe {
1027 (*(self.0)).SelectionEnd = pos as i32;
1028 }
1029 }
1030
1031 pub fn select_all(&mut self) {
1033 unsafe {
1034 (*(self.0)).SelectionStart = 0;
1035 (*(self.0)).SelectionEnd = (*(self.0)).BufTextLen;
1036 }
1037 }
1038
1039 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 pub fn has_selection(&self) -> bool {
1049 unsafe { (*(self.0)).SelectionStart != (*(self.0)).SelectionEnd }
1050 }
1051
1052 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 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 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 pub fn set_dirty(&mut self) {
1115 unsafe {
1116 (*(self.0)).BufDirty = true;
1117 }
1118 }
1119
1120 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 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
1137pub struct PassthroughCallback;
1142impl InputTextCallbackHandler for PassthroughCallback {}
1143
1144extern "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 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 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 buffer.reserve(additional_bytes);
1164
1165 (*data).Buf = buffer.as_mut_ptr() as *mut _;
1166 (*data).BufDirty = true;
1167 }
1168 }
1169 }
1170 _ => {
1171 }
1175 }
1176
1177 0
1178}
1179
1180#[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 #[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 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 #[inline]
1227 pub fn step(mut self, value: T) -> Self {
1228 self.step = Some(value);
1229 self
1230 }
1231
1232 #[inline]
1234 pub fn step_fast(mut self, value: T) -> Self {
1235 self.step_fast = Some(value);
1236 self
1237 }
1238
1239 #[inline]
1241 pub fn flags(mut self, flags: InputTextFlags) -> Self {
1242 self.flags = flags;
1243 self
1244 }
1245
1246 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#[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 #[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 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 #[inline]
1321 pub fn step(mut self, value: T) -> Self {
1322 self.step = Some(value);
1323 self
1324 }
1325
1326 #[inline]
1328 pub fn step_fast(mut self, value: T) -> Self {
1329 self.step_fast = Some(value);
1330 self
1331 }
1332
1333 #[inline]
1335 pub fn flags(mut self, flags: InputTextFlags) -> Self {
1336 self.flags = flags;
1337 self
1338 }
1339
1340 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#[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 #[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 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 #[inline]
1407 pub fn flags(mut self, flags: InputTextFlags) -> Self {
1408 self.flags = flags;
1409 self
1410 }
1411
1412 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#[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 #[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 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 #[inline]
1464 pub fn flags(mut self, flags: InputTextFlags) -> Self {
1465 self.flags = flags;
1466 self
1467 }
1468
1469 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#[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 #[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 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 #[inline]
1521 pub fn flags(mut self, flags: InputTextFlags) -> Self {
1522 self.flags = flags;
1523 self
1524 }
1525
1526 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#[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 #[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 #[inline]
1563 pub fn flags(mut self, flags: InputTextFlags) -> Self {
1564 self.flags = flags;
1565 self
1566 }
1567
1568 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#[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 #[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 #[inline]
1607 pub fn flags(mut self, flags: InputTextFlags) -> Self {
1608 self.flags = flags;
1609 self
1610 }
1611
1612 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#[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 #[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 #[inline]
1651 pub fn flags(mut self, flags: InputTextFlags) -> Self {
1652 self.flags = flags;
1653 self
1654 }
1655
1656 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}