mirror of
https://github.com/ocornut/imgui.git
synced 2024-11-27 17:10:57 +01:00
InputText: amends: add stb_textedit_text() api. (#7925)
It seems sensible to push this change in stb_textedit repo eventually.
This commit is contained in:
parent
d1b7817959
commit
1674fe96ff
@ -1130,6 +1130,7 @@ struct IMGUI_API ImGuiInputTextState
|
|||||||
void ClearText() { CurLenA = 0; TextA[0] = 0; CursorClamp(); }
|
void ClearText() { CurLenA = 0; TextA[0] = 0; CursorClamp(); }
|
||||||
void ClearFreeMemory() { TextA.clear(); InitialTextA.clear(); }
|
void ClearFreeMemory() { TextA.clear(); InitialTextA.clear(); }
|
||||||
void OnKeyPressed(int key); // Cannot be inline because we call in code in stb_textedit.h implementation
|
void OnKeyPressed(int key); // Cannot be inline because we call in code in stb_textedit.h implementation
|
||||||
|
void OnCharPressed(unsigned int c);
|
||||||
|
|
||||||
// Cursor & Selection
|
// Cursor & Selection
|
||||||
void CursorAnimReset();
|
void CursorAnimReset();
|
||||||
|
@ -3889,7 +3889,6 @@ namespace ImStb
|
|||||||
static int STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj) { return obj->CurLenA; }
|
static int STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj) { return obj->CurLenA; }
|
||||||
static char STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx) { IM_ASSERT(idx <= obj->CurLenA); return obj->TextA[idx]; }
|
static char STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx) { IM_ASSERT(idx <= obj->CurLenA); return obj->TextA[idx]; }
|
||||||
static float STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx) { unsigned int c; ImTextCharFromUtf8(&c, obj->TextA.Data + line_start_idx + char_idx, obj->TextA.Data + obj->TextA.Size); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance((ImWchar)c) * g.FontScale; }
|
static float STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx) { unsigned int c; ImTextCharFromUtf8(&c, obj->TextA.Data + line_start_idx + char_idx, obj->TextA.Data + obj->TextA.Size); if ((ImWchar)c == '\n') return IMSTB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *obj->Ctx; return g.Font->GetCharAdvance((ImWchar)c) * g.FontScale; }
|
||||||
static int STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x200000 ? 0 : key; }
|
|
||||||
static char STB_TEXTEDIT_NEWLINE = '\n';
|
static char STB_TEXTEDIT_NEWLINE = '\n';
|
||||||
static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx)
|
static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx)
|
||||||
{
|
{
|
||||||
@ -4101,12 +4100,18 @@ ImGuiInputTextState::~ImGuiInputTextState()
|
|||||||
|
|
||||||
void ImGuiInputTextState::OnKeyPressed(int key)
|
void ImGuiInputTextState::OnKeyPressed(int key)
|
||||||
{
|
{
|
||||||
//We prematurely convert the key to a UTF8 byte sequence, even for keys where that doesn't even make sense (e.g. arrow keys).
|
stb_textedit_key(this, Stb, key);
|
||||||
//Not optimal but stb_textedit_key will only use the UTF8 values for valid character keys anyways.
|
CursorFollow = true;
|
||||||
//The changes we had to make to stb_textedit_key make it very much UTF8 specific which is not too great.
|
CursorAnimReset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImGuiInputTextState::OnCharPressed(unsigned int c)
|
||||||
|
{
|
||||||
|
// Convert the key to a UTF8 byte sequence.
|
||||||
|
// The changes we had to make to stb_textedit_key made it very much UTF-8 specific which is not too great.
|
||||||
char utf8[5];
|
char utf8[5];
|
||||||
ImTextCharToUtf8(utf8, key);
|
ImTextCharToUtf8(utf8, c);
|
||||||
stb_textedit_key(this, Stb, key, utf8, (int)strlen(utf8));
|
stb_textedit_text(this, Stb, utf8, (int)strlen(utf8));
|
||||||
CursorFollow = true;
|
CursorFollow = true;
|
||||||
CursorAnimReset();
|
CursorAnimReset();
|
||||||
}
|
}
|
||||||
@ -4674,7 +4679,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
{
|
{
|
||||||
unsigned int c = '\t'; // Insert TAB
|
unsigned int c = '\t'; // Insert TAB
|
||||||
if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data))
|
if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data))
|
||||||
state->OnKeyPressed((int)c);
|
state->OnCharPressed(c);
|
||||||
}
|
}
|
||||||
// FIXME: Implement Shift+Tab
|
// FIXME: Implement Shift+Tab
|
||||||
/*
|
/*
|
||||||
@ -4697,7 +4702,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
if (c == '\t') // Skip Tab, see above.
|
if (c == '\t') // Skip Tab, see above.
|
||||||
continue;
|
continue;
|
||||||
if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data))
|
if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data))
|
||||||
state->OnKeyPressed((int)c);
|
state->OnCharPressed(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consume characters
|
// Consume characters
|
||||||
@ -4781,7 +4786,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|||||||
{
|
{
|
||||||
unsigned int c = '\n'; // Insert new line
|
unsigned int c = '\n'; // Insert new line
|
||||||
if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data))
|
if (InputTextFilterCharacter(&g, &c, flags, callback, callback_user_data))
|
||||||
state->OnKeyPressed((int)c);
|
state->OnCharPressed(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (is_cancel)
|
else if (is_cancel)
|
||||||
|
@ -211,6 +211,7 @@
|
|||||||
// int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
// int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state)
|
||||||
// int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
|
// int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int len)
|
||||||
// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key)
|
// void stb_textedit_key(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXEDIT_KEYTYPE key)
|
||||||
|
// void stb_textedit_text(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE *text, int text_len)
|
||||||
//
|
//
|
||||||
// Each of these functions potentially updates the string and updates the
|
// Each of these functions potentially updates the string and updates the
|
||||||
// state.
|
// state.
|
||||||
@ -245,7 +246,12 @@
|
|||||||
// various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit
|
// various definitions like STB_TEXTEDIT_K_LEFT have the is-key-event bit
|
||||||
// set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is
|
// set, and make STB_TEXTEDIT_KEYTOCHAR check that the is-key-event bit is
|
||||||
// clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to
|
// clear. STB_TEXTEDIT_KEYTYPE defaults to int, but you can #define it to
|
||||||
// anything other type you wante before including.
|
// anything other type you want before including.
|
||||||
|
// if the STB_TEXTEDIT_KEYTOTEXT function is defined, selected keys are
|
||||||
|
// transformed into text and stb_textedit_text() is automatically called.
|
||||||
|
//
|
||||||
|
// text: [DEAR IMGUI] added 2024-09
|
||||||
|
// call this to text inputs sent to the textfield.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// When rendering, you can read the cursor position and selection state from
|
// When rendering, you can read the cursor position and selection state from
|
||||||
@ -733,37 +739,44 @@ static int stb_textedit_paste_internal(IMSTB_TEXTEDIT_STRING *str, STB_TexteditS
|
|||||||
#define STB_TEXTEDIT_KEYTYPE int
|
#define STB_TEXTEDIT_KEYTYPE int
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// [DEAR IMGUI] Added stb_textedit_text(), extracted out and called by stb_textedit_key() for backward compatibility.
|
||||||
|
static void stb_textedit_text(IMSTB_TEXTEDIT_STRING* str, STB_TexteditState* state, const IMSTB_TEXTEDIT_CHARTYPE* text, int text_len)
|
||||||
|
{
|
||||||
|
// can't add newline in single-line mode
|
||||||
|
if (text[0] == '\n' && state->single_line)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
|
||||||
|
stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
|
||||||
|
STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
|
||||||
|
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
|
||||||
|
state->cursor += text_len;
|
||||||
|
state->has_preferred_x = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stb_textedit_delete_selection(str, state); // implicitly clamps
|
||||||
|
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, text, text_len)) {
|
||||||
|
stb_text_makeundo_insert(state, state->cursor, text_len);
|
||||||
|
state->cursor += text_len;
|
||||||
|
state->has_preferred_x = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// API key: process a keyboard input
|
// API key: process a keyboard input
|
||||||
//[DEAR IMGUI] In addition to the key we also pass in the decoded UTF8 byte sequence, if it is a character key.
|
static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key)
|
||||||
//This is a bit ugly and only makes sense for UTF8. One could think of other solutions that wouldn't make this function so UTF8 specific.
|
|
||||||
//If the idea is to push the changes upstream to stb_textedit it might be worth thinking about but since this is just for [DEAR IMGUI], it might not be worth the complication
|
|
||||||
static void stb_textedit_key(IMSTB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_KEYTYPE key, const IMSTB_TEXTEDIT_CHARTYPE* decoded, int decoded_size)
|
|
||||||
{
|
{
|
||||||
retry:
|
retry:
|
||||||
switch (key) {
|
switch (key) {
|
||||||
default: {
|
default: {
|
||||||
|
#ifdef STB_TEXTEDIT_KEYTOTEXT
|
||||||
int c = STB_TEXTEDIT_KEYTOTEXT(key);
|
int c = STB_TEXTEDIT_KEYTOTEXT(key);
|
||||||
if (c > 0) {
|
if (c > 0) {
|
||||||
// can't add newline in single-line mode
|
IMSTB_TEXTEDIT_CHARTYPE ch = (IMSTB_TEXTEDIT_CHARTYPE)c;
|
||||||
if (c == '\n' && state->single_line)
|
stb_textedit_text(str, state, &ch, 1);
|
||||||
break;
|
|
||||||
|
|
||||||
if (state->insert_mode && !STB_TEXT_HAS_SELECTION(state) && state->cursor < STB_TEXTEDIT_STRINGLEN(str)) {
|
|
||||||
stb_text_makeundo_replace(str, state, state->cursor, 1, 1);
|
|
||||||
STB_TEXTEDIT_DELETECHARS(str, state->cursor, 1);
|
|
||||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, decoded, decoded_size)) {
|
|
||||||
state->cursor += decoded_size;
|
|
||||||
state->has_preferred_x = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
stb_textedit_delete_selection(str,state); // implicitly clamps
|
|
||||||
if (STB_TEXTEDIT_INSERTCHARS(str, state->cursor, decoded, decoded_size)) {
|
|
||||||
stb_text_makeundo_insert(state, state->cursor, decoded_size);
|
|
||||||
state->cursor += decoded_size;
|
|
||||||
state->has_preferred_x = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user