Skip to content

Commit

Permalink
Merge pull request #658 from tetenpapier/main
Browse files Browse the repository at this point in the history
Add bindings to TextFilter
  • Loading branch information
dbr committed Oct 5, 2022
2 parents 45c2d28 + c004b3a commit f1c87a1
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 0 deletions.
26 changes: 26 additions & 0 deletions imgui-examples/examples/test_window_impl.rs
Expand Up @@ -53,6 +53,7 @@ struct State {
stacked_modals_item: usize,
stacked_modals_color: [f32; 4],
app_log: Vec<String>,
filter: imgui::TextFilter,

tabs: TabState,
}
Expand Down Expand Up @@ -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(),
}
}
Expand Down Expand Up @@ -747,6 +749,30 @@ 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!"];

ui.same_line();
if ui.button("Clear##clear_filter") {
state.filter.clear();
}

for i in lines.iter() {
if state.filter.pass_filter(i) {
ui.bullet_text(i);
}
}
}

if CollapsingHeader::new("Popups & Modal windows").build(ui) {
if let Some(_t) = ui.tree_node("Popups") {
ui.text_wrapped(
Expand Down
2 changes: 2 additions & 0 deletions imgui/src/lib.rs
Expand Up @@ -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::*;
Expand Down Expand Up @@ -81,6 +82,7 @@ mod style;
mod tables;
#[cfg(test)]
mod test;
pub mod text_filter;
mod utils;
mod widget;
mod window;
Expand Down
107 changes: 107 additions & 0 deletions imgui/src/text_filter.rs
@@ -0,0 +1,107 @@
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,
}

impl TextFilter {
/// 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 {
Self::new_with_filter(label, String::new())
}

/// Creates a new TextFilter with a custom filter.
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 {
id: label,
raw: unsafe { sys::ImGuiTextFilter_ImGuiTextFilter(ptr as *mut sys::cty::c_char) },
}
}

/// 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 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_with_size(0.0);
}

/// 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');
let ptr = id.as_mut_ptr();
sys::ImGuiTextFilter_Draw(self.raw, ptr as *mut sys::cty::c_char, size);
}
}

/// Returns true if the filter is not empty (`""`).
pub fn is_active(&self) -> bool {
unsafe { sys::ImGuiTextFilter_IsActive(self.raw) }
}

/// 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, buf: &str) -> bool {
let mut buf = String::from(buf);
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_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();
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,
)
}
}

/// Clears the filter.
pub fn clear(&self) {
unsafe {
sys::ImGuiTextFilter_Clear(self.raw);
}
}
}

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)
}
}

0 comments on commit f1c87a1

Please sign in to comment.