TypingSelect: Added first version of GetTypingSelectRequest() API.

# Conflicts:
#	imgui_internal.h
#	imgui_widgets.cpp
This commit is contained in:
ocornut 2023-09-08 17:16:19 +02:00
parent 7812039402
commit 0962c9fb72
2 changed files with 139 additions and 0 deletions

View File

@ -23,6 +23,7 @@ Index of this file:
// [SECTION] Inputs support
// [SECTION] Clipper support
// [SECTION] Navigation support
// [SECTION] Typing-select support
// [SECTION] Columns support
// [SECTION] Multi-select support
// [SECTION] Docking support
@ -153,6 +154,8 @@ struct ImGuiTableInstanceData; // Storage for one instance of a same table
struct ImGuiTableTempData; // Temporary storage for one table (one per table in the stack), shared between tables.
struct ImGuiTableSettings; // Storage for a table .ini settings
struct ImGuiTableColumnsSettings; // Storage for a column .ini settings
struct ImGuiTypingSelectData; // Storage for GetTypingSelectRequest()
struct ImGuiTypingSelectRequest; // Storage for GetTypingSelectRequest() (aimed to be public)
struct ImGuiWindow; // Storage for one window
struct ImGuiWindowTempData; // Temporary storage for one window (that's the data which in theory we could ditch at the end of the frame, in practice we currently keep it for each window)
struct ImGuiWindowSettings; // Storage for a window .ini settings (we keep one of those even if the actual window wasn't instanced during this session)
@ -178,6 +181,7 @@ typedef int ImGuiScrollFlags; // -> enum ImGuiScrollFlags_ // F
typedef int ImGuiSeparatorFlags; // -> enum ImGuiSeparatorFlags_ // Flags: for SeparatorEx()
typedef int ImGuiTextFlags; // -> enum ImGuiTextFlags_ // Flags: for TextEx()
typedef int ImGuiTooltipFlags; // -> enum ImGuiTooltipFlags_ // Flags: for BeginTooltipEx()
typedef int ImGuiTypingSelectFlags; // -> enum ImGuiTypingSelectFlags_ // Flags: for GetTypingSelectRequest()
typedef void (*ImGuiErrorLogCallback)(void* user_data, const char* fmt, ...);
@ -1532,6 +1536,39 @@ struct ImGuiNavItemData
void Clear() { Window = NULL; ID = FocusScopeId = 0; InFlags = 0; DistBox = DistCenter = DistAxial = FLT_MAX; }
};
//-----------------------------------------------------------------------------
// [SECTION] Typing-select support
//-----------------------------------------------------------------------------
// Flags for GetTypingSelectRequest()
enum ImGuiTypingSelectFlags_
{
ImGuiTypingSelectFlags_None = 0,
ImGuiTypingSelectFlags_AllowBackspace = 1 << 0, // Backspace to delete character inputs. If using: ensure GetTypingSelectRequest() is not called more than once per frame (filter by e.g. focus state)
};
// Returned by GetTypingSelectRequest(), designed to eventually be public.
struct IMGUI_API ImGuiTypingSelectRequest
{
const char* SearchBuffer;
int SearchBufferLen;
bool SelectRequest; // Set when buffer was modified this frame, requesting a selection.
bool RepeatCharMode; // Notify when buffer contains same character repeated, to implement special mode.
ImS8 RepeatCharSize; // Length in bytes of first letter codepoint (1 for ascii, 2-4 for UTF-8). If (SearchBufferLen==RepeatCharSize) only 1 letter has been input.
};
// Storage for GetTypingSelectRequest()
struct IMGUI_API ImGuiTypingSelectData
{
ImGuiTypingSelectRequest Request; // User-facing data
char SearchBuffer[64]; // Search buffer: no need to make dynamic as this search is very transient.
ImGuiID FocusScope;
int LastRequestFrame = 0;
float LastRequestTime = 0.0f;
ImGuiTypingSelectData() { memset(this, 0, sizeof(*this)); }
};
//-----------------------------------------------------------------------------
// [SECTION] Columns support
//-----------------------------------------------------------------------------
@ -2019,6 +2056,7 @@ struct ImGuiContext
short TooltipOverrideCount;
ImVector<char> ClipboardHandlerData; // If no custom clipboard handler is defined
ImVector<ImGuiID> MenusIdSubmittedThisFrame; // A list of menu IDs that were rendered at least once
ImGuiTypingSelectData TypingSelectData;
// Platform support
ImGuiPlatformImeData PlatformImeData; // Data updated by current frame
@ -3057,6 +3095,9 @@ namespace ImGui
IMGUI_API bool IsDragDropPayloadBeingAccepted();
IMGUI_API void RenderDragDropTargetRect(const ImRect& bb);
// Typing-Select API
IMGUI_API const ImGuiTypingSelectRequest* GetTypingSelectRequest(ImGuiTypingSelectFlags flags = ImGuiTypingSelectFlags_None);
// 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 BeginColumns(const char* str_id, int count, ImGuiOldColumnFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns().

View File

@ -18,6 +18,7 @@ Index of this file:
// [SECTION] Widgets: ColorEdit, ColorPicker, ColorButton, etc.
// [SECTION] Widgets: TreeNode, CollapsingHeader, etc.
// [SECTION] Widgets: Selectable
// [SECTION] Widgets: Typing-Select support
// [SECTION] Widgets: ListBox
// [SECTION] Widgets: PlotLines, PlotHistogram
// [SECTION] Widgets: Value helpers
@ -6597,6 +6598,103 @@ bool ImGui::Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags
return false;
}
//-------------------------------------------------------------------------
// [SECTION] Widgets: Typing-Select support
//-------------------------------------------------------------------------
// [Experimental] Currently not exposed in public API.
// Consume character inputs and return search request, if any.
// This would typically only be called on the focused window or location you want to grab inputs for, e.g.
// if (ImGui::IsWindowFocused(...))
// if (const ImGuiTypingSelectRequest* req = ImGui::GetTypingSelectRequest())
// if (req->SearchRequest)
// // perform search
// However the code is written in a way where calling it from multiple locations is safe (e.g. to obtain buffer).
const ImGuiTypingSelectRequest* ImGui::GetTypingSelectRequest(ImGuiTypingSelectFlags flags)
{
ImGuiContext& g = *GImGui;
ImGuiTypingSelectData* data = &g.TypingSelectData;
ImGuiTypingSelectRequest* out_request = &data->Request;
// Clear buffer
if (data->SearchBuffer[0] != 0)
{
const float TYPING_SELECT_RESET_TIMER = 1.70f; // FIXME: Potentially move to IO config.
bool clear_buffer = false;
clear_buffer |= (g.NavFocusScopeId != data->FocusScope);
clear_buffer |= (data->LastRequestTime + TYPING_SELECT_RESET_TIMER < g.Time);
clear_buffer |= g.NavAnyRequest;
clear_buffer |= g.ActiveId != 0 && g.NavActivateId == 0; // Allow temporary SPACE activation to not interfere
clear_buffer |= IsKeyPressed(ImGuiKey_Escape) || IsKeyPressed(ImGuiKey_Enter);
clear_buffer |= IsKeyPressed(ImGuiKey_Backspace) && (flags & ImGuiTypingSelectFlags_AllowBackspace) == 0;
//if (clear_buffer) { IMGUI_DEBUG_LOG("GetTypingSelectRequest(): Clear SearchBuffer.\n"); }
if (clear_buffer)
data->SearchBuffer[0] = 0;
}
// Append to buffer
const int buffer_max_len = IM_ARRAYSIZE(data->SearchBuffer) - 1;
int buffer_len = (int)strlen(data->SearchBuffer);
bool buffer_changed = false;
for (ImWchar w : g.IO.InputQueueCharacters)
{
if (w < 32 || (buffer_len == 0 && ImCharIsBlankW(w))) // Ignore leading blanks
continue;
int utf8_len = ImTextCountUtf8BytesFromStr(&w, &w + 1);
if (buffer_len + utf8_len > buffer_max_len)
break;
ImTextCharToUtf8(data->SearchBuffer + buffer_len, (unsigned int)w);
buffer_len += utf8_len;
buffer_changed = true;
}
g.IO.InputQueueCharacters.resize(0);
if ((flags & ImGuiTypingSelectFlags_AllowBackspace) && IsKeyPressed(ImGuiKey_Backspace, 0, ImGuiInputFlags_Repeat))
{
char* p = (char*)(void*)ImTextFindPreviousUtf8Codepoint(data->SearchBuffer, data->SearchBuffer + buffer_len);
*p = 0;
buffer_len = (int)(p - data->SearchBuffer);
}
if (buffer_len == 0)
return NULL;
// Return request if any
if (buffer_changed)
{
data->FocusScope = g.NavFocusScopeId;
data->LastRequestFrame = g.FrameCount;
data->LastRequestTime = (float)g.Time;
}
out_request->SearchBuffer = data->SearchBuffer;
out_request->SearchBufferLen = buffer_len;
out_request->SelectRequest = (data->LastRequestFrame == g.FrameCount);
out_request->RepeatCharMode = false;
out_request->RepeatCharSize = 0;
// Calculate if buffer contains the same character repeated.
// - This can be used to implement a special search mode on first character.
// - Performed on UTF-8 codepoint for correctness.
// - RepeatCharMode is always set for first input character, because it usually leads to a "next".
const char* buf_begin = out_request->SearchBuffer;
const char* buf_end = out_request->SearchBuffer + out_request->SearchBufferLen;
const int c0_len = ImTextCountUtf8BytesFromChar(buf_begin, buf_end);
const char* p = buf_begin + c0_len;
for (; p < buf_end; p += c0_len)
if (memcmp(buf_begin, p, (size_t)c0_len) != 0)
break;
out_request->RepeatCharMode = (p == buf_end);
out_request->RepeatCharSize = out_request->RepeatCharMode ? (ImS8)c0_len : 0;
return out_request;
}
//-------------------------------------------------------------------------
// [SECTION] Widgets: Multi-Select support
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
// [SECTION] Widgets: ListBox
//-------------------------------------------------------------------------