diff --git a/CHANGELOG.txt b/CHANGELOG.txt index c6993726..4867abea 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -43,6 +43,8 @@ Breaking Changes: Other Changes: + - Nav: To keep the navigated item in view we also attempt to scroll the parent window as well as the current window. (#787) + ----------------------------------------------------------------------- VERSION 1.61 (Released 2018-05-14) diff --git a/imgui.cpp b/imgui.cpp index 2ef17af8..f562d56a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3005,39 +3005,35 @@ static void ImGui::NavUpdateWindowing() } // NB: We modify rect_rel by the amount we scrolled for, so it is immediately updated. -static void NavScrollToBringItemIntoView(ImGuiWindow* window, ImRect& item_rect_rel) +static void NavScrollToBringItemIntoView(ImGuiWindow* window, const ImRect& item_rect) { // Scroll to keep newly navigated item fully into view - ImRect window_rect_rel(window->InnerMainRect.Min - window->Pos - ImVec2(1, 1), window->InnerMainRect.Max - window->Pos + ImVec2(1, 1)); - //g.OverlayDrawList.AddRect(window->Pos + window_rect_rel.Min, window->Pos + window_rect_rel.Max, IM_COL32_WHITE); // [DEBUG] - if (window_rect_rel.Contains(item_rect_rel)) + ImRect window_rect(window->InnerMainRect.Min - ImVec2(1, 1), window->InnerMainRect.Max + ImVec2(1, 1)); + //g.OverlayDrawList.AddRect(window_rect.Min, window_rect.Max, IM_COL32_WHITE); // [DEBUG] + if (window_rect.Contains(item_rect)) return; ImGuiContext& g = *GImGui; - if (window->ScrollbarX && item_rect_rel.Min.x < window_rect_rel.Min.x) + if (window->ScrollbarX && item_rect.Min.x < window_rect.Min.x) { - window->ScrollTarget.x = item_rect_rel.Min.x + window->Scroll.x - g.Style.ItemSpacing.x; + window->ScrollTarget.x = item_rect.Min.x - window->Pos.x + window->Scroll.x - g.Style.ItemSpacing.x; window->ScrollTargetCenterRatio.x = 0.0f; } - else if (window->ScrollbarX && item_rect_rel.Max.x >= window_rect_rel.Max.x) + else if (window->ScrollbarX && item_rect.Max.x >= window_rect.Max.x) { - window->ScrollTarget.x = item_rect_rel.Max.x + window->Scroll.x + g.Style.ItemSpacing.x; + window->ScrollTarget.x = item_rect.Max.x - window->Pos.x + window->Scroll.x + g.Style.ItemSpacing.x; window->ScrollTargetCenterRatio.x = 1.0f; } - if (item_rect_rel.Min.y < window_rect_rel.Min.y) + if (item_rect.Min.y < window_rect.Min.y) { - window->ScrollTarget.y = item_rect_rel.Min.y + window->Scroll.y - g.Style.ItemSpacing.y; + window->ScrollTarget.y = item_rect.Min.y - window->Pos.y + window->Scroll.y - g.Style.ItemSpacing.y; window->ScrollTargetCenterRatio.y = 0.0f; } - else if (item_rect_rel.Max.y >= window_rect_rel.Max.y) + else if (item_rect.Max.y >= window_rect.Max.y) { - window->ScrollTarget.y = item_rect_rel.Max.y + window->Scroll.y + g.Style.ItemSpacing.y; + window->ScrollTarget.y = item_rect.Max.y - window->Pos.y + window->Scroll.y + g.Style.ItemSpacing.y; window->ScrollTargetCenterRatio.y = 1.0f; } - - // Estimate upcoming scroll so we can offset our relative mouse position so mouse position can be applied immediately after in NavUpdate() - ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window, false); - item_rect_rel.Translate(window->Scroll - next_scroll); } static void ImGui::NavUpdate() @@ -3101,9 +3097,18 @@ static void ImGui::NavUpdate() IM_ASSERT(g.NavWindow && result->Window); - // Scroll to keep newly navigated item fully into view + // Scroll to keep newly navigated item fully into view. Also scroll parent window if necessary. if (g.NavLayer == 0) - NavScrollToBringItemIntoView(result->Window, result->RectRel); + { + ImRect rect_abs = ImRect(result->RectRel.Min + result->Window->Pos, result->RectRel.Max + result->Window->Pos); + NavScrollToBringItemIntoView(result->Window, rect_abs); + if (result->Window->Flags & ImGuiWindowFlags_ChildWindow) + NavScrollToBringItemIntoView(result->Window->ParentWindow, 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); + result->RectRel.Translate(result->Window->Scroll - next_scroll); + } // Apply result from previous frame navigation directional move request ClearActiveID(); @@ -6153,7 +6158,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->SizeFullAtLastBegin = window->SizeFull; // Update various regions. Variables they depends on are set above in this function. - // FIXME: window->ContentsRegion.Max is currently very misleading / partly faulty, but some BeginChild() patterns relies on it. + // FIXME: window->ContentsRegionRect.Max is currently very misleading / partly faulty, but some BeginChild() patterns relies on it. window->ContentsRegionRect.Min.x = window->Pos.x - window->Scroll.x + window->WindowPadding.x; window->ContentsRegionRect.Min.y = window->Pos.y - window->Scroll.y + window->WindowPadding.y + window->TitleBarHeight() + window->MenuBarHeight(); window->ContentsRegionRect.Max.x = window->Pos.x - window->Scroll.x - window->WindowPadding.x + (window->SizeContentsExplicit.x != 0.0f ? window->SizeContentsExplicit.x : (window->Size.x - window->ScrollbarSizes.x));