mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-22 03:47:00 +00:00
WIP insert mode (2863)
missing cursor rendering (keep caret when on carriage return) missing storage of insert state
This commit is contained in:
parent
287bd9b984
commit
30f2ca893f
@ -1272,6 +1272,7 @@ static void ShowDemoWindowWidgets()
|
|||||||
static ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput;
|
static ImGuiInputTextFlags flags = ImGuiInputTextFlags_AllowTabInput;
|
||||||
HelpMarker("You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputTextMultiline() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example. (This is not demonstrated in imgui_demo.cpp because we don't want to include <string> in here)");
|
HelpMarker("You can use the ImGuiInputTextFlags_CallbackResize facility if you need to wire InputTextMultiline() to a dynamic string type. See misc/cpp/imgui_stdlib.h for an example. (This is not demonstrated in imgui_demo.cpp because we don't want to include <string> in here)");
|
||||||
ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly);
|
ImGui::CheckboxFlags("ImGuiInputTextFlags_ReadOnly", &flags, ImGuiInputTextFlags_ReadOnly);
|
||||||
|
ImGui::CheckboxFlags("ImGuiInputTextFlags_AlwaysOverwrite", &flags, ImGuiInputTextFlags_AlwaysOverwrite);
|
||||||
ImGui::CheckboxFlags("ImGuiInputTextFlags_AllowTabInput", &flags, ImGuiInputTextFlags_AllowTabInput);
|
ImGui::CheckboxFlags("ImGuiInputTextFlags_AllowTabInput", &flags, ImGuiInputTextFlags_AllowTabInput);
|
||||||
ImGui::CheckboxFlags("ImGuiInputTextFlags_CtrlEnterForNewLine", &flags, ImGuiInputTextFlags_CtrlEnterForNewLine);
|
ImGui::CheckboxFlags("ImGuiInputTextFlags_CtrlEnterForNewLine", &flags, ImGuiInputTextFlags_CtrlEnterForNewLine);
|
||||||
ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), flags);
|
ImGui::InputTextMultiline("##source", text, IM_ARRAYSIZE(text), ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 16), flags);
|
||||||
|
@ -976,6 +976,7 @@ struct IMGUI_API ImGuiInputTextState
|
|||||||
bool CursorFollow; // set when we want scrolling to follow the current cursor position (not always!)
|
bool CursorFollow; // set when we want scrolling to follow the current cursor position (not always!)
|
||||||
bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection
|
bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection
|
||||||
bool Edited; // edited this frame
|
bool Edited; // edited this frame
|
||||||
|
bool OverwriteMode; // toggle with INSERT key
|
||||||
ImGuiInputTextFlags UserFlags; // Temporarily set while we call user's callback
|
ImGuiInputTextFlags UserFlags; // Temporarily set while we call user's callback
|
||||||
ImGuiInputTextCallback UserCallback; // "
|
ImGuiInputTextCallback UserCallback; // "
|
||||||
void* UserCallbackData; // "
|
void* UserCallbackData; // "
|
||||||
|
@ -3672,6 +3672,7 @@ static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const Im
|
|||||||
#define STB_TEXTEDIT_K_WORDRIGHT 0x20000D // keyboard input to move cursor right one word
|
#define STB_TEXTEDIT_K_WORDRIGHT 0x20000D // keyboard input to move cursor right one word
|
||||||
#define STB_TEXTEDIT_K_PGUP 0x20000E // keyboard input to move cursor up a page
|
#define STB_TEXTEDIT_K_PGUP 0x20000E // keyboard input to move cursor up a page
|
||||||
#define STB_TEXTEDIT_K_PGDOWN 0x20000F // keyboard input to move cursor down a page
|
#define STB_TEXTEDIT_K_PGDOWN 0x20000F // keyboard input to move cursor down a page
|
||||||
|
#define STB_TEXTEDIT_K_INSERT 0x200010 // keyboard input to toggle insert mode
|
||||||
#define STB_TEXTEDIT_K_SHIFT 0x400000
|
#define STB_TEXTEDIT_K_SHIFT 0x400000
|
||||||
|
|
||||||
#define STB_TEXTEDIT_IMPLEMENTATION
|
#define STB_TEXTEDIT_IMPLEMENTATION
|
||||||
@ -3980,8 +3981,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
if (!is_multiline && focus_requested_by_code)
|
if (!is_multiline && focus_requested_by_code)
|
||||||
select_all = true;
|
select_all = true;
|
||||||
}
|
}
|
||||||
if (flags & ImGuiInputTextFlags_AlwaysOverwrite)
|
|
||||||
state->Stb.insert_mode = 1; // stb field name is indeed incorrect (see #2863)
|
|
||||||
if (!is_multiline && (focus_requested_by_tab || (user_clicked && io.KeyCtrl)))
|
if (!is_multiline && (focus_requested_by_tab || (user_clicked && io.KeyCtrl)))
|
||||||
select_all = true;
|
select_all = true;
|
||||||
}
|
}
|
||||||
@ -4064,6 +4063,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
state->UserCallback = callback;
|
state->UserCallback = callback;
|
||||||
state->UserCallbackData = callback_user_data;
|
state->UserCallbackData = callback_user_data;
|
||||||
|
|
||||||
|
// Update overwrite / insert mode
|
||||||
|
state->Stb.insert_mode = (flags & ImGuiInputTextFlags_AlwaysOverwrite) ? 1 : state->OverwriteMode; // stb field name is confusing (see #2863)
|
||||||
|
|
||||||
// Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
|
// Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
|
||||||
// Down the line we should have a cleaner library-wide concept of Selected vs Active.
|
// Down the line we should have a cleaner library-wide concept of Selected vs Active.
|
||||||
g.ActiveIdAllowOverlap = !io.MouseDown[0];
|
g.ActiveIdAllowOverlap = !io.MouseDown[0];
|
||||||
@ -4164,6 +4166,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
else if (IsKeyPressedMap(ImGuiKey_DownArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); }
|
else if (IsKeyPressedMap(ImGuiKey_DownArrow) && is_multiline) { if (io.KeyCtrl) SetScrollY(draw_window, ImMin(draw_window->Scroll.y + g.FontSize, GetScrollMaxY())); else state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTEND : STB_TEXTEDIT_K_DOWN) | k_mask); }
|
||||||
else if (IsKeyPressedMap(ImGuiKey_PageUp) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGUP | k_mask); scroll_y -= row_count_per_page * g.FontSize; }
|
else if (IsKeyPressedMap(ImGuiKey_PageUp) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGUP | k_mask); scroll_y -= row_count_per_page * g.FontSize; }
|
||||||
else if (IsKeyPressedMap(ImGuiKey_PageDown) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGDOWN | k_mask); scroll_y += row_count_per_page * g.FontSize; }
|
else if (IsKeyPressedMap(ImGuiKey_PageDown) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGDOWN | k_mask); scroll_y += row_count_per_page * g.FontSize; }
|
||||||
|
else if (IsKeyPressedMap(ImGuiKey_Insert) && !is_readonly) { if ((flags & ImGuiInputTextFlags_AlwaysOverwrite) == 0) { state->OnKeyPressed(STB_TEXTEDIT_K_INSERT | k_mask); state->OverwriteMode = state->Stb.insert_mode != 0; } }
|
||||||
else if (IsKeyPressedMap(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
|
else if (IsKeyPressedMap(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
|
||||||
else if (IsKeyPressedMap(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
|
else if (IsKeyPressedMap(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
|
||||||
else if (IsKeyPressedMap(ImGuiKey_Delete) && !is_readonly) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
|
else if (IsKeyPressedMap(ImGuiKey_Delete) && !is_readonly) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
|
||||||
@ -4585,27 +4588,44 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
const ImVec2 cursor_screen_pos = draw_pos + cursor_offset - draw_scroll;
|
||||||
|
bool cursor_is_visible = false;
|
||||||
|
bool cursor_is_overwrite_mode = false;
|
||||||
|
if (render_cursor)
|
||||||
|
{
|
||||||
|
state->CursorAnim += io.DeltaTime;
|
||||||
|
cursor_is_visible = (!g.IO.ConfigInputTextCursorBlink) || (state->CursorAnim <= 0.0f) || ImFmod(state->CursorAnim, 1.20f) <= 0.80f;
|
||||||
|
const bool cursor_at_eol = state->TextW[state->Stb.cursor] == 0 || state->TextW[state->Stb.cursor] == '\n';
|
||||||
|
cursor_is_overwrite_mode = state->Stb.insert_mode && !state->HasSelection() && !cursor_at_eol;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw blinking cursor (overwrite cursor)
|
||||||
|
if (cursor_is_visible && cursor_is_overwrite_mode)
|
||||||
|
{
|
||||||
|
ImVec2 rect_size = InputTextCalcTextSizeW(&state->TextW[state->Stb.cursor], &state->TextW[state->Stb.cursor] + 1, NULL, NULL, false);
|
||||||
|
ImRect cursor_rect(cursor_screen_pos.x, cursor_screen_pos.y - rect_size.y, cursor_screen_pos.x + rect_size.x, cursor_screen_pos.y);
|
||||||
|
if (cursor_rect.Overlaps(clip_rect))
|
||||||
|
draw_window->DrawList->AddRectFilled(cursor_rect.Min, cursor_rect.Max, GetColorU32(ImGuiCol_Text, 0.20f));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw text 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)
|
||||||
{
|
{
|
||||||
ImU32 col = GetColorU32(is_displaying_hint ? ImGuiCol_TextDisabled : ImGuiCol_Text);
|
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_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 (append cursor)
|
||||||
if (render_cursor)
|
if (cursor_is_visible && !cursor_is_overwrite_mode)
|
||||||
{
|
{
|
||||||
state->CursorAnim += io.DeltaTime;
|
ImRect cursor_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x, cursor_screen_pos.y - 0.5f);
|
||||||
bool cursor_is_visible = (!g.IO.ConfigInputTextCursorBlink) || (state->CursorAnim <= 0.0f) || ImFmod(state->CursorAnim, 1.20f) <= 0.80f;
|
if (cursor_rect.Overlaps(clip_rect))
|
||||||
ImVec2 cursor_screen_pos = draw_pos + cursor_offset - draw_scroll;
|
draw_window->DrawList->AddLine(cursor_rect.Min, cursor_rect.Max, GetColorU32(ImGuiCol_Text));
|
||||||
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));
|
|
||||||
|
|
||||||
// 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)
|
|
||||||
g.PlatformImePos = ImVec2(cursor_screen_pos.x - 1.0f, cursor_screen_pos.y - g.FontSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 (cursor_is_visible && !is_readonly)
|
||||||
|
g.PlatformImePos = ImVec2(cursor_screen_pos.x - 1.0f, cursor_screen_pos.y - g.FontSize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -740,7 +740,9 @@ retry:
|
|||||||
if (c == '\n' && state->single_line)
|
if (c == '\n' && state->single_line)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
|
if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)
|
||||||
|
&& (STB_TEXTEDIT_GETCHAR(str, state->cursor) != STB_TEXTEDIT_NEWLINE) // [DEAR IMGUI]
|
||||||
|
) {
|
||||||
stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
|
stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
|
||||||
STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
|
STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
|
||||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
|
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, &ch, 1)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user