Troubles with callbacks

Started by Negatio, 28 March 2014, 17:26:25

Negatio

Hello! Firstly sorry for my bad english.

Recently I try to make a menu build with a identical panel but with differents position.y like a "list of panel".
Like that:


Here is the loop that I built the menu:
    for(int i=0;i<_worlds.size();i++)
    {
        tgui::Panel::Ptr panel;
        panel->setSize(390, 130);
        panel->setPosition(100, /*(i * 130) +*/ 10);

        tgui::Label::Ptr label(*panel);
            label->load("Resources/Gui/test/test.conf");
            label->setTextFont(*ResourcesManager::LoadFont("Orbitron-Regular.ttf"));
            label->setText(_worlds[i]);
            label->setPosition(10, 10);
            label->setTextColor(sf::Color::Blue);

        tgui::Button::Ptr playButton(*panel);
            playButton->load("Resources/Gui/test/test.conf");
            playButton->setTextFont(*ResourcesManager::LoadFont("Orbitron-Regular.ttf"));
            playButton->setPosition(60, 60);
            playButton->setSize(130, 30);
            playButton->setText(Lang::GetWord("worldselection.gui.play"));
            int id = 0;
            playButton->bindCallback(/*Here I don't know what to type*/);

        tgui::Button::Ptr deleteButton(*panel);
            deleteButton->load("Resources/Gui/test/test.conf");
            deleteButton->setTextFont(*ResourcesManager::LoadFont("Orbitron-Regular.ttf"));
            deleteButton->setPosition(200, 60);
            deleteButton->setSize(130, 30);
            deleteButton->setText(Lang::GetWord("worldselection.gui.delete"));
            deleteButton->bindCallback(/*Here either*/);
            deleteButton->setCallbackId(2);

        _gui.add(panel, std::string("panel_" + Util::toString(i)));
    }

But the problem is that I don't know how to handle all the buttons because I would each buttons call a same function but with diferent arguments. I tried many times to use callbacks but it's the first time I have to use.
On the tutorial I saw this:
QuoteUntil now, the functions did not have any parameters. But you can technically use any function to which you have bound parameters.
void function(tgui::Gui& gui);
button->bindCallback(std::bind(function, std::ref(gui)), tgui::CheckBox::Checked | tgui::CheckBox::Unchecked);
But I never seen std::bind or std::ref before.
I don't even know if my way to is good. If someone know a better way to make that kind of menu I enjoy him to tell it to me.
Thanks to read! (and sorry again for my frenchi enhlish :/)

texus

#1
You can give the buttons an id to identify them.

void callbackFunction(const Callback& callback)
{
   // callback.id will be either 0 or 1 or ... or _worlds.size()-1
}

for(int i=0;i<_worlds.size();i++)
{
    /* ... */
    button->setCallbackId(i);
    button->bindCallbackEx(callbackFunction, tgui::Button::LeftMouseClicked);
    /* ... */
}


The std::bind method is for when you want you callback function to have a parameter other than the Callback struct.

QuoteI don't even know if my way to is good.
It looks good to me.

Negatio

Thanks to answer.

As my callback function (not static) is in the class from which I build the buttons I do that?:
myButton->bindCallbackEx(MyClass::CallbackFunction, tgui::Button::LeftMouseClicked);
that?:
myButton->bindCallbackEx(&MyClass::CallbackFunction, tgui::Button::LeftMouseClicked);
or that?:
myButton->bindCallbackEx(CallbackFunction, tgui::Button::LeftMouseClicked);

I think It's the first option but when I do that I get a very strange error that I don't understand:
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\functional|2013|error: no match for call to '(std::_Mem_fn<void (MyClass::*)(const tgui::Callback&)>) (const tgui::Callback&)'|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\functional|525|note: candidates are:|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\functional|548|note: _Res std::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class&, _ArgTypes ...) const [with _Res = void; _Class = MyClass; _ArgTypes = {const tgui::Callback&}]|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\functional|548|note:   candidate expects 2 arguments, 1 provided|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\functional|553|note: _Res std::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class*, _ArgTypes ...) const [with _Res = void; _Class = MyClass; _ArgTypes = {const tgui::Callback&}]|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\functional|553|note:   candidate expects 2 arguments, 1 provided|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\functional|559|note: template<class _Tp> _Res std::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Tp&, _ArgTypes ...) const [with _Tp = _Tp; _Res = void; _Class = MyClass; _ArgTypes = {const tgui::Callback&}]|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\functional|559|note:   template argument deduction/substitution failed:|
c:\program files (x86)\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.7.1\include\c++\functional|2013|note:   candidate expects 2 arguments, 1 provided|


texus

Neither of the 3 options are correct.
The compiler has to know which function (which is what you pass in your codes), but it also should know on which object it should call this function. So the correct line becomes:
myButton->bindCallbackEx(&MyClass::CallbackFunction, &myClassInstance, tgui::Button::LeftMouseClicked);

Actually that line is just shorthand for the following code:
myButton->bindCallbackEx(std::bind(&MyClass::CallbackFunction, &myClassInstance), tgui::Button::LeftMouseClicked);

When the code is called inside the class fom which you want to call the function, then "&myClassInstance" is just "this".

Negatio

It's working!

QuoteThe compiler has to know which function (which is what you pass in your codes), but it also should know on which object it should call this function. So the correct line becomes:
It' logical.

QuoteActually that line is just shorthand for the following code:
myButton->bindCallbackEx(std::bind(&MyClass::CallbackFunction, &myClassInstance), tgui::Button::LeftMouseClicked);
Thank to you I understand what std::bind is for!

Thank you very much and sorry for my stupid questions and my bad english :-[