1#![allow(
28 clippy::cast_possible_truncation,
29 clippy::cast_sign_loss,
30 clippy::as_conversions
31)]
32use crate::InputTextFlags;
33use crate::internal::DataTypeKind;
34use crate::string::ImString;
35use crate::sys;
36use crate::ui::Ui;
37use std::ffi::{c_int, c_void};
38use std::marker::PhantomData;
39use std::ptr;
40
41impl Ui {
43 #[doc(alias = "InputText", alias = "InputTextWithHint")]
57 pub fn input_text<'p>(
58 &self,
59 label: impl AsRef<str>,
60 buf: &'p mut String,
61 ) -> InputText<'_, 'p, String, String, PassthroughCallback> {
62 InputText::new(self, label, buf)
63 }
64
65 pub fn input_text_imstr<'p>(
67 &self,
68 label: impl AsRef<str>,
69 buf: &'p mut ImString,
70 ) -> InputTextImStr<'_, 'p, String, String, PassthroughCallback> {
71 InputTextImStr::new(self, label, buf)
72 }
73
74 #[doc(alias = "InputTextMultiline")]
88 pub fn input_text_multiline<'p>(
89 &self,
90 label: impl AsRef<str>,
91 buf: &'p mut String,
92 size: impl Into<[f32; 2]>,
93 ) -> InputTextMultiline<'_, 'p> {
94 InputTextMultiline::new(self, label, buf, size)
95 }
96
97 pub fn input_text_multiline_imstr<'p>(
99 &self,
100 label: impl AsRef<str>,
101 buf: &'p mut ImString,
102 size: impl Into<[f32; 2]>,
103 ) -> InputTextMultilineImStr<'_, 'p> {
104 InputTextMultilineImStr::new(self, label, buf, size)
105 }
106
107 #[doc(alias = "InputInt")]
111 pub fn input_int(&self, label: impl AsRef<str>, value: &mut i32) -> bool {
112 self.input_int_config(label).build(value)
113 }
114
115 #[doc(alias = "InputFloat")]
119 pub fn input_float(&self, label: impl AsRef<str>, value: &mut f32) -> bool {
120 self.input_float_config(label).build(value)
121 }
122
123 #[doc(alias = "InputDouble")]
127 pub fn input_double(&self, label: impl AsRef<str>, value: &mut f64) -> bool {
128 self.input_double_config(label).build(value)
129 }
130
131 pub fn input_int_config(&self, label: impl AsRef<str>) -> InputInt<'_> {
133 InputInt::new(self, label)
134 }
135
136 pub fn input_float_config(&self, label: impl AsRef<str>) -> InputFloat<'_> {
138 InputFloat::new(self, label)
139 }
140
141 pub fn input_double_config(&self, label: impl AsRef<str>) -> InputDouble<'_> {
143 InputDouble::new(self, label)
144 }
145
146 #[doc(alias = "InputScalar")]
149 pub fn input_scalar<'p, L, T>(&self, label: L, value: &'p mut T) -> InputScalar<'_, 'p, T, L>
150 where
151 L: AsRef<str>,
152 T: DataTypeKind,
153 {
154 InputScalar::new(self, label, value)
155 }
156
157 #[doc(alias = "InputScalarN")]
161 pub fn input_scalar_n<'p, L, T>(
162 &self,
163 label: L,
164 values: &'p mut [T],
165 ) -> InputScalarN<'_, 'p, T, L>
166 where
167 L: AsRef<str>,
168 T: DataTypeKind,
169 {
170 InputScalarN::new(self, label, values)
171 }
172
173 #[doc(alias = "InputFloat2")]
175 pub fn input_float2<'p, L>(&self, label: L, value: &'p mut [f32; 2]) -> InputFloat2<'_, 'p, L>
176 where
177 L: AsRef<str>,
178 {
179 InputFloat2::new(self, label, value)
180 }
181
182 #[doc(alias = "InputFloat3")]
184 pub fn input_float3<'p, L>(&self, label: L, value: &'p mut [f32; 3]) -> InputFloat3<'_, 'p, L>
185 where
186 L: AsRef<str>,
187 {
188 InputFloat3::new(self, label, value)
189 }
190
191 #[doc(alias = "InputFloat4")]
193 pub fn input_float4<'p, L>(&self, label: L, value: &'p mut [f32; 4]) -> InputFloat4<'_, 'p, L>
194 where
195 L: AsRef<str>,
196 {
197 InputFloat4::new(self, label, value)
198 }
199
200 #[doc(alias = "InputInt2")]
202 pub fn input_int2<'p, L>(&self, label: L, value: &'p mut [i32; 2]) -> InputInt2<'_, 'p, L>
203 where
204 L: AsRef<str>,
205 {
206 InputInt2::new(self, label, value)
207 }
208
209 #[doc(alias = "InputInt3")]
211 pub fn input_int3<'p, L>(&self, label: L, value: &'p mut [i32; 3]) -> InputInt3<'_, 'p, L>
212 where
213 L: AsRef<str>,
214 {
215 InputInt3::new(self, label, value)
216 }
217
218 #[doc(alias = "InputInt4")]
220 pub fn input_int4<'p, L>(&self, label: L, value: &'p mut [i32; 4]) -> InputInt4<'_, 'p, L>
221 where
222 L: AsRef<str>,
223 {
224 InputInt4::new(self, label, value)
225 }
226}
227
228#[must_use]
230pub struct InputText<'ui, 'p, L = String, H = String, T = PassthroughCallback> {
231 ui: &'ui Ui,
232 label: L,
233 buf: &'p mut String,
234 flags: InputTextFlags,
235 capacity_hint: Option<usize>,
236 hint: Option<H>,
237 callback_handler: T,
238 _phantom: PhantomData<&'ui ()>,
239}
240
241#[must_use]
243pub struct InputTextImStr<'ui, 'p, L = String, H = String, T = PassthroughCallback> {
244 ui: &'ui Ui,
245 label: L,
246 buf: &'p mut ImString,
247 flags: InputTextFlags,
248 hint: Option<H>,
249 callback_handler: T,
250 _phantom: PhantomData<&'ui ()>,
251}
252
253impl<'ui, 'p> InputTextImStr<'ui, 'p, String, String, PassthroughCallback> {
254 pub fn new(ui: &'ui Ui, label: impl AsRef<str>, buf: &'p mut ImString) -> Self {
255 Self {
256 ui,
257 label: label.as_ref().to_string(),
258 buf,
259 flags: InputTextFlags::empty(),
260 hint: None,
261 callback_handler: PassthroughCallback,
262 _phantom: PhantomData,
263 }
264 }
265}
266
267impl<'ui, 'p, L: AsRef<str>, H: AsRef<str>, T> InputTextImStr<'ui, 'p, L, H, T> {
268 pub fn flags(mut self, flags: InputTextFlags) -> Self {
269 self.flags = flags;
270 self
271 }
272 pub fn hint<H2: AsRef<str>>(self, hint: H2) -> InputTextImStr<'ui, 'p, L, H2, T> {
273 InputTextImStr {
274 ui: self.ui,
275 label: self.label,
276 buf: self.buf,
277 flags: self.flags,
278 hint: Some(hint),
279 callback_handler: self.callback_handler,
280 _phantom: PhantomData,
281 }
282 }
283 pub fn read_only(mut self, ro: bool) -> Self {
284 self.flags.set(InputTextFlags::READ_ONLY, ro);
285 self
286 }
287 pub fn password(mut self, pw: bool) -> Self {
288 self.flags.set(InputTextFlags::PASSWORD, pw);
289 self
290 }
291 pub fn auto_select_all(mut self, v: bool) -> Self {
292 self.flags.set(InputTextFlags::AUTO_SELECT_ALL, v);
293 self
294 }
295 pub fn enter_returns_true(mut self, v: bool) -> Self {
296 self.flags.set(InputTextFlags::ENTER_RETURNS_TRUE, v);
297 self
298 }
299
300 pub fn build(self) -> bool {
301 let label_ptr = self.ui.scratch_txt(self.label.as_ref());
302 let hint_ptr = if let Some(ref hint) = self.hint {
303 self.ui.scratch_txt(hint.as_ref())
304 } else {
305 std::ptr::null()
306 };
307 let buf_ptr = self.buf.as_mut_ptr();
308 let buf_size = self.buf.capacity_with_nul();
309 let user_ptr = self.buf as *mut ImString as *mut c_void;
310
311 extern "C" fn resize_cb_imstr(data: *mut sys::ImGuiInputTextCallbackData) -> c_int {
312 unsafe {
313 if (*data).EventFlag == (sys::ImGuiInputTextFlags_CallbackResize as i32) {
314 let im = &mut *((*data).UserData as *mut ImString);
315 let requested = (*data).BufSize as usize;
316 if im.0.len() < requested {
317 im.0.resize(requested, 0);
318 }
319 (*data).Buf = im.as_mut_ptr();
320 (*data).BufDirty = true;
321 }
322 }
323 0
324 }
325
326 let flags = self.flags | InputTextFlags::CALLBACK_RESIZE;
327 let result = unsafe {
328 if hint_ptr.is_null() {
329 sys::igInputText(
330 label_ptr,
331 buf_ptr,
332 buf_size,
333 flags.bits(),
334 Some(resize_cb_imstr),
335 user_ptr,
336 )
337 } else {
338 sys::igInputTextWithHint(
339 label_ptr,
340 hint_ptr,
341 buf_ptr,
342 buf_size,
343 flags.bits(),
344 Some(resize_cb_imstr),
345 user_ptr,
346 )
347 }
348 };
349 unsafe { self.buf.refresh_len() };
351 result
352 }
353}
354impl<'ui, 'p> InputText<'ui, 'p, String, String, PassthroughCallback> {
355 pub fn new(ui: &'ui Ui, label: impl AsRef<str>, buf: &'p mut String) -> Self {
357 Self {
358 ui,
359 label: label.as_ref().to_string(),
360 buf,
361 flags: InputTextFlags::NONE,
362 capacity_hint: None,
363 hint: None,
364 callback_handler: PassthroughCallback,
365 _phantom: PhantomData,
366 }
367 }
368}
369
370impl<'ui, 'p, L, H, T> InputText<'ui, 'p, L, H, T> {
371 pub fn flags(mut self, flags: InputTextFlags) -> Self {
373 self.flags = flags;
374 self
375 }
376
377 pub fn capacity_hint(mut self, cap: usize) -> Self {
379 self.capacity_hint = Some(cap);
380 self
381 }
382
383 pub fn hint<H2: AsRef<str>>(self, hint: H2) -> InputText<'ui, 'p, L, H2, T> {
385 InputText {
386 ui: self.ui,
387 label: self.label,
388 buf: self.buf,
389 flags: self.flags,
390 capacity_hint: self.capacity_hint,
391 hint: Some(hint),
392 callback_handler: self.callback_handler,
393 _phantom: PhantomData,
394 }
395 }
396
397 pub fn callback<T2: InputTextCallbackHandler>(
399 self,
400 callback_handler: T2,
401 ) -> InputText<'ui, 'p, L, H, T2> {
402 InputText {
403 ui: self.ui,
404 label: self.label,
405 buf: self.buf,
406 flags: self.flags,
407 capacity_hint: self.capacity_hint,
408 hint: self.hint,
409 callback_handler,
410 _phantom: PhantomData,
411 }
412 }
413
414 pub fn callback_flags(mut self, callback_flags: InputTextCallback) -> Self {
416 self.flags |= InputTextFlags::from_bits_truncate(callback_flags.bits() as i32);
417 self
418 }
419
420 pub fn read_only(mut self, read_only: bool) -> Self {
422 self.flags.set(InputTextFlags::READ_ONLY, read_only);
423 self
424 }
425
426 pub fn password(mut self, password: bool) -> Self {
428 self.flags.set(InputTextFlags::PASSWORD, password);
429 self
430 }
431
432 pub fn auto_select_all(mut self, auto_select: bool) -> Self {
434 self.flags.set(InputTextFlags::AUTO_SELECT_ALL, auto_select);
435 self
436 }
437
438 pub fn enter_returns_true(mut self, enter_returns: bool) -> Self {
440 self.flags
441 .set(InputTextFlags::ENTER_RETURNS_TRUE, enter_returns);
442 self
443 }
444
445 pub fn chars_decimal(mut self, decimal: bool) -> Self {
447 self.flags.set(InputTextFlags::CHARS_DECIMAL, decimal);
448 self
449 }
450
451 pub fn chars_hexadecimal(mut self, hex: bool) -> Self {
453 self.flags.set(InputTextFlags::CHARS_HEXADECIMAL, hex);
454 self
455 }
456
457 pub fn chars_uppercase(mut self, uppercase: bool) -> Self {
459 self.flags.set(InputTextFlags::CHARS_UPPERCASE, uppercase);
460 self
461 }
462
463 pub fn chars_no_blank(mut self, no_blank: bool) -> Self {
465 self.flags.set(InputTextFlags::CHARS_NO_BLANK, no_blank);
466 self
467 }
468}
469
470impl<'ui, 'p, L, H, T> InputText<'ui, 'p, L, H, T>
472where
473 L: AsRef<str>,
474 H: AsRef<str>,
475 T: InputTextCallbackHandler,
476{
477 pub fn build(self) -> bool {
479 let label_ptr = self.ui.scratch_txt(self.label.as_ref());
480 let hint_ptr = if let Some(ref hint) = self.hint {
481 self.ui.scratch_txt(hint.as_ref())
482 } else {
483 std::ptr::null()
484 };
485
486 if let Some(extra) = self.capacity_hint {
487 let needed = extra.saturating_sub(self.buf.capacity().saturating_sub(self.buf.len()));
488 if needed > 0 {
489 self.buf.reserve(needed);
490 }
491 }
492
493 self.buf.push('\0');
495 let capacity = self.buf.capacity();
496 let buf_ptr = self.buf.as_mut_ptr() as *mut std::os::raw::c_char;
497
498 #[repr(C)]
499 struct UserData<T> {
500 container: *mut String,
501 handler: T,
502 }
503
504 extern "C" fn callback_router<T: InputTextCallbackHandler>(
505 data: *mut sys::ImGuiInputTextCallbackData,
506 ) -> c_int {
507 let event_flag = unsafe { InputTextFlags::from_bits_truncate((*data).EventFlag) };
508 let user = unsafe { &mut *((*data).UserData as *mut UserData<T>) };
509 match event_flag {
510 InputTextFlags::CALLBACK_RESIZE => unsafe {
511 let requested = (*data).BufSize as usize;
512 let s = &mut *user.container;
513 debug_assert_eq!(s.as_ptr() as *const _, (*data).Buf);
514 if requested > s.capacity() {
515 let additional = requested.saturating_sub(s.len());
516 s.reserve(additional);
517 (*data).Buf = s.as_mut_ptr() as *mut _;
518 (*data).BufDirty = true;
519 }
520 0
521 },
522 InputTextFlags::CALLBACK_COMPLETION => {
523 let info = unsafe { TextCallbackData::new(data) };
524 user.handler.on_completion(info);
525 0
526 }
527 InputTextFlags::CALLBACK_HISTORY => {
528 let key = unsafe { (*data).EventKey };
529 let dir = if key == sys::ImGuiKey_UpArrow {
530 HistoryDirection::Up
531 } else {
532 HistoryDirection::Down
533 };
534 let info = unsafe { TextCallbackData::new(data) };
535 user.handler.on_history(dir, info);
536 0
537 }
538 InputTextFlags::CALLBACK_ALWAYS => {
539 let info = unsafe { TextCallbackData::new(data) };
540 user.handler.on_always(info);
541 0
542 }
543 InputTextFlags::CALLBACK_EDIT => {
544 let info = unsafe { TextCallbackData::new(data) };
545 user.handler.on_edit(info);
546 0
547 }
548 InputTextFlags::CALLBACK_CHAR_FILTER => {
549 let ch =
550 unsafe { std::char::from_u32((*data).EventChar as u32).unwrap_or('\0') };
551 let new_ch = user.handler.char_filter(ch).map(|c| c as u32).unwrap_or(0);
552 unsafe {
553 (*data).EventChar = new_ch as u16;
554 }
555 0
556 }
557 _ => 0,
558 }
559 }
560
561 let mut user_data = UserData {
562 container: self.buf as *mut String,
563 handler: self.callback_handler,
564 };
565 let user_ptr = &mut user_data as *mut _ as *mut c_void;
566
567 let flags = self.flags | InputTextFlags::CALLBACK_RESIZE;
568 let result = unsafe {
569 if hint_ptr.is_null() {
570 sys::igInputText(
571 label_ptr,
572 buf_ptr,
573 capacity,
574 flags.bits(),
575 Some(callback_router::<T>),
576 user_ptr,
577 )
578 } else {
579 sys::igInputTextWithHint(
580 label_ptr,
581 hint_ptr,
582 buf_ptr,
583 capacity,
584 flags.bits(),
585 Some(callback_router::<T>),
586 user_ptr,
587 )
588 }
589 };
590
591 let cap = unsafe { (&*user_data.container).capacity() };
593 let slice = unsafe { std::slice::from_raw_parts((&*user_data.container).as_ptr(), cap) };
594 if let Some(len) = slice.iter().position(|&b| b == 0) {
595 unsafe { (&mut *user_data.container).as_mut_vec().set_len(len) };
596 }
597 result
598 }
599}
600
601#[derive(Debug)]
603#[must_use]
604pub struct InputTextMultiline<'ui, 'p> {
605 ui: &'ui Ui,
606 label: String,
607 buf: &'p mut String,
608 size: [f32; 2],
609 flags: InputTextFlags,
610 capacity_hint: Option<usize>,
611}
612
613#[derive(Debug)]
615#[must_use]
616pub struct InputTextMultilineImStr<'ui, 'p> {
617 ui: &'ui Ui,
618 label: String,
619 buf: &'p mut ImString,
620 size: [f32; 2],
621 flags: InputTextFlags,
622}
623
624impl<'ui, 'p> InputTextMultilineImStr<'ui, 'p> {
625 pub fn new(
626 ui: &'ui Ui,
627 label: impl AsRef<str>,
628 buf: &'p mut ImString,
629 size: impl Into<[f32; 2]>,
630 ) -> Self {
631 Self {
632 ui,
633 label: label.as_ref().to_string(),
634 buf,
635 size: size.into(),
636 flags: InputTextFlags::NONE,
637 }
638 }
639 pub fn flags(mut self, flags: InputTextFlags) -> Self {
640 self.flags = flags;
641 self
642 }
643 pub fn read_only(mut self, v: bool) -> Self {
644 self.flags.set(InputTextFlags::READ_ONLY, v);
645 self
646 }
647 pub fn build(self) -> bool {
648 let label_ptr = self.ui.scratch_txt(&self.label);
649 let buf_ptr = self.buf.as_mut_ptr();
650 let buf_size = self.buf.capacity_with_nul();
651 let user_ptr = self.buf as *mut ImString as *mut c_void;
652 let size_vec: sys::ImVec2 = self.size.into();
653
654 extern "C" fn resize_cb_imstr(data: *mut sys::ImGuiInputTextCallbackData) -> c_int {
655 unsafe {
656 if (*data).EventFlag == (sys::ImGuiInputTextFlags_CallbackResize as i32) {
657 let im = &mut *((*data).UserData as *mut ImString);
658 let requested = (*data).BufSize as usize;
659 if im.0.len() < requested {
660 im.0.resize(requested, 0);
661 }
662 (*data).Buf = im.as_mut_ptr();
663 (*data).BufDirty = true;
664 }
665 }
666 0
667 }
668
669 let flags = self.flags | InputTextFlags::CALLBACK_RESIZE;
670 let result = unsafe {
671 sys::igInputTextMultiline(
672 label_ptr,
673 buf_ptr,
674 buf_size,
675 size_vec,
676 flags.bits(),
677 Some(resize_cb_imstr),
678 user_ptr,
679 )
680 };
681 unsafe { self.buf.refresh_len() };
683 result
684 }
685}
686impl<'ui, 'p> InputTextMultiline<'ui, 'p> {
687 pub fn new(
689 ui: &'ui Ui,
690 label: impl AsRef<str>,
691 buf: &'p mut String,
692 size: impl Into<[f32; 2]>,
693 ) -> Self {
694 Self {
695 ui,
696 label: label.as_ref().to_string(),
697 buf,
698 size: size.into(),
699 flags: InputTextFlags::NONE,
700 capacity_hint: None,
701 }
702 }
703
704 pub fn flags(mut self, flags: InputTextFlags) -> Self {
706 self.flags = flags;
707 self
708 }
709
710 pub fn capacity_hint(mut self, cap: usize) -> Self {
712 self.capacity_hint = Some(cap);
713 self
714 }
715
716 pub fn read_only(mut self, read_only: bool) -> Self {
718 self.flags.set(InputTextFlags::READ_ONLY, read_only);
719 self
720 }
721
722 pub fn build(self) -> bool {
724 let label_ptr = self.ui.scratch_txt(&self.label);
725
726 if let Some(extra) = self.capacity_hint {
728 let needed = extra.saturating_sub(self.buf.capacity().saturating_sub(self.buf.len()));
729 if needed > 0 {
730 self.buf.reserve(needed);
731 }
732 }
733
734 self.buf.push('\0');
736 let capacity = self.buf.capacity();
737 let buf_ptr = self.buf.as_mut_ptr() as *mut std::os::raw::c_char;
738
739 #[repr(C)]
740 struct UserData {
741 container: *mut String,
742 }
743
744 extern "C" fn callback_router(data: *mut sys::ImGuiInputTextCallbackData) -> c_int {
745 let event_flag = unsafe { InputTextFlags::from_bits_truncate((*data).EventFlag) };
746 match event_flag {
747 InputTextFlags::CALLBACK_RESIZE => unsafe {
748 let requested = (*data).BufSize as usize;
749 let s = &mut *(&mut *((*data).UserData as *mut UserData)).container;
750 debug_assert_eq!(s.as_ptr() as *const _, (*data).Buf);
751 if requested > s.capacity() {
752 let additional = requested.saturating_sub(s.len());
753 s.reserve(additional);
754 (*data).Buf = s.as_mut_ptr() as *mut _;
755 (*data).BufDirty = true;
756 }
757 0
758 },
759 _ => 0,
760 }
761 }
762
763 let mut user_data = UserData {
764 container: self.buf as *mut String,
765 };
766 let user_ptr = &mut user_data as *mut _ as *mut c_void;
767
768 let size_vec: sys::ImVec2 = self.size.into();
769 let flags = self.flags | InputTextFlags::CALLBACK_RESIZE;
770 let result = unsafe {
771 sys::igInputTextMultiline(
772 label_ptr,
773 buf_ptr,
774 capacity,
775 size_vec,
776 flags.bits(),
777 Some(callback_router),
778 user_ptr,
779 )
780 };
781
782 let cap = unsafe { (&*user_data.container).capacity() };
784 let slice = unsafe { std::slice::from_raw_parts((&*user_data.container).as_ptr(), cap) };
785 if let Some(len) = slice.iter().position(|&b| b == 0) {
786 unsafe { (&mut *user_data.container).as_mut_vec().set_len(len) };
787 }
788 result
789 }
790
791 pub fn callback<T2: InputTextCallbackHandler>(
793 mut self,
794 callbacks: InputTextCallback,
795 handler: T2,
796 ) -> InputTextMultilineWithCb<'ui, 'p, T2> {
797 if callbacks.contains(InputTextCallback::ALWAYS) {
800 self.flags.insert(InputTextFlags::CALLBACK_ALWAYS);
801 }
802 if callbacks.contains(InputTextCallback::CHAR_FILTER) {
803 self.flags.insert(InputTextFlags::CALLBACK_CHAR_FILTER);
804 }
805 if callbacks.contains(InputTextCallback::EDIT) {
806 self.flags.insert(InputTextFlags::CALLBACK_EDIT);
807 }
808
809 InputTextMultilineWithCb {
810 ui: self.ui,
811 label: self.label,
812 buf: self.buf,
813 size: self.size,
814 flags: self.flags,
815 capacity_hint: self.capacity_hint,
816 handler,
817 }
818 }
819}
820
821pub struct InputTextMultilineWithCb<'ui, 'p, T> {
823 ui: &'ui Ui,
824 label: String,
825 buf: &'p mut String,
826 size: [f32; 2],
827 flags: InputTextFlags,
828 capacity_hint: Option<usize>,
829 handler: T,
830}
831
832impl<'ui, 'p, T: InputTextCallbackHandler> InputTextMultilineWithCb<'ui, 'p, T> {
833 pub fn build(self) -> bool {
834 let label_ptr = self.ui.scratch_txt(&self.label);
835
836 if let Some(extra) = self.capacity_hint {
837 let needed = extra.saturating_sub(self.buf.capacity().saturating_sub(self.buf.len()));
838 if needed > 0 {
839 self.buf.reserve(needed);
840 }
841 }
842
843 self.buf.push('\0');
845 let capacity = self.buf.capacity();
846 let buf_ptr = self.buf.as_mut_ptr() as *mut std::os::raw::c_char;
847
848 #[repr(C)]
849 struct UserData<T> {
850 container: *mut String,
851 handler: T,
852 }
853
854 extern "C" fn callback_router<T: InputTextCallbackHandler>(
855 data: *mut sys::ImGuiInputTextCallbackData,
856 ) -> c_int {
857 let event_flag = unsafe { InputTextFlags::from_bits_truncate((*data).EventFlag) };
858 let user = unsafe { &mut *((*data).UserData as *mut UserData<T>) };
859 match event_flag {
860 InputTextFlags::CALLBACK_RESIZE => unsafe {
861 let requested = (*data).BufSize as usize;
862 let s = &mut *user.container;
863 debug_assert_eq!(s.as_ptr() as *const _, (*data).Buf);
864 if requested > s.capacity() {
865 let additional = requested.saturating_sub(s.len());
866 s.reserve(additional);
867 (*data).Buf = s.as_mut_ptr() as *mut _;
868 (*data).BufDirty = true;
869 }
870 0
871 },
872 InputTextFlags::CALLBACK_COMPLETION => {
873 let info = unsafe { TextCallbackData::new(data) };
874 user.handler.on_completion(info);
875 0
876 }
877 InputTextFlags::CALLBACK_HISTORY => {
878 let key = unsafe { (*data).EventKey };
879 let dir = if key == sys::ImGuiKey_UpArrow {
880 HistoryDirection::Up
881 } else {
882 HistoryDirection::Down
883 };
884 let info = unsafe { TextCallbackData::new(data) };
885 user.handler.on_history(dir, info);
886 0
887 }
888 InputTextFlags::CALLBACK_ALWAYS => {
889 let info = unsafe { TextCallbackData::new(data) };
890 user.handler.on_always(info);
891 0
892 }
893 InputTextFlags::CALLBACK_EDIT => {
894 let info = unsafe { TextCallbackData::new(data) };
895 user.handler.on_edit(info);
896 0
897 }
898 InputTextFlags::CALLBACK_CHAR_FILTER => {
899 let ch =
900 unsafe { std::char::from_u32((*data).EventChar as u32).unwrap_or('\0') };
901 let new_ch = user.handler.char_filter(ch).map(|c| c as u32).unwrap_or(0);
902 unsafe {
903 (*data).EventChar = new_ch as u16;
904 }
905 0
906 }
907 _ => 0,
908 }
909 }
910
911 let mut user_data = UserData {
912 container: self.buf as *mut String,
913 handler: self.handler,
914 };
915 let user_ptr = &mut user_data as *mut _ as *mut c_void;
916
917 let size_vec: sys::ImVec2 = self.size.into();
918 let flags = self.flags | InputTextFlags::CALLBACK_RESIZE;
919 let result = unsafe {
920 sys::igInputTextMultiline(
921 label_ptr,
922 buf_ptr,
923 capacity,
924 size_vec,
925 flags.bits(),
926 Some(callback_router::<T>),
927 user_ptr,
928 )
929 };
930
931 let cap = unsafe { (&*user_data.container).capacity() };
933 let slice = unsafe { std::slice::from_raw_parts((&*user_data.container).as_ptr(), cap) };
934 if let Some(len) = slice.iter().position(|&b| b == 0) {
935 unsafe { (&mut *user_data.container).as_mut_vec().set_len(len) };
936 }
937 result
938 }
939}
940
941#[derive(Debug)]
943#[must_use]
944pub struct InputInt<'ui> {
945 ui: &'ui Ui,
946 label: String,
947 step: i32,
948 step_fast: i32,
949 flags: InputTextFlags,
950}
951
952impl<'ui> InputInt<'ui> {
953 pub fn new(ui: &'ui Ui, label: impl AsRef<str>) -> Self {
955 Self {
956 ui,
957 label: label.as_ref().to_string(),
958 step: 1,
959 step_fast: 100,
960 flags: InputTextFlags::NONE,
961 }
962 }
963
964 pub fn step(mut self, step: i32) -> Self {
966 self.step = step;
967 self
968 }
969
970 pub fn step_fast(mut self, step_fast: i32) -> Self {
972 self.step_fast = step_fast;
973 self
974 }
975
976 pub fn flags(mut self, flags: InputTextFlags) -> Self {
978 self.flags = flags;
979 self
980 }
981
982 pub fn build(self, value: &mut i32) -> bool {
984 let label_ptr = self.ui.scratch_txt(&self.label);
985 unsafe {
986 sys::igInputInt(
987 label_ptr,
988 value as *mut i32,
989 self.step,
990 self.step_fast,
991 self.flags.bits(),
992 )
993 }
994 }
995}
996
997#[derive(Debug)]
999#[must_use]
1000pub struct InputFloat<'ui> {
1001 ui: &'ui Ui,
1002 label: String,
1003 step: f32,
1004 step_fast: f32,
1005 format: Option<String>,
1006 flags: InputTextFlags,
1007}
1008
1009impl<'ui> InputFloat<'ui> {
1010 pub fn new(ui: &'ui Ui, label: impl AsRef<str>) -> Self {
1012 Self {
1013 ui,
1014 label: label.as_ref().to_string(),
1015 step: 0.0,
1016 step_fast: 0.0,
1017 format: None,
1018 flags: InputTextFlags::NONE,
1019 }
1020 }
1021
1022 pub fn step(mut self, step: f32) -> Self {
1024 self.step = step;
1025 self
1026 }
1027
1028 pub fn step_fast(mut self, step_fast: f32) -> Self {
1030 self.step_fast = step_fast;
1031 self
1032 }
1033
1034 pub fn format(mut self, format: impl AsRef<str>) -> Self {
1036 self.format = Some(format.as_ref().to_string());
1037 self
1038 }
1039
1040 pub fn flags(mut self, flags: InputTextFlags) -> Self {
1042 self.flags = flags;
1043 self
1044 }
1045
1046 pub fn build(self, value: &mut f32) -> bool {
1048 let label_ptr = self.ui.scratch_txt(&self.label);
1049 let format_ptr = self.ui.scratch_txt_opt(self.format.as_ref());
1050 let format_ptr = if format_ptr.is_null() {
1051 self.ui.scratch_txt("%.3f")
1052 } else {
1053 format_ptr
1054 };
1055
1056 unsafe {
1057 sys::igInputFloat(
1058 label_ptr,
1059 value as *mut f32,
1060 self.step,
1061 self.step_fast,
1062 format_ptr,
1063 self.flags.bits(),
1064 )
1065 }
1066 }
1067}
1068
1069#[derive(Debug)]
1071#[must_use]
1072pub struct InputDouble<'ui> {
1073 ui: &'ui Ui,
1074 label: String,
1075 step: f64,
1076 step_fast: f64,
1077 format: Option<String>,
1078 flags: InputTextFlags,
1079}
1080
1081impl<'ui> InputDouble<'ui> {
1082 pub fn new(ui: &'ui Ui, label: impl AsRef<str>) -> Self {
1084 Self {
1085 ui,
1086 label: label.as_ref().to_string(),
1087 step: 0.0,
1088 step_fast: 0.0,
1089 format: None,
1090 flags: InputTextFlags::NONE,
1091 }
1092 }
1093
1094 pub fn step(mut self, step: f64) -> Self {
1096 self.step = step;
1097 self
1098 }
1099
1100 pub fn step_fast(mut self, step_fast: f64) -> Self {
1102 self.step_fast = step_fast;
1103 self
1104 }
1105
1106 pub fn format(mut self, format: impl AsRef<str>) -> Self {
1108 self.format = Some(format.as_ref().to_string());
1109 self
1110 }
1111
1112 pub fn flags(mut self, flags: InputTextFlags) -> Self {
1114 self.flags = flags;
1115 self
1116 }
1117
1118 pub fn build(self, value: &mut f64) -> bool {
1120 let label_ptr = self.ui.scratch_txt(&self.label);
1121 let format_ptr = self.ui.scratch_txt_opt(self.format.as_ref());
1122 let format_ptr = if format_ptr.is_null() {
1123 self.ui.scratch_txt("%.6f")
1124 } else {
1125 format_ptr
1126 };
1127
1128 unsafe {
1129 sys::igInputDouble(
1130 label_ptr,
1131 value as *mut f64,
1132 self.step,
1133 self.step_fast,
1134 format_ptr,
1135 self.flags.bits(),
1136 )
1137 }
1138 }
1139}
1140
1141bitflags::bitflags! {
1145 #[repr(transparent)]
1147 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1148 pub struct InputTextCallback: u32 {
1149 const COMPLETION = sys::ImGuiInputTextFlags_CallbackCompletion as u32;
1151 const HISTORY = sys::ImGuiInputTextFlags_CallbackHistory as u32;
1153 const ALWAYS = sys::ImGuiInputTextFlags_CallbackAlways as u32;
1155 const CHAR_FILTER = sys::ImGuiInputTextFlags_CallbackCharFilter as u32;
1157 const EDIT = sys::ImGuiInputTextFlags_CallbackEdit as u32;
1160 }
1161}
1162
1163#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1165pub enum HistoryDirection {
1166 Up,
1168 Down,
1170}
1171
1172pub trait InputTextCallbackHandler {
1177 fn char_filter(&mut self, _c: char) -> Option<char> {
1182 None
1183 }
1184
1185 fn on_completion(&mut self, _data: TextCallbackData) {}
1189
1190 fn on_history(&mut self, _direction: HistoryDirection, _data: TextCallbackData) {}
1194
1195 fn on_always(&mut self, _data: TextCallbackData) {}
1199
1200 fn on_edit(&mut self, _data: TextCallbackData) {}
1204}
1205
1206pub struct TextCallbackData(*mut sys::ImGuiInputTextCallbackData);
1210
1211impl TextCallbackData {
1212 unsafe fn new(data: *mut sys::ImGuiInputTextCallbackData) -> Self {
1214 Self(data)
1215 }
1216
1217 pub fn str(&self) -> &str {
1219 unsafe {
1220 std::str::from_utf8(std::slice::from_raw_parts(
1221 (*(self.0)).Buf as *const _,
1222 (*(self.0)).BufTextLen as usize,
1223 ))
1224 .expect("internal imgui error -- it boofed a utf8")
1225 }
1226 }
1227
1228 pub fn cursor_pos(&self) -> usize {
1230 unsafe { (*(self.0)).CursorPos as usize }
1231 }
1232
1233 pub fn set_cursor_pos(&mut self, pos: usize) {
1235 unsafe {
1236 (*(self.0)).CursorPos = pos as i32;
1237 }
1238 }
1239
1240 pub fn selection_start(&self) -> usize {
1242 unsafe { (*(self.0)).SelectionStart as usize }
1243 }
1244
1245 pub fn set_selection_start(&mut self, pos: usize) {
1247 unsafe {
1248 (*(self.0)).SelectionStart = pos as i32;
1249 }
1250 }
1251
1252 pub fn selection_end(&self) -> usize {
1254 unsafe { (*(self.0)).SelectionEnd as usize }
1255 }
1256
1257 pub fn set_selection_end(&mut self, pos: usize) {
1259 unsafe {
1260 (*(self.0)).SelectionEnd = pos as i32;
1261 }
1262 }
1263
1264 pub fn select_all(&mut self) {
1266 unsafe {
1267 (*(self.0)).SelectionStart = 0;
1268 (*(self.0)).SelectionEnd = (*(self.0)).BufTextLen;
1269 }
1270 }
1271
1272 pub fn clear_selection(&mut self) {
1274 unsafe {
1275 (*(self.0)).SelectionStart = (*(self.0)).CursorPos;
1276 (*(self.0)).SelectionEnd = (*(self.0)).CursorPos;
1277 }
1278 }
1279
1280 pub fn has_selection(&self) -> bool {
1282 unsafe { (*(self.0)).SelectionStart != (*(self.0)).SelectionEnd }
1283 }
1284
1285 pub fn remove_chars(&mut self, pos: usize, bytes_count: usize) {
1287 unsafe {
1288 sys::ImGuiInputTextCallbackData_DeleteChars(self.0, pos as i32, bytes_count as i32);
1289 }
1290 }
1291
1292 pub fn insert_chars(&mut self, pos: usize, text: &str) {
1294 let text_cstr = format!("{}\0", text);
1295 unsafe {
1296 sys::ImGuiInputTextCallbackData_InsertChars(
1297 self.0,
1298 pos as i32,
1299 text_cstr.as_ptr() as *const std::os::raw::c_char,
1300 text_cstr.as_ptr().add(text.len()) as *const std::os::raw::c_char,
1301 );
1302 }
1303 }
1304
1305 pub unsafe fn str_as_bytes_mut(&mut self) -> &mut [u8] {
1325 unsafe {
1326 let str = std::str::from_utf8_mut(std::slice::from_raw_parts_mut(
1327 (*(self.0)).Buf as *const _ as *mut _,
1328 (*(self.0)).BufTextLen as usize,
1329 ))
1330 .expect("internal imgui error -- it boofed a utf8");
1331
1332 str.as_bytes_mut()
1333 }
1334 }
1335
1336 pub fn set_dirty(&mut self) {
1348 unsafe {
1349 (*(self.0)).BufDirty = true;
1350 }
1351 }
1352
1353 pub fn selected(&self) -> &str {
1356 let start = self.selection_start().min(self.selection_end());
1357 let end = self.selection_start().max(self.selection_end());
1358 &self.str()[start..end]
1359 }
1360
1361 pub fn push_str(&mut self, text: &str) {
1365 let current_len = unsafe { (*(self.0)).BufTextLen as usize };
1366 self.insert_chars(current_len, text);
1367 }
1368}
1369
1370pub struct PassthroughCallback;
1375impl InputTextCallbackHandler for PassthroughCallback {}
1376
1377extern "C" fn callback(data: *mut sys::ImGuiInputTextCallbackData) -> c_int {
1379 let event_flag = unsafe { InputTextFlags::from_bits_truncate((*data).EventFlag) };
1380 let buffer_ptr = unsafe { (*data).UserData as *mut String };
1381
1382 match event_flag {
1384 InputTextFlags::CALLBACK_RESIZE => {
1385 unsafe {
1386 let requested_size = (*data).BufSize as usize;
1387 let buffer = &mut *buffer_ptr;
1388
1389 debug_assert_eq!(buffer.as_ptr() as *const _, (*data).Buf);
1391
1392 if requested_size > buffer.capacity() {
1393 let additional_bytes = requested_size - buffer.len();
1394
1395 buffer.reserve(additional_bytes);
1397
1398 (*data).Buf = buffer.as_mut_ptr() as *mut _;
1399 (*data).BufDirty = true;
1400 }
1401 }
1402 }
1403 _ => {
1404 }
1408 }
1409
1410 0
1411}
1412
1413#[must_use]
1415pub struct InputScalar<'ui, 'p, T, L, F = &'static str> {
1416 value: &'p mut T,
1417 label: L,
1418 step: Option<T>,
1419 step_fast: Option<T>,
1420 display_format: Option<F>,
1421 flags: InputTextFlags,
1422 ui: &'ui Ui,
1423}
1424
1425impl<'ui, 'p, L: AsRef<str>, T: DataTypeKind> InputScalar<'ui, 'p, T, L> {
1426 #[doc(alias = "InputScalar")]
1428 pub fn new(ui: &'ui Ui, label: L, value: &'p mut T) -> Self {
1429 InputScalar {
1430 value,
1431 label,
1432 step: None,
1433 step_fast: None,
1434 display_format: None,
1435 flags: InputTextFlags::empty(),
1436 ui,
1437 }
1438 }
1439}
1440
1441impl<'ui, 'p, L: AsRef<str>, T: DataTypeKind, F: AsRef<str>> InputScalar<'ui, 'p, T, L, F> {
1442 pub fn display_format<F2: AsRef<str>>(
1444 self,
1445 display_format: F2,
1446 ) -> InputScalar<'ui, 'p, T, L, F2> {
1447 InputScalar {
1448 value: self.value,
1449 label: self.label,
1450 step: self.step,
1451 step_fast: self.step_fast,
1452 display_format: Some(display_format),
1453 flags: self.flags,
1454 ui: self.ui,
1455 }
1456 }
1457
1458 #[inline]
1460 pub fn step(mut self, value: T) -> Self {
1461 self.step = Some(value);
1462 self
1463 }
1464
1465 #[inline]
1467 pub fn step_fast(mut self, value: T) -> Self {
1468 self.step_fast = Some(value);
1469 self
1470 }
1471
1472 #[inline]
1474 pub fn flags(mut self, flags: InputTextFlags) -> Self {
1475 self.flags = flags;
1476 self
1477 }
1478
1479 pub fn build(self) -> bool {
1483 unsafe {
1484 let (one, two) = self
1485 .ui
1486 .scratch_txt_with_opt(self.label, self.display_format);
1487
1488 sys::igInputScalar(
1489 one,
1490 T::KIND as i32,
1491 self.value as *mut T as *mut c_void,
1492 self.step
1493 .as_ref()
1494 .map(|step| step as *const T)
1495 .unwrap_or(ptr::null()) as *const c_void,
1496 self.step_fast
1497 .as_ref()
1498 .map(|step| step as *const T)
1499 .unwrap_or(ptr::null()) as *const c_void,
1500 two,
1501 self.flags.bits() as i32,
1502 )
1503 }
1504 }
1505}
1506
1507#[must_use]
1509pub struct InputScalarN<'ui, 'p, T, L, F = &'static str> {
1510 values: &'p mut [T],
1511 label: L,
1512 step: Option<T>,
1513 step_fast: Option<T>,
1514 display_format: Option<F>,
1515 flags: InputTextFlags,
1516 ui: &'ui Ui,
1517}
1518
1519impl<'ui, 'p, L: AsRef<str>, T: DataTypeKind> InputScalarN<'ui, 'p, T, L> {
1520 #[doc(alias = "InputScalarN")]
1522 pub fn new(ui: &'ui Ui, label: L, values: &'p mut [T]) -> Self {
1523 InputScalarN {
1524 values,
1525 label,
1526 step: None,
1527 step_fast: None,
1528 display_format: None,
1529 flags: InputTextFlags::empty(),
1530 ui,
1531 }
1532 }
1533}
1534
1535impl<'ui, 'p, L: AsRef<str>, T: DataTypeKind, F: AsRef<str>> InputScalarN<'ui, 'p, T, L, F> {
1536 pub fn display_format<F2: AsRef<str>>(
1538 self,
1539 display_format: F2,
1540 ) -> InputScalarN<'ui, 'p, T, L, F2> {
1541 InputScalarN {
1542 values: self.values,
1543 label: self.label,
1544 step: self.step,
1545 step_fast: self.step_fast,
1546 display_format: Some(display_format),
1547 flags: self.flags,
1548 ui: self.ui,
1549 }
1550 }
1551
1552 #[inline]
1554 pub fn step(mut self, value: T) -> Self {
1555 self.step = Some(value);
1556 self
1557 }
1558
1559 #[inline]
1561 pub fn step_fast(mut self, value: T) -> Self {
1562 self.step_fast = Some(value);
1563 self
1564 }
1565
1566 #[inline]
1568 pub fn flags(mut self, flags: InputTextFlags) -> Self {
1569 self.flags = flags;
1570 self
1571 }
1572
1573 pub fn build(self) -> bool {
1577 unsafe {
1578 let (one, two) = self
1579 .ui
1580 .scratch_txt_with_opt(self.label, self.display_format);
1581
1582 sys::igInputScalarN(
1583 one,
1584 T::KIND as i32,
1585 self.values.as_mut_ptr() as *mut c_void,
1586 self.values.len() as i32,
1587 self.step
1588 .as_ref()
1589 .map(|step| step as *const T)
1590 .unwrap_or(ptr::null()) as *const c_void,
1591 self.step_fast
1592 .as_ref()
1593 .map(|step| step as *const T)
1594 .unwrap_or(ptr::null()) as *const c_void,
1595 two,
1596 self.flags.bits() as i32,
1597 )
1598 }
1599 }
1600}
1601
1602#[must_use]
1604pub struct InputFloat2<'ui, 'p, L, F = &'static str> {
1605 label: L,
1606 value: &'p mut [f32; 2],
1607 display_format: Option<F>,
1608 flags: InputTextFlags,
1609 ui: &'ui Ui,
1610}
1611
1612impl<'ui, 'p, L: AsRef<str>> InputFloat2<'ui, 'p, L> {
1613 #[doc(alias = "InputFloat2")]
1615 pub fn new(ui: &'ui Ui, label: L, value: &'p mut [f32; 2]) -> Self {
1616 InputFloat2 {
1617 label,
1618 value,
1619 display_format: None,
1620 flags: InputTextFlags::empty(),
1621 ui,
1622 }
1623 }
1624}
1625
1626impl<'ui, 'p, L: AsRef<str>, F: AsRef<str>> InputFloat2<'ui, 'p, L, F> {
1627 pub fn display_format<F2: AsRef<str>>(self, display_format: F2) -> InputFloat2<'ui, 'p, L, F2> {
1629 InputFloat2 {
1630 label: self.label,
1631 value: self.value,
1632 display_format: Some(display_format),
1633 flags: self.flags,
1634 ui: self.ui,
1635 }
1636 }
1637
1638 #[inline]
1640 pub fn flags(mut self, flags: InputTextFlags) -> Self {
1641 self.flags = flags;
1642 self
1643 }
1644
1645 pub fn build(self) -> bool {
1649 unsafe {
1650 let (one, two) = self
1651 .ui
1652 .scratch_txt_with_opt(self.label, self.display_format);
1653
1654 sys::igInputFloat2(one, self.value.as_mut_ptr(), two, self.flags.bits() as i32)
1655 }
1656 }
1657}
1658
1659#[must_use]
1661pub struct InputFloat3<'ui, 'p, L, F = &'static str> {
1662 label: L,
1663 value: &'p mut [f32; 3],
1664 display_format: Option<F>,
1665 flags: InputTextFlags,
1666 ui: &'ui Ui,
1667}
1668
1669impl<'ui, 'p, L: AsRef<str>> InputFloat3<'ui, 'p, L> {
1670 #[doc(alias = "InputFloat3")]
1672 pub fn new(ui: &'ui Ui, label: L, value: &'p mut [f32; 3]) -> Self {
1673 InputFloat3 {
1674 label,
1675 value,
1676 display_format: None,
1677 flags: InputTextFlags::empty(),
1678 ui,
1679 }
1680 }
1681}
1682
1683impl<'ui, 'p, L: AsRef<str>, F: AsRef<str>> InputFloat3<'ui, 'p, L, F> {
1684 pub fn display_format<F2: AsRef<str>>(self, display_format: F2) -> InputFloat3<'ui, 'p, L, F2> {
1686 InputFloat3 {
1687 label: self.label,
1688 value: self.value,
1689 display_format: Some(display_format),
1690 flags: self.flags,
1691 ui: self.ui,
1692 }
1693 }
1694
1695 #[inline]
1697 pub fn flags(mut self, flags: InputTextFlags) -> Self {
1698 self.flags = flags;
1699 self
1700 }
1701
1702 pub fn build(self) -> bool {
1706 unsafe {
1707 let (one, two) = self
1708 .ui
1709 .scratch_txt_with_opt(self.label, self.display_format);
1710
1711 sys::igInputFloat3(one, self.value.as_mut_ptr(), two, self.flags.bits() as i32)
1712 }
1713 }
1714}
1715
1716#[must_use]
1718pub struct InputFloat4<'ui, 'p, L, F = &'static str> {
1719 label: L,
1720 value: &'p mut [f32; 4],
1721 display_format: Option<F>,
1722 flags: InputTextFlags,
1723 ui: &'ui Ui,
1724}
1725
1726impl<'ui, 'p, L: AsRef<str>> InputFloat4<'ui, 'p, L> {
1727 #[doc(alias = "InputFloat4")]
1729 pub fn new(ui: &'ui Ui, label: L, value: &'p mut [f32; 4]) -> Self {
1730 InputFloat4 {
1731 label,
1732 value,
1733 display_format: None,
1734 flags: InputTextFlags::empty(),
1735 ui,
1736 }
1737 }
1738}
1739
1740impl<'ui, 'p, L: AsRef<str>, F: AsRef<str>> InputFloat4<'ui, 'p, L, F> {
1741 pub fn display_format<F2: AsRef<str>>(self, display_format: F2) -> InputFloat4<'ui, 'p, L, F2> {
1743 InputFloat4 {
1744 label: self.label,
1745 value: self.value,
1746 display_format: Some(display_format),
1747 flags: self.flags,
1748 ui: self.ui,
1749 }
1750 }
1751
1752 #[inline]
1754 pub fn flags(mut self, flags: InputTextFlags) -> Self {
1755 self.flags = flags;
1756 self
1757 }
1758
1759 pub fn build(self) -> bool {
1763 unsafe {
1764 let (one, two) = self
1765 .ui
1766 .scratch_txt_with_opt(self.label, self.display_format);
1767
1768 sys::igInputFloat4(one, self.value.as_mut_ptr(), two, self.flags.bits() as i32)
1769 }
1770 }
1771}
1772
1773#[must_use]
1775pub struct InputInt2<'ui, 'p, L> {
1776 label: L,
1777 value: &'p mut [i32; 2],
1778 flags: InputTextFlags,
1779 ui: &'ui Ui,
1780}
1781
1782impl<'ui, 'p, L: AsRef<str>> InputInt2<'ui, 'p, L> {
1783 #[doc(alias = "InputInt2")]
1785 pub fn new(ui: &'ui Ui, label: L, value: &'p mut [i32; 2]) -> Self {
1786 InputInt2 {
1787 label,
1788 value,
1789 flags: InputTextFlags::empty(),
1790 ui,
1791 }
1792 }
1793
1794 #[inline]
1796 pub fn flags(mut self, flags: InputTextFlags) -> Self {
1797 self.flags = flags;
1798 self
1799 }
1800
1801 pub fn build(self) -> bool {
1805 unsafe {
1806 let label_cstr = self.ui.scratch_txt(self.label);
1807
1808 sys::igInputInt2(
1809 label_cstr,
1810 self.value.as_mut_ptr(),
1811 self.flags.bits() as i32,
1812 )
1813 }
1814 }
1815}
1816
1817#[must_use]
1819pub struct InputInt3<'ui, 'p, L> {
1820 label: L,
1821 value: &'p mut [i32; 3],
1822 flags: InputTextFlags,
1823 ui: &'ui Ui,
1824}
1825
1826impl<'ui, 'p, L: AsRef<str>> InputInt3<'ui, 'p, L> {
1827 #[doc(alias = "InputInt3")]
1829 pub fn new(ui: &'ui Ui, label: L, value: &'p mut [i32; 3]) -> Self {
1830 InputInt3 {
1831 label,
1832 value,
1833 flags: InputTextFlags::empty(),
1834 ui,
1835 }
1836 }
1837
1838 #[inline]
1840 pub fn flags(mut self, flags: InputTextFlags) -> Self {
1841 self.flags = flags;
1842 self
1843 }
1844
1845 pub fn build(self) -> bool {
1849 unsafe {
1850 let label_cstr = self.ui.scratch_txt(self.label);
1851
1852 sys::igInputInt3(
1853 label_cstr,
1854 self.value.as_mut_ptr(),
1855 self.flags.bits() as i32,
1856 )
1857 }
1858 }
1859}
1860
1861#[must_use]
1863pub struct InputInt4<'ui, 'p, L> {
1864 label: L,
1865 value: &'p mut [i32; 4],
1866 flags: InputTextFlags,
1867 ui: &'ui Ui,
1868}
1869
1870impl<'ui, 'p, L: AsRef<str>> InputInt4<'ui, 'p, L> {
1871 #[doc(alias = "InputInt4")]
1873 pub fn new(ui: &'ui Ui, label: L, value: &'p mut [i32; 4]) -> Self {
1874 InputInt4 {
1875 label,
1876 value,
1877 flags: InputTextFlags::empty(),
1878 ui,
1879 }
1880 }
1881
1882 #[inline]
1884 pub fn flags(mut self, flags: InputTextFlags) -> Self {
1885 self.flags = flags;
1886 self
1887 }
1888
1889 pub fn build(self) -> bool {
1893 unsafe {
1894 let label_cstr = self.ui.scratch_txt(self.label);
1895
1896 sys::igInputInt4(
1897 label_cstr,
1898 self.value.as_mut_ptr(),
1899 self.flags.bits() as i32,
1900 )
1901 }
1902 }
1903}