|
// code for: https://x.com/amu_mhr/status/2006940064711053355?s=20 |
|
|
|
extern int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...); |
|
|
|
// dubious function to focus `InputText` widgets with nav cursor, this avoid having to press enter to edit them |
|
// NOTE: `ImGui::Shortcut` handles focusing but not sure how to replicate that when using arrow keys (i.e no shortcut just navigation) |
|
// This has a downside that items to the left/right of the input box cannot be reached using arrow keys (only up/down nav will work!) |
|
auto AutoFocusNextItem = [](const char* item_label) |
|
{ |
|
const ImGuiID item_id = ImGui::GetCurrentWindow()->GetID(item_label); |
|
ImGui::PushID(item_id); |
|
|
|
const ImGuiID StorageId = ImGui::GetCurrentWindow()->GetID("AutoActivate"); |
|
const bool had_focus = ImGui::GetStateStorage()->GetBool(StorageId); |
|
const bool has_focus = (ImGui::GetFocusID() == item_id); |
|
|
|
if (has_focus && !had_focus) |
|
{ |
|
ImGui::SetKeyboardFocusHere(); |
|
} |
|
|
|
ImGui::GetStateStorage()->SetBool(StorageId, has_focus); |
|
ImGui::PopID(); |
|
}; |
|
|
|
if (ImGui::Begin("Test")) |
|
{ |
|
// keep track of childb focus state in order to register shortcuts |
|
static bool childb_has_focus = false; |
|
static int childb_last_focused_item = -1; |
|
|
|
if (ImGui::BeginChild("ChildA", ImVec2(0, 0), ImGuiChildFlags_FrameStyle | ImGuiChildFlags_NavFlattened | ImGuiChildFlags_AutoResizeY)) |
|
{ |
|
static char buff0[64], buff1[64]; |
|
|
|
if (childb_has_focus) //shortcut mapping |
|
{ |
|
ImGui::SetNextItemShortcut(ImGuiKey_Tab, ImGuiInputFlags_Repeat); |
|
} |
|
AutoFocusNextItem("Text0"); |
|
ImGui::InputText("Text0", buff0, sizeof(buff0)); |
|
|
|
if (childb_has_focus && childb_last_focused_item == 0) //shortcut mapping |
|
{ |
|
ImGui::SetNextItemShortcut(ImGuiKey_UpArrow, ImGuiInputFlags_Repeat); |
|
} |
|
AutoFocusNextItem("Text1"); |
|
ImGui::InputText("Text1", buff1, sizeof(buff1)); |
|
} |
|
ImGui::EndChild(); |
|
|
|
if (ImGui::BeginChild("ChildB", ImVec2(0,0), ImGuiChildFlags_FrameStyle)) |
|
{ |
|
childb_has_focus = ImGui::IsWindowFocused(); |
|
|
|
// auto activate the window once it has has nav cursor (don't have to press enter to focus) |
|
// this however draws the child window nav cursor for one frame, appears as a flicker :( |
|
const bool had_nav_focus = childb_has_focus; |
|
const bool has_nav_focus = (ImGui::GetCurrentContext()->NavId == ImGui::GetCurrentWindow()->ChildId); |
|
const bool trigger_auto_activate = has_nav_focus && !had_nav_focus; |
|
if (trigger_auto_activate && childb_last_focused_item == -1) |
|
{ |
|
// make sure to select the first item as we don't have flattened nav which automatically handles this. |
|
childb_last_focused_item = 0; |
|
} |
|
|
|
for (int i = 0; i < 64; ++i) |
|
{ |
|
char labelBuff[32]; |
|
ImFormatString(labelBuff, sizeof(labelBuff), "Item %i", i); |
|
if (trigger_auto_activate && (childb_last_focused_item == i)) |
|
{ |
|
ImGui::SetKeyboardFocusHere(); |
|
} |
|
if (ImGui::Selectable(labelBuff, childb_last_focused_item == i)) { /* do something */ } |
|
if (ImGui::IsItemFocused()) |
|
{ |
|
childb_last_focused_item = i; |
|
} |
|
} |
|
} |
|
ImGui::EndChild(); |
|
} |
|
ImGui::End(); |