Closed MayitaMayoso closed 1 month ago
Use ImGui::GetScrollMaxY() > 0.0f
is there's scrolling, and window->ScrollbarY
(imgui_internal.h) if there's a scrollbar. You can have a scrolling range without a scrollbar.
But it is also very likely that you may be facing a XY Problem because you normally should not need to know about this. Can you clarify/explain why do you want to know if a scrollbar is visible?
First of all thanks for the quick response as always. It worked perfectly!
I am doing some custom drawing within a child window. I have used the ScrollBarSize in order for the symbols to not go under the ScrollBar. But when there is no Scrollar you can see an empty space. I want to know if there is Scrollbar to decide if I deduce the size or not of the total size for my own calculations for the drawings.
I want to know if there is Scrollbar to decide if I deduce the size or not of the total size for my own calculations for the drawings.
This seems to be a XY Problem indeed. You should not need to query scrollbar visibility.
You should call GetContentRegionAvail()
instead to obtain the drawable size.
ImVec2 pos_min = ImGui::GetCursorScreenPos();
ImVec2 pos_max = pos_min + ImGui::GetContentRegionAvail();
If you are not sure what some positions/values are, draw them on screen:
ImGui::GetForegroundDrawList()->AddRect(pos_min, pos_max, IM_COL32(255, 0, 0, 255));
The problem is that I need the size of the scroll before ImGui knows there is a scroll(?). I begin with an empty child window and I get the available size. Next I use the DrawList functionalities to draw my elements. These calls are followed by moving the cursor in order to let ImGui know the space has been occupied and if exceeded the height of the window make the scrollbar appear.
void SymbolColorComponent::RenderSymbols()
{
// Window parameters
auto Style = ImGui::State(ImGuiCol_ChildBg, Color4::Grey(.5f, .1f));
Vec2 WindowStart = ImGui::GetWindowPos() + ImGui::GetCursorPos();
Vec2 WindowSize = ImGui::GetContentRegionAvail();
ImGui::BeginChild(ImGui::GetID("Symbols"), WindowSize);
if (ImGui::GetScrollMaxY())
{
WindowSize -= Vec2(ImGui::GetStyle().ScrollbarSize, 0.0f);
}
// Symbol parameters
Vec2 SymbolStart = WindowStart - Vec2(0, ImGui::GetScrollY());
Vec2 SymbolPos = SymbolStart;
Vec2 SymbolSize(100);
// Fixing symbol width to fit window span
auto SymbolsHorizontalCount = std::floor(WindowSize.x / SymbolSize.x);
SymbolSize.x += (WindowSize.x - SymbolSize.x * SymbolsHorizontalCount) / SymbolsHorizontalCount;
ImGui::GetWindowDrawList()->PushClipRect(WindowStart, WindowStart + WindowSize);
for (const auto& [Symbol, _] : mColors)
{
if (SymbolMatchFilter(Symbol))
{
RenderSymbol(Symbol, SymbolPos, SymbolSize);
UpdateSymbol(Symbol, SymbolPos, SymbolSize);
SymbolPos += SymbolSize * Vec2(1, 0);
if (SymbolPos.x + SymbolSize.x > WindowStart.x + WindowSize.x + 1)
{
SymbolPos = Vec2(SymbolStart.x, SymbolPos.y + SymbolSize.y);
ImGui::SetCursorPos(ImGui::GetCursorPos() + SymbolSize * Vec2(0, 1));
}
if (SymbolPos.y > WindowStart.y + WindowSize.y)
{
break;
}
}
}
ImGui::SetCursorPos(ImGui::GetCursorPos() + SymbolSize * Vec2(0, 1));
ImGui::GetWindowDrawList()->PopClipRect();
ImGui::EndChild();
}
Some suggestions
(1)
Vec2 WindowStart = ImGui::GetWindowPos() + ImGui::GetCursorPos();
Use
Vec2 WindowStart = ImGui::GetCursorScreenPos()`
Avoid all functions returning local coordinates. They make everything more complicated.
Vec2 SymbolStart = WindowStart - Vec2(0, ImGui::GetScrollY());
This also simply:
Vec2 SymbolStart = ImGui::GetCursorScreenPos();
(2)
I don't understand your explanation above and I don't think you need to do most of this.
You only need to use GetCursorScreenPos()
and GetContentRegionAvail()
.
(3)
These calls are followed by moving the cursor in order
This is illegal since 1.89: (#5548)
ImGui::SetCursorPos(ImGui::GetCursorPos() + SymbolSize * Vec2(0, 1));
You should do
ImGui::SetCursorPos(ImGui::GetCursorPos() + SymbolSize * Vec2(0, 1));
ImGui::Dummy({0,0});
or
ImGui::Dummy(SymbolSize * Vec2(0, 1));
See v1.89 release notes.
In spite of multiple warnings in the comments, it has been such a recurrent issue that people are using GetWindowPos(), GetCursorPos() etc. they tend to be source of confusion and comlexity.
I have increased and boldened the warnings in comments. I have also moved next step forward by obsoleting GetContentRegionMax()
, GetWindowContentRegionMin()
, GetWindowContentRegionMax()
.
I have also reorganized headers a little bit to move GetContentRegionAvail()
need to GetCursorScreenPos()
.
Those two functions are everyone's best friend and you really cater 99% of needs.
It will be my new crusade :)
Version/Branch of Dear ImGui:
Version 1.89.7, Branch: docking (master/docking/etc.)
Back-ends:
imgui_impl_glfw.cpp + imgui_impl_opengl3.cpp
Compiler, OS:
Debian 10 + GNUC
Question:
Is there a way to know if the scrollbar is visible other than pre-calculating if the size of the window / child window / frame exceeds the available region? Style has ScrollBarSize which I use for drawing some stuff but since the scrollbar only appears if there is something to scroll I was wondering if there is maybe any Getter I have missed when searching for an answer.