diff --git a/examples/test_window_impl.rs b/examples/test_window_impl.rs index 1856363..a4b83d2 100644 --- a/examples/test_window_impl.rs +++ b/examples/test_window_impl.rs @@ -33,6 +33,8 @@ struct State { bg_alpha: f32, wrap_width: f32, buf: String, + text: String, + int: i32, auto_resize_state: AutoResizeState, file_menu: FileMenuState } @@ -42,6 +44,10 @@ impl Default for State { let mut buf = "日本語".to_owned(); buf.extend(repeat('\0').take(32)); buf.truncate(32); + let mut text = String::with_capacity(128); + text.push_str("Hello, world!"); + let remaining = text.capacity() - text.len(); + text.extend(repeat('\0').take(remaining)); State { clear_color: (114.0 / 255.0, 144.0 / 255.0, 154.0 / 255.0, 1.0), show_app_metrics: false, @@ -64,6 +70,8 @@ impl Default for State { bg_alpha: 0.65, wrap_width: 200.0, buf: buf, + text: text, + int: 123, auto_resize_state: Default::default(), file_menu: Default::default() } @@ -281,6 +289,10 @@ fn show_test_window<'a>(ui: &Ui<'a>, state: &mut State, opened: &mut bool) { ui.text(im_str!("Kanjis: 日本語 (nihongo)")); ui.input_text(im_str!("UTF-8 input"), &mut state.buf).build(); }); + ui.separator(); + ui.label_text(im_str!("label"), im_str!("Value")); + ui.input_text(im_str!("input text"), &mut state.text).build(); + ui.input_int(im_str!("input int"), &mut state.int).build(); } }) } diff --git a/src/input.rs b/src/input.rs index 3948e54..aeb85fc 100644 --- a/src/input.rs +++ b/src/input.rs @@ -15,6 +15,123 @@ use super::{ ImStr }; +macro_rules! impl_text_flags { + ($T:ident) => { + #[inline] + pub fn flags(self, flags: ImGuiInputTextFlags) -> Self { + $T { + flags: flags, + .. self + } + } + + #[inline] + pub fn chars_decimal(self, value: bool) -> Self { + $T { + flags: self.flags.with(ImGuiInputTextFlags_CharsDecimal, value), + .. self + } + } + + #[inline] + pub fn chars_hexadecimal(self, value: bool) -> Self { + $T { + flags: self.flags.with(ImGuiInputTextFlags_CharsHexadecimal, value), + .. self + } + } + + #[inline] + pub fn chars_uppercase(self, value: bool) -> Self { + $T { + flags: self.flags.with(ImGuiInputTextFlags_CharsUppercase, value), + .. self + } + } + + #[inline] + pub fn chars_noblank(self, value: bool) -> Self { + $T { + flags: self.flags.with(ImGuiInputTextFlags_CharsNoBlank, value), + .. self + } + } + + #[inline] + pub fn auto_select_all(self, value: bool) -> Self { + $T { + flags: self.flags.with(ImGuiInputTextFlags_AutoSelectAll, value), + .. self + } + } + + #[inline] + pub fn enter_returns_true(self, value: bool) -> Self { + $T { + flags: self.flags.with(ImGuiInputTextFlags_EnterReturnsTrue, value), + .. self + } + } + + #[inline] + pub fn callback_completion(self, value: bool) -> Self { + $T { + flags: self.flags.with(ImGuiInputTextFlags_CallbackCompletion, value), + .. self + } + } + + #[inline] + pub fn callback_history(self, value: bool) -> Self { + $T { + flags: self.flags.with(ImGuiInputTextFlags_CallbackHistory, value), + .. self + } + } + + #[inline] + pub fn callback_always(self, value: bool) -> Self { + $T { + flags: self.flags.with(ImGuiInputTextFlags_CallbackAlways, value), + .. self + } + } + + #[inline] + pub fn callback_char_filter(self, value: bool) -> Self { + $T { + flags: self.flags.with(ImGuiInputTextFlags_CallbackCharFilter, value), + .. self + } + } + + #[inline] + pub fn allow_tab_input(self, value: bool) -> Self { + $T { + flags: self.flags.with(ImGuiInputTextFlags_AllowTabInput, value), + .. self + } + } + + #[inline] + pub fn no_horizontal_scroll(self, value: bool) -> Self { + $T { + flags: self.flags.with(ImGuiInputTextFlags_NoHorizontalScroll, value), + .. self + } + } + + #[inline] + pub fn always_insert_mode(self, value: bool) -> Self { + $T { + flags: self.flags.with(ImGuiInputTextFlags_AlwaysInsertMode, value), + .. self + } + } + + } +} + #[must_use] pub struct InputText<'ui, 'p> { label: ImStr<'p>, @@ -33,117 +150,7 @@ impl<'ui, 'p> InputText<'ui, 'p> { } } - #[inline] - pub fn flags(self, flags: ImGuiInputTextFlags) -> Self { - InputText { - flags: flags, - .. self - } - } - - #[inline] - pub fn chars_decimal(self, value: bool) -> Self { - InputText { - flags: self.flags.with(ImGuiInputTextFlags_CharsDecimal, value), - .. self - } - } - - #[inline] - pub fn chars_hexadecimal(self, value: bool) -> Self { - InputText { - flags: self.flags.with(ImGuiInputTextFlags_CharsHexadecimal, value), - .. self - } - } - - #[inline] - pub fn chars_uppercase(self, value: bool) -> Self { - InputText { - flags: self.flags.with(ImGuiInputTextFlags_CharsUppercase, value), - .. self - } - } - - #[inline] - pub fn chars_noblank(self, value: bool) -> Self { - InputText { - flags: self.flags.with(ImGuiInputTextFlags_CharsNoBlank, value), - .. self - } - } - - #[inline] - pub fn auto_select_all(self, value: bool) -> Self { - InputText { - flags: self.flags.with(ImGuiInputTextFlags_AutoSelectAll, value), - .. self - } - } - - #[inline] - pub fn enter_returns_true(self, value: bool) -> Self { - InputText { - flags: self.flags.with(ImGuiInputTextFlags_EnterReturnsTrue, value), - .. self - } - } - - #[inline] - pub fn callback_completion(self, value: bool) -> Self { - InputText { - flags: self.flags.with(ImGuiInputTextFlags_CallbackCompletion, value), - .. self - } - } - - #[inline] - pub fn callback_history(self, value: bool) -> Self { - InputText { - flags: self.flags.with(ImGuiInputTextFlags_CallbackHistory, value), - .. self - } - } - - #[inline] - pub fn callback_always(self, value: bool) -> Self { - InputText { - flags: self.flags.with(ImGuiInputTextFlags_CallbackAlways, value), - .. self - } - } - - #[inline] - pub fn callback_char_filter(self, value: bool) -> Self { - InputText { - flags: self.flags.with(ImGuiInputTextFlags_CallbackCharFilter, value), - .. self - } - } - - #[inline] - pub fn allow_tab_input(self, value: bool) -> Self { - InputText { - flags: self.flags.with(ImGuiInputTextFlags_AllowTabInput, value), - .. self - } - } - - #[inline] - pub fn no_horizontal_scroll(self, value: bool) -> Self { - InputText { - flags: self.flags.with(ImGuiInputTextFlags_NoHorizontalScroll, value), - .. self - } - } - - #[inline] - pub fn always_insert_mode(self, value: bool) -> Self { - InputText { - flags: self.flags.with(ImGuiInputTextFlags_AlwaysInsertMode, value), - .. self - } - } + impl_text_flags!(InputText); // TODO: boxed closure...? // pub fn callback(self) -> Self { } @@ -161,3 +168,55 @@ impl<'ui, 'p> InputText<'ui, 'p> { } } } + +#[must_use] +pub struct InputInt<'ui, 'p> { + label: ImStr<'p>, + value: &'p mut i32, + step: i32, + step_fast: i32, + flags: ImGuiInputTextFlags, + _phantom: PhantomData<&'ui Ui<'ui>> +} + +impl<'ui, 'p> InputInt<'ui, 'p> { + pub fn new(label: ImStr<'p>, value: &'p mut i32) -> Self { + InputInt { + label: label, + value: value, + step: 1, + step_fast: 100, + flags: ImGuiInputTextFlags::empty(), + _phantom: PhantomData + } + } + + #[inline] + pub fn step(self, value: i32) -> Self { + InputInt { + step: value, + .. self + } + } + + #[inline] + pub fn step_fast(self, value: i32) -> Self { + InputInt { + step_fast: value, + .. self + } + } + + impl_text_flags!(InputInt); + + pub fn build(self) -> bool { + unsafe { + imgui_sys::igInputInt( + self.label.as_ptr(), + self.value as *mut i32, + self.step, + self.step_fast, + self.flags) + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 459b9a2..73de401 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,7 +39,7 @@ pub use imgui_sys::{ ImVec2, ImVec4, ImGuiKey }; -pub use input::{InputText}; +pub use input::{InputInt, InputText}; pub use menus::{Menu, MenuItem}; pub use sliders::{SliderFloat, SliderInt}; pub use trees::{TreeNode}; @@ -447,6 +447,9 @@ impl<'ui> Ui<'ui> { // Widgets: Input impl<'ui> Ui<'ui> { + pub fn input_int<'p>(&self, label: ImStr<'p>, value: &'p mut i32) -> InputInt<'ui, 'p> { + InputInt::new(label, value) + } pub fn input_text<'p>(&self, label: ImStr<'p>, buf: &'p mut str) -> InputText<'ui, 'p> { InputText::new(label, buf) }