From 4eba6cd47063e1e1523fd1f01041783b93b0fb90 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 2 Jul 2015 20:53:45 -0600 Subject: [PATCH] Added SetScrollY(), SetScrollFromPosY(). Renamed SetScrollPosHere() to SetScrollFromCursorPos(). (#150) --- imgui.cpp | 58 +++++++++++++++++++++++++++++++++++-------------------- imgui.h | 9 ++++++--- 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index fab85fff..d6a84c18 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -136,7 +136,8 @@ Occasionally introducing changes that are breaking the API. The breakage are generally minor and easy to fix. Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. - - 2015/07/01 (1.42) - renamed GetScrollPosY() to GetScrollY(). Necessary to reduce confusion along with other scrolling functions, because positions (e.g. cursor position) are not equivalent to scrolling amount. + - 2015/07/02 (1.42) - renamed SetScrollPosHere() to SetScrollFromCursorPos(). Kept inline redirection function (will obsolete). + - 2015/07/02 (1.42) - renamed GetScrollPosY() to GetScrollY(). Necessary to reduce confusion along with other scrolling functions, because positions (e.g. cursor position) are not equivalent to scrolling amount. - 2015/06/14 (1.41) - changed ImageButton() default bg_col parameter from (0,0,0,1) (black) to (0,0,0,0) (transparent) - makes a difference when texture have transparence - 2015/06/14 (1.41) - changed Selectable() API from (label, selected, size) to (label, selected, flags, size). Size override should have been rarely be used. Sorry! - 2015/05/31 (1.40) - renamed GetWindowCollapsed() to IsWindowCollapsed() for consistency. Kept inline redirection function (will obsolete). @@ -339,7 +340,6 @@ - window: resizing from any sides? + mouse cursor directives for app. - window: get size/pos helpers given names (see discussion in #249) - scrolling: add horizontal scroll -!- scrolling: set scrolling given a position. !- scrolling: allow immediately effective change of scroll if we haven't appended items yet - widgets: display mode: widget-label, label-widget (aligned on column or using fixed size), label-newline-tab-widget etc. - widgets: clean up widgets internal toward exposing everything. @@ -1419,7 +1419,7 @@ struct ImGuiWindow ImVec2 WindowPadding; // Window padding at the time of begin. We need to lock it, in particular manipulation of the ShowBorder would have an effect ImGuiID MoveID; // == window->GetID("#MOVE") float ScrollY; - float ScrollTargetRelY; // 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 ScrollTargetRelY; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX 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() @@ -1786,7 +1786,7 @@ ImGuiWindow::ImGuiWindow(const char* name) SizeContents = ImVec2(0.0f, 0.0f); WindowPadding = ImVec2(0.0f, 0.0f); ScrollY = 0.0f; - ScrollTargetRelY = -1.0f; + ScrollTargetRelY = FLT_MAX; ScrollTargetCenterRatioY = 0.5f; ScrollbarY = false; Active = WasActive = false; @@ -3858,11 +3858,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->ScrollTargetRelY >= 0.0f) + if (window->ScrollTargetRelY < FLT_MAX) { float center_ratio_y = window->ScrollTargetCenterRatioY; window->ScrollY = window->ScrollTargetRelY - ((1.0f - center_ratio_y) * window->TitleBarHeight()) - (center_ratio_y * window->SizeFull.y); - window->ScrollTargetRelY = -1.0f; + window->ScrollTargetRelY = FLT_MAX; } window->ScrollY = ImMax(window->ScrollY, 0.0f); if (!window->Collapsed && !window->SkipItems) @@ -4505,8 +4505,7 @@ bool ImGui::IsRootWindowOrAnyChildFocused() float ImGui::GetWindowWidth() { - ImGuiState& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; + ImGuiWindow* window = GImGui->CurrentWindow; return window->Size.x; } @@ -4828,19 +4827,31 @@ float ImGui::GetScrollMaxY() return window->SizeContents.y - window->SizeFull.y; } -void ImGui::SetScrollPosHere(float center_y_ratio) +void ImGui::SetScrollY(float scroll_y) +{ + ImGuiWindow* window = GetCurrentWindow(); + window->ScrollTargetRelY = scroll_y + window->TitleBarHeight(); // title bar height cancelled out when using ScrollTargetRelY + window->ScrollTargetCenterRatioY = 0.0f; +} + +void ImGui::SetScrollFromPosY(float pos_y, 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 - ImGuiState& g = *GImGui; - IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f); ImGuiWindow* window = GetCurrentWindow(); - window->ScrollTargetRelY = (float)(int)(window->ScrollY + window->DC.CursorPosPrevLine.y - window->Pos.y + (window->DC.PrevLineHeight) * center_y_ratio); - window->ScrollTargetRelY += g.Style.ItemSpacing.y * (center_y_ratio - 0.5f) * 2.0f; + IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f); + window->ScrollTargetRelY = (float)(int)(pos_y + window->ScrollY); if (center_y_ratio <= 0.0f && window->ScrollTargetRelY <= window->WindowPadding.y) // Minor hack to make "scroll to top" take account of WindowPadding, else it would scroll to (WindowPadding.y - ItemSpacing.y) window->ScrollTargetRelY = 0.0f; window->ScrollTargetCenterRatioY = center_y_ratio; } +void ImGui::SetScrollFromCursorPos(float center_y_ratio) +{ + ImGuiWindow* window = GetCurrentWindow(); + float target_y = window->DC.CursorPosPrevLine.y + (window->DC.PrevLineHeight * center_y_ratio) + (GImGui->Style.ItemSpacing.y * (center_y_ratio - 0.5f) * 2.0f); // Precisely aim above, in the middle or below the last line. + ImGui::SetScrollFromPosY(target_y - window->Pos.y, center_y_ratio); +} + void ImGui::SetKeyboardFocusHere(int offset) { ImGuiWindow* window = GetCurrentWindow(); @@ -7751,7 +7762,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi *current_item = i; } if (item_selected && menu_toggled) - ImGui::SetScrollPosHere(); + ImGui::SetScrollFromCursorPos(); ImGui::PopID(); } ImGui::EndPopup(); @@ -11300,10 +11311,10 @@ void ImGui::ShowTestWindow(bool* opened) { ImGui::Text("%04d: scrollable region", i); if (goto_line && line == i) - ImGui::SetScrollPosHere(); + ImGui::SetScrollFromCursorPos(); } if (goto_line && line >= 100) - ImGui::SetScrollPosHere(); + ImGui::SetScrollFromCursorPos(); ImGui::EndChild(); ImGui::SameLine(); @@ -11497,11 +11508,14 @@ void ImGui::ShowTestWindow(bool* opened) if (ImGui::TreeNode("Scrolling")) { - ImGui::TextWrapped("Use SetScrollPosHere() to scroll to a given position."); + ImGui::TextWrapped("Use SetScrollFromPos() or SetScrollFromCursorPos() to scroll to a given position."); static bool track = true; - static int track_line = 50; + static int track_line = 50, scroll_to_px = 200; ImGui::Checkbox("Track", &track); - ImGui::SameLine(); ImGui::SliderInt("##line", &track_line, 0, 99, "Line %.0f"); + ImGui::SameLine(130); track |= ImGui::DragInt("##line", &track_line, 0.25f, 0, 9999, "Line %.0f"); + bool scroll_to = ImGui::Button("Scroll To"); + ImGui::SameLine(130); scroll_to |= ImGui::DragInt("##pos_y", &scroll_to_px, 1.00f, 0, 9999, "y = %.0f px"); + if (scroll_to) track = false; for (int i = 0; i < 3; i++) { @@ -11509,11 +11523,13 @@ void ImGui::ShowTestWindow(bool* opened) ImGui::BeginGroup(); ImGui::Text(i == 0 ? "Top" : i == 1 ? "Center" : "Bottom"); ImGui::BeginChild(ImGui::GetID((void *)i), ImVec2(ImGui::GetWindowWidth() * 0.25f, 200.0f), true); + if (scroll_to) + ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_px, i * 0.50f); for (int line = 0; line < 100; line++) { ImGui::Text("Line %d", line); if (track && line == track_line) - ImGui::SetScrollPosHere(i * 0.50f); // 0.0f,0.5f,1.0f + ImGui::SetScrollFromCursorPos(i * 0.50f); // 0.0f:top, 0.5f:center, 1.0f:bottom } ImGui::EndChild(); ImGui::EndGroup(); @@ -12272,7 +12288,7 @@ struct ExampleAppConsole ImGui::PopStyleColor(); } if (ScrollToBottom) - ImGui::SetScrollPosHere(); + ImGui::SetScrollFromCursorPos(); ScrollToBottom = false; ImGui::PopStyleVar(); ImGui::EndChild(); diff --git a/imgui.h b/imgui.h index 70d06485..56ff0676 100644 --- a/imgui.h +++ b/imgui.h @@ -135,9 +135,11 @@ namespace ImGui IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiSetCond cond = 0); // set named window collapsed state IMGUI_API void SetWindowFocus(const char* name); // set named window to be focused / front-most. use NULL to remove focus. - IMGUI_API float GetScrollY(); // get scrolling position [0..GetScrollMaxY()] - IMGUI_API float GetScrollMaxY(); // get maximum scrolling position == ContentSize.Y - WindowSize.Y - 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 float GetScrollY(); // get scrolling amount [0..GetScrollMaxY()] + IMGUI_API float GetScrollMaxY(); // get maximum scrolling amount == ContentSize.Y - WindowSize.Y + IMGUI_API void SetScrollY(float scroll_y); // set scrolling amount [0..GetScrollMaxY()] + IMGUI_API void SetScrollFromCursorPos(float center_y_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_y_ratio=0.0: top, 0.5: center, 1.0: bottom. + IMGUI_API void SetScrollFromPosY(float pos_y, float center_y_ratio = 0.5f); // adjust scrolling amount to make given position valid. use GetCursorPos() or GetCursorStartPos()+offset to get valid positions. 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(); @@ -409,6 +411,7 @@ namespace ImGui static inline bool IsClipped(const ImVec2& size) { return !IsRectVisible(size); } // OBSOLETE 1.38+ static inline bool IsRectClipped(const ImVec2& size) { return !IsRectVisible(size); } // OBSOLETE 1.39+ static inline bool IsMouseHoveringBox(const ImVec2& rect_min, const ImVec2& rect_max) { return IsMouseHoveringRect(rect_min, rect_max); } // OBSOLETE 1.36+ + static inline void SetScrollPosHere() { SetScrollFromCursorPos(); } // OBSOLETE 1.42+ #endif } // namespace ImGui