diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 672c24c30..82c2ffe00 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -84,10 +84,12 @@ 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) - 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) - - Added a "incl,-excl" hint by default when the search field is empty. (#6206, #6395, #6447) + - Added a "incl -excl" hint by default when the search field is empty. (#6206, #6395, #6447) - Style: - Inverted `ImGuiCol_TitleBgXXX` colors for `StyleColorsLight()` so that the selected window title bar appears brighter. diff --git a/imgui.cpp b/imgui.cpp index 8968a8f3f..e0065362c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3090,7 +3090,7 @@ IM_MSVC_RUNTIME_CHECKS_RESTORE // [SECTION] ImGuiTextFilter //----------------------------------------------------------------------------- -// Helper: Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" +// Helper: Parse and apply text filters e.g. 'aaa bbb -ccc'. ImGuiTextFilter::ImGuiTextFilter(const char* default_filter) //-V1077 { InputBuf[0] = 0; @@ -3104,7 +3104,7 @@ ImGuiTextFilter::ImGuiTextFilter(const char* default_filter) //-V1077 bool ImGuiTextFilter::Draw(const char* label) { - return DrawWithHint(label, "incl,-excl"); + return DrawWithHint(label, "incl -excl"); } // Use ImGui::SetNextItemWidth() manually if you want to use this. @@ -3118,17 +3118,20 @@ bool ImGuiTextFilter::DrawWithHint(const char* label, const char* hint) static void ImGuiTextFilter_BuildAddItem(ImGuiTextFilter* f, const char* word_b, const char* word_e) { - // Trim (FIXME: UTF-8 support?) - while (word_b < word_e && ImCharIsBlankA(word_b[0])) - word_b++; - while (word_e > word_b && ImCharIsBlankA(word_e[-1])) - word_e--; - if (word_e - word_b <= 0) + // Trim blanks + if (word_b < word_e && word_b[0] != '\"') + { + while (word_b < word_e && ImCharIsBlankA(word_b[0])) // FIXME: UTF-8 support + word_b++; + while (word_e > word_b && ImCharIsBlankA(word_e[-1])) + word_e--; + } + const bool is_excl = (word_b < word_e && word_b[0] == '-'); + if (word_e - word_b - (is_excl ? 1 : 0) <= 0) return; // Add to list - // FIXME-OPT: on push_front(): as N is derived from user inputs we expect this to be fine. - const bool is_excl = (word_b[0] == '-'); + // FIXME-OPT: about ~push_front(): as N is derived from user inputs we expect this to be fine. f->_Items.insert(is_excl ? f->_Items.Data : f->_Items.end(), ImGuiTextFilter::ImGuiTextFilterItem(word_b, word_e)); if (!is_excl) f->_CountInclude++; @@ -3140,18 +3143,26 @@ void ImGuiTextFilter::Build() _Items.resize(0); _CountInclude = 0; const char* buf_e = InputBuf + ImStrlen(InputBuf); - const char* word_b = InputBuf; - const char* word_e = word_b; - while (word_e < buf_e) + const char* word_e; + for (const char* word_b = InputBuf; word_b < buf_e; word_b = word_e + 1) { - if (*word_e == ',') + const bool is_excl = (word_b[0] == '-'); + if (word_b[0] == '\"' || (is_excl && word_b + 1 < buf_e && word_b[1] == '\"')) { - ImGuiTextFilter_BuildAddItem(this, word_b, word_e); - word_b = word_e + 1; + // Parsing "word". Store leading " to distinguish -"word" from "-word", but omit trailing ". + word_e = ImStrchrRange(word_b + (is_excl ? 2 : 1), buf_e, '\"'); + if (word_e == NULL) + word_e = buf_e; } - word_e++; + else + { + // Handle both ' ' and ',' separators. + for (word_e = word_b; word_e < buf_e; word_e++) + if (*word_e == ' ' || *word_e == ',') + break; + } + ImGuiTextFilter_BuildAddItem(this, word_b, word_e); } - ImGuiTextFilter_BuildAddItem(this, word_b, word_e); } bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const @@ -3164,16 +3175,15 @@ bool ImGuiTextFilter::PassFilter(const char* text, const char* text_end) const // Filters are sorted so that '-' ones are always leading. for (const ImGuiTextFilterItem& item : _Items) { - if (item.Begin[0] == '-') - { - if (ImStristr(text, text_end, item.Begin + 1, item.End) != NULL) // Exclude - return false; - } - else - { - if (ImStristr(text, text_end, item.Begin, item.End) != NULL) // Include - return true; - } + const char* word_b = item.Begin; + const char* word_e = item.End; + const bool is_excl = (word_b[0] == '-'); + if (is_excl) + word_b++; + if (word_b < word_e && word_b[0] == '\"') + word_b++; + if (ImStristr(text, text_end, word_b, word_e) != NULL) + return is_excl ? false : true; } // When no inclusion are specified (only exclusions) we implicitly pass diff --git a/imgui.h b/imgui.h index d66f70d24..20fb5fc96 100644 --- a/imgui.h +++ b/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. In format "aaaaa[,bbbb][,ccccc]" +// Helper: Parse and apply text filters e.g. 'aaa bbb -ccc'. struct ImGuiTextFilter { IMGUI_API ImGuiTextFilter(const char* default_filter = ""); @@ -2796,7 +2796,7 @@ struct ImGuiTextFilter // Helper to call InputText() + Build() when buffer is changed. IMGUI_API bool Draw(const char* label = "Filter"); - IMGUI_API bool DrawWithHint(const char* label = "Filter", const char* hint = "incl,-excl"); + IMGUI_API bool DrawWithHint(const char* label = "Filter", const char* hint = "incl -excl"); #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS inline bool Draw(const char* label, float width) { if (width != 0.0f) ImGui::SetNextItemWidth(width); return Draw(label); } #endif diff --git a/imgui_demo.cpp b/imgui_demo.cpp index c5e0697aa..5ef47f3af 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1453,7 +1453,7 @@ static void DemoWindowWidgetsComboBoxes() } ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F); ImGui::SetNextItemWidth(-FLT_MIN); - filter.DrawWithHint("##Filter", "Filter (incl,-excl)"); + filter.DrawWithHint("##Filter", "Filter (incl -excl)"); for (int n = 0; n < IM_COUNTOF(items); n++) { @@ -3947,7 +3947,7 @@ static void DemoWindowWidgetsTextFilter() " \"xxx,yyy\" display lines containing \"xxx\" or \"yyy\"\n" " \"-xxx\" hide lines containing \"xxx\""); ImGui::SetNextItemWidth(-FLT_MIN); - filter.DrawWithHint("##Filter", "Filter (incl,-excl)"); + filter.DrawWithHint("##Filter", "Filter (incl -excl)"); 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])) @@ -8833,7 +8833,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) static ImGuiTextFilter filter; SetNextItemWidth(-FLT_MIN); - filter.DrawWithHint("##FilterColors", "Filter Colors (incl,-excl)"); + filter.DrawWithHint("##FilterColors", "Filter Colors (incl -excl)"); SetNextWindowSizeConstraints(ImVec2(0.0f, GetTextLineHeightWithSpacing() * 10), ImVec2(FLT_MAX, FLT_MAX)); BeginChild("##colors", ImVec2(0, 0), ImGuiChildFlags_Borders | ImGuiChildFlags_NavFlattened, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar); @@ -9250,7 +9250,7 @@ struct ExampleAppConsole ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F, ImGuiInputFlags_Tooltip); ImGui::SetNextItemWidth(-FLT_MIN); - Filter.DrawWithHint("##Filter", "Filter (incl,-excl)"); + Filter.DrawWithHint("##Filter", "Filter (incl -excl)"); ImGui::Separator(); // Reserve enough left-over height for 1 separator + 1 input text @@ -9586,7 +9586,7 @@ struct ExampleAppLog bool copy = ImGui::Button("Copy"); ImGui::SameLine(); ImGui::SetNextItemWidth(-FLT_MIN); - Filter.DrawWithHint("##Filter", "Filter (incl,-excl)"); + Filter.DrawWithHint("##Filter", "Filter (incl -excl)"); ImGui::Separator(); @@ -9781,7 +9781,7 @@ struct ExampleAppPropertyEditor ImGui::Text("(%d root nodes)", root_node->Childs.Size); ImGui::SetNextItemWidth(-FLT_MIN); ImGui::SetNextItemShortcut(ImGuiMod_Ctrl | ImGuiKey_F, ImGuiInputFlags_Tooltip); - if (ImGui::InputTextWithHint("##Filter", "incl,-excl", Filter.InputBuf, IM_COUNTOF(Filter.InputBuf), ImGuiInputTextFlags_EscapeClearsAll)) + if (ImGui::InputTextWithHint("##Filter", "incl -excl", Filter.InputBuf, IM_COUNTOF(Filter.InputBuf), ImGuiInputTextFlags_EscapeClearsAll)) Filter.Build(); ImGui::PopItemFlag();