|
@@ -1,4 +1,4 @@
|
|
|
-// dear imgui, v1.88
|
|
|
|
|
|
|
+// dear imgui, v1.89 WIP
|
|
|
// (widgets code)
|
|
// (widgets code)
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -3603,7 +3603,7 @@ 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)
|
|
|
{
|
|
{
|
|
|
- IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline()
|
|
|
|
|
|
|
+ IM_ASSERT(!(flags & ImGuiInputTextFlags_Multiline)); // call InputTextMultiline() or InputTextEx() manually if you need multi-line + hint.
|
|
|
return InputTextEx(label, hint, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data);
|
|
return InputTextEx(label, hint, buf, (int)buf_size, ImVec2(0, 0), flags, callback, user_data);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -4179,7 +4179,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|
|
const bool render_cursor = (g.ActiveId == id) || (state && user_scroll_active);
|
|
const bool render_cursor = (g.ActiveId == id) || (state && user_scroll_active);
|
|
|
bool render_selection = state && (state->HasSelection() || select_all) && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor);
|
|
bool render_selection = state && (state->HasSelection() || select_all) && (RENDER_SELECTION_WHEN_INACTIVE || render_cursor);
|
|
|
bool value_changed = false;
|
|
bool value_changed = false;
|
|
|
- bool enter_pressed = false;
|
|
|
|
|
|
|
+ bool validated = false;
|
|
|
|
|
|
|
|
// When read-only we always use the live data passed to the function
|
|
// When read-only we always use the live data passed to the function
|
|
|
// FIXME-OPT: Because our selection/cursor code currently needs the wide text we need to convert it when active, which is not ideal :(
|
|
// FIXME-OPT: Because our selection/cursor code currently needs the wide text we need to convert it when active, which is not ideal :(
|
|
@@ -4346,9 +4346,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|
|
const bool is_redo = ((is_shortcut_key && IsKeyPressed(ImGuiKey_Y)) || (is_osx_shift_shortcut && IsKeyPressed(ImGuiKey_Z))) && !is_readonly && is_undoable;
|
|
const bool is_redo = ((is_shortcut_key && IsKeyPressed(ImGuiKey_Y)) || (is_osx_shift_shortcut && IsKeyPressed(ImGuiKey_Z))) && !is_readonly && is_undoable;
|
|
|
|
|
|
|
|
// We allow validate/cancel with Nav source (gamepad) to makes it easier to undo an accidental NavInput press with no keyboard wired, but otherwise it isn't very useful.
|
|
// We allow validate/cancel with Nav source (gamepad) to makes it easier to undo an accidental NavInput press with no keyboard wired, but otherwise it isn't very useful.
|
|
|
- const bool is_validate_enter = IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_KeypadEnter);
|
|
|
|
|
|
|
+ const bool is_enter_pressed = IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_KeypadEnter);
|
|
|
const bool is_validate_nav = (IsNavInputTest(ImGuiNavInput_Activate, ImGuiNavReadMode_Pressed) && !IsKeyPressed(ImGuiKey_Space)) || IsNavInputTest(ImGuiNavInput_Input, ImGuiNavReadMode_Pressed);
|
|
const bool is_validate_nav = (IsNavInputTest(ImGuiNavInput_Activate, ImGuiNavReadMode_Pressed) && !IsKeyPressed(ImGuiKey_Space)) || IsNavInputTest(ImGuiNavInput_Input, ImGuiNavReadMode_Pressed);
|
|
|
- const bool is_cancel = IsKeyPressed(ImGuiKey_Escape) || IsNavInputTest(ImGuiNavInput_Cancel, ImGuiNavReadMode_Pressed);
|
|
|
|
|
|
|
+ const bool is_cancel = IsKeyPressed(ImGuiKey_Escape) || IsNavInputTest(ImGuiNavInput_Cancel, ImGuiNavReadMode_Pressed);
|
|
|
|
|
|
|
|
if (IsKeyPressed(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); }
|
|
if (IsKeyPressed(ImGuiKey_LeftArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); }
|
|
|
else if (IsKeyPressed(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); }
|
|
else if (IsKeyPressed(ImGuiKey_RightArrow)) { state->OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); }
|
|
@@ -4370,12 +4370,17 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|
|
}
|
|
}
|
|
|
state->OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask);
|
|
state->OnKeyPressed(STB_TEXTEDIT_K_BACKSPACE | k_mask);
|
|
|
}
|
|
}
|
|
|
- else if (is_validate_enter)
|
|
|
|
|
|
|
+ else if (is_enter_pressed)
|
|
|
{
|
|
{
|
|
|
|
|
+ // Determine if we turn Enter into a \n character
|
|
|
bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0;
|
|
bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0;
|
|
|
if (!is_multiline || (ctrl_enter_for_new_line && !io.KeyCtrl) || (!ctrl_enter_for_new_line && io.KeyCtrl))
|
|
if (!is_multiline || (ctrl_enter_for_new_line && !io.KeyCtrl) || (!ctrl_enter_for_new_line && io.KeyCtrl))
|
|
|
{
|
|
{
|
|
|
- enter_pressed = clear_active_id = true;
|
|
|
|
|
|
|
+ validated = true;
|
|
|
|
|
+ if (io.ConfigInputTextEnterKeepActive && !is_multiline)
|
|
|
|
|
+ state->SelectAll(); // No need to scroll
|
|
|
|
|
+ else
|
|
|
|
|
+ clear_active_id = true;
|
|
|
}
|
|
}
|
|
|
else if (!is_readonly)
|
|
else if (!is_readonly)
|
|
|
{
|
|
{
|
|
@@ -4386,8 +4391,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|
|
}
|
|
}
|
|
|
else if (is_validate_nav)
|
|
else if (is_validate_nav)
|
|
|
{
|
|
{
|
|
|
- IM_ASSERT(!is_validate_enter);
|
|
|
|
|
- enter_pressed = clear_active_id = true;
|
|
|
|
|
|
|
+ IM_ASSERT(!is_enter_pressed);
|
|
|
|
|
+ validated = clear_active_id = true;
|
|
|
}
|
|
}
|
|
|
else if (is_cancel)
|
|
else if (is_cancel)
|
|
|
{
|
|
{
|
|
@@ -4491,7 +4496,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|
|
// When using 'ImGuiInputTextFlags_EnterReturnsTrue' as a special case we reapply the live buffer back to the input buffer before clearing ActiveId, even though strictly speaking it wasn't modified on this frame.
|
|
// When using 'ImGuiInputTextFlags_EnterReturnsTrue' as a special case we reapply the live buffer back to the input buffer before clearing ActiveId, even though strictly speaking it wasn't modified on this frame.
|
|
|
// If we didn't do that, code like InputInt() with ImGuiInputTextFlags_EnterReturnsTrue would fail.
|
|
// If we didn't do that, code like InputInt() with ImGuiInputTextFlags_EnterReturnsTrue would fail.
|
|
|
// This also allows the user to use InputText() with ImGuiInputTextFlags_EnterReturnsTrue without maintaining any user-side storage (please note that if you use this property along ImGuiInputTextFlags_CallbackResize you can end up with your temporary string object unnecessarily allocating once a frame, either store your string data, either if you don't then don't use ImGuiInputTextFlags_CallbackResize).
|
|
// This also allows the user to use InputText() with ImGuiInputTextFlags_EnterReturnsTrue without maintaining any user-side storage (please note that if you use this property along ImGuiInputTextFlags_CallbackResize you can end up with your temporary string object unnecessarily allocating once a frame, either store your string data, either if you don't then don't use ImGuiInputTextFlags_CallbackResize).
|
|
|
- const bool apply_edit_back_to_user_buffer = !cancel_edit || (enter_pressed && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0);
|
|
|
|
|
|
|
+ const bool apply_edit_back_to_user_buffer = !cancel_edit || (validated && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0);
|
|
|
if (apply_edit_back_to_user_buffer)
|
|
if (apply_edit_back_to_user_buffer)
|
|
|
{
|
|
{
|
|
|
// Apply new value immediately - copy modified buffer back
|
|
// Apply new value immediately - copy modified buffer back
|
|
@@ -4868,7 +4873,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
|
|
|
|
|
|
|
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
|
|
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
|
|
|
if ((flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0)
|
|
if ((flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0)
|
|
|
- return enter_pressed;
|
|
|
|
|
|
|
+ return validated;
|
|
|
else
|
|
else
|
|
|
return value_changed;
|
|
return value_changed;
|
|
|
}
|
|
}
|
|
@@ -5904,7 +5909,14 @@ bool ImGui::TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char
|
|
|
return TreeNodeBehavior(window->GetID(ptr_id), flags, label, label_end);
|
|
return TreeNodeBehavior(window->GetID(ptr_id), flags, label, label_end);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags)
|
|
|
|
|
|
|
+void ImGui::TreeNodeSetOpen(ImGuiID id, bool open)
|
|
|
|
|
+{
|
|
|
|
|
+ ImGuiContext& g = *GImGui;
|
|
|
|
|
+ ImGuiStorage* storage = g.CurrentWindow->DC.StateStorage;
|
|
|
|
|
+ storage->SetInt(id, open ? 1 : 0);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+bool ImGui::TreeNodeUpdateNextOpen(ImGuiID id, ImGuiTreeNodeFlags flags)
|
|
|
{
|
|
{
|
|
|
if (flags & ImGuiTreeNodeFlags_Leaf)
|
|
if (flags & ImGuiTreeNodeFlags_Leaf)
|
|
|
return true;
|
|
return true;
|
|
@@ -5920,7 +5932,7 @@ bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags)
|
|
|
if (g.NextItemData.OpenCond & ImGuiCond_Always)
|
|
if (g.NextItemData.OpenCond & ImGuiCond_Always)
|
|
|
{
|
|
{
|
|
|
is_open = g.NextItemData.OpenVal;
|
|
is_open = g.NextItemData.OpenVal;
|
|
|
- storage->SetInt(id, is_open);
|
|
|
|
|
|
|
+ TreeNodeSetOpen(id, is_open);
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
@@ -5929,7 +5941,7 @@ bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags)
|
|
|
if (stored_value == -1)
|
|
if (stored_value == -1)
|
|
|
{
|
|
{
|
|
|
is_open = g.NextItemData.OpenVal;
|
|
is_open = g.NextItemData.OpenVal;
|
|
|
- storage->SetInt(id, is_open);
|
|
|
|
|
|
|
+ TreeNodeSetOpen(id, is_open);
|
|
|
}
|
|
}
|
|
|
else
|
|
else
|
|
|
{
|
|
{
|
|
@@ -5995,7 +6007,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
|
|
// For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop().
|
|
// For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop().
|
|
|
// This is currently only support 32 level deep and we are fine with (1 << Depth) overflowing into a zero.
|
|
// This is currently only support 32 level deep and we are fine with (1 << Depth) overflowing into a zero.
|
|
|
const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0;
|
|
const bool is_leaf = (flags & ImGuiTreeNodeFlags_Leaf) != 0;
|
|
|
- bool is_open = TreeNodeBehaviorIsOpen(id, flags);
|
|
|
|
|
|
|
+ bool is_open = TreeNodeUpdateNextOpen(id, flags);
|
|
|
if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
|
if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
|
|
window->DC.TreeJumpToParentOnPopMask |= (1 << window->DC.TreeDepth);
|
|
window->DC.TreeJumpToParentOnPopMask |= (1 << window->DC.TreeDepth);
|
|
|
|
|
|