How to use ScrollablePanel?

Started by kiwon0905, 18 October 2017, 03:49:28

kiwon0905

Code (cpp) Select

auto scrollPanel = tgui::ScrollablePanel::create({ "300", "300" });
scrollPanel->getRenderer()->setBackgroundColor(sf::Color::White);
auto grid = tgui::Grid::create();
grid->setAutoSize(true);

for (int r = 0; r < 100; ++r)
grid->addWidget(tgui::Label::create("h"), r, 0);
scrollPanel->add(grid);
gui.add(scrollPanel);


I'd like the scrollbar to appear when the grid gets bigger than the panel, but I don't see any scrollbar.


texus

I don't have time to actually check it now, but I think the issue is with Grid. I think its size will be (0,0) when no size is given to it.
I'll have a look at this tonight as it looks like a bug that I must have introduced some weeks/months ago when I changed the way the size is handled in Grid. If the issue is as simple as I currently think it is then I should be able to have it fixed today once I get back from work.

texus

There seem to be 2 unrelated issues. The first one was the bug I expected with Grid and has been fixed now.

The second "issue" is that ScrollbablePanel only checks the size and position of widgets when they are added to it. When "scrollPanel->add(grid);" is executed, the size of the Grid is still (0,0) since all the labels have size (0,0) since they don't have a font yet. When no font is set, the one from the parent is used. The widgets thus only get a size when "gui.add(scrollPanel);" is called but at that point the ScrollbablePanel no longer changes.

I'll soon look into how I will improve the ScrollbablePanel to automatically recalculate when one of its widgets is changed, but for now your code will work if you download the latest version again (to have the fix for the Grid) and swap the order of the "scrollPanel->add(grid);" and "gui.add(scrollPanel);" calls.

kiwon0905

The fix works. Thank you for the fast response!

kiwon0905

Hi texus,
I'm trying to make something like this:


I tried inserting HorizontalLayouts to the grids, but I don't get the scrollbars.
Code (cpp) Select
auto scrollPanel = tgui::ScrollablePanel::create({ "75%", "75%" });
scrollPanel->getRenderer()->setBackgroundColor(sf::Color::Green);
auto grid = tgui::Grid::create();
for (int i = 0; i < 100; ++i)
{
auto h = tgui::HorizontalLayout::create({ tgui::bindWidth(scrollPanel), tgui::bindHeight(scrollPanel) / 10 });
h->add(tgui::Label::create("Hello"));
h->add(tgui::Label::create("Hello"));
h->add(tgui::Label::create("Hello"));
h->add(tgui::Label::create("Hello"));
grid->addWidget(h, i, 0);
}

gui.add(scrollPanel);
scrollPanel->add(grid);




What would be the best way to implement something like this?

texus

Weird, I do get scrollbars with that code. Could you show a complete code, something that I can copy, paste and run so that I have the exact same code?
But the clipping is definately broken, seems like it only took 4 days for someone to find a bug in the new implementation.
The scrolling also seems a bit wrong, I either terribly messed something up in the new clipping code (which was just rewritten from scratch to work around and SFML issue) or there is some other issue in ScrollablePanel that I never noticed yet.
The widgets you are playing with are all relatively new or received quite some recent changes and are thus less tested, so you might hit a bit more issues with them than usual.

Writing something like that is probably not going to be easy, but maybe you can try with a VerticalLayout instead of a Grid. It requires you to manually specify the size, but you might be able to easily calculate it. The width would just be the size of the ScrollbablePanel (maybe minus the scrollbar width) while the height is the amount of items multiplied with the height of each row. You would have to change the height of the VerticalLayout every time you add or remove a row, but I think it might be the best solution.

kiwon0905


Ok i think i just messed up the order of grid.add(scrollPanel); and scrollPanel.add(grid); before.
Thanks.

texus

#7
The clipping bug (that caused the text to be displayed outside the ScrollbablePanel) has now been fixed as well.
This weekend I will add the improvements to the ScrollablePanel class such that the order of the add calls will no longer matter.

Update: ScrollablePanel has been updated, the code from your first post now works.

kiwon0905

Thank you. I really appreciate your work.
I have a last question:

Code (cpp) Select

sf::RenderWindow window{ { 800, 600 }, "Window" };
tgui::Gui gui{ window }; // Create the gui and attach it to the window
auto scrollPanel = tgui::ScrollablePanel::create({ "50%", "50%" });
auto grid = tgui::Grid::create();
for (int i = 0; i < 100; ++i)
{
auto label = tgui::Label::create("Hi");
label->getRenderer()->setBackgroundColor(sf::Color::Green);
label->setSize({ tgui::bindWidth(scrollPanel), tgui::bindHeight(scrollPanel) / 10});
grid->addWidget(label, i, 0);
}
scrollPanel->add(grid);
gui.add(scrollPanel);
while (window.isOpen())
{
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();

gui.handleEvent(event); // Pass the event to the widgets
}
window.clear();
gui.draw(); // Draw all widgets
window.display();
}





Using the above code, I get a horizontal scrollbar. When setting the size of the label, I think i need to subtract the width of the vertical scrollbar to not get it. How can I get the size of the scrollbar?

texus

I have added a getScrollbarWidth (and setScrollbarWidth) function now.
I couldn't decide earlier about whether I should go for a getScrollbarWidth function or for a method that simply disabled the horizontal scrollbar. I delayed the decision and apparently forgot about it afterwards. Currently ScrollablePanel implements a minimal API simply because I don't fully know how the widget will be used. So feel free to suggest other functionality that you feel is missing.

kiwon0905

How about taking similar approach to SFGUI?

enum ScrollbarPolicy
{
    VerticalAutomatic = 1 << 0,
    VerticalAlways = 1 << 1,
    VerticalNever = 1 << 2,
    HorizontalAutomatic = 1 << 3,
    HorizontalAlways = 1 << 4,
    HorizontalNeve = 1 << 5
}
void setScrollbarPolicy(ScrollbarPolicy policy);

texus

That seems like a good way to implement it. This reminds me once again that I should look at existing libraries instead of just making random decisions.

texus

I've added a scrollbar policy in the latest version so alternatively to subtracting the scrollbar width you can now remove the horizontal scrollbar like this:
Code (cpp) Select
panel->setHorizontalScrollbarPolicy(tgui::ScrollablePanel::ScrollbarPolicy::Never);