Switching to 0.7

Started by Heinrich, 23 September 2014, 13:38:03

Heinrich

Hello,

I am (still) using v0.6 for a hobby project.  Would you recommend switching to 0.7 now or should I await later versions?

texus

It depends.

There is still going to change a lot in v0.7. Any code you write with it might have to be rewritten in a few months if you decide to update the a newer v0.7-dev version.

So I wouldn't really recommend it for bigger projects, but if it is a small project that doesn't take many months to develop then it is ok.
At least there should be some need for one of its features. If it is just a program with a few buttons then there is no need to use v0.7-dev.

Heinrich

What would you assume is more work: Sticking to 0.6 now and rewriting when 0.7release comes out or rewriting for 0.7dev now and rewriting when 0.7release comes out?

texus

The second option will most likely be a little less work.
I'm also thinking about delaying the rewrite of the widget creation to v0.8 so that the current v0.7-dev code does not need a complete change later.

But note that v0.7-dev is still lacking a few features that were in v0.6, mainly loading widgets from a file.

Heinrich

I'm trying to port to 0.7dev. Does the Grid Widget workyet? It doesn't display anything that's added to it. Giving it borders and calling show() on it also does nothing.

texus

Are you calling the addWidget function after you created the widget?
If so, could you show a small example code?

Heinrich

#6
Okay, that's interesting. I used grid->add(button) instead of grid->addWidget(button). What does add() do?
Now, the button shows, but it doesn't display it's text (and doesn't react to hovering or clicking). Code is:


tgui::Gui gui(*mWin);
gui.setGlobalFont(Settings::getDataFolderBasePath()+"font/FixedSysEx.ttf");
tgui::Grid::Ptr grid = tgui::Grid::create();// (gui);   
grid->setSize(400, 400);
grid->setPosition(10,10);
std::string test = Settings::getDataFolderBasePath() + "gui/widgets/Black.conf";
tgui::Button::Ptr button0 = tgui::Button::create(test);
button0->setSize(200,100);
button0->setText("Host");
button0->setTextSize(16);
grid->addWidget(button0,0,0);
gui.add(grid);


The button displays it's text correctly only when it is added directly to the GUI.

To clarify: if I do gui.add(button0) it works without any changes. So it is not that the font is not set or something.

On a sidenote, I use the grid widget for layouting, centering multiple widgets that is. Can I achieve this via bind methods also? I haven't looked into them yet.

texus

#7
The grid widget will be changed later in v0.7 to make it easier to use.

But right now you still need both the add and addWidget function.
I don't think I changed the bahavior so you should have a look at the v0.6 tutorial for Grid.

The add function in Grid is the exact same add function as the one in Gui.

So basically need both these lines:
grid->add(button0); // Add the widget to the (grid) container
grid->addWidget(button0, 0, 0); // Place the widget in a cell


QuoteOn a sidenote, I use the grid widget for layouting, centering multiple widgets that is. Can I achieve this via bind methods also? I haven't looked into them yet.
You could indeed use the bind methods to achieve this. The Grid widget is a simple but limited way to set relative positions, the bind functions (and the entire layout system that those functions use in the background) is a more advanced way of having relative position and sizes.

Heinrich

#8
Quote from: texus on 09 October 2014, 08:21:52
But right now you still need both the add and addWidget function.
I don't think I changed the bahavior so you should have a look at the v0.6 tutorial for Grid.

grid->add(button0); // Add the widget to the (grid) container
grid->addWidget(button0, 0, 0); // Place the widget in a cell



Oh dog, I totally forgot about this, the GUI code in my application has been untouched for over a year.
What about buttons in a grid not displaying their text? Can you reproduce this/know what silly mistakes I'm making?
Wait, wait. Right, I need to add&addWidget. Works alright now. If you do not plan major API refinements for the grid, I think simply having addWidget(Widget) call this.add((Widget) internally would enough to make it easier to use. I can picture many confused users with the same erroneous assumption.

texus

I would have to check this to be sure but I think I know what goes wrong.

The font from the parent is given to the widget when you call the add function.

What I think happens is:
auto grid = Grid::create(); // Grid is created, has no font
auto button = Button::create(); // Button is created, has no font
grid->add(button); // button copies font from grid, but grid doesn't has a font yet
gui.add(grid); // Grid is given the global font here, existing widgets remain untouched


If this is the problem then you can work around it by doing this:
auto grid = Grid::create(); // Grid is created, has no font
gui.add(grid); // Grid is given the global font here
auto button = Button::create(); // Button is created, has no font
grid->add(button); // button copies font from grid, which had a valid font

Heinrich

Sorry, I edited my post while you were answering. It does indeed work without your workaround (in fact I was adding the grid before I added widgets to the grid ever since). The problem was that I only grid->addWidget() them, but not also grid->add() them. Turns out one needs to do both.

texus

Yeah, add is needed for inheriting the font while addWidget is needed for all the rest.

When rewriting the Grid widget I will make sure that you will only need to call one function, instead of both add and addWidget. This design was chosen due to the way widgets were created in 0.6, but in 0.7 I can change this.

Heinrich

I had a quick glance over your code. I see Container maintains a list of widgets and Grid inherits this list but never uses it, instead using it's own grid_widget list for everything, including drawing. The hook is, widgetPtr->initialize(this); is only called in Container::add().

texus

In v0.7 you have to call the add function manually, which is why it is now possible to change it or even remove it.

The problem with v0.6 was that the add function was called automatically when the widget was created, since creating it and adding it the gui happened in one step. So the add function was already called before you could use the widget so an extra addWidget function was needed.

The Grid widget hasn't changed since v0.6 at all so far, which is why the initialize is still called inside the add function as it was required in v0.6.

I could do a quick fix with moving the initialize call to addWidget, so that you don't have to call the add function anymore. But without serious changes you will always have to ability to call the add function even if it doesn't need it for anything (due to the inheritance from Container).

Heinrich

Leave it be for a refactoring of Grid in the future, then, I'll just call add() meanwhile.
Now for something completely different, do you have any suggestions?
I am using my own little State manager that works like this:


virtual class State { virtual State* run();};
class SomeState: public State { State* run(){return new SomeOtherState();} };
main(){
State* state = new SomeState();
while(state != SomeQuitState)
{ state = state->run();}
}


The run() method of a State was usually one of these SFML while(window.isOpen()) loops that also did a tgui::pollcallback() to see if e.g. a closebutton has been pressed and then returned a new state (e.g. Quit). Now, with the new function callbacks in 0.7 this is no longer possible, because I cannot call return inside the run() method anymore. As a workaround, I could set flags in State and then switchCase those flags to see if I should return a state. Do you have any brilliant design idea to get around this?

texus

You could create an extra boolean in your function, e.g. called "running".

If you e.g. want to change the running variable when a button is pressed you can do
button->connect([&](){ running = false; });

If your callback function contains too much code for being a lambda function you could pass the running variable by reference.
void myFunction(bool&);
button->connect(myFunction, std::ref(running));


Another solution might perhaps be not to have the main loop inside your state.
Your state should have the functions like handleEvent, update an draw while the main loop just calls these functions on the active state.