Skip to content

Commit 0236bc2

Browse files
committed
Scrollbar: Fade out and disable interaction when too small, in order to facilitate using the resize grab on very small window, as well as reducing visual noise/overlap. (+1 squashed commits)
Internals: Added GetScrollbarID(). (ocornut#1185)
1 parent 57a586b commit 0236bc2

File tree

3 files changed

+28
-6
lines changed

3 files changed

+28
-6
lines changed

docs/CHANGELOG.txt

+2
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ Other Changes:
6161
- RadioButton: Fixed label horizontal alignment to precisely match Checkbox().
6262
- Window: When resizing from an edge, the border is more visible and better follow the rounded corners.
6363
- Window: Fixed initial width of collapsed windows not taking account of contents width (broken in 1.67). (#2336, #176)
64+
- Scrollbar: Fade out and disable interaction when too small, in order to facilitate using the resize grab on very
65+
small window, as well as reducing visual noise/overlap.
6466
- ListBox: Better optimized when clipped / non-visible.
6567
- InputTextMultiline: Better optimized when clipped / non-visible.
6668
- Font: Fixed high-level ImGui::CalcTextSize() used by most widgets from erroneously subtracting 1.0f*scale to

imgui_internal.h

+1
Original file line numberDiff line numberDiff line change
@@ -1464,6 +1464,7 @@ namespace ImGui
14641464
IMGUI_API bool CollapseButton(ImGuiID id, const ImVec2& pos);
14651465
IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags);
14661466
IMGUI_API void Scrollbar(ImGuiLayoutType direction);
1467+
IMGUI_API ImGuiID GetScrollbarID(ImGuiLayoutType direction);
14671468
IMGUI_API void VerticalSeparator(); // Vertical separator, for menu bars (use current line height). Not exposed because it is misleading and it doesn't have an effect on regular layout.
14681469

14691470
// Widgets low-level behaviors

imgui_widgets.cpp

+25-6
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,13 @@ bool ImGui::CollapseButton(ImGuiID id, const ImVec2& pos)
710710
return pressed;
711711
}
712712

713+
ImGuiID ImGui::GetScrollbarID(ImGuiLayoutType direction)
714+
{
715+
ImGuiContext& g = *GImGui;
716+
ImGuiWindow* window = g.CurrentWindow;
717+
return window->GetID((direction == ImGuiLayoutType_Horizontal) ? "#SCROLLX" : "#SCROLLY");
718+
}
719+
713720
// Vertical/Horizontal scrollbar
714721
// The entire piece of code below is rather confusing because:
715722
// - We handle absolute seeking (when first clicking outside the grab) and relative manipulation (afterward or when clicking inside the grab)
@@ -722,8 +729,8 @@ void ImGui::Scrollbar(ImGuiLayoutType direction)
722729

723730
const bool horizontal = (direction == ImGuiLayoutType_Horizontal);
724731
const ImGuiStyle& style = g.Style;
725-
const ImGuiID id = window->GetID(horizontal ? "#SCROLLX" : "#SCROLLY");
726-
732+
const ImGuiID id = GetScrollbarID(direction);
733+
727734
// Render background
728735
bool other_scrollbar = (horizontal ? window->ScrollbarY : window->ScrollbarX);
729736
float other_scrollbar_size_w = other_scrollbar ? style.ScrollbarSize : 0.0f;
@@ -734,9 +741,21 @@ void ImGui::Scrollbar(ImGuiLayoutType direction)
734741
: ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + border_size, window_rect.Max.x - border_size, window_rect.Max.y - other_scrollbar_size_w - border_size);
735742
if (!horizontal)
736743
bb.Min.y += window->TitleBarHeight() + ((window->Flags & ImGuiWindowFlags_MenuBar) ? window->MenuBarHeight() : 0.0f);
737-
if (bb.GetWidth() <= 0.0f || bb.GetHeight() <= 0.0f)
744+
745+
const float bb_height = bb.GetHeight();
746+
if (bb.GetWidth() <= 0.0f || bb_height <= 0.0f)
738747
return;
739748

749+
// When we are too small, start hiding and disabling the grab (this reduce visual noise on very small window and facilitate using the resize grab)
750+
float alpha = 1.0f;
751+
if ((direction == ImGuiLayoutType_Vertical) && bb_height < g.FontSize + g.Style.FramePadding.y * 2.0f)
752+
{
753+
alpha = ImSaturate((bb_height - g.FontSize) / (g.Style.FramePadding.y * 2.0f));
754+
if (alpha <= 0.0f)
755+
return;
756+
}
757+
const bool allow_interaction = (alpha >= 1.0f);
758+
740759
int window_rounding_corners;
741760
if (horizontal)
742761
window_rounding_corners = ImDrawCornerFlags_BotLeft | (other_scrollbar ? 0 : ImDrawCornerFlags_BotRight);
@@ -767,7 +786,7 @@ void ImGui::Scrollbar(ImGuiLayoutType direction)
767786
float scroll_max = ImMax(1.0f, win_size_contents_v - win_size_avail_v);
768787
float scroll_ratio = ImSaturate(scroll_v / scroll_max);
769788
float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;
770-
if (held && grab_h_norm < 1.0f)
789+
if (held && allow_interaction && grab_h_norm < 1.0f)
771790
{
772791
float scrollbar_pos_v = horizontal ? bb.Min.x : bb.Min.y;
773792
float mouse_pos_v = horizontal ? g.IO.MousePos.x : g.IO.MousePos.y;
@@ -810,8 +829,8 @@ void ImGui::Scrollbar(ImGuiLayoutType direction)
810829
*click_delta_to_grab_center_v = clicked_v_norm - grab_v_norm - grab_h_norm*0.5f;
811830
}
812831

813-
// Render
814-
const ImU32 grab_col = GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab);
832+
// Render grab
833+
const ImU32 grab_col = GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab, alpha);
815834
ImRect grab_rect;
816835
if (horizontal)
817836
grab_rect = ImRect(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y, ImMin(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, window_rect.Max.x), bb.Max.y);

0 commit comments

Comments
 (0)