cancel
Showing results for 
Search instead for 
Did you mean: 

What is the difference between the Callback and GenericCallback classes?

FPare.1
Associate

I'm trying to write a class that contain a clickable Box. The action of the click event is handled in the Screen1View.

I'm total loss with GenericCallback and Callback.

Here the code:

MyObj.hpp:

class MyObj : public TextureMapper
{
public:
	MyObj();
	~MyObj();
 
	virtual void handleClickEvent(const ClickEvent& event);
 
	void setAction(GenericCallback<const MyObj&>& callback) 
	{
		action = &callback;
	}
 
protected:
	ClickListener< Box > clickable_box;
 
	// Declaring callback type of box and clickEvent
	GenericCallback< const MyObj& >* action;
};

MyObj.cpp:

#include <gui\common\MyObj.hpp>
 
MyObj::MyObj() :
	TextureMapper(),
	action()
{
	setTouchable(true);
 
	//clickable_box.setClickAction(action);
}
 
MyObj::~MyObj()
{
}
 
void MyObj::handleClickEvent(const ClickEvent& event)
{
	clickable_box.handleClickEvent(event);
}

And in ScreenView:

ScreenView.hpp:

#include <gui_generated/screen1_screen/Screen1ViewBase.hpp>
#include <gui/screen1_screen/Screen1Presenter.hpp>
#include <gui/common/MyObj.hpp>
#include <touchgfx/widgets/TextureMapper.hpp>
#include <touchgfx/Callback.hpp>
 
 
class Screen1View : public Screen1ViewBase
{
public:
    Screen1View();
    virtual ~Screen1View() {}
    virtual void setupScreen();
    virtual void tearDownScreen();
 
    virtual void handleClickEvent(const ClickEvent& evt);
 
    void handle_MyObj_click(const MyObj& b, const ClickEvent& e);
 
protected:
    MyObj _myObj;
 
    Callback< Screen1View, const MyObj&, const ClickEvent& > _myObj_clickable;
    //GenericCallback< Screen1View, const MyObj&, const ClickEvent& > _myObj_clickable;
};

ScreenView.cpp:

#include <gui/screen1_screen/Screen1View.hpp>
 
Screen1View::Screen1View():
    _myObj_clickable(this, &Screen1View::handle_MyObj_click),
    _myObj()
{
    _myObj.setAction(_myObj_clickable); // error: C++ impossible to initialize a type reference (not qualified by const) with a type value
    add(_myObj);
}
 
void Screen1View::setupScreen()
{
    Screen1ViewBase::setupScreen();
}
 
void Screen1View::tearDownScreen()
{
    Screen1ViewBase::tearDownScreen();
}
 
void Screen1View::handleClickEvent(const ClickEvent& evt)
{
    View::handleClickEvent(evt);
}
 
void Screen1View::handle_MyObj_click(const MyObj& b, const ClickEvent& e)
{
    // do something
}

2 REPLIES 2
Martin KJELDSEN
Chief III

I understand your confusion. I'm not sure there's a good explanation of it in the documentation if you want to write your own classes with callbacks. I've been meaning to do it but focus was primarily on tool-generated workflows when we did the re-write - Some of these topics got lost in transition.

Let me get back to you - Maybe attach the project here and i'll get it working and we can discuss based on that

Martin KJELDSEN
Chief III

GenericCallback (https://support.touchgfx.com/docs/api/classes/classtouchgfx_1_1_generic_callback/)

> GenericCallback is the base class for callbacks. The reason this base class exists, is that a normal Callback requires the class type where the callback function resides to be known. This is problematic for ie. framework widgets like AbstractButton, on which it should be possible to register a callback on object types that are user-specific and thus unknown to AbstractButton. This is solved by having AbstractButton contain a pointer to a GenericCallback instead. This pointer must then be initialized to point on an instance of Callback, created by the user, which is initialized with the appropriate object type.

Callback (https://support.touchgfx.com/docs/api/classes/structtouchgfx_1_1_callback/)

> A Callback is basically a wrapper of a pointer-to-member-function. It is used for registering callbacks between widgets. For instance, a Button can be configured to call a member function when it is clicked. The class is templated in order to provide the class type of the object in which the member function resides, and the argument types of the function to call. The Callback class exists in four versions, for supporting member functions with 0, 1, 2 or 3 arguments. The compiler will infer which type to use automatically.

So, you would define a Callback parameterized with the class in which it resides (E.g. MyView) and the arguments that you expect to pass through this callback. With the Callback declaration you have here, you're saying that you, at some point, want to execute a callback with arguments ClickEvent and a reference to an object. Maybe that's what you want, i don't know.

Callback< Screen1View, const MyObj&, const ClickEvent& > _myObj_clickable;

Let's say we have something simple like a class that inherits from Button that would be able to send a callback both on PRESS and RELEASE. Maybe we want to couple a Callback object in MyButton to a callback handler in the view in which the button is active. I'd have a function inside MyButton that takes a callback

void MyButton::setCallback(touchgfx::GenericCallback< const MyButton &, ButtonEvent > &callback_)
{
    callback = &callback_;
}

This way, when i execute the logic inside handleClickEvent() in MyButton, i can execute the callback with a reference to which button fired, and the click event. Like the following code. I can fire this code whenever i want, but it might not be hooked up to an actual handler in my View yet. We'll get to that.,

void MyButton::handleClickEvent(const ClickEvent& evt)
{
    bool pressed = (evt.getType() == touchgfx::ClickEvent::PRESSED);
 
     //Some logic here to determine states and what to fire when
     if (callback && callback->isValid())
     {
         callback->execute(*this, BTN_EVENT_PRESSED); //or BTN_EVENT_RELEASED
      }
 
    invalidate();
}

So, now i need to set up my view so that the execute() from MyButton actually hits a handler and i can process the arguments. In my View i woulddeclare a Callback object that matches the one i have declared inside MyButton, so the arguments will match, and a handler that matches those arguments:

MyButton button;
    Callback<MyView, const MyButton&, ButtonEvent> myButtonPressedCallback;
    void myButtonPressedHandler(const MyButton& btn, ButtonEvent evt);

Now that we have the declarations in the view to match the intention from MyButton, let's finish initialization and definiing the handler inside MyView:

Set up the callback for the button:

button.setCallback(myButtonPressedCallback);

Tie the callback to a handler that matches the arguments (compiler will complain otherwise).

MyView::MyView() :
   myButtonPressedCallback(this, &MyView::myButtonPressedHandler),
  ...

And finally define the actual handler function myButtonPressedHandler():

void MyView::myButtonPressedHandler(const MyButton& btn, ButtonEvent evt)
{
    if (evt == BTN_EVENT_PRESSED)
    { ... }
    if (evt == BTN_EVENT_RELEASED)
    { ... }
}

Now when you click your custom button, a callback will fire and that call chain will end up in MyView::myButtonPressedHandler().

The designer will generate similar code when you're adding a simple Button - You can try to inspect the code to get some inspiration, and also inspect the AbstractButton class to see what happens when you fire an event based on a click.

/Martin