mirror of
				https://github.com/Drezil/imgui.git
				synced 2025-10-31 13:11:05 +01:00 
			
		
		
		
	InputText: made double-click select word, triple-line select line. Word delimitation logic differs slightly from the one used by CTRL+arrows. (#2244)
This commit is contained in:
		| @@ -39,6 +39,8 @@ Breaking Changes: | ||||
| Other Changes: | ||||
|  | ||||
| - Added IsMouseTripleClicked() function. Tracking multi-click count in IO structure. (#3229) [@kudaba] | ||||
| - InputText: made double-click select word, triple-line select line. Word delimitation logic differs | ||||
|   slightly from the one used by CTRL+arrows. (#2244) | ||||
| - Backends: Vulkan: Call vkCmdSetScissor() at the end of render with a full-viewport to reduce | ||||
|   likehood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling | ||||
|   vkCmdSetScissor() explicitly every frame. (#4644) | ||||
|   | ||||
| @@ -3679,17 +3679,18 @@ static void    STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* ob | ||||
| } | ||||
|  | ||||
| // When ImGuiInputTextFlags_Password is set, we don't want actions such as CTRL+Arrow to leak the fact that underlying data are blanks or separators. | ||||
| static bool is_separator(unsigned int c)                                        { return ImCharIsBlankW(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; } | ||||
| static bool is_separator(unsigned int c)                                        { return ImCharIsBlankW(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|' || c=='\n' || c=='\r'; } | ||||
| static int  is_word_boundary_from_right(ImGuiInputTextState* obj, int idx)      { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (is_separator(obj->TextW[idx - 1]) && !is_separator(obj->TextW[idx]) ) : 1; } | ||||
| static int  is_word_boundary_from_left(ImGuiInputTextState* obj, int idx)       { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (!is_separator(obj->TextW[idx - 1]) && is_separator(obj->TextW[idx])) : 1; } | ||||
| static int  STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx)   { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; } | ||||
| #ifdef __APPLE__    // FIXME: Move setting to IO structure | ||||
| static int  is_word_boundary_from_left(ImGuiInputTextState* obj, int idx)       { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (!is_separator(obj->TextW[idx - 1]) && is_separator(obj->TextW[idx]) ) : 1; } | ||||
| static int  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(ImGuiInputTextState* obj, int idx)  { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; } | ||||
| #else | ||||
| static int  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(ImGuiInputTextState* obj, int idx)  { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; } | ||||
| #endif | ||||
| static int  STB_TEXTEDIT_MOVEWORDRIGHT_MAC(ImGuiInputTextState* obj, int idx)   { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; } | ||||
| static int  STB_TEXTEDIT_MOVEWORDRIGHT_WIN(ImGuiInputTextState* obj, int idx)   { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; } | ||||
| #define STB_TEXTEDIT_MOVEWORDLEFT   STB_TEXTEDIT_MOVEWORDLEFT_IMPL    // They need to be #define for stb_textedit.h | ||||
| #define STB_TEXTEDIT_MOVEWORDRIGHT  STB_TEXTEDIT_MOVEWORDRIGHT_IMPL | ||||
| #ifdef __APPLE__    // FIXME: Move setting to IO structure | ||||
| #define STB_TEXTEDIT_MOVEWORDRIGHT  STB_TEXTEDIT_MOVEWORDRIGHT_MAC | ||||
| #else | ||||
| #define STB_TEXTEDIT_MOVEWORDRIGHT  STB_TEXTEDIT_MOVEWORDRIGHT_WIN | ||||
| #endif | ||||
|  | ||||
| static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n) | ||||
| { | ||||
| @@ -3881,11 +3882,12 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f | ||||
|     // Generic named filters | ||||
|     if (apply_named_filters && (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_CharsScientific))) | ||||
|     { | ||||
|         // The libc allows overriding locale, with e.g. 'setlocale(LC_NUMERIC, "de_DE.UTF-8");' which affect the output/input of printf/scanf. | ||||
|         // The libc allows overriding locale, with e.g. 'setlocale(LC_NUMERIC, "de_DE.UTF-8");' which affect the output/input of printf/scanf to use e.g. ',' instead of '.'. | ||||
|         // The standard mandate that programs starts in the "C" locale where the decimal point is '.'. | ||||
|         // We don't really intend to provide widespread support for it, but out of empathy for people stuck with using odd API, we support the bare minimum aka overriding the decimal point. | ||||
|         // Change the default decimal_point with: | ||||
|         //   ImGui::GetCurrentContext()->PlatformLocaleDecimalPoint = *localeconv()->decimal_point; | ||||
|         // Users of non-default decimal point (in particular ',') may be affected by word-selection logic (is_word_boundary_from_right/is_word_boundary_from_left) functions. | ||||
|         ImGuiContext& g = *GImGui; | ||||
|         const unsigned c_decimal_point = (unsigned int)g.PlatformLocaleDecimalPoint; | ||||
|  | ||||
| @@ -4176,19 +4178,41 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_ | ||||
|         const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y) : (g.FontSize * 0.5f)); | ||||
|  | ||||
|         const bool is_osx = io.ConfigMacOSXBehaviors; | ||||
|         if (select_all || (hovered && !is_osx && io.MouseClickedCount[0] == 2)) | ||||
|         if (select_all) | ||||
|         { | ||||
|             state->SelectAll(); | ||||
|             state->SelectedAllMouseLock = true; | ||||
|         } | ||||
|         else if (hovered && is_osx && io.MouseClickedCount[0] == 2) | ||||
|         else if (hovered && io.MouseClickedCount[0] >= 2 && !io.KeyShift) | ||||
|         { | ||||
|             // Double-click select a word only, OS X style (by simulating keystrokes) | ||||
|             state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT); | ||||
|             state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT); | ||||
|             stb_textedit_click(state, &state->Stb, mouse_x, mouse_y); | ||||
|             const int multiclick_count = (io.MouseClickedCount[0] - 2); | ||||
|             if ((multiclick_count % 2) == 0) | ||||
|             { | ||||
|                 // Double-click: Select word | ||||
|                 // We always use the "Mac" word advance for double-click select vs CTRL+Right which use the platform dependent variant: | ||||
|                 // FIXME: There are likely many ways to improve this behavior, but there's no "right" behavior (depends on use-case, software, OS) | ||||
|                 const bool is_bol = (state->Stb.cursor == 0) || ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb.cursor - 1) == '\n'; | ||||
|                 if (STB_TEXT_HAS_SELECTION(&state->Stb) || !is_bol) | ||||
|                     state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT); | ||||
|                 //state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT); | ||||
|                 if (!STB_TEXT_HAS_SELECTION(&state->Stb)) | ||||
|                     ImStb::stb_textedit_prep_selection_at_cursor(&state->Stb); | ||||
|                 state->Stb.cursor = ImStb::STB_TEXTEDIT_MOVEWORDRIGHT_MAC(state, state->Stb.cursor); | ||||
|                 state->Stb.select_end = state->Stb.cursor; | ||||
|                 ImStb::stb_textedit_clamp(state, &state->Stb); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 // Triple-click: Select line | ||||
|                 state->OnKeyPressed(STB_TEXTEDIT_K_LINESTART); | ||||
|                 state->OnKeyPressed(STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT); | ||||
|             } | ||||
|             state->CursorAnimReset(); | ||||
|         } | ||||
|         else if (io.MouseClicked[0] && !state->SelectedAllMouseLock) | ||||
|         { | ||||
|             // FIXME: unselect on late click could be done release? | ||||
|             if (hovered) | ||||
|             { | ||||
|                 stb_textedit_click(state, &state->Stb, mouse_x, mouse_y); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user