Skip to content

Commit 5f30191

Browse files
committed
TabBar: Tab-bars with ImGuiTabBarFlags_FittingPolicyScroll can be scrolled with horizontal mouse-wheel (or Shift + WheelY). (#2702)
1 parent 84fd0c7 commit 5f30191

File tree

4 files changed

+26
-4
lines changed

4 files changed

+26
-4
lines changed

docs/CHANGELOG.txt

+2
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ Other changes:
5252
- Nav: Made Ctrl+Tab/Ctrl+Shift+Tab windowing register ownership to held modifier so
5353
it doesn't interfere with other code when remapping those actions. (#4828, #3255, #5641)
5454
- ColorEdit: Fixed shading of S/V triangle in Hue Wheel mode. (#5200, #6254) [@jamesthomasgriffin]
55+
- TabBar: Tab-bars with ImGuiTabBarFlags_FittingPolicyScroll can be scrolled with
56+
horizontal mouse-wheel (or Shift + WheelY). (#2702)
5557
- Rendering: Using adaptative tesselation for: RadioButton, ColorEdit preview circles,
5658
Windows Close and Collapse Buttons.
5759
- Misc: Fixed ImVec2 operator[] violating aliasing rules causing issue with Intel C++

imgui.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -3867,7 +3867,7 @@ void ImGui::MarkItemEdited(ImGuiID id)
38673867
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
38683868
}
38693869

3870-
static inline bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
3870+
bool ImGui::IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
38713871
{
38723872
// An active popup disable hovering on other windows (apart from its own children)
38733873
// FIXME-OPT: This could be cached/stored within the window.

imgui_internal.h

+1
Original file line numberDiff line numberDiff line change
@@ -2828,6 +2828,7 @@ namespace ImGui
28282828
inline void ItemSize(const ImRect& bb, float text_baseline_y = -1.0f) { ItemSize(bb.GetSize(), text_baseline_y); } // FIXME: This is a misleading API since we expect CursorPos to be bb.Min.
28292829
IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL, ImGuiItemFlags extra_flags = 0);
28302830
IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id);
2831+
IMGUI_API bool IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags = 0);
28312832
IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id);
28322833
IMGUI_API void SetLastItemData(ImGuiID item_id, ImGuiItemFlags in_flags, ImGuiItemStatusFlags status_flags, const ImRect& item_rect);
28332834
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h);

imgui_widgets.cpp

+22-3
Original file line numberDiff line numberDiff line change
@@ -7618,6 +7618,12 @@ void ImGui::EndTabBar()
76187618
g.CurrentTabBar = g.CurrentTabBarStack.empty() ? NULL : GetTabBarFromTabBarRef(g.CurrentTabBarStack.back());
76197619
}
76207620

7621+
// Scrolling happens only in the central section (leading/trailing sections are not scrolling)
7622+
static float TabBarCalcScrollableWidth(ImGuiTabBar* tab_bar, ImGuiTabBarSection* sections)
7623+
{
7624+
return tab_bar->BarRect.GetWidth() - sections[0].Width - sections[2].Width - sections[1].Spacing;
7625+
}
7626+
76217627
// This is called only once a frame before by the first call to ItemTab()
76227628
// The reason we're not calling it in BeginTabBar() is to leave a chance to the user to call the SetTabItemClosed() functions.
76237629
static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
@@ -7820,9 +7826,23 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
78207826
tab_bar->VisibleTabId = tab_bar->SelectedTabId;
78217827
tab_bar->VisibleTabWasSubmitted = false;
78227828

7823-
// Update scrolling
7829+
// Apply request requests
78247830
if (scroll_to_tab_id != 0)
78257831
TabBarScrollToTab(tab_bar, scroll_to_tab_id, sections);
7832+
else if ((tab_bar->Flags & ImGuiTabBarFlags_FittingPolicyScroll) && IsMouseHoveringRect(tab_bar->BarRect.Min, tab_bar->BarRect.Max, true) && IsWindowContentHoverable(g.CurrentWindow))
7833+
{
7834+
const float wheel = g.IO.MouseWheelRequestAxisSwap ? g.IO.MouseWheel : g.IO.MouseWheelH;
7835+
const ImGuiKey wheel_key = g.IO.MouseWheelRequestAxisSwap ? ImGuiKey_MouseWheelY : ImGuiKey_MouseWheelX;
7836+
if (TestKeyOwner(wheel_key, tab_bar->ID) && wheel != 0.0f)
7837+
{
7838+
const float scroll_step = wheel * TabBarCalcScrollableWidth(tab_bar, sections) / 3.0f;
7839+
tab_bar->ScrollingTargetDistToVisibility = 0.0f;
7840+
tab_bar->ScrollingTarget = TabBarScrollClamp(tab_bar, tab_bar->ScrollingTarget - scroll_step);
7841+
}
7842+
SetKeyOwner(wheel_key, tab_bar->ID);
7843+
}
7844+
7845+
// Update scrolling
78267846
tab_bar->ScrollingAnim = TabBarScrollClamp(tab_bar, tab_bar->ScrollingAnim);
78277847
tab_bar->ScrollingTarget = TabBarScrollClamp(tab_bar, tab_bar->ScrollingTarget);
78287848
if (tab_bar->ScrollingAnim != tab_bar->ScrollingTarget)
@@ -7959,8 +7979,7 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
79597979
int order = TabBarGetTabOrder(tab_bar, tab);
79607980

79617981
// Scrolling happens only in the central section (leading/trailing sections are not scrolling)
7962-
// FIXME: This is all confusing.
7963-
float scrollable_width = tab_bar->BarRect.GetWidth() - sections[0].Width - sections[2].Width - sections[1].Spacing;
7982+
float scrollable_width = TabBarCalcScrollableWidth(tab_bar, sections);
79647983

79657984
// We make all tabs positions all relative Sections[0].Width to make code simpler
79667985
float tab_x1 = tab->Offset - sections[0].Width + (order > sections[0].TabCount - 1 ? -margin : 0.0f);

0 commit comments

Comments
 (0)