Bind this function for all callbacks

Started by Strikerklm96, 16 September 2015, 21:44:25

Strikerklm96

Code (cpp) Select
m_pWidget->bindCallbackEx(&WidgetBase::f_callback, this, tgui::ClickableWidget::AllClickableWidgetCallbacks);
I want to bind this so that it will call f_callback for ALL possible callback triggers. How can I do this?
Can I bind it to multiple triggers?

texus

Doesn't that line work?
If it doesn't work, what error do you get?
If if does work, could you explain a bit better (perhaps with a small example) what you want to do?

Strikerklm96

It doesnt get called for editbox callbacks, such as tgui::EditBox::ReturnKeyPressed

Basically I am calling that bind on a base pointer to the widget, and I have a function that I want to get called for all possible triggers that would trigger the derived widget. For instance, m_pWidget could be a tgui::EditBox::Ptr or tgui::Button::Ptr.

texus

It's a bit of a hack but you can do this:
Code (cpp) Select
m_pWidget->bindCallbackEx(&WidgetBase::f_callback, this, 4095);

Triggers can be combined so they are numbered 1, 2, 4, 8, 16, etc so that binding 3 would result in binding both 1 and 2. The 4095 is just (2^N)-1 with N big enough so that it includes all triggers.

But why are you trying to bind all triggers? You are going to discard almost all callbacks in your f_callback function anyway since you don't need to know about them. I'm asking because in TGUI 0.7-dev a hack like this is not possible and I'd like to know if the new callback system covers your use case.

Strikerklm96

#4
It's complicated :P

I have wrappers for various tgui things such as editboxes, buttons, panels, because I have a gamewide eventing system for my game, which I want the tgui stuff to use (and it does and works great)

I put a bunch of logic in a base class, and one thing that I wanted to put in there was the f_callback (binded) function.

Code (cpp) Select
void WidgetBase::f_callback(const tgui::Callback& callback)
{
if(callbackHook(callback))
{

}
else if(callback.trigger == tgui::Widget::WidgetCallbacks::MouseEntered)
{
f_MouseEntered();
}
else if(callback.trigger == tgui::Widget::WidgetCallbacks::MouseLeft)
{
f_MouseLeft();
}
else if(callback.trigger == tgui::ClickableWidget::LeftMouseClicked)
{
f_LeftMouseClicked();
}
else if(callback.trigger == tgui::ClickableWidget::LeftMousePressed)
{
f_LeftMousePressed();
}
else if(callback.trigger == tgui::ClickableWidget::LeftMouseReleased)
{
f_LeftMouseReleased();
}
}
void WidgetBase::f_MouseEntered()
{
sf::Packet pack;
mouseEnteredHook(pack);
m_io.event(EventType::MouseEntered, 0, pack);
}


Then, derived classes can override
Code (cpp) Select
bool callbackHook(const tgui::Callback& callback);
to see if they want to handle the callback.

There are also hooks on the event functions such as mouseEnteredHook which some of the classes do special things with.
So essentially, the derived classes can only handle special events if the function was binded to recieve all events, because the widgetbase binds the function
Code (cpp) Select

void WidgetBase::f_assign(tgui::Widget* pWidget)
{
m_pWidget->bindCallbackEx(&WidgetBase::f_callback, this, 4095);
}

texus

Hmm, that gives me something to think about for the next tgui version. The new callback system was not designed for handling multiple triggers in the same function. I will add an "all" callback trigger in v0.7 so that this can still be done. But once the legacy part of the system gets removed (which would not happen before 0.8 which is still many many years away anyway) then there would no longer be a way to know what trigger caused the callback. I'll make sure to keep this use case in mind when I eventually remove the Callback class.

Strikerklm96

Haha thanks, I could always use an old version of TGUI, or do it the way you intend, which is to bind a function to each callback possibility (right?)

texus

The problem with binding a function for each callback is that not every widget has the same callbacks. When trying to bind a callback that the widget does not has an exception would be thrown. So you either have to do it per widget type or you would have to add a lot of try-catches to try and bind every trigger.

You could also do things like putting all triggers in a map with the widget type as key so that you can easily bind the callback, but you would still need to fill the map with contents somewhere.

So binding all triggers would take much more work then it should.

Anyway, this doesn't even matter to neither of us right now. It will still take 3 years or so before support for code like that could be dropped, I'm sure that I will have made some decision by then.