Refactor focusable/tabbalbe item registration toward allowing to handle it prior to clipping (not yet the case) (#343, #4079)

Now performed in ItemAdd(). It can't be trivially moved above clipping effectively because it would require us to scroll to be useful, meaning we'd be better off locking the bounding box a frame earlier. Still wip.
As-is this commit has no value for end-user, but it's a reengineering that moves us closer to the solution. + Internals: moved internal flags.
This commit is contained in:
ocornut
2021-04-30 22:18:31 +02:00
parent 2c3f25d2d9
commit 393941ceea
4 changed files with 67 additions and 44 deletions

View File

@ -3249,11 +3249,13 @@ void ImGui::SetLastItemData(ImGuiWindow* window, ImGuiID item_id, ImGuiItemStatu
}
// Process TAB/Shift+TAB. Be mindful that this function may _clear_ the ActiveID when tabbing out.
bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id)
void ImGui::ItemFocusable(ImGuiWindow* window, ImGuiID id)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(id != 0 && id == window->DC.LastItemId);
// Increment counters
// FIXME: ImGuiItemFlags_Disabled should disable more.
const bool is_tab_stop = (g.CurrentItemFlags & (ImGuiItemFlags_NoTabStop | ImGuiItemFlags_Disabled)) == 0;
window->DC.FocusCounterRegular++;
if (is_tab_stop)
@ -3275,25 +3277,21 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id)
if (g.TabFocusRequestCurrWindow == window)
{
if (window->DC.FocusCounterRegular == g.TabFocusRequestCurrCounterRegular)
return true;
{
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_FocusedByCode;
return;
}
if (is_tab_stop && window->DC.FocusCounterTabStop == g.TabFocusRequestCurrCounterTabStop)
{
g.NavJustTabbedId = id;
return true;
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_FocusedByTabbing;
return;
}
// If another item is about to be focused, we clear our own active id
if (g.ActiveId == id)
ClearActiveID();
}
return false;
}
void ImGui::FocusableItemUnregister(ImGuiWindow* window)
{
window->DC.FocusCounterRegular--;
window->DC.FocusCounterTabStop--;
}
float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x)
@ -7384,7 +7382,7 @@ void ImGui::ItemSize(const ImRect& bb, float text_baseline_y)
// Declare item bounding box for clipping and interaction.
// Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface
// declare their minimum size requirement to ItemSize() and provide a larger region to ItemAdd() which is used drawing/interaction.
bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg)
bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGuiItemAddFlags flags)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
@ -7433,6 +7431,11 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg)
return false;
//if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG]
// Tab stop handling (previously was using internal ItemFocusable() api)
// FIXME-NAV: We would now want to move this above the clipping test, but this would require being able to scroll and currently this would mean an extra frame. (#4079, #343)
if (flags & ImGuiItemAddFlags_Focusable)
ItemFocusable(window, id);
// We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them)
if (IsMouseHoveringRect(bb.Min, bb.Max))
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredRect;