Browse Source

InputTextWithHint: Fix for Password fields. Update changelog, demo. (#2400)

omar 6 years ago
parent
commit
c779fbb651
3 changed files with 30 additions and 38 deletions
  1. 3 1
      docs/CHANGELOG.txt
  2. 3 1
      imgui_demo.cpp
  3. 24 36
      imgui_widgets.cpp

+ 3 - 1
docs/CHANGELOG.txt

@@ -45,7 +45,9 @@ Other Changes:
 - Added GetBackgroundDrawList() helper to quickly get access to a ImDrawList that will be rendered
 - Added GetBackgroundDrawList() helper to quickly get access to a ImDrawList that will be rendered
   behind every other windows. (#2391)
   behind every other windows. (#2391)
 - DragScalar, InputScalar, SliderScalar: Added support for u8/s8/u16/s16 data types.
 - DragScalar, InputScalar, SliderScalar: Added support for u8/s8/u16/s16 data types.
-  We are reusing function instances for larger types to reduce code size. (#643, #320, #708, #1011)
+  We are reusing function instances of larger types to reduce code size. (#643, #320, #708, #1011)
+- Added InputTextWithHint() to display a description/hint in the text box when no text
+  has been entered. (#2400) [@Organic-Code, @ocornut]
 - Nav: Fixed a tap on AltGR (e.g. German keyboard) from navigating to the menu layer.
 - Nav: Fixed a tap on AltGR (e.g. German keyboard) from navigating to the menu layer.
 - Nav: Fixed Ctrl+Tab keeping active InputText() of a previous window active after the switch. (#2380)
 - Nav: Fixed Ctrl+Tab keeping active InputText() of a previous window active after the switch. (#2380)
 - Fixed IsItemDeactivated()/IsItemDeactivatedAfterEdit() from not correctly returning true
 - Fixed IsItemDeactivated()/IsItemDeactivatedAfterEdit() from not correctly returning true

+ 3 - 1
imgui_demo.cpp

@@ -770,6 +770,7 @@ static void ShowDemoWindowWidgets()
         // Expose flags as checkbox for the demo
         // Expose flags as checkbox for the demo
         static ImGuiComboFlags flags = 0;
         static ImGuiComboFlags flags = 0;
         ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", (unsigned int*)&flags, ImGuiComboFlags_PopupAlignLeft);
         ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", (unsigned int*)&flags, ImGuiComboFlags_PopupAlignLeft);
+        ImGui::SameLine(); ShowHelpMarker("Only makes a difference if the popup is larger than the combo");
         if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", (unsigned int*)&flags, ImGuiComboFlags_NoArrowButton))
         if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", (unsigned int*)&flags, ImGuiComboFlags_NoArrowButton))
             flags &= ~ImGuiComboFlags_NoPreview;     // Clear the other flag, as we cannot combine both
             flags &= ~ImGuiComboFlags_NoPreview;     // Clear the other flag, as we cannot combine both
         if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", (unsigned int*)&flags, ImGuiComboFlags_NoPreview))
         if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", (unsigned int*)&flags, ImGuiComboFlags_NoPreview))
@@ -934,6 +935,7 @@ static void ShowDemoWindowWidgets()
         static char bufpass[64] = "password123";
         static char bufpass[64] = "password123";
         ImGui::InputText("password", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank);
         ImGui::InputText("password", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank);
         ImGui::SameLine(); ShowHelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
         ImGui::SameLine(); ShowHelpMarker("Display all characters as '*'.\nDisable clipboard cut and copy.\nDisable logging.\n");
+        ImGui::InputTextWithHint("password (w/ hint)", "<password>", bufpass, 64, ImGuiInputTextFlags_Password | ImGuiInputTextFlags_CharsNoBlank);
         ImGui::InputText("password (clear)", bufpass, 64, ImGuiInputTextFlags_CharsNoBlank);
         ImGui::InputText("password (clear)", bufpass, 64, ImGuiInputTextFlags_CharsNoBlank);
 
 
         ImGui::TreePop();
         ImGui::TreePop();
@@ -2177,7 +2179,7 @@ static void ShowDemoWindowPopups()
 
 
         // We can also use OpenPopupOnItemClick() which is the same as BeginPopupContextItem() but without the Begin call.
         // We can also use OpenPopupOnItemClick() which is the same as BeginPopupContextItem() but without the Begin call.
         // So here we will make it that clicking on the text field with the right mouse button (1) will toggle the visibility of the popup above.
         // So here we will make it that clicking on the text field with the right mouse button (1) will toggle the visibility of the popup above.
-        ImGui::Text("(You can also right-click me to the same popup as above.)");
+        ImGui::Text("(You can also right-click me to open the same popup as above.)");
         ImGui::OpenPopupOnItemClick("item context menu", 1);
         ImGui::OpenPopupOnItemClick("item context menu", 1);
 
 
         // When used after an item that has an ID (here the Button), we can skip providing an ID to BeginPopupContextItem().
         // When used after an item that has an ID (here the Button), we can skip providing an ID to BeginPopupContextItem().

+ 24 - 36
imgui_widgets.cpp

@@ -2904,7 +2904,8 @@ bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, co
 
 
 bool ImGui::InputTextWithHint(const char* label, const char* hint, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
 bool ImGui::InputTextWithHint(const char* label, const char* hint, char* buf, size_t buf_size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
 {
 {
-    return InputTextEx(label, hint, buf, (int)buf_size, ImVec2(0,0), flags, callback, user_data);
+    IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline()
+    return InputTextEx(label, hint, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data);
 }
 }
 
 
 static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end)
 static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end)
@@ -3364,8 +3365,18 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     bool value_changed = false;
     bool value_changed = false;
     bool enter_pressed = false;
     bool enter_pressed = false;
 
 
+    // Select the buffer to render.
+    const char* buf_display = ((render_cursor || render_selection || g.ActiveId == id) && !is_readonly && state->TextAIsValid) ? state->TextA.Data : buf;
+    const char* buf_display_end = NULL; // We have specialized paths below for setting the length
+    const bool is_displaying_hint = (hint != NULL && buf_display[0] == 0);
+    if (is_displaying_hint)
+    {
+        buf_display = hint;
+        buf_display_end = hint + strlen(hint);
+    }
+
     // Password pushes a temporary font with only a fallback glyph
     // Password pushes a temporary font with only a fallback glyph
-    if (is_password)
+    if (is_password && !is_displaying_hint)
     {
     {
         const ImFontGlyph* glyph = g.Font->FindGlyph('*');
         const ImFontGlyph* glyph = g.Font->FindGlyph('*');
         ImFont* password_font = &g.InputTextPasswordFont;
         ImFont* password_font = &g.InputTextPasswordFont;
@@ -3729,14 +3740,14 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     // without any carriage return, which would makes ImFont::RenderText() reserve too many vertices and probably crash. Avoid it altogether.
     // without any carriage return, which would makes ImFont::RenderText() reserve too many vertices and probably crash. Avoid it altogether.
     // Note that we only use this limit on single-line InputText(), so a pathologically large line on a InputTextMultiline() would still crash.
     // Note that we only use this limit on single-line InputText(), so a pathologically large line on a InputTextMultiline() would still crash.
     const int buf_display_max_length = 2 * 1024 * 1024;
     const int buf_display_max_length = 2 * 1024 * 1024;
-    const char* buf_display = NULL;
-    const char* buf_display_end = NULL;
-    ImGuiCol text_color = ImGuiCol_COUNT;
 
 
     // Render text. We currently only render selection when the widget is active or while scrolling.
     // Render text. We currently only render selection when the widget is active or while scrolling.
     // FIXME: We could remove the '&& render_cursor' to keep rendering selection when inactive.
     // FIXME: We could remove the '&& render_cursor' to keep rendering selection when inactive.
     if (render_cursor || render_selection)
     if (render_cursor || render_selection)
     {
     {
+        if (!is_displaying_hint)
+            buf_display_end = buf_display + state->CurLenA;
+
         // Render text (with cursor and selection)
         // Render text (with cursor and selection)
         // This is going to be messy. We need to:
         // This is going to be messy. We need to:
         // - Display the text (this alone can be more easily clipped)
         // - Display the text (this alone can be more easily clipped)
@@ -3868,25 +3879,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
             }
             }
         }
         }
 
 
-        if (state->CurLenA != 0 || hint == NULL)
-        {
-            buf_display = (!is_readonly && state->TextAIsValid) ? state->TextA.Data : buf;
-            buf_display_end = buf_display + state->CurLenA;
-            text_color = ImGuiCol_Text;
-        }
-        else
-        {
-            buf_display = hint;
-            buf_display_end = hint + strlen(hint);
-            text_color = ImGuiCol_TextDisabled;
-        }
-
-
         // 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.
         // 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.
         if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length)
         if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length)
         {
         {
-            IM_ASSERT(text_color != ImGuiCol_COUNT);
-            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);
+            ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text);
+            draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos - draw_scroll, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect);
         }
         }
 
 
         // Draw blinking cursor
         // Draw blinking cursor
@@ -3907,26 +3904,17 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
     else
     else
     {
     {
         // Render text only (no selection, no cursor)
         // Render text only (no selection, no cursor)
-        text_color = ImGuiCol_Text;
-        buf_display = (g.ActiveId == id && !is_readonly && state->TextAIsValid) ? state->TextA.Data : buf;
         if (is_multiline)
         if (is_multiline)
             text_size = ImVec2(size.x, InputTextCalcTextLenAndLineCount(buf_display, &buf_display_end) * g.FontSize); // We don't need width
             text_size = ImVec2(size.x, InputTextCalcTextLenAndLineCount(buf_display, &buf_display_end) * g.FontSize); // We don't need width
-        else if (g.ActiveId == id)
+        else if (!is_displaying_hint && g.ActiveId == id)
             buf_display_end = buf_display + state->CurLenA;
             buf_display_end = buf_display + state->CurLenA;
-        else
+        else if (!is_displaying_hint)
             buf_display_end = buf_display + strlen(buf_display);
             buf_display_end = buf_display + strlen(buf_display);
 
 
-        if (buf_display_end == buf_display && hint != NULL)
-        {
-            buf_display = hint;
-            buf_display_end = buf_display + strlen(buf_display);
-            text_color = ImGuiCol_TextDisabled;
-        }
-
         if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length)
         if (is_multiline || (buf_display_end - buf_display) < buf_display_max_length)
         {
         {
-            IM_ASSERT(text_color != ImGuiCol_COUNT);
-            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);
+            ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text);
+            draw_window->DrawList->AddText(g.Font, g.FontSize, draw_pos, col, buf_display, buf_display_end, 0.0f, is_multiline ? NULL : &clip_rect);
         }
         }
     }
     }
 
 
@@ -3937,11 +3925,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
         EndGroup();
         EndGroup();
     }
     }
 
 
-    if (is_password)
+    if (is_password && !is_displaying_hint)
         PopFont();
         PopFont();
 
 
     // Log as text
     // Log as text
-    if (g.LogEnabled && !is_password)
+    if (g.LogEnabled && !(is_password && !is_displaying_hint))
         LogRenderedText(&draw_pos, buf_display, buf_display_end);
         LogRenderedText(&draw_pos, buf_display, buf_display_end);
 
 
     if (label_size.x > 0)
     if (label_size.x > 0)