mirror of
https://github.com/ocornut/imgui.git
synced 2026-09-26 16:05:45 +03:00
ImGuiTextFilter: reworked filter to make space an AND operator. Demo: tweaked demo.
Removed FilterOp, MinWordSize added a few commits ago.
This commit is contained in:
parent
420f179341
commit
d5c68c301a
4 changed files with 73 additions and 48 deletions
|
|
@ -84,8 +84,10 @@ Other Changes:
|
|||
hasn't been owned by another items. This is more correct and also necessary
|
||||
to avoid Drags/Sliders cancelling also triggering a cancel menu. (#8564, #9534)
|
||||
- ImGuiTextFilter:
|
||||
- Added support for space ' ' as separator, which is more standard. (#2435, #30)
|
||||
- Added support for quoted "xxx" blocks to e.g. match words sequences. (#2435)
|
||||
- Added support for space as an "and" filter, which is the standard. (#2435, #30)
|
||||
e.g. w/ filter 'hello world' (without quotes) both words needs to be in input data.
|
||||
- Added support for double-quoted "xxx" blocks to e.g. match words sequences. (#2435)
|
||||
e.g. w/ filter "hello world" the exact sequence needs to be in input data.
|
||||
- Fixed filtering when mixing "include" and "-exclude" keyword so that an "-exclude"
|
||||
match always filters out. (#2435) [@kudaba, @ocornut]
|
||||
- Added `DrawWithHint()` function. (#6206, #6395, #6447)
|
||||
|
|
|
|||
74
imgui.cpp
74
imgui.cpp
|
|
@ -3094,9 +3094,7 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE
|
|||
ImGuiTextFilter::ImGuiTextFilter(const char* default_filter) //-V1077
|
||||
{
|
||||
InputBuf[0] = 0;
|
||||
FilterOp = '|';
|
||||
MinWordSize = 1;
|
||||
_CountExclude = _CountInclude = 0;
|
||||
_CountExclude = 0;
|
||||
if (default_filter)
|
||||
{
|
||||
ImStrncpy(InputBuf, default_filter, IM_COUNTOF(InputBuf));
|
||||
|
|
@ -3118,14 +3116,15 @@ bool ImGuiTextFilter::DrawWithHint(const char* label, const char* hint)
|
|||
return value_changed;
|
||||
}
|
||||
|
||||
// Parse filter and split into items
|
||||
// Parse filter and split into a format optimal for PassFilter()
|
||||
void ImGuiTextFilter::Build()
|
||||
{
|
||||
_Items.resize(0);
|
||||
_CountExclude = _CountInclude = 0;
|
||||
IM_ASSERT(FilterOp == '|' || FilterOp == '&');
|
||||
_CountExclude = 0;
|
||||
|
||||
const char* buf_e = InputBuf + ImStrlen(InputBuf);
|
||||
const char* word_e;
|
||||
int seq_incl_start_idx = -1;
|
||||
for (const char* word_b = InputBuf; word_b < buf_e; word_b = word_e + 1)
|
||||
{
|
||||
// Trim blanks
|
||||
|
|
@ -3151,20 +3150,33 @@ void ImGuiTextFilter::Build()
|
|||
}
|
||||
|
||||
// Min length
|
||||
if (word_e - word_b < MinWordSize)
|
||||
continue;
|
||||
|
||||
// Add to list
|
||||
// The '-' is not stored in items but implicitly inferred using (n < CountExclude).
|
||||
// FIXME-OPT: about ~push_front(): as N is derived from user inputs we expect this to be fine.
|
||||
_Items.insert(is_excl ? _Items.Data : _Items.Data + _Items.Size, ImGuiTextFilter::ImGuiTextFilterItem(word_b, word_e));
|
||||
if (word_e - word_b > 0)
|
||||
{
|
||||
// Add to list. The '-' is not stored in items but implicitly inferred using (n < CountExclude).
|
||||
// FIXME-OPT: as items are derived from user input buffer and we expect the insert() to behave sanely.
|
||||
if (is_excl)
|
||||
{
|
||||
_Items.insert(_Items.Data + _CountExclude, ImGuiTextFilter::ImGuiTextFilterItem(word_b, word_e));
|
||||
_CountExclude++;
|
||||
if (seq_incl_start_idx != -1)
|
||||
seq_incl_start_idx++;
|
||||
}
|
||||
else
|
||||
_CountInclude++;
|
||||
{
|
||||
if (seq_incl_start_idx == -1)
|
||||
seq_incl_start_idx = _Items.Size;
|
||||
_Items.insert(_Items.Data + _Items.Size, ImGuiTextFilter::ImGuiTextFilterItem(word_b, word_e));
|
||||
_Items.Data[seq_incl_start_idx].CountInclude++;
|
||||
}
|
||||
}
|
||||
|
||||
// Next sequence
|
||||
if (word_e[0] == ',')
|
||||
seq_incl_start_idx = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Could use a specialized ImStristr() + pre-convert our filter to uppercase.
|
||||
bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const
|
||||
{
|
||||
if (_Items.Size == 0)
|
||||
|
|
@ -3173,24 +3185,28 @@ bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const
|
|||
text = text_end = "";
|
||||
|
||||
// Filters are sorted so that '-' ones are always leading.
|
||||
int n;
|
||||
for (n = 0; n < _CountExclude; n++)
|
||||
if (ImStristr(text, text_end, _Items.Data[n].Begin, _Items.Data[n].End) != NULL)
|
||||
ImGuiTextFilterItem* seq = _Items.Data;
|
||||
ImGuiTextFilterItem* seq_excl_end = _Items.Data + _CountExclude;
|
||||
for (; seq < seq_excl_end; seq++)
|
||||
if (ImStristr(text, text_end, seq->Begin, seq->Begin + seq->Len) != NULL)
|
||||
return false;
|
||||
const bool is_and_filter = (FilterOp == '&');
|
||||
for (; n < _Items.Size; n++)
|
||||
{
|
||||
const bool is_match = ImStristr(text, text_end, _Items.Data[n].Begin, _Items.Data[n].End) != NULL;
|
||||
if (is_match && !is_and_filter) // or incl 1 -> true
|
||||
return true; // or incl 0 -> continue
|
||||
if (!is_match && is_and_filter) // and incl 1 -> continue
|
||||
return false; // and incl 0 -> false
|
||||
}
|
||||
|
||||
// When no inclusion are specified (only exclusions) we implicitly pass
|
||||
if (_CountInclude == 0)
|
||||
// Process includes
|
||||
ImGuiTextFilterItem* seq_incl_end = _Items.Data + _Items.Size;
|
||||
if (seq == seq_incl_end) // When no inclusion are specified (only exclusions) we implicitly pass
|
||||
return true;
|
||||
return is_and_filter;
|
||||
while (seq < seq_incl_end)
|
||||
{
|
||||
ImGuiTextFilterItem* seq_next = seq + seq->CountInclude;
|
||||
IM_ASSERT_PARANOID(seq->CountInclude > 0 && seq_next <= seq_incl_end);
|
||||
for (; seq < seq_next; seq++)
|
||||
if (ImStristr(text, text_end, seq->Begin, seq->Begin + seq->Len) == NULL)
|
||||
break;
|
||||
if (seq == seq_next) // All matched
|
||||
return true;
|
||||
seq = seq_next; // Try next
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
14
imgui.h
14
imgui.h
|
|
@ -2785,7 +2785,7 @@ struct ImGuiOnceUponAFrame
|
|||
operator bool() const { int current_frame = ImGui::GetFrameCount(); if (RefFrame == current_frame) return false; RefFrame = current_frame; return true; }
|
||||
};
|
||||
|
||||
// Helper: Parse and apply text filters e.g. 'aaa bbb -ccc'.
|
||||
// Helper: Parse and apply text filters e.g. 'aaa bbb' (all), 'aaa,bbb' (any), '-aaa' (exclude), '"Hello, world"' (exact sequence)
|
||||
struct ImGuiTextFilter
|
||||
{
|
||||
IMGUI_API ImGuiTextFilter(const char* default_filter = "");
|
||||
|
|
@ -2801,20 +2801,18 @@ struct ImGuiTextFilter
|
|||
inline bool Draw(const char* label, float width) { if (width != 0.0f) ImGui::SetNextItemWidth(width); return Draw(label); }
|
||||
#endif
|
||||
|
||||
// [Internal] Don't use! Will be replaced with ImStrv.
|
||||
// [Internal] Types
|
||||
struct ImGuiTextFilterItem
|
||||
{
|
||||
const char* Begin;
|
||||
const char* End;
|
||||
ImGuiTextFilterItem(const char* b, const char* e) { Begin = b; End = e; }
|
||||
int Len;
|
||||
int CountInclude; // >0 when beginning of an AND chain.
|
||||
ImGuiTextFilterItem(const char* b, const char* e) { IM_ASSERT(e > b); Begin = b; Len = (int)(e - b); CountInclude = 0; }
|
||||
};
|
||||
|
||||
// [Internal] Members
|
||||
char InputBuf[256]; // User input buffer
|
||||
char FilterOp; // == '|' (any) pr '&' (all)
|
||||
ImU8 MinWordSize; // == 1
|
||||
int _CountExclude; // >= 0
|
||||
int _CountInclude; // >= 0
|
||||
int _CountExclude; // >= 0 count of leading exclude
|
||||
ImVector<ImGuiTextFilterItem> _Items; // Pre-parsed, trimmed, reordered items
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3943,15 +3943,24 @@ static void DemoWindowWidgetsTextFilter()
|
|||
static ImGuiTextFilter filter;
|
||||
ImGui::Text("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\"");
|
||||
" xxx display lines containing \"xxx\"\n"
|
||||
" xxx yyy display lines containing \"xxx\" and \"yyy\"\n"
|
||||
" \"xxx yyy\" display lines containing \"xxx yyy\"\n"
|
||||
" xxx,yyy display lines containing \"xxx\" or \"yyy\"\n"
|
||||
" -xxx hide lines containing \"xxx\"");
|
||||
ImGui::SetNextItemWidth(-FLT_MIN);
|
||||
filter.DrawWithHint("##Filter", "Filter (incl -excl)");
|
||||
if (ImGui::BeginChild("##items", ImVec2(-FLT_MIN, ImGui::GetTextLineHeightWithSpacing() * 15), ImGuiChildFlags_FrameStyle))
|
||||
{
|
||||
const char* lines[] = { "aaa1.c", "bbb1.c", "ccc1.c", "aaa2.cpp", "bbb2.cpp", "ccc2.cpp", "abc.h", "hello, world" };
|
||||
for (int i = 0; i < IM_COUNTOF(lines); i++)
|
||||
if (filter.PassFilter(lines[i]))
|
||||
ImGui::BulletText("%s", lines[i]);
|
||||
for (const char* item : lines)
|
||||
if (filter.PassFilter(item))
|
||||
ImGui::TextUnformatted(item);
|
||||
for (const char* item : ExampleNames)
|
||||
if (filter.PassFilter(item))
|
||||
ImGui::TextUnformatted(item);
|
||||
}
|
||||
ImGui::EndChild();
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue