Vertical/Horizontal scrollbar The entire piece of code below is rather confusing because: - We handle absolute seeking (when first clicking outside the grab) and relative manipulation (afterward or when clicking inside the grab) - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar - We handle both horizontal and vertical s
| 922 | // - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal. |
| 923 | // Still, the code should probably be made simpler.. |
| 924 | bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS64* p_scroll_v, ImS64 size_avail_v, ImS64 size_contents_v, ImDrawFlags flags) |
| 925 | { |
| 926 | ImGuiContext& g = *GImGui; |
| 927 | ImGuiWindow* window = g.CurrentWindow; |
| 928 | if (window->SkipItems) |
| 929 | return false; |
| 930 | |
| 931 | const float bb_frame_width = bb_frame.GetWidth(); |
| 932 | const float bb_frame_height = bb_frame.GetHeight(); |
| 933 | if (bb_frame_width <= 0.0f || bb_frame_height <= 0.0f) |
| 934 | return false; |
| 935 | |
| 936 | // When we are too small, start hiding and disabling the grab (this reduce visual noise on very small window and facilitate using the window resize grab) |
| 937 | float alpha = 1.0f; |
| 938 | if ((axis == ImGuiAxis_Y) && bb_frame_height < g.FontSize + g.Style.FramePadding.y * 2.0f) |
| 939 | alpha = ImSaturate((bb_frame_height - g.FontSize) / (g.Style.FramePadding.y * 2.0f)); |
| 940 | if (alpha <= 0.0f) |
| 941 | return false; |
| 942 | |
| 943 | const ImGuiStyle& style = g.Style; |
| 944 | const bool allow_interaction = (alpha >= 1.0f); |
| 945 | |
| 946 | ImRect bb = bb_frame; |
| 947 | bb.Expand(ImVec2(-ImClamp(IM_FLOOR((bb_frame_width - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp(IM_FLOOR((bb_frame_height - 2.0f) * 0.5f), 0.0f, 3.0f))); |
| 948 | |
| 949 | // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar) |
| 950 | const float scrollbar_size_v = (axis == ImGuiAxis_X) ? bb.GetWidth() : bb.GetHeight(); |
| 951 | |
| 952 | // Calculate the height of our grabbable box. It generally represent the amount visible (vs the total scrollable amount) |
| 953 | // But we maintain a minimum size in pixel to allow for the user to still aim inside. |
| 954 | IM_ASSERT(ImMax(size_contents_v, size_avail_v) > 0.0f); // Adding this assert to check if the ImMax(XXX,1.0f) is still needed. PLEASE CONTACT ME if this triggers. |
| 955 | const ImS64 win_size_v = ImMax(ImMax(size_contents_v, size_avail_v), (ImS64)1); |
| 956 | const float grab_h_pixels = ImClamp(scrollbar_size_v * ((float)size_avail_v / (float)win_size_v), style.GrabMinSize, scrollbar_size_v); |
| 957 | const float grab_h_norm = grab_h_pixels / scrollbar_size_v; |
| 958 | |
| 959 | // Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar(). |
| 960 | bool held = false; |
| 961 | bool hovered = false; |
| 962 | ItemAdd(bb_frame, id, NULL, ImGuiItemFlags_NoNav); |
| 963 | ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus); |
| 964 | |
| 965 | const ImS64 scroll_max = ImMax((ImS64)1, size_contents_v - size_avail_v); |
| 966 | float scroll_ratio = ImSaturate((float)*p_scroll_v / (float)scroll_max); |
| 967 | float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; // Grab position in normalized space |
| 968 | if (held && allow_interaction && grab_h_norm < 1.0f) |
| 969 | { |
| 970 | const float scrollbar_pos_v = bb.Min[axis]; |
| 971 | const float mouse_pos_v = g.IO.MousePos[axis]; |
| 972 | |
| 973 | // Click position in scrollbar normalized space (0.0f->1.0f) |
| 974 | const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v); |
| 975 | SetHoveredID(id); |
| 976 | |
| 977 | bool seek_absolute = false; |
| 978 | if (g.ActiveIdIsJustActivated) |
| 979 | { |
| 980 | // On initial click calculate the distance between mouse and the center of the grab |
| 981 | seek_absolute = (clicked_v_norm < grab_v_norm || clicked_v_norm > grab_v_norm + grab_h_norm); |
nothing calls this directly
no test coverage detected