diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 9dee4195..649e75ed 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -39,6 +39,8 @@ Other Changes: when enabled will have small overlap glitches with (style.Alpha < 1.0). - TabBar: fixed ScrollToBar request creating bouncing loop when tab is larger than available space. - TabBar: fixed single-tab not shrinking their width down. +- TabBar: improved shrinking for large number of tabs to avoid leaving extraneous space on the right side. + Individuals tabs are given integer-rounded width and remainder is spread between tabs left-to-right. - SliderScalar: Improved assert when using U32 or U64 types with a large v_max value. (#2765) [@loicmouton] - ImDrawList: clarified the name of many parameters so reading the code is a little easier. (#2740) - Using offsetof() when available in C++11. Avoids Clang sanitizer complaining about old-style macros. (#94) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 79f5b2d4..42e13243 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1370,14 +1370,28 @@ void ImGui::ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_exc int count_same_width = 1; while (width_excess > 0.0f && count_same_width < count) { - while (count_same_width < count && items[0].Width == items[count_same_width].Width) + while (count_same_width < count && items[0].Width <= items[count_same_width].Width) count_same_width++; - float width_to_remove_per_item_max = (count_same_width < count) ? (items[0].Width - items[count_same_width].Width) : (items[0].Width - 1.0f); - float width_to_remove_per_item = ImMin(width_excess / count_same_width, width_to_remove_per_item_max); + float max_width_to_remove_per_item = (count_same_width < count) ? (items[0].Width - items[count_same_width].Width) : (items[0].Width - 1.0f); + float width_to_remove_per_item = ImMin(width_excess / count_same_width, max_width_to_remove_per_item); for (int item_n = 0; item_n < count_same_width; item_n++) items[item_n].Width -= width_to_remove_per_item; width_excess -= width_to_remove_per_item * count_same_width; } + + // Round width and redistribute remainder left-to-right (could make it an option of the function?) + // Ensure that e.g. the right-most tab of a shrunk tab-bar always reaches exactly at the same distance from the right-most edge of the tab bar separator. + width_excess = 0.0f; + for (int n = 0; n < count; n++) + { + float width_rounded = ImFloor(items[n].Width); + width_excess += items[n].Width - width_rounded; + items[n].Width = width_rounded; + } + if (width_excess > 0.0f) + for (int n = 0; n < count; n++) + if (items[n].Index < (int)(width_excess + 0.01f)) + items[n].Width += 1.0f; } //-------------------------------------------------------------------------