From 85f327d8d3710a32bbde08cb8995649ab257b765 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 20 Sep 2022 15:57:58 +0200 Subject: [PATCH] InputText: added ImGuiInputTextFlags_EscapeClearsAll (#5688) --- docs/CHANGELOG.txt | 2 ++ imgui.h | 1 + imgui_demo.cpp | 14 +++++++++----- imgui_widgets.cpp | 37 ++++++++++++++++++++++++++++++------- 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 61bfbbc7f..cbeff3276 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -91,6 +91,8 @@ Other Changes: Enter keep the input active and select all text. - InputText: numerical fields automatically accept full-width characters (U+FF01..U+FF5E) by converting them to half-width (U+0021..U+007E). +- InputText: added ImGuiInputTextFlags_EscapeClearsAll flag: first press on Escape clears + text if any, second press deactivate the InputText(). (#5688) - InputText: added support for shift+click style selection. (#5619) [@procedural] - InputText: clarified that callbacks cannot modify buffer when using the ReadOnly flag. - InputText: fixed minor one-frame selection glitch when reverting with Escape. diff --git a/imgui.h b/imgui.h index 0db55825b..d63623b61 100644 --- a/imgui.h +++ b/imgui.h @@ -1007,6 +1007,7 @@ enum ImGuiInputTextFlags_ ImGuiInputTextFlags_CharsScientific = 1 << 17, // Allow 0123456789.+-*/eE (Scientific notation input) ImGuiInputTextFlags_CallbackResize = 1 << 18, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this) ImGuiInputTextFlags_CallbackEdit = 1 << 19, // Callback on any edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active) + ImGuiInputTextFlags_EscapeClearsAll = 1 << 20, // Escape key clears content if not empty, and deactivate otherwise (constrast to default behavior of Escape to revert) // Obsolete names (will be removed soon) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 9b2a42d2f..c3c821804 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -8,11 +8,15 @@ // Read imgui.cpp for more details, documentation and comments. // Get the latest version at https://github.com/ocornut/imgui +// ------------------------------------------------- +// PLEASE DO NOT REMOVE THIS FILE FROM YOUR PROJECT! +// ------------------------------------------------- // Message to the person tempted to delete this file when integrating Dear ImGui into their codebase: -// Do NOT remove this file from your project! Think again! It is the most useful reference code that you and other -// coders will want to refer to and call. Have the ImGui::ShowDemoWindow() function wired in an always-available -// debug menu of your game/app! Removing this file from your project is hindering access to documentation for everyone -// in your team, likely leading you to poorer usage of the library. +// Think again! It is the most useful reference code that you and other coders will want to refer to and call. +// Have the ImGui::ShowDemoWindow() function wired in an always-available debug menu of your game/app! +// Also include Metrics! ItemPicker! DebugLog! and other debug features. +// Removing this file from your project is hindering access to documentation for everyone in your team, +// likely leading you to poorer usage of the library. // Everything in this file will be stripped out by the linker if you don't call ImGui::ShowDemoWindow(). // If you want to link core Dear ImGui in your shipped builds but want a thorough guarantee that the demo will not be // linked, you can setup your imconfig.h with #define IMGUI_DISABLE_DEMO_WINDOWS and those functions will be empty. @@ -6718,7 +6722,7 @@ struct ExampleAppConsole // Command-line bool reclaim_focus = false; - ImGuiInputTextFlags input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory; + ImGuiInputTextFlags input_text_flags = ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_EscapeClearsAll | ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory; if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), input_text_flags, &TextEditCallbackStub, (void*)this)) { char* s = InputBuf; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index c9c0c9e93..98761f043 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4301,7 +4301,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ } // Process other shortcuts/key-presses - bool cancel_edit = false; + bool revert_edit = false; if (g.ActiveId == id && !g.ActiveIdIsJustActivated && !clear_active_id) { IM_ASSERT(state != NULL); @@ -4372,8 +4372,23 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ } else if (is_cancel) { - clear_active_id = cancel_edit = true; - render_cursor = render_selection = false; + if (flags & ImGuiInputTextFlags_EscapeClearsAll) + { + if (state->CurLenA > 0) + { + revert_edit = true; + } + else + { + render_cursor = render_selection = false; + clear_active_id = true; + } + } + else + { + clear_active_id = revert_edit = true; + render_cursor = render_selection = false; + } } else if (is_undo || is_redo) { @@ -4444,11 +4459,19 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ if (g.ActiveId == id) { IM_ASSERT(state != NULL); - if (cancel_edit && !is_readonly) + if (revert_edit && !is_readonly) { - // Restore initial value. Only return true if restoring to the initial value changes the current buffer contents. - if (strcmp(buf, state->InitialTextA.Data) != 0) + if (flags & ImGuiInputTextFlags_EscapeClearsAll) { + // Clear input + apply_new_text = ""; + apply_new_text_length = 0; + STB_TEXTEDIT_CHARTYPE empty_string; + stb_textedit_replace(state, &state->Stb, &empty_string, 0); + } + else if (strcmp(buf, state->InitialTextA.Data) != 0) + { + // Restore initial value. Only return true if restoring to the initial value changes the current buffer contents. // Push records into the undo stack so we can CTRL+Z the revert operation itself apply_new_text = state->InitialTextA.Data; apply_new_text_length = state->InitialTextA.Size - 1; @@ -4473,7 +4496,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ // When using 'ImGuiInputTextFlags_EnterReturnsTrue' as a special case we reapply the live buffer back to the input buffer before clearing ActiveId, even though strictly speaking it wasn't modified on this frame. // If we didn't do that, code like InputInt() with ImGuiInputTextFlags_EnterReturnsTrue would fail. // This also allows the user to use InputText() with ImGuiInputTextFlags_EnterReturnsTrue without maintaining any user-side storage (please note that if you use this property along ImGuiInputTextFlags_CallbackResize you can end up with your temporary string object unnecessarily allocating once a frame, either store your string data, either if you don't then don't use ImGuiInputTextFlags_CallbackResize). - const bool apply_edit_back_to_user_buffer = !cancel_edit || (validated && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0); + const bool apply_edit_back_to_user_buffer = !revert_edit || (validated && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0); if (apply_edit_back_to_user_buffer) { // Apply new value immediately - copy modified buffer back