From 5fc64b7e68599144b8afa88ff7433cf99cf17d6f Mon Sep 17 00:00:00 2001 From: tetenpapier Date: Wed, 10 Aug 2022 18:01:44 +0200 Subject: [PATCH 1/7] add TextFilter --- imgui-examples/examples/test_window_impl.rs | 20 ++++++ imgui/src/lib.rs | 1 + imgui/src/widget/mod.rs | 1 + imgui/src/widget/text_filter.rs | 76 +++++++++++++++++++++ 4 files changed, 98 insertions(+) create mode 100644 imgui/src/widget/text_filter.rs diff --git a/imgui-examples/examples/test_window_impl.rs b/imgui-examples/examples/test_window_impl.rs index c89f06835..69f0f451e 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 cadb3a202..19cdaeaf5 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 9ca788764..72a923dd3 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 000000000..b123c2024 --- /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) + } +} From 3d7b56a331f9dc81eb05facd6a97f0fec2845580 Mon Sep 17 00:00:00 2001 From: tetenpapier Date: Wed, 10 Aug 2022 19:40:53 +0200 Subject: [PATCH 2/7] add pass_filter_end --- imgui/src/widget/text_filter.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/imgui/src/widget/text_filter.rs b/imgui/src/widget/text_filter.rs index b123c2024..c6be59acd 100644 --- a/imgui/src/widget/text_filter.rs +++ b/imgui/src/widget/text_filter.rs @@ -58,8 +58,18 @@ impl TextFilter { } } - pub fn pass_filter_end(_buf: String, _end: String) -> bool { - true + pub fn pass_filter_end(&self, mut start: String, mut end: String) -> bool { + start.push('\0'); + end.push('\0'); + let b_ptr = start.as_mut_ptr(); + let e_ptr = end.as_mut_ptr(); + unsafe { + sys::ImGuiTextFilter_PassFilter( + self.raw, + b_ptr as *mut sys::cty::c_char, + e_ptr as *mut sys::cty::c_char, + ) + } } pub fn clear(&mut self) { From b02c1eb7b2f2823033594c04ad458aac5ac5f599 Mon Sep 17 00:00:00 2001 From: tetenpapier Date: Wed, 10 Aug 2022 19:51:52 +0200 Subject: [PATCH 3/7] add doc --- imgui/src/widget/text_filter.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/imgui/src/widget/text_filter.rs b/imgui/src/widget/text_filter.rs index c6be59acd..b17f0045c 100644 --- a/imgui/src/widget/text_filter.rs +++ b/imgui/src/widget/text_filter.rs @@ -1,3 +1,4 @@ +//! Helper to parse and apply text filters use crate::sys; use crate::Ui; use std::ptr; @@ -9,15 +10,19 @@ pub struct TextFilter { } impl TextFilter { - pub fn new(id: String) -> Self { - Self::new_with_filter(id, String::new()) + /// Creates a new TextFilter with a empty filter. + /// + /// This is equivalent of [new_with_filter](Self::new_with_filter) with `filter` set to `""`. + pub fn new(label: String) -> Self { + Self::new_with_filter(label, String::new()) } - pub fn new_with_filter(id: String, mut filter: String) -> Self { + /// Creates a new TextFilter with a custom filter. + pub fn new_with_filter(label: String, mut filter: String) -> Self { filter.push('\0'); let ptr = filter.as_mut_ptr(); Self { - id, + id: label, size: 0.0, raw: unsafe { sys::ImGuiTextFilter_ImGuiTextFilter(ptr as *mut sys::cty::c_char) }, } @@ -27,12 +32,13 @@ impl TextFilter { self.size = size; } - pub fn build(&mut self) { + pub fn build(&self) { unsafe { sys::ImGuiTextFilter_Build(self.raw); } } + /// Draws the TextFilter. pub fn draw(&self) { self.draw_size(0.0); } @@ -50,6 +56,7 @@ impl TextFilter { unsafe { sys::ImGuiTextFilter_IsActive(self.raw) } } + /// Returns true if the text matches the filter. pub fn pass_filter(&self, mut buf: String) -> bool { buf.push('\0'); let ptr = buf.as_mut_ptr(); @@ -72,7 +79,7 @@ impl TextFilter { } } - pub fn clear(&mut self) { + pub fn clear(&self) { unsafe { sys::ImGuiTextFilter_Clear(self.raw); } From 5450ee613609543bd61001e14a1f9d7da39fa961 Mon Sep 17 00:00:00 2001 From: tetenpapier Date: Thu, 11 Aug 2022 10:12:34 +0200 Subject: [PATCH 4/7] add doc and example, remove useless function --- imgui-examples/examples/test_window_impl.rs | 6 +++++ imgui/src/widget/text_filter.rs | 29 ++++++++++++--------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/imgui-examples/examples/test_window_impl.rs b/imgui-examples/examples/test_window_impl.rs index 69f0f451e..92f723c35 100644 --- a/imgui-examples/examples/test_window_impl.rs +++ b/imgui-examples/examples/test_window_impl.rs @@ -745,6 +745,12 @@ CTRL+click on individual component to input value.\n", state.filter.draw(); let lines = vec!["aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world!"]; + + ui.same_line(); + if ui.button("Clear##clear_filter") { + state.filter.clear(); + } + for i in lines.iter() { if state.filter.pass_filter(String::from(*i)) { ui.bullet_text(i); diff --git a/imgui/src/widget/text_filter.rs b/imgui/src/widget/text_filter.rs index b17f0045c..95d583bb2 100644 --- a/imgui/src/widget/text_filter.rs +++ b/imgui/src/widget/text_filter.rs @@ -5,12 +5,11 @@ use std::ptr; pub struct TextFilter { id: String, - size: f32, raw: *mut sys::ImGuiTextFilter, } impl TextFilter { - /// Creates a new TextFilter with a empty filter. + /// Creates a new TextFilter with an empty filter. /// /// This is equivalent of [new_with_filter](Self::new_with_filter) with `filter` set to `""`. pub fn new(label: String) -> Self { @@ -23,27 +22,31 @@ impl TextFilter { let ptr = filter.as_mut_ptr(); Self { id: label, - 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; - } - + /// Builds the TextFilter with its filter attribute. You can use + /// `[pass_filter()](Self::pass_filter)` after it. + /// + /// If you want control the filter with an InputText, check `[draw()](Self::draw)`. pub fn build(&self) { unsafe { sys::ImGuiTextFilter_Build(self.raw); } } - /// Draws the TextFilter. + /// Draws an [InputText](crate::input_widget::InputText) to control the filter of the TextFilter. + /// + /// This is equivalent of [draw_with_size](Self::draw_with_size) with `size` set to `0.0`. pub fn draw(&self) { - self.draw_size(0.0); + self.draw_with_size(0.0); } - pub fn draw_size(&self, size: f32) { + /// Draws an [InputText](crate::input_widget::InputText) to control the filter of the TextFilter. + /// + /// The InputText has the size passed in parameters. + pub fn draw_with_size(&self, size: f32) { unsafe { let mut id = self.id.clone(); id.push('\0'); @@ -52,11 +55,12 @@ impl TextFilter { } } + /// Returns true if the filter is not empty (`""`). pub fn is_active(&self) -> bool { unsafe { sys::ImGuiTextFilter_IsActive(self.raw) } } - /// Returns true if the text matches the filter. + /// Returns true if the buffer matches the filter. pub fn pass_filter(&self, mut buf: String) -> bool { buf.push('\0'); let ptr = buf.as_mut_ptr(); @@ -65,7 +69,7 @@ impl TextFilter { } } - pub fn pass_filter_end(&self, mut start: String, mut end: String) -> bool { + pub fn pass_filter_with_end(&self, mut start: String, mut end: String) -> bool { start.push('\0'); end.push('\0'); let b_ptr = start.as_mut_ptr(); @@ -79,6 +83,7 @@ impl TextFilter { } } + /// Clears the filter. pub fn clear(&self) { unsafe { sys::ImGuiTextFilter_Clear(self.raw); From 2d8ae7c9d0f230bcbd8ca812ed1c11d2815d512e Mon Sep 17 00:00:00 2001 From: tetenpapier Date: Thu, 11 Aug 2022 10:24:58 +0200 Subject: [PATCH 5/7] add new function in ui for textfilter and doc --- imgui/src/widget/text_filter.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/imgui/src/widget/text_filter.rs b/imgui/src/widget/text_filter.rs index 95d583bb2..eeac13716 100644 --- a/imgui/src/widget/text_filter.rs +++ b/imgui/src/widget/text_filter.rs @@ -1,8 +1,8 @@ -//! Helper to parse and apply text filters use crate::sys; use crate::Ui; use std::ptr; +/// Helper to parse and apply text filters pub struct TextFilter { id: String, raw: *mut sys::ImGuiTextFilter, @@ -27,9 +27,9 @@ impl TextFilter { } /// Builds the TextFilter with its filter attribute. You can use - /// `[pass_filter()](Self::pass_filter)` after it. + /// [`pass_filter()`](Self::pass_filter) after it. /// - /// If you want control the filter with an InputText, check `[draw()](Self::draw)`. + /// If you want control the filter with an InputText, check [`draw()`](Self::draw). pub fn build(&self) { unsafe { sys::ImGuiTextFilter_Build(self.raw); @@ -61,6 +61,8 @@ impl TextFilter { } /// Returns true if the buffer matches the filter. + /// + /// [`draw()`](Self::draw) or [`build()`](Self::build) mut be called **before** this function. pub fn pass_filter(&self, mut buf: String) -> bool { buf.push('\0'); let ptr = buf.as_mut_ptr(); @@ -95,4 +97,8 @@ impl Ui { pub fn text_filter(label: String) -> TextFilter { TextFilter::new(label) } + + pub fn text_filter_with_filter(label: String, filter: String) -> TextFilter { + TextFilter::new_with_filter(label, filter) + } } From 5f5450487f706bb2aa33d39292459ec20654f85f Mon Sep 17 00:00:00 2001 From: tetenpapier Date: Fri, 12 Aug 2022 17:32:11 +0200 Subject: [PATCH 6/7] use &str instead of String --- imgui-examples/examples/test_window_impl.rs | 2 +- imgui/src/widget/text_filter.rs | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/imgui-examples/examples/test_window_impl.rs b/imgui-examples/examples/test_window_impl.rs index 92f723c35..dd13a7163 100644 --- a/imgui-examples/examples/test_window_impl.rs +++ b/imgui-examples/examples/test_window_impl.rs @@ -752,7 +752,7 @@ CTRL+click on individual component to input value.\n", } for i in lines.iter() { - if state.filter.pass_filter(String::from(*i)) { + if state.filter.pass_filter(i) { ui.bullet_text(i); } } diff --git a/imgui/src/widget/text_filter.rs b/imgui/src/widget/text_filter.rs index eeac13716..b64ebf909 100644 --- a/imgui/src/widget/text_filter.rs +++ b/imgui/src/widget/text_filter.rs @@ -63,7 +63,8 @@ impl TextFilter { /// Returns true if the buffer matches the filter. /// /// [`draw()`](Self::draw) or [`build()`](Self::build) mut be called **before** this function. - pub fn pass_filter(&self, mut buf: String) -> bool { + pub fn pass_filter(&self, buf: &str) -> bool { + let mut buf = String::from(buf); buf.push('\0'); let ptr = buf.as_mut_ptr(); unsafe { @@ -71,7 +72,8 @@ impl TextFilter { } } - pub fn pass_filter_with_end(&self, mut start: String, mut end: String) -> bool { + pub fn pass_filter_with_end(&self, start: &str, end: &str) -> bool { + let (mut start, mut end) = (String::from(start), String::from(end)); start.push('\0'); end.push('\0'); let b_ptr = start.as_mut_ptr(); From c004b3a619ffaa24dae21fb77f714f58aa53b279 Mon Sep 17 00:00:00 2001 From: tetenpapier Date: Fri, 12 Aug 2022 17:34:02 +0200 Subject: [PATCH 7/7] move text_filter file --- imgui/src/lib.rs | 3 ++- imgui/src/{widget => }/text_filter.rs | 3 ++- imgui/src/widget/mod.rs | 1 - 3 files changed, 4 insertions(+), 3 deletions(-) rename imgui/src/{widget => }/text_filter.rs (96%) diff --git a/imgui/src/lib.rs b/imgui/src/lib.rs index 19cdaeaf5..02b858d10 100644 --- a/imgui/src/lib.rs +++ b/imgui/src/lib.rs @@ -33,6 +33,7 @@ pub use self::style::*; #[cfg(feature = "tables-api")] pub use self::tables::*; +pub use self::text_filter::*; pub use self::utils::*; pub use self::widget::color_editors::*; pub use self::widget::combo_box::*; @@ -45,7 +46,6 @@ 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::*; @@ -82,6 +82,7 @@ mod style; mod tables; #[cfg(test)] mod test; +pub mod text_filter; mod utils; mod widget; mod window; diff --git a/imgui/src/widget/text_filter.rs b/imgui/src/text_filter.rs similarity index 96% rename from imgui/src/widget/text_filter.rs rename to imgui/src/text_filter.rs index b64ebf909..eaf86b8f5 100644 --- a/imgui/src/widget/text_filter.rs +++ b/imgui/src/text_filter.rs @@ -17,7 +17,8 @@ impl TextFilter { } /// Creates a new TextFilter with a custom filter. - pub fn new_with_filter(label: String, mut filter: String) -> Self { + pub fn new_with_filter(label: String, filter: String) -> Self { + let mut filter = filter.clone(); filter.push('\0'); let ptr = filter.as_mut_ptr(); Self { diff --git a/imgui/src/widget/mod.rs b/imgui/src/widget/mod.rs index 72a923dd3..9ca788764 100644 --- a/imgui/src/widget/mod.rs +++ b/imgui/src/widget/mod.rs @@ -10,5 +10,4 @@ pub mod selectable; pub mod slider; pub mod tab; pub mod text; -pub mod text_filter; pub mod tree;