TypingSelect: tidy up some more + split ino functions to make reuse simpler.

This commit is contained in:
ocornut 2023-09-14 18:26:43 +02:00
parent 661a70fc79
commit 779568bb38
2 changed files with 44 additions and 33 deletions

View File

@ -1559,7 +1559,7 @@ struct ImGuiNavItemData
// [SECTION] Typing-select support // [SECTION] Typing-select support
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Flags for GetTypingSelectRequest(), TypingSelectFindResult() // Flags for GetTypingSelectRequest()
enum ImGuiTypingSelectFlags_ enum ImGuiTypingSelectFlags_
{ {
ImGuiTypingSelectFlags_None = 0, ImGuiTypingSelectFlags_None = 0,
@ -1572,7 +1572,7 @@ struct IMGUI_API ImGuiTypingSelectRequest
{ {
ImGuiTypingSelectFlags Flags; // Flags passed to GetTypingSelectRequest() ImGuiTypingSelectFlags Flags; // Flags passed to GetTypingSelectRequest()
int SearchBufferLen; int SearchBufferLen;
const char* SearchBuffer; const char* SearchBuffer; // Search buffer contents (use full string. unless SingleCharMode is set, in which case use SingleCharSize).
bool SelectRequest; // Set when buffer was modified this frame, requesting a selection. bool SelectRequest; // Set when buffer was modified this frame, requesting a selection.
bool SingleCharMode; // Notify when buffer contains same character repeated, to implement special mode. In this situation it preferred to not display any on-screen search indication. bool SingleCharMode; // Notify when buffer contains same character repeated, to implement special mode. In this situation it preferred to not display any on-screen search indication.
ImS8 SingleCharSize; // Length in bytes of first letter codepoint (1 for ascii, 2-4 for UTF-8). If (SearchBufferLen==RepeatCharSize) only 1 letter has been input. ImS8 SingleCharSize; // Length in bytes of first letter codepoint (1 for ascii, 2-4 for UTF-8). If (SearchBufferLen==RepeatCharSize) only 1 letter has been input.
@ -3126,7 +3126,9 @@ namespace ImGui
// Typing-Select API // Typing-Select API
IMGUI_API ImGuiTypingSelectRequest* GetTypingSelectRequest(ImGuiTypingSelectFlags flags = ImGuiTypingSelectFlags_None); IMGUI_API ImGuiTypingSelectRequest* GetTypingSelectRequest(ImGuiTypingSelectFlags flags = ImGuiTypingSelectFlags_None);
IMGUI_API int TypingSelectFindTargetIndex(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx); IMGUI_API int TypingSelectFindMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx);
IMGUI_API int TypingSelectFindNextSingleCharMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx);
IMGUI_API int TypingSelectFindBestLeadingMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data);
// Internal Columns API (this is not exposed because we will encourage transitioning to the Tables API) // Internal Columns API (this is not exposed because we will encourage transitioning to the Tables API)
IMGUI_API void SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect); IMGUI_API void SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect);

View File

@ -6614,7 +6614,7 @@ bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags
// This would typically only be called on the focused window or location you want to grab inputs for, e.g. // This would typically only be called on the focused window or location you want to grab inputs for, e.g.
// if (ImGui::IsWindowFocused(...)) // if (ImGui::IsWindowFocused(...))
// if (ImGuiTypingSelectRequest* req = ImGui::GetTypingSelectRequest()) // if (ImGuiTypingSelectRequest* req = ImGui::GetTypingSelectRequest())
// focus_idx = ImGui::TypingSelectFindResult(req, my_items.size(), [](void*, int n) { return my_items[n]->Name; }, &my_items, -1); // focus_idx = ImGui::TypingSelectFindMatch(req, my_items.size(), [](void*, int n) { return my_items[n]->Name; }, &my_items, -1);
// However the code is written in a way where calling it from multiple locations is safe (e.g. to obtain buffer). // However the code is written in a way where calling it from multiple locations is safe (e.g. to obtain buffer).
ImGuiTypingSelectRequest* ImGui::GetTypingSelectRequest(ImGuiTypingSelectFlags flags) ImGuiTypingSelectRequest* ImGui::GetTypingSelectRequest(ImGuiTypingSelectFlags flags)
{ {
@ -6721,25 +6721,33 @@ static int ImStrimatchlen(const char* s1, const char* s1_end, const char* s2)
} }
// Default handler for finding a result for typing-select. You may implement your own. // Default handler for finding a result for typing-select. You may implement your own.
// You might want to display a tooltip to visualize the current request. // You might want to display a tooltip to visualize the current request SearchBuffer
// When SingleCharMode is set: // When SingleCharMode is set:
// - it is better to NOT display a tooltip of other on-screen display indicator. // - it is better to NOT display a tooltip of other on-screen display indicator.
// - the index of the currently focused item is required. // - the index of the currently focused item is required.
// if your SetNextItemSelectionData() values are index, you can obtain it from ImGuiMultiSelectIO::NavIdItem, otherwise from g.NavLastValidSelectionUserData. // if your SetNextItemSelectionData() values are indices, you can obtain it from ImGuiMultiSelectIO::NavIdItem, otherwise from g.NavLastValidSelectionUserData.
int ImGui::TypingSelectFindTargetIndex(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx) int ImGui::TypingSelectFindMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx)
{ {
if (req->SelectRequest == false) if (req == NULL || req->SelectRequest == false) // Support NULL parameter so both calls can be done from same spot.
return -1; return -1;
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
g.NavDisableMouseHover = true; int idx = -1;
if (req->SingleCharMode && (req->Flags & ImGuiTypingSelectFlags_AllowSingleCharMode)) if (req->SingleCharMode && (req->Flags & ImGuiTypingSelectFlags_AllowSingleCharMode))
idx = TypingSelectFindNextSingleCharMatch(req, items_count, get_item_name_func, user_data, nav_item_idx);
else
idx = TypingSelectFindBestLeadingMatch(req, items_count, get_item_name_func, user_data);
if (idx != -1)
g.NavDisableMouseHover = true;
return idx;
}
// Special handling when a single character is repeated: perform search on a single letter and goes to next.
int ImGui::TypingSelectFindNextSingleCharMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data, int nav_item_idx)
{ {
// FIXME: Assume selection user data is index. Would be extremely practical. // FIXME: Assume selection user data is index. Would be extremely practical.
//if (nav_item_idx == -1) //if (nav_item_idx == -1)
// nav_item_idx = (int)g.NavLastValidSelectionUserData; // nav_item_idx = (int)g.NavLastValidSelectionUserData;
// Special handling when a same character is typed twice in a row : perform search on a single letter and goes to next.
int first_match_idx = -1; int first_match_idx = -1;
bool return_next_match = false; bool return_next_match = false;
for (int idx = 0; idx < items_count; idx++) for (int idx = 0; idx < items_count; idx++)
@ -6759,7 +6767,8 @@ int ImGui::TypingSelectFindTargetIndex(ImGuiTypingSelectRequest* req, int items_
return first_match_idx; // First result return first_match_idx; // First result
} }
// Find longest match in item list int ImGui::TypingSelectFindBestLeadingMatch(ImGuiTypingSelectRequest* req, int items_count, const char* (*get_item_name_func)(void*, int), void* user_data)
{
int longest_match_idx = -1; int longest_match_idx = -1;
int longest_match_len = 0; int longest_match_len = 0;
for (int idx = 0; idx < items_count; idx++) for (int idx = 0; idx < items_count; idx++)