mirror of
https://github.com/ocornut/imgui.git
synced 2024-12-12 20:19:02 +08:00
Refactor: Internals: Moved Navigation functions in imgui.cpp in their own section (extracted some code out of NavUpdate()). (part 3) (#2036, #787)
This commit is contained in:
parent
9a4234ea8e
commit
f5ed5478e1
172
imgui.cpp
172
imgui.cpp
@ -894,7 +894,11 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2&
|
|||||||
static void NavUpdate();
|
static void NavUpdate();
|
||||||
static void NavUpdateWindowing();
|
static void NavUpdateWindowing();
|
||||||
static void NavUpdateWindowingList();
|
static void NavUpdateWindowingList();
|
||||||
|
static void NavUpdateMoveResult();
|
||||||
|
static float NavUpdatePageUpPageDown(int allowed_dir_flags);
|
||||||
|
static inline void NavUpdateAnyRequestFlag();
|
||||||
static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id);
|
static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id);
|
||||||
|
static ImVec2 NavCalcPreferredRefPos();
|
||||||
|
|
||||||
static void UpdateMouseInputs();
|
static void UpdateMouseInputs();
|
||||||
static void UpdateMouseWheel();
|
static void UpdateMouseWheel();
|
||||||
@ -2362,7 +2366,7 @@ static void NavRestoreLayer(int layer)
|
|||||||
ImGui::NavInitWindow(g.NavWindow, true);
|
ImGui::NavInitWindow(g.NavWindow, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void NavUpdateAnyRequestFlag()
|
static inline void ImGui::NavUpdateAnyRequestFlag()
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
g.NavAnyRequest = g.NavMoveRequest || g.NavInitRequest || (IMGUI_DEBUG_NAV_SCORING && g.NavWindow != NULL);
|
g.NavAnyRequest = g.NavMoveRequest || g.NavInitRequest || (IMGUI_DEBUG_NAV_SCORING && g.NavWindow != NULL);
|
||||||
@ -2723,7 +2727,7 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static ImVec2 NavCalcPreferredRefPos()
|
static ImVec2 ImGui::NavCalcPreferredRefPos()
|
||||||
{
|
{
|
||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
if (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow)
|
if (g.NavDisableHighlight || !g.NavDisableMouseHover || !g.NavWindow)
|
||||||
@ -3073,44 +3077,7 @@ static void ImGui::NavUpdate()
|
|||||||
|
|
||||||
// Process navigation move request
|
// Process navigation move request
|
||||||
if (g.NavMoveRequest && (g.NavMoveResultLocal.ID != 0 || g.NavMoveResultOther.ID != 0))
|
if (g.NavMoveRequest && (g.NavMoveResultLocal.ID != 0 || g.NavMoveResultOther.ID != 0))
|
||||||
{
|
NavUpdateMoveResult();
|
||||||
// Select which result to use
|
|
||||||
ImGuiNavMoveResult* result = (g.NavMoveResultLocal.ID != 0) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
|
|
||||||
|
|
||||||
// PageUp/PageDown behavior first jumps to the bottom/top mostly visible item, _otherwise_ use the result from the previous/next page.
|
|
||||||
if (g.NavMoveRequestFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet)
|
|
||||||
if (g.NavMoveResultLocalVisibleSet.ID != 0 && g.NavMoveResultLocalVisibleSet.ID != g.NavId)
|
|
||||||
result = &g.NavMoveResultLocalVisibleSet;
|
|
||||||
|
|
||||||
// Maybe entering a flattened child from the outside? In this case solve the tie using the regular scoring rules.
|
|
||||||
if (result != &g.NavMoveResultOther && g.NavMoveResultOther.ID != 0 && g.NavMoveResultOther.Window->ParentWindow == g.NavWindow)
|
|
||||||
if ((g.NavMoveResultOther.DistBox < result->DistBox) || (g.NavMoveResultOther.DistBox == result->DistBox && g.NavMoveResultOther.DistCenter < result->DistCenter))
|
|
||||||
result = &g.NavMoveResultOther;
|
|
||||||
IM_ASSERT(g.NavWindow && result->Window);
|
|
||||||
|
|
||||||
// Scroll to keep newly navigated item fully into view.
|
|
||||||
if (g.NavLayer == 0)
|
|
||||||
{
|
|
||||||
ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos);
|
|
||||||
NavScrollToBringItemIntoView(result->Window, rect_abs);
|
|
||||||
|
|
||||||
// Estimate upcoming scroll so we can offset our result position so mouse position can be applied immediately after in NavUpdate()
|
|
||||||
ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(result->Window, false);
|
|
||||||
ImVec2 delta_scroll = result->Window->Scroll - next_scroll;
|
|
||||||
result->RectRel.Translate(delta_scroll);
|
|
||||||
|
|
||||||
// Also scroll parent window to keep us into view if necessary (we could/should technically recurse back the whole the parent hierarchy).
|
|
||||||
if (result->Window->Flags & ImGuiWindowFlags_ChildWindow)
|
|
||||||
NavScrollToBringItemIntoView(result->Window->ParentWindow, ImRect(rect_abs.Min + delta_scroll, rect_abs.Max + delta_scroll));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply result from previous frame navigation directional move request
|
|
||||||
ClearActiveID();
|
|
||||||
g.NavWindow = result->Window;
|
|
||||||
SetNavIDWithRectRel(result->ID, g.NavLayer, result->RectRel);
|
|
||||||
g.NavJustMovedToId = result->ID;
|
|
||||||
g.NavMoveFromClampedRefRect = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// When a forwarded move request failed, we restore the highlight that we disabled during the forward frame
|
// When a forwarded move request failed, we restore the highlight that we disabled during the forward frame
|
||||||
if (g.NavMoveRequestForward == ImGuiNavForward_ForwardActive)
|
if (g.NavMoveRequestForward == ImGuiNavForward_ForwardActive)
|
||||||
@ -3242,42 +3209,8 @@ static void ImGui::NavUpdate()
|
|||||||
|
|
||||||
// PageUp/PageDown scroll
|
// PageUp/PageDown scroll
|
||||||
float nav_scoring_rect_offset_y = 0.0f;
|
float nav_scoring_rect_offset_y = 0.0f;
|
||||||
if (nav_keyboard_active && g.NavMoveDir == ImGuiDir_None && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget && g.NavLayer == 0)
|
if (nav_keyboard_active)
|
||||||
{
|
nav_scoring_rect_offset_y = NavUpdatePageUpPageDown(allowed_dir_flags);
|
||||||
ImGuiWindow* window = g.NavWindow;
|
|
||||||
bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && (allowed_dir_flags & (1 << ImGuiDir_Up));
|
|
||||||
bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && (allowed_dir_flags & (1 << ImGuiDir_Down));
|
|
||||||
if ((page_up_held && !page_down_held) || (page_down_held && !page_up_held))
|
|
||||||
{
|
|
||||||
if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll)
|
|
||||||
{
|
|
||||||
// Fallback manual-scroll when window has no navigable item
|
|
||||||
if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
|
|
||||||
SetWindowScrollY(window, window->Scroll.y - window->InnerClipRect.GetHeight());
|
|
||||||
else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
|
|
||||||
SetWindowScrollY(window, window->Scroll.y + window->InnerClipRect.GetHeight());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer];
|
|
||||||
const float page_offset_y = ImMax(0.0f, window->InnerClipRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight());
|
|
||||||
if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
|
|
||||||
{
|
|
||||||
nav_scoring_rect_offset_y = -page_offset_y;
|
|
||||||
g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item)
|
|
||||||
g.NavMoveClipDir = ImGuiDir_Up;
|
|
||||||
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
|
|
||||||
}
|
|
||||||
else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
|
|
||||||
{
|
|
||||||
nav_scoring_rect_offset_y = +page_offset_y;
|
|
||||||
g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item)
|
|
||||||
g.NavMoveClipDir = ImGuiDir_Down;
|
|
||||||
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g.NavMoveDir != ImGuiDir_None)
|
if (g.NavMoveDir != ImGuiDir_None)
|
||||||
{
|
{
|
||||||
@ -8855,6 +8788,93 @@ void ImGui::NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags mov
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
static void ImGui::NavUpdateMoveResult()
|
||||||
|
{
|
||||||
|
// Select which result to use
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
ImGuiNavMoveResult* result = (g.NavMoveResultLocal.ID != 0) ? &g.NavMoveResultLocal : &g.NavMoveResultOther;
|
||||||
|
|
||||||
|
// PageUp/PageDown behavior first jumps to the bottom/top mostly visible item, _otherwise_ use the result from the previous/next page.
|
||||||
|
if (g.NavMoveRequestFlags & ImGuiNavMoveFlags_AlsoScoreVisibleSet)
|
||||||
|
if (g.NavMoveResultLocalVisibleSet.ID != 0 && g.NavMoveResultLocalVisibleSet.ID != g.NavId)
|
||||||
|
result = &g.NavMoveResultLocalVisibleSet;
|
||||||
|
|
||||||
|
// Maybe entering a flattened child from the outside? In this case solve the tie using the regular scoring rules.
|
||||||
|
if (result != &g.NavMoveResultOther && g.NavMoveResultOther.ID != 0 && g.NavMoveResultOther.Window->ParentWindow == g.NavWindow)
|
||||||
|
if ((g.NavMoveResultOther.DistBox < result->DistBox) || (g.NavMoveResultOther.DistBox == result->DistBox && g.NavMoveResultOther.DistCenter < result->DistCenter))
|
||||||
|
result = &g.NavMoveResultOther;
|
||||||
|
IM_ASSERT(g.NavWindow && result->Window);
|
||||||
|
|
||||||
|
// Scroll to keep newly navigated item fully into view.
|
||||||
|
if (g.NavLayer == 0)
|
||||||
|
{
|
||||||
|
ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos);
|
||||||
|
NavScrollToBringItemIntoView(result->Window, rect_abs);
|
||||||
|
|
||||||
|
// Estimate upcoming scroll so we can offset our result position so mouse position can be applied immediately after in NavUpdate()
|
||||||
|
ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(result->Window, false);
|
||||||
|
ImVec2 delta_scroll = result->Window->Scroll - next_scroll;
|
||||||
|
result->RectRel.Translate(delta_scroll);
|
||||||
|
|
||||||
|
// Also scroll parent window to keep us into view if necessary (we could/should technically recurse back the whole the parent hierarchy).
|
||||||
|
if (result->Window->Flags & ImGuiWindowFlags_ChildWindow)
|
||||||
|
NavScrollToBringItemIntoView(result->Window->ParentWindow, ImRect(rect_abs.Min + delta_scroll, rect_abs.Max + delta_scroll));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply result from previous frame navigation directional move request
|
||||||
|
ClearActiveID();
|
||||||
|
g.NavWindow = result->Window;
|
||||||
|
SetNavIDWithRectRel(result->ID, g.NavLayer, result->RectRel);
|
||||||
|
g.NavJustMovedToId = result->ID;
|
||||||
|
g.NavMoveFromClampedRefRect = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags)
|
||||||
|
{
|
||||||
|
ImGuiContext& g = *GImGui;
|
||||||
|
if (g.NavMoveDir == ImGuiDir_None && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget && g.NavLayer == 0)
|
||||||
|
{
|
||||||
|
ImGuiWindow* window = g.NavWindow;
|
||||||
|
bool page_up_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageUp]) && (allowed_dir_flags & (1 << ImGuiDir_Up));
|
||||||
|
bool page_down_held = IsKeyDown(g.IO.KeyMap[ImGuiKey_PageDown]) && (allowed_dir_flags & (1 << ImGuiDir_Down));
|
||||||
|
if ((page_up_held && !page_down_held) || (page_down_held && !page_up_held))
|
||||||
|
{
|
||||||
|
if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll)
|
||||||
|
{
|
||||||
|
// Fallback manual-scroll when window has no navigable item
|
||||||
|
if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
|
||||||
|
SetWindowScrollY(window, window->Scroll.y - window->InnerClipRect.GetHeight());
|
||||||
|
else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
|
||||||
|
SetWindowScrollY(window, window->Scroll.y + window->InnerClipRect.GetHeight());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer];
|
||||||
|
const float page_offset_y = ImMax(0.0f, window->InnerClipRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight());
|
||||||
|
float nav_scoring_rect_offset_y = 0.0f;
|
||||||
|
if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
|
||||||
|
{
|
||||||
|
nav_scoring_rect_offset_y = -page_offset_y;
|
||||||
|
g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item)
|
||||||
|
g.NavMoveClipDir = ImGuiDir_Up;
|
||||||
|
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
|
||||||
|
}
|
||||||
|
else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
|
||||||
|
{
|
||||||
|
nav_scoring_rect_offset_y = +page_offset_y;
|
||||||
|
g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset, we intentionally request the opposite direction (so we can always land on the last item)
|
||||||
|
g.NavMoveClipDir = ImGuiDir_Down;
|
||||||
|
g.NavMoveRequestFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveFlags_AlsoScoreVisibleSet;
|
||||||
|
}
|
||||||
|
return nav_scoring_rect_offset_y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// COLUMNS
|
// COLUMNS
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user