mirror of
https://github.com/ocornut/imgui.git
synced 2026-03-30 21:05:54 -05:00
Merge branch 'master' into docking
This commit is contained in:
@@ -622,7 +622,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
||||
// Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button.
|
||||
pressed = true;
|
||||
SetActiveID(id, window);
|
||||
g.ActiveIdSource = ImGuiInputSource_Nav;
|
||||
g.ActiveIdSource = g.NavInputSource;
|
||||
if (!(flags & ImGuiButtonFlags_NoNavFocus))
|
||||
SetFocusID(id, window);
|
||||
}
|
||||
@@ -660,7 +660,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
||||
if (!(flags & ImGuiButtonFlags_NoNavFocus))
|
||||
g.NavDisableHighlight = true;
|
||||
}
|
||||
else if (g.ActiveIdSource == ImGuiInputSource_Nav)
|
||||
else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
|
||||
{
|
||||
// When activated using Nav, we hold on the ActiveID until activation button is released
|
||||
if (g.NavActivateDownId != id)
|
||||
@@ -2251,7 +2251,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
|
||||
if (g.IO.KeyShift)
|
||||
adjust_delta *= 10.0f;
|
||||
}
|
||||
else if (g.ActiveIdSource == ImGuiInputSource_Nav)
|
||||
else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
|
||||
{
|
||||
const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0;
|
||||
const bool tweak_slow = IsKeyDown((g.NavInputSource == ImGuiInputSource_Gamepad) ? ImGuiKey_NavGamepadTweakSlow : ImGuiKey_NavKeyboardTweakSlow);
|
||||
@@ -2358,7 +2358,7 @@ bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v
|
||||
// Those are the things we can do easily outside the DragBehaviorT<> template, saves code generation.
|
||||
if (g.ActiveIdSource == ImGuiInputSource_Mouse && !g.IO.MouseDown[0])
|
||||
ClearActiveID();
|
||||
else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated)
|
||||
else if ((g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad) && g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated)
|
||||
ClearActiveID();
|
||||
}
|
||||
if (g.ActiveId != id)
|
||||
@@ -2827,7 +2827,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
|
||||
set_new_value = true;
|
||||
}
|
||||
}
|
||||
else if (g.ActiveIdSource == ImGuiInputSource_Nav)
|
||||
else if (g.ActiveIdSource == ImGuiInputSource_Keyboard || g.ActiveIdSource == ImGuiInputSource_Gamepad)
|
||||
{
|
||||
if (g.ActiveIdIsJustActivated)
|
||||
{
|
||||
@@ -3306,7 +3306,7 @@ void ImParseFormatSanitizeForPrinting(const char* fmt_in, char* fmt_out, size_t
|
||||
*fmt_out = 0; // Zero-terminate
|
||||
}
|
||||
|
||||
// - For scanning we need to remove all width and precision fields "%3.7f" -> "%f". BUT don't strip types like "%I64d" which includes digits. ! "%07I64d" -> "%I64d"
|
||||
// - For scanning we need to remove all width and precision fields and flags "%+3.7f" -> "%f". BUT don't strip types like "%I64d" which includes digits. ! "%07I64d" -> "%I64d"
|
||||
const char* ImParseFormatSanitizeForScanning(const char* fmt_in, char* fmt_out, size_t fmt_out_size)
|
||||
{
|
||||
const char* fmt_end = ImParseFormatFindEnd(fmt_in);
|
||||
@@ -3317,7 +3317,7 @@ const char* ImParseFormatSanitizeForScanning(const char* fmt_in, char* fmt_out,
|
||||
while (fmt_in < fmt_end)
|
||||
{
|
||||
char c = *fmt_in++;
|
||||
if (!has_type && ((c >= '0' && c <= '9') || c == '.'))
|
||||
if (!has_type && ((c >= '0' && c <= '9') || c == '.' || c == '+' || c == '#'))
|
||||
continue;
|
||||
has_type |= ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); // Stop skipping digits
|
||||
if (c != '\'' && c != '$' && c != '_') // Custom flags provided by stb_sprintf.h. POSIX 2008 also supports '.
|
||||
@@ -3456,7 +3456,12 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
|
||||
flags |= ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string.
|
||||
|
||||
bool value_changed = false;
|
||||
if (p_step != NULL)
|
||||
if (p_step == NULL)
|
||||
{
|
||||
if (InputText(label, buf, IM_ARRAYSIZE(buf), flags))
|
||||
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format);
|
||||
}
|
||||
else
|
||||
{
|
||||
const float button_size = GetFrameHeight();
|
||||
|
||||
@@ -3499,11 +3504,6 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
|
||||
PopID();
|
||||
EndGroup();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (InputText(label, buf, IM_ARRAYSIZE(buf), flags))
|
||||
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format);
|
||||
}
|
||||
if (value_changed)
|
||||
MarkItemEdited(g.LastItemData.ID);
|
||||
|
||||
@@ -4005,6 +4005,21 @@ static void InputTextReconcileUndoStateAfterUserCallback(ImGuiInputTextState* st
|
||||
p[i] = ImStb::STB_TEXTEDIT_GETCHAR(state, first_diff + i);
|
||||
}
|
||||
|
||||
// As InputText() retain textual data and we currently provide a path for user to not retain it (via local variables)
|
||||
// we need some form of hook to reapply data back to user buffer on deactivation frame. (#4714)
|
||||
// It would be more desirable that we discourage users from taking advantage of the "user not retaining data" trick,
|
||||
// but that more likely be attractive when we do have _NoLiveEdit flag available.
|
||||
void ImGui::InputTextDeactivateHook(ImGuiID id)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiInputTextState* state = &g.InputTextState;
|
||||
if (id == 0 || state->ID != id)
|
||||
return;
|
||||
g.InputTextDeactivatedState.ID = state->ID;
|
||||
g.InputTextDeactivatedState.TextA.resize(state->CurLenA + 1);
|
||||
memcpy(g.InputTextDeactivatedState.TextA.Data, state->TextA.Data, state->CurLenA + 1);
|
||||
}
|
||||
|
||||
// Edit a string of text
|
||||
// - buf_size account for the zero-terminator, so a buf_size of 6 can hold "Hello" but not "Hello!".
|
||||
// This is so we can easily call InputText() on static arrays using ARRAYSIZE() and to match
|
||||
@@ -4110,7 +4125,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
|
||||
float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX;
|
||||
|
||||
const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline);
|
||||
const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline); // state != NULL means its our state.
|
||||
const bool init_make_active = (user_clicked || user_scroll_finish || input_requested_by_nav || input_requested_by_tabbing);
|
||||
const bool init_state = (init_make_active || user_scroll_active);
|
||||
if ((init_state && g.ActiveId != id) || init_changed_specs)
|
||||
@@ -4119,6 +4134,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
state = &g.InputTextState;
|
||||
state->CursorAnimReset();
|
||||
|
||||
// Backup state of deactivating item so they'll have a chance to do a write to output buffer on the same frame they report IsItemDeactivatedAfterEdit (#4714)
|
||||
InputTextDeactivateHook(state->ID);
|
||||
|
||||
// Take a copy of the initial buffer value (both in original UTF-8 format and converted to wchar)
|
||||
// From the moment we focused we are ignoring the content of 'buf' (unless we are in read-only mode)
|
||||
const int buf_len = (int)strlen(buf);
|
||||
@@ -4531,6 +4549,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
// Push records into the undo stack so we can CTRL+Z the revert operation itself
|
||||
apply_new_text = state->InitialTextA.Data;
|
||||
apply_new_text_length = state->InitialTextA.Size - 1;
|
||||
value_changed = true;
|
||||
ImVector<ImWchar> w_text;
|
||||
if (apply_new_text_length > 0)
|
||||
{
|
||||
@@ -4644,10 +4663,24 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
{
|
||||
apply_new_text = state->TextA.Data;
|
||||
apply_new_text_length = state->CurLenA;
|
||||
value_changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle reapplying final data on deactivation (see InputTextDeactivateHook() for details)
|
||||
if (g.InputTextDeactivatedState.ID == id)
|
||||
{
|
||||
if (g.ActiveId != id && IsItemDeactivatedAfterEdit() && !is_readonly)
|
||||
{
|
||||
apply_new_text = g.InputTextDeactivatedState.TextA.Data;
|
||||
apply_new_text_length = g.InputTextDeactivatedState.TextA.Size - 1;
|
||||
value_changed |= (strcmp(g.InputTextDeactivatedState.TextA.Data, buf) != 0);
|
||||
//IMGUI_DEBUG_LOG("InputText(): apply Deactivated data for 0x%08X: \"%.*s\".\n", id, apply_new_text_length, apply_new_text);
|
||||
}
|
||||
g.InputTextDeactivatedState.ID = 0;
|
||||
}
|
||||
|
||||
// Copy result to user buffer. This can currently only happen when (g.ActiveId == id)
|
||||
if (apply_new_text != NULL)
|
||||
{
|
||||
@@ -4675,7 +4708,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
|
||||
// If the underlying buffer resize was denied or not carried to the next frame, apply_new_text_length+1 may be >= buf_size.
|
||||
ImStrncpy(buf, apply_new_text, ImMin(apply_new_text_length + 1, buf_size));
|
||||
value_changed = true;
|
||||
}
|
||||
|
||||
// Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value)
|
||||
|
||||
Reference in New Issue
Block a user