diff --git a/imgui-examples/examples/test_window_impl.rs b/imgui-examples/examples/test_window_impl.rs index c89f068..69f0f45 100644 --- a/imgui-examples/examples/test_window_impl.rs +++ b/imgui-examples/examples/test_window_impl.rs @@ -53,6 +53,7 @@ struct State { stacked_modals_item: usize, stacked_modals_color: [f32; 4], app_log: Vec, + filter: imgui::TextFilter, tabs: TabState, } @@ -117,6 +118,7 @@ impl Default for State { stacked_modals_item: 0, stacked_modals_color: [0.4, 0.7, 0.0, 0.5], app_log: Vec::new(), + filter: TextFilter::new(String::from("Test")), tabs: TabState::default(), } } @@ -732,6 +734,24 @@ CTRL+click on individual component to input value.\n", } } + if CollapsingHeader::new("Filtering").build(ui) { + ui.text_wrapped( + "Filter usage:\n\ + \"\" display all lines\n\ + \"xxx\" display lines containing \"xxx\"\n\ + \"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n\ + \"-xxx\" hide lines containing \"xxx\"" + ); + + state.filter.draw(); + let lines = vec!["aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world!"]; + for i in lines.iter() { + if state.filter.pass_filter(String::from(*i)) { + ui.bullet_text(i); + } + } + } + if CollapsingHeader::new("Popups & Modal windows").build(ui) { if let Some(_t) = ui.tree_node("Popups") { ui.text_wrapped( diff --git a/imgui/src/lib.rs b/imgui/src/lib.rs index cadb3a2..19cdaea 100644 --- a/imgui/src/lib.rs +++ b/imgui/src/lib.rs @@ -45,6 +45,7 @@ pub use self::widget::progress_bar::*; pub use self::widget::selectable::*; pub use self::widget::slider::*; pub use self::widget::tab::*; +pub use self::widget::text_filter::*; pub use self::widget::tree::*; pub use self::window::child_window::*; pub use self::window::*; diff --git a/imgui/src/widget/mod.rs b/imgui/src/widget/mod.rs index 9ca7887..72a923d 100644 --- a/imgui/src/widget/mod.rs +++ b/imgui/src/widget/mod.rs @@ -10,4 +10,5 @@ pub mod selectable; pub mod slider; pub mod tab; pub mod text; +pub mod text_filter; pub mod tree; diff --git a/imgui/src/widget/text_filter.rs b/imgui/src/widget/text_filter.rs new file mode 100644 index 0000000..b123c20 --- /dev/null +++ b/imgui/src/widget/text_filter.rs @@ -0,0 +1,76 @@ +use crate::sys; +use crate::Ui; +use std::ptr; + +pub struct TextFilter { + id: String, + size: f32, + raw: *mut sys::ImGuiTextFilter, +} + +impl TextFilter { + pub fn new(id: String) -> Self { + Self::new_with_filter(id, String::new()) + } + + pub fn new_with_filter(id: String, mut filter: String) -> Self { + filter.push('\0'); + let ptr = filter.as_mut_ptr(); + Self { + id, + size: 0.0, + raw: unsafe { sys::ImGuiTextFilter_ImGuiTextFilter(ptr as *mut sys::cty::c_char) }, + } + } + + pub fn set_size(&mut self, size: f32) { + self.size = size; + } + + pub fn build(&mut self) { + unsafe { + sys::ImGuiTextFilter_Build(self.raw); + } + } + + pub fn draw(&self) { + self.draw_size(0.0); + } + + pub fn draw_size(&self, size: f32) { + unsafe { + let mut id = self.id.clone(); + id.push('\0'); + let ptr = id.as_mut_ptr(); + sys::ImGuiTextFilter_Draw(self.raw, ptr as *mut sys::cty::c_char, size); + } + } + + pub fn is_active(&self) -> bool { + unsafe { sys::ImGuiTextFilter_IsActive(self.raw) } + } + + pub fn pass_filter(&self, mut buf: String) -> bool { + buf.push('\0'); + let ptr = buf.as_mut_ptr(); + unsafe { + sys::ImGuiTextFilter_PassFilter(self.raw, ptr as *mut sys::cty::c_char, ptr::null()) + } + } + + pub fn pass_filter_end(_buf: String, _end: String) -> bool { + true + } + + pub fn clear(&mut self) { + unsafe { + sys::ImGuiTextFilter_Clear(self.raw); + } + } +} + +impl Ui { + pub fn text_filter(label: String) -> TextFilter { + TextFilter::new(label) + } +}