From 9afeae399826015357962607b4aeb0109fde698e Mon Sep 17 00:00:00 2001 From: Lucas Lazare Date: Mon, 4 Mar 2019 23:43:28 -0500 Subject: [PATCH] Added InputTextHinted --- imgui.h | 4 ++- imgui_demo.cpp | 6 ++++- imgui_widgets.cpp | 56 ++++++++++++++++++++++++++++++++++----- misc/cpp/imgui_stdlib.cpp | 12 +++++++++ misc/cpp/imgui_stdlib.h | 1 + 5 files changed, 70 insertions(+), 9 deletions(-) diff --git a/imgui.h b/imgui.h index eeb9b81de..3fbfa1da6 100644 --- a/imgui.h +++ b/imgui.h @@ -450,6 +450,7 @@ namespace ImGui // - Most of the ImGuiInputTextFlags flags are only useful for InputText() and not for InputFloatX, InputIntX, InputDouble etc. IMGUI_API bool InputText(const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputTextMultiline(const char* label, char* buf, size_t buf_size, const ImVec2& size = ImVec2(0,0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); + IMGUI_API bool InputTextHinted(const char* label, const char* hint, char* buf, size_t buf_size, bool* is_user_data, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputFloat(const char* label, float* v, float step = 0.0f, float step_fast = 0.0f, const char* format = "%.3f", ImGuiInputTextFlags flags = 0); IMGUI_API bool InputFloat2(const char* label, float v[2], const char* format = "%.3f", ImGuiInputTextFlags flags = 0); IMGUI_API bool InputFloat3(const char* label, float v[3], const char* format = "%.3f", ImGuiInputTextFlags flags = 0); @@ -757,7 +758,8 @@ 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) // [Internal] - ImGuiInputTextFlags_Multiline = 1 << 20 // For internal use by InputTextMultiline() + ImGuiInputTextFlags_Multiline = 1 << 20, // For internal use by InputTextMultiline() + ImGuiInputTextFlags_ShowTextAsDisabled = 1 << 21 // For internal use by InputTextHinted (text within the input text field is showed with the ImGuiCol_TextDisabled color) }; // Flags for ImGui::TreeNodeEx(), ImGui::CollapsingHeader*() diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 080d92bd4..16659c309 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -481,10 +481,14 @@ static void ShowDemoWindowWidgets() { static char str0[128] = "Hello, world!"; - static int i0 = 123; ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0)); ImGui::SameLine(); ShowHelpMarker("USER:\nHold SHIFT or use mouse to select text.\n" "CTRL+Left/Right to word jump.\n" "CTRL+A or double-click to select all.\n" "CTRL+X,CTRL+C,CTRL+V clipboard.\n" "CTRL+Z,CTRL+Y undo/redo.\n" "ESCAPE to revert.\n\nPROGRAMMER:\nYou can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputText() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example (this is not demonstrated in imgui_demo.cpp)."); + static char str1[128] = ""; + static bool is_user_data{false}; + ImGui::InputTextHinted("hinted input text", "type text here", str1, IM_ARRAYSIZE(str1), &is_user_data); + + static int i0 = 123; ImGui::InputInt("input int", &i0); ImGui::SameLine(); ShowHelpMarker("You can apply arithmetic operators +,*,/ on numerical values.\n e.g. [ 100 ], input \'*2\', result becomes [ 200 ]\nUse +- to subtract.\n"); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index abdeca0c6..26348b643 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -2882,10 +2882,11 @@ bool ImGui::InputDouble(const char* label, double* v, double step, double step_f } //------------------------------------------------------------------------- -// [SECTION] Widgets: InputText, InputTextMultiline +// [SECTION] Widgets: InputText, InputTextMultiline, InputTextHinted //------------------------------------------------------------------------- // - InputText() // - InputTextMultiline() +// - InputTextHinted() // - InputTextEx() [Internal] //------------------------------------------------------------------------- @@ -2900,6 +2901,41 @@ bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, co return InputTextEx(label, buf, (int)buf_size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data); } +bool ImGui::InputTextHinted(const char* label, const char* hint, char* buf, size_t buf_size, bool* is_user_data, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) +{ + ImGuiWindow* window = GetCurrentWindow(); + const ImGuiID id = window->GetID(label); + + if (id != GetActiveID()) { + if (buf_size > 0 && !*buf) { + unsigned int len = (unsigned int)strlen(hint) + 1; + IM_ASSERT(buf_size >= len); + memcpy(buf, hint, len); + *is_user_data = false; + } + } else { + if (!*is_user_data) { + ImGuiInputTextState& state = GImGui->InputTextState; + state.TextW[0] = '\0'; + state.CurLenW = 0; + state.TextA[0] = '\0'; + state.CurLenA = 0; + state.InitialTextA[0] = '\0'; + state.Stb.cursor = 0; + *is_user_data = true; + } + } + + if (!*is_user_data) { + ImGuiInputTextFlags CallbackFlags = ImGuiInputTextFlags_CallbackCompletion | ImGuiInputTextFlags_CallbackHistory | ImGuiInputTextFlags_CallbackAlways | ImGuiInputTextFlags_CallbackCharFilter; + + InputTextEx(label, buf, (int) buf_size, ImVec2(0, 0), (flags | ImGuiInputTextFlags_ShowTextAsDisabled) & ~CallbackFlags, NULL, NULL); + return false; + } else { + return InputTextEx(label, buf, (int)buf_size, ImVec2(0,0), flags, callback, user_data); + } +} + static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end) { int line_count = 0; @@ -3859,8 +3895,10 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 // We test for 'buf_display_max_length' as a way to avoid some pathological cases (e.g. single-line 1 MB string) which would make ImDrawList crash. buf_display = (!is_readonly && state->TextAIsValid) ? state->TextA.Data : buf; buf_display_end = buf_display + state->CurLenA; - if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length) - draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos - draw_scroll, GetColorU32(ImGuiCol_Text), buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect); + if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length) { + ImGuiCol text_color = flags & ImGuiInputTextFlags_ShowTextAsDisabled ? ImGuiCol_TextDisabled : ImGuiCol_Text; + draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos - draw_scroll, GetColorU32(text_color), buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect); + } // Draw blinking cursor if (render_cursor) @@ -3869,8 +3907,10 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 bool cursor_is_visible = (!g.IO.ConfigInputTextCursorBlink) || (state->CursorAnim <= 0.0f) || ImFmod(state->CursorAnim, 1.20f) <= 0.80f; ImVec2 cursor_screen_pos = draw_pos + cursor_offset - draw_scroll; ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f); - if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect)) - draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text)); + if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect)) { + ImGuiCol text_color = flags & ImGuiInputTextFlags_ShowTextAsDisabled ? ImGuiCol_TextDisabled : ImGuiCol_Text; + draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(text_color)); + } // Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.) if (!is_readonly) @@ -3887,8 +3927,10 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 buf_display_end = buf_display + state->CurLenA; else buf_display_end = buf_display + strlen(buf_display); - if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length) - draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos, GetColorU32(ImGuiCol_Text), buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect); + if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length) { + ImGuiCol text_color = flags & ImGuiInputTextFlags_ShowTextAsDisabled ? ImGuiCol_TextDisabled : ImGuiCol_Text; + draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos, GetColorU32(text_color), buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect); + } } if (is_multiline) diff --git a/misc/cpp/imgui_stdlib.cpp b/misc/cpp/imgui_stdlib.cpp index 694813a48..0791b695a 100644 --- a/misc/cpp/imgui_stdlib.cpp +++ b/misc/cpp/imgui_stdlib.cpp @@ -63,3 +63,15 @@ bool ImGui::InputTextMultiline(const char* label, std::string* str, const ImVec2 cb_user_data.ChainCallbackUserData = user_data; return InputTextMultiline(label, (char*)str->c_str(), str->capacity() + 1, size, flags, InputTextCallback, &cb_user_data); } + +bool ImGui::InputTextHinted(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) +{ + IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); + flags |= ImGuiInputTextFlags_CallbackResize; + + InputTextCallback_UserData cb_user_data; + cb_user_data.Str = str; + cb_user_data.ChainCallback = callback; + cb_user_data.ChainCallbackUserData = user_data; + return InputTextHinted(label, hint, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data); +} diff --git a/misc/cpp/imgui_stdlib.h b/misc/cpp/imgui_stdlib.h index 06b06b9ad..a1a00588c 100644 --- a/misc/cpp/imgui_stdlib.h +++ b/misc/cpp/imgui_stdlib.h @@ -19,4 +19,5 @@ namespace ImGui // Because text input needs dynamic resizing, we need to setup a callback to grow the capacity IMGUI_API bool InputText(const char* label, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); IMGUI_API bool InputTextMultiline(const char* label, std::string* str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); + IMGUI_API bool InputTextHinted(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); }