Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decorating scroll bars #3114

Closed
wolfpld opened this issue Apr 9, 2020 · 4 comments
Closed

Decorating scroll bars #3114

wolfpld opened this issue Apr 9, 2020 · 4 comments

Comments

@wolfpld
Copy link
Contributor

wolfpld commented Apr 9, 2020

I would like to add decorations to a (child) window scroll bar. Something alike to the following examples:

VTune (let's ignore that decorations are placed next to the scroll bar here):
scroll

MSVC:
scroll2

I can't see anything in the API, which would allow doing so. I would imagine at least the following functions should be added:

if( ImGui::IsDisplayingScrollBar() ) {
    auto draw = ImGui::GetScrollDrawList();
    auto pos = ImGui::GetScrollScreenPos();
    auto region = ImGui::GetScrollSize();
    ...
}

A bit of thought is required to decide in which place user elements should be placed: before scroll bar is drawn, after scroll bar is drawn, or between drawing scroll background and scroll grab element. It may be best to expose all the possibilities through a parameter to GetScrollDrawList(), but to get things running quickly it seems reasonable to use the third option. This way user elements won't ever be obscuring the grab element.

@rokups
Copy link
Contributor

rokups commented Apr 10, 2020

Hey @wolfpld,
There is no built in way to do that. However you may cheat a little. Window scrollbars are rendered as part of Begin() call. You could try rendering extra information on to scrollbar rect right after Begin(), it might yield similar results like in MSVC screenshot. If that is not enough i am afraid you would have to modify scrollbar rendering in imgui itself.

ocornut added a commit that referenced this issue Apr 10, 2020
…tidying up code to make it more obvious how to draw over scrollbars. (#3114)
@ocornut
Copy link
Owner

ocornut commented Apr 10, 2020

I have pushed a first change toward that: f7852fa

  • There now a GetWindowScrollbarRect() function in imgui_internal.h
  • Tweaked various scrollbar related functions and comments to ease understanding of what's going on.
    (This commit merges in docking without conflicts so you may cherry-pick it today).

Using imgui_internal.h:

ImGui::Begin("Hello, world!");
ImGuiWindow* window = ImGui::GetCurrentWindow();
if (window->ScrollbarX || window->ScrollbarY)
{
    ImGui::PushClipRect(window->OuterRectClipped.Min, window->OuterRectClipped.Max, false);
    if (window->ScrollbarX)
    {
        ImRect r = ImGui::GetWindowScrollbarRect(window, ImGuiAxis_X);
        window->DrawList->AddRect(r.Min, r.Max, IM_COL32(255, 0, 0, 255));
    }
    if (window->ScrollbarY)
    {
        ImRect r = ImGui::GetWindowScrollbarRect(window, ImGuiAxis_Y);
        window->DrawList->AddRect(r.Min, r.Max, IM_COL32(255, 0, 0, 255));
    }
    ImGui::PopClipRect();
}
[...]

EDIT If you don't use any ImGui:: interactive/function in the drawing, you can replace ImGui::PushClipRect/PopClipRect by the lower-level window->DrawList->PushClipRect() equivalent.

image

  • If you now look at the ImGui::Scrollbar() function in imgui_widgets.cpp (after the change I just pushed), stripping away a few details you don't care about, those 5 lines are probably the essential info you would need to correctly "project" your rendering.
ImGuiID id = GetWindowScrollbarID(window, axis);
ImRect bb = GetWindowScrollbarRect(window, axis);
float size_avail = window->InnerRect.Max[axis] - window->InnerRect.Min[axis];
float size_contents = window->ContentSize[axis] + window->WindowPadding[axis] * 2.0f;
ScrollbarEx(bb, id, axis, &window->Scroll[axis], size_avail, size_contents, rounding_corners);
  • The scrollbar interaction will always run on Begin(). If you want to render OVER the scrollbar then you can use the info above. If you somehow need to render UNDER the scrollbar then we have a bit of a problem but an easy workaround would be to set all those colors to zero:
ImGui::PushStyleColor(ImGuiCol_ScrollbarBg, ImVec4(0, 0, 0, 0));
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrab, ImVec4(0, 0, 0, 0));
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabActive, ImVec4(0, 0, 0, 0));
ImGui::PushStyleColor(ImGuiCol_ScrollbarGrabHovered, ImVec4(0, 0, 0, 0));
ImGui::Begin(...)
ImGui::PopStyleColor(4);

And then you have the render it yourself, which is a little bit awkward but not super complicated (and you don't necessarily need to match all edge cases behavior handled by ScrollbarEx).

  • If you eventually wanted to draw next to the scrollbar, and therefore move the scrollbar, as in the first shot (VTune), the simpler hack imho would be to add an extra window (Begin+BeginChild).

I hope this is useful and I'd be interested in seeing that you can do with the above information. I'm happy to make further change or add more internal helpers. Don't hesitate to post your result or link to the code if you do end with something, even if you don't have explicit requests it may be helpful as a resources and I may still come up with improvements on our side of the fence.

@wolfpld
Copy link
Contributor Author

wolfpld commented Apr 10, 2020

This everything I need. Usage example:

auto win = ImGui::GetCurrentWindow();
if( win->ScrollbarY )
{
    auto draw = ImGui::GetWindowDrawList();
    auto rect = ImGui::GetWindowScrollbarRect( win, ImGuiAxis_Y );
    ImGui::PushClipRect( rect.Min, rect.Max, false );
    if( m_selectedLine != 0 )
    {
        auto ly = round( rect.Min.y + ( m_selectedLine - 0.5f ) / m_lines.size() * rect.GetHeight() );
        draw->AddLine( ImVec2( rect.Min.x, ly ), ImVec2( rect.Max.x, ly ), 0x8899994C, 3 );
    }
    ImGui::PopClipRect();
}

I will post a screenshot when I'm finished with everything I want to have here. Thanks.

@wolfpld
Copy link
Contributor Author

wolfpld commented Apr 10, 2020

There are two kinds of information shown with scroll bar decorations on the screenshot below:
1a. Currently selected source line and the corresponding assembly instructions.
1b. Currently hovered source line and the corresponding assembly instructions.
2. Relative "hotness" of source/assembly lines.

obraz

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants