From b74d8e4c875b08cb61971b2d817f62c0b30d710b Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 1 Jul 2015 17:51:44 -0600 Subject: [PATCH] SetScrollPosHere() takes a y centering ratio and can be used to aim the top or bottom of the window (relate #150) --- imgui.cpp | 20 +++++++++++++------- imgui.h | 2 +- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 974fd3f3a..c4e6d5e08 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1412,7 +1412,8 @@ struct ImGuiWindow ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame ImGuiID MoveID; // == window->GetID("#MOVE") float ScrollY; - float ScrollTargetCenterY; // position which we aim to center on + float ScrollTargetAbsY; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (-1.0f for no change) + float ScrollTargetCenterRatioY; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered bool ScrollbarY; bool Active; // Set to true on Begin() bool WasActive; @@ -1778,7 +1779,8 @@ ImGuiWindow::ImGuiWindow(const char* name) Size = SizeFull = ImVec2(0.0f, 0.0f); SizeContents = ImVec2(0.0f, 0.0f); ScrollY = 0.0f; - ScrollTargetCenterY = -1.0f; + ScrollTargetAbsY = -1.0f; + ScrollTargetCenterRatioY = 0.5f; ScrollbarY = false; Active = WasActive = false; Accessed = false; @@ -3836,10 +3838,11 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_ window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = IM_INT_MAX; // Apply scrolling - if (window->ScrollTargetCenterY >= 0.0f) + if (window->ScrollTargetAbsY >= 0.0f) { - window->ScrollY = window->ScrollTargetCenterY - (window->Pos.y + (window->SizeFull.y + window->TitleBarHeight() + window->WindowPadding().y) * 0.5f); - window->ScrollTargetCenterY = -1.0f; + float center_ratio_y = window->ScrollTargetCenterRatioY; + window->ScrollY = window->ScrollTargetAbsY - (window->Pos.y + (1.0f - center_ratio_y) * window->TitleBarHeight() + center_ratio_y * window->SizeFull.y); + window->ScrollTargetAbsY = -1.0f; } window->ScrollY = ImMax(window->ScrollY, 0.0f); if (!window->Collapsed && !window->SkipItems) @@ -4800,10 +4803,13 @@ float ImGui::GetScrollMaxY() return window->SizeContents.y - window->SizeFull.y; } -void ImGui::SetScrollPosHere() +void ImGui::SetScrollPosHere(float center_y_ratio) { + // We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size + IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f); ImGuiWindow* window = GetCurrentWindow(); - window->ScrollTargetCenterY = (float)(int)(window->DC.CursorPos.y + window->ScrollY - window->DC.PrevLineHeight * 0.5f); + window->ScrollTargetAbsY = (float)(int)(window->ScrollY + window->DC.CursorPosPrevLine.y + (window->DC.PrevLineHeight) * center_y_ratio); + window->ScrollTargetCenterRatioY = center_y_ratio; } void ImGui::SetKeyboardFocusHere(int offset) diff --git a/imgui.h b/imgui.h index cf8ff5f71..6905e778e 100644 --- a/imgui.h +++ b/imgui.h @@ -138,7 +138,7 @@ namespace ImGui IMGUI_API float GetScrollPosY(); // get scrolling position [0..GetScrollMaxY()] IMGUI_API float GetScrollMaxY(); // get maximum scrolling position == ContentSize.Y - WindowSize.Y - IMGUI_API void SetScrollPosHere(); // adjust scrolling position to center into the current cursor position + IMGUI_API void SetScrollPosHere(float center_y_ratio = 0.5f); // adjust scrolling position to make the current cursor position visible. center_y_ratio=0.0: top, =0.5: center, =1.0: bottom. IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget IMGUI_API void SetStateStorage(ImGuiStorage* tree); // replace tree state storage with our own (if you want to manipulate it yourself, typically clear subsection of it) IMGUI_API ImGuiStorage* GetStateStorage();