diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1375cb8e4..11c98068a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -57,7 +57,8 @@ Other Changes: - ColorEdit: Fixed the color picker popup only displaying inputs as HSV instead of showing multiple options. (#2587, broken in 1.69 by #2384). - CollapsingHeader: Better clipping when a close button is enabled and it overlaps the label. (#600) -- Scrollbar: Very minor bounding box adjustment to cope with various border size. +- Scrollbar: Minor bounding box adjustment to cope with various border size. +- Scrollbar, Style: Changed default style.ScrollbarSize from 16 to 14. - Combo: Fixed rounding not applying with the ImGuiComboFlags_NoArrowButton flag. (#2607) [@DucaRii] - Nav: Fixed gamepad/keyboard moving of window affecting contents size incorrectly, sometimes leading to scrollbars appearing during the movement. diff --git a/imgui.cpp b/imgui.cpp index bc51d8aaa..039f93f67 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1146,7 +1146,7 @@ ImGuiStyle::ImGuiStyle() TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! IndentSpacing = 21.0f; // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns. Preferably > (FramePadding.x + 1). - ScrollbarSize = 16.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar + ScrollbarSize = 14.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar ScrollbarRounding = 9.0f; // Radius of grab corners rounding for scrollbar GrabMinSize = 10.0f; // Minimum width/height of a grab box for slider/scrollbar GrabRounding = 0.0f; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs. @@ -5375,23 +5375,36 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Calculate auto-fit size, handle automatic resize const ImVec2 size_auto_fit = CalcSizeAutoFit(window, window->ContentSize); - ImVec2 size_full_modified(FLT_MAX, FLT_MAX); + bool use_current_size_for_scrollbar_x = window_just_created; + bool use_current_size_for_scrollbar_y = window_just_created; if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window->Collapsed) { // Using SetNextWindowSize() overrides ImGuiWindowFlags_AlwaysAutoResize, so it can be used on tooltips/popups, etc. if (!window_size_x_set_by_api) - window->SizeFull.x = size_full_modified.x = size_auto_fit.x; + { + window->SizeFull.x = size_auto_fit.x; + use_current_size_for_scrollbar_x = true; + } if (!window_size_y_set_by_api) - window->SizeFull.y = size_full_modified.y = size_auto_fit.y; + { + window->SizeFull.y = size_auto_fit.y; + use_current_size_for_scrollbar_y = true; + } } else if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0) { // Auto-fit may only grow window during the first few frames // We still process initial auto-fit on collapsed windows to get a window width, but otherwise don't honor ImGuiWindowFlags_AlwaysAutoResize when collapsed. if (!window_size_x_set_by_api && window->AutoFitFramesX > 0) - window->SizeFull.x = size_full_modified.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x; + { + window->SizeFull.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x; + use_current_size_for_scrollbar_x = true; + } if (!window_size_y_set_by_api && window->AutoFitFramesY > 0) - window->SizeFull.y = size_full_modified.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y; + { + window->SizeFull.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y; + use_current_size_for_scrollbar_y = true; + } if (!window->Collapsed) MarkIniSettingsDirty(window); } @@ -5403,18 +5416,19 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Decoration size const float decoration_up_height = window->TitleBarHeight() + window->MenuBarHeight(); - // SCROLLBAR STATUS + // SCROLLBAR VISIBILITY - // Update scrollbar status (based on the Size that was effective during last frame or the auto-resized Size). + // Update scrollbar visibility (based on the Size that was effective during last frame or the auto-resized Size). if (!window->Collapsed) { // When reading the current size we need to read it after size constraints have been applied. // When we use InnerRect here we are intentionally reading last frame size, same for ScrollbarSizes values before we set them again. ImVec2 avail_size_from_current_frame = ImVec2(window->SizeFull.x, window->SizeFull.y - decoration_up_height); ImVec2 avail_size_from_last_frame = window->InnerRect.GetSize() + window->ScrollbarSizes; - ImVec2 needed_size_from_last_frame = window_just_created ? ImVec2(0,0) : window->ContentSize + window->WindowPadding * 2.0f; - float size_x_for_scrollbars = (size_full_modified.x != FLT_MAX || window_just_created) ? avail_size_from_current_frame.x : avail_size_from_last_frame.x; - float size_y_for_scrollbars = (size_full_modified.y != FLT_MAX || window_just_created) ? avail_size_from_current_frame.y : avail_size_from_last_frame.y; + ImVec2 needed_size_from_last_frame = window_just_created ? ImVec2(0, 0) : window->ContentSize + window->WindowPadding * 2.0f; + float size_x_for_scrollbars = use_current_size_for_scrollbar_x ? avail_size_from_current_frame.x : avail_size_from_last_frame.x; + float size_y_for_scrollbars = use_current_size_for_scrollbar_y ? avail_size_from_current_frame.y : avail_size_from_last_frame.y; + //bool scrollbar_y_from_last_frame = window->ScrollbarY; // FIXME: May want to use that in the ScrollbarX expression? How many pros vs cons? window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar)); window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((needed_size_from_last_frame.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); if (window->ScrollbarX && !window->ScrollbarY) @@ -5597,8 +5611,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // - BeginTabBar() for right-most edge const bool allow_scrollbar_x = !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar); const bool allow_scrollbar_y = !(flags & ImGuiWindowFlags_NoScrollbar); - const float work_rect_size_x = (window->ContentSizeExplicit.x != 0.0f ? window->ContentSizeExplicit.x : ImMax(allow_scrollbar_x ? window->ContentSize.x : 0.0f, window->InnerRect.GetWidth() - window->WindowPadding.x * 2.0f)); - const float work_rect_size_y = (window->ContentSizeExplicit.y != 0.0f ? window->ContentSizeExplicit.y : ImMax(allow_scrollbar_y ? window->ContentSize.y : 0.0f, window->InnerRect.GetHeight() - window->WindowPadding.y * 2.0f)); + const float work_rect_size_x = (window->ContentSizeExplicit.x != 0.0f ? window->ContentSizeExplicit.x : ImMax(allow_scrollbar_x ? window->ContentSize.x : 0.0f, window->Size.x - window->WindowPadding.x * 2.0f - window->ScrollbarSizes.x)); + const float work_rect_size_y = (window->ContentSizeExplicit.y != 0.0f ? window->ContentSizeExplicit.y : ImMax(allow_scrollbar_y ? window->ContentSize.y : 0.0f, window->Size.y - window->WindowPadding.y * 2.0f - decoration_up_height - window->ScrollbarSizes.y)); window->WorkRect.Min.x = ImFloor(window->InnerRect.Min.x - window->Scroll.x + ImMax(window->WindowPadding.x, window->WindowBorderSize)); window->WorkRect.Min.y = ImFloor(window->InnerRect.Min.y - window->Scroll.y + ImMax(window->WindowPadding.y, window->WindowBorderSize)); window->WorkRect.Max.x = window->WorkRect.Min.x + work_rect_size_x; @@ -5606,13 +5620,12 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // [LEGACY] Contents Region // FIXME-OBSOLETE: window->ContentsRegionRect.Max is currently very misleading / partly faulty, but some BeginChild() patterns relies on it. - // NB: WindowBorderSize is included in WindowPadding _and_ ScrollbarSizes so we need to cancel one out when we have both. // Used by: // - Mouse wheel scrolling + many other things 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 + decoration_up_height; - window->ContentsRegionRect.Max.x = window->Pos.x - window->Scroll.x - window->WindowPadding.x + (window->ContentSizeExplicit.x != 0.0f ? window->ContentSizeExplicit.x : (window->Size.x - window->ScrollbarSizes.x + ImMin(window->ScrollbarSizes.x, window->WindowBorderSize))); - window->ContentsRegionRect.Max.y = window->Pos.y - window->Scroll.y - window->WindowPadding.y + (window->ContentSizeExplicit.y != 0.0f ? window->ContentSizeExplicit.y : (window->Size.y - window->ScrollbarSizes.y + ImMin(window->ScrollbarSizes.y, window->WindowBorderSize))); + window->ContentsRegionRect.Max.x = window->ContentsRegionRect.Min.x + (window->ContentSizeExplicit.x != 0.0f ? window->ContentSizeExplicit.x : (window->Size.x - window->WindowPadding.x * 2.0f - window->ScrollbarSizes.x)); + window->ContentsRegionRect.Max.y = window->ContentsRegionRect.Min.y + (window->ContentSizeExplicit.y != 0.0f ? window->ContentSizeExplicit.y : (window->Size.y - window->WindowPadding.y * 2.0f - decoration_up_height - window->ScrollbarSizes.y)); // Setup drawing context // (NB: That term "drawing context / DC" lost its meaning a long time ago. Initially was meant to hold transient data only. Nowadays difference between window-> and window->DC-> is dubious.) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 58f1dbecb..6abfbbf24 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2168,6 +2168,7 @@ static void ShowDemoWindowLayout() static bool show_text_wrapped = false; static bool show_columns = true; static bool show_tab_bar = true; + static bool show_child = false; static bool explicit_content_size = false; static float contents_size_x = 300.0f; if (explicit_content_size) @@ -2182,7 +2183,9 @@ static void ShowDemoWindowLayout() ImGui::Checkbox("Text wrapped", &show_text_wrapped);// Will grow and use contents size ImGui::Checkbox("Columns", &show_columns); // Will use contents size ImGui::Checkbox("Tab bar", &show_tab_bar); // Will use contents size + ImGui::Checkbox("Child", &show_child); // Will grow and use contents size ImGui::Checkbox("Explicit content size", &explicit_content_size); + ImGui::Text("Scroll %.1f/%.1f %.1f/%.1f", ImGui::GetScrollX(), ImGui::GetScrollMaxX(), ImGui::GetScrollY(), ImGui::GetScrollMaxY()); if (explicit_content_size) { ImGui::SameLine(); @@ -2235,6 +2238,11 @@ static void ShowDemoWindowLayout() if (ImGui::BeginTabItem("FourFourFour")) { ImGui::EndTabItem(); } ImGui::EndTabBar(); } + if (show_child) + { + ImGui::BeginChild("child", ImVec2(0,0), true); + ImGui::EndChild(); + } ImGui::End(); } diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index becb5fe92..39307243d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -884,21 +884,22 @@ void ImGui::Scrollbar(ImGuiAxis axis) // Calculate scrollbar bounding box const ImRect outer_rect = window->Rect(); const ImRect inner_rect = window->InnerRect; + const float border_size = window->WindowBorderSize; const float scrollbar_size = window->ScrollbarSizes[axis ^ 1]; - IM_ASSERT(scrollbar_size > 0.0f); IM_UNUSED(scrollbar_size); + IM_ASSERT(scrollbar_size > 0.0f); const float other_scrollbar_size = window->ScrollbarSizes[axis]; ImDrawCornerFlags rounding_corners = (other_scrollbar_size <= 0.0f) ? ImDrawCornerFlags_BotRight : 0; ImRect bb; if (axis == ImGuiAxis_X) { - bb.Min = ImVec2(inner_rect.Min.x, inner_rect.Max.y); - bb.Max = ImVec2(inner_rect.Max.x, outer_rect.Max.y - window->WindowBorderSize); + bb.Min = ImVec2(inner_rect.Min.x, outer_rect.Max.y - border_size - scrollbar_size); + bb.Max = ImVec2(inner_rect.Max.x, outer_rect.Max.y); rounding_corners |= ImDrawCornerFlags_BotLeft; } else { - bb.Min = ImVec2(inner_rect.Max.x, inner_rect.Min.y); - bb.Max = ImVec2(outer_rect.Max.x - window->WindowBorderSize, window->InnerRect.Max.y); + bb.Min = ImVec2(outer_rect.Max.x - border_size - scrollbar_size, inner_rect.Min.y); + bb.Max = ImVec2(outer_rect.Max.x, window->InnerRect.Max.y); rounding_corners |= ((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? ImDrawCornerFlags_TopRight : 0; } ScrollbarEx(bb, id, axis, &window->Scroll[axis], inner_rect.Max[axis] - inner_rect.Min[axis], window->ContentSize[axis] + window->WindowPadding[axis] * 2.0f, rounding_corners);