Possible bug with layouts and panels

Started by Dincio, 08 March 2017, 00:09:05

Dincio

I've been playing around with layouts and I've found a possible bug. First, I compiled this code (and it worked as expected, drawing both the panel and the text box on the window in the right positions):

Code (cpp) Select

/*! constructor inside a class that handles a text based interface */
mDialogInterface = std::make_shared<tgui::Panel>();
mDialogInterface->setPosition(0, mWindow->getSize().y / 4.f * 3.f);
mDialogInterface->setSize(mWindow->getSize().x, mWindow->getSize().y / 4.f);
mDialogInterface->setBackgroundColor(sf::Color::Red);
auto dialogBox = std::make_shared<tgui::TextBox>();
dialogBox->setText("hello there!");
dialogBox->setSize("parent.width / 4 * 3", "parent.height");
dialogBox->setPosition("parent.left", "parent.top");
mDialogInterface->add(dialogBox, "dialog");


Code (cpp) Select

/*! function that handles drawing (from the same class) */
void *::handleDrawing()
{
    ... //draw other stuff using views
    mWindow->setView(mWindow->getDefaultView());
    mWindow->draw(*mDialogInterface);
}


outcome shown in "right.png"


The problem is that when I change the eighth line of the first segment of code from this:
Code (cpp) Select
dialogBox->setPosition("parent.left", "parent.top");
to this:
Code (cpp) Select
dialogBox->setPosition("parent.width / 4", "parent.top");
which is what I want to do, but really I could change i 8)t to whatever inolves any type of calculation, like:
Code (cpp) Select
dialogBox->setPosition("parent.left + 1", "parent.top");
and still the problem will persist. The problem is that the text box becomes invisible (outcome shown in "wrong.png").

The only way I can seem to solve the issue is by drawing the textbox directly to the window, but this seems just some kind of workaround... so is this a bug or am I doing something wrong?

Also, as a side note, I've tryed receiving input from the panel via panel->handleInput(const sf::Event& event) but the compiler tells me that the function is protected. Is there any other way of doing this without relying on guis (aka, in my case, using panels)?

texus

That is indeed a bug in my layout system, but apparently not how you are expecting it. It turns out that the behavior of "parent.left + 1" is more correct than the one for "parent.left". Positions are already relative to the parent, so to put a widget in the top left corner of its parent you must give it position (0,0). You are placing your dialogBox far below the screen in your code.

QuoteAlso, as a side note, I've tryed receiving input from the panel via panel->handleInput(const sf::Event& event) but the compiler tells me that the function is protected. Is there any other way of doing this without relying on guis (aka, in my case, using panels)?
Apparently not. It seems like you will have to use a Gui if you need to handle events.

Dincio

#2
So the bug is that when I use parent.left alone it uses absolute position, while when I add some calculations in it uses relative position?

Dincio

#3
In this case (and pardon my double post) how would I be able to implement what I had in mind in the first place? That is: having the textbox's x coordinate be exactly one fourth of its parent's width.

texus

The bug is that somehow the expression is not being evaluated when there is no expression. When mWindow->getSize().y is 600 then mDialogInterface->getPosition().y will be 450 and thus parent.top should be 450. The bug is that it is 0. When you put an expression into the x position then it suddenly gets interpreted correctly and the dialogBox is placed on y position 450 instead of y position 0.

What you need is the following:
Code (cpp) Select
dialogBox->setSize("parent.width / 4", 0);

Dincio

Ok I understand the bug now, thanks for the quick reply :)

Yes I already resized the textbox that, but what I want to do is to keep the starting position of the text box (its top-left corner) exactly one fourth of the panel's length into the panel. I'll try to draw it to make myself clear. The expression I would iintuitively use to accomplish this would be:
Code (cpp) Select
dialogBox->setPosition("parent.width / 4", "parent.top");
or
Code (cpp) Select
dialogBox->setPosition(bindWidth(mDialogInterface) / 4.f, bindTop(mDialogInterface));
but neither seem to work... even though they should, even with the bug in place (or maybe I still haven't understood everything...)

texus

I just figured out that the bug isn't even in the layout system. It is specific to TextBox (and maybe a few other classes with similar code). It's basically a caching issue.

I told you what to write in my last post: you don't need "parent.top", you just need a 0.
If your panel is located at position (10, 20) and the widget inside the panel is placed at position (30, 40) then on the screen the widget will appear at pixel (40, 60). All positions are relative to the parent, that is why the top of your text box should be 0.

Dincio

oh yes sorry I understand now  ;D I even read it but just didn't notice the 0... ok everything seems to work now, thanks again.

About the bug; is it fixable?

Dincio

#8
The bug seems to persist even when calculations are involved... I did as you said, writing the code:
Code (cpp) Select
dialogBox->setPosition("parent.width / 4", 0);
but the textbox was drawn at position (0, 0) (relative to the parent) instead of (parent.width / 4, 0) as I wanted.

and also, being the expression parent.top - without any calculation - evaluated as 0 relative to the parent and not parent.top relative to the parent (because of the bug), isn't setPosition("parent.width / 4", "parent.top") also correct?

texus

I'll make sure it gets fixed in the next hour. You will have to rebuild tgui yourself afterward though.

A workaround for now is to call dialogBox->setPosition(1,1) before calling dialogBox->setPosition("parent.width / 4", 0).

Dincio

#10
Ok thanks for everything!  ;D

I'll rebuild it as soon as I can, for now I'll just use the workaround, which works perfectly.

Dincio

Also, as a side note, I needed to set the load an external font myself to make the textbox work... I don't know if this is normal or if the textbox is suposed to have a default font active when no font was selected.

texus

The fix has been made in the master branch on github (download zip).

QuoteAlso, as a side note, I needed to set the load an external font myself to make the textbox work... I don't know if this is normal or if the textbox is suposed to have a default font active when no font was selected.
Looks like you found another reason on why the Gui class is useful. All widgets added to the gui come with a build-in font.

You don't have to manually set the font for each widget btw, it gets inherited from the parent. So if you set the font of a panel then all widgets inside that panel will get that font as well.

Dincio

#13
Ok got it... it's just a shame that a Gui cannot be copied, but I'll have to make do :)

texus

I still don't see what you gain from copying it. You would save one line of code as you wouldn't have to call gui.setWindow again, but that's about it.