-
-
Notifications
You must be signed in to change notification settings - Fork 5
Implementing listeners
In order to use our library, user needs to implement a listener and register for events. When an event occurs, our library will call one of the functions implemented by an user to do some specific action.
As a part of our library, we've created several abstract classes, representing interfaces to be implemented by an user. These interfaces represent an API (a contract), so that there's a guarantee that an object registered as a listener does provide all the required member functions.
To create an listener, which is able to receive OnClick
events, create a class, which inherits from IOnClickListener
interface and provide implementation for an onClick(...)
callback function, i.e.:
#include <ObjectButton.h>
#include <interfaces/IOnClickListener.h>
class OnClickListener : private virtual IOnClickListener {
public:
OnClickListener() = default;
....
private:
void onClick(ObjectButton &button) override;
...
};
void OnClickListener::onClick(ObjectButton &button) {
// React to button click
}
Very similarily, to create an listener, which is able to receive OnDoubleClick
events, create a class, which inherits from IOnDoubleClickListener
interface and provide implementation for an onDoubleClick(...)
callback function, i.e.:
#include <ObjectButton.h>
#include <interfaces/IOnClickListener.h>
class OnDoubleClickListener : private virtual IOnDoubleClickListener {
public:
OnDoubleClickListener() = default;
....
private:
void onDoubleClick(ObjectButton &button) override;
...
};
void OnDoubleClickListener::onDoubleClick(ObjectButton &button) {
// React to button click
}
Finally, to create an listener, which is able to receive OnPress
, OnRelease
, OnLongPressStart
and OnLongPressEnd
events, create a class, which inherits from IOnPressListener
interface and provide implementation for member functions defined in the OnPressListener
.
Note: If you are not interested in some of the events received by this listener, you could provide void implementation of a specific callback function. See an example below.
#include <ObjectButton.h>
#include <interfaces/IOnPressListener.h>
class OnPressListener : private virtual IOnPressListener {
public:
OnPressListener() = default;
...
private:
// Void implementation, which does nothing
void onPress(ObjectButton &button) override {};
// Void implementation, which does nothing
void onRelease(ObjectButton &button) override {};
void onLongPressStart(ObjectButton &button) override;
void onLongPressEnd(ObjectButton &button) override;
...
};
void OnPressListener::onLongPressStart(ObjectButton &button) {
// Do some action after long press has started
}
void OnPressListener::onLongPressEnd(ObjectButton &button) {
// Do some action after long press has started
}
Now when you have a listener, you can finally register it to receive events.
// Create an ObjectButton instance
ObjectButton button = ObjectButton(...);
/*
* Assign some listeners to the button
* If you don't assign a listener, specific event won't be reported.
*/
OnClickListener onClickListener = OnClickListener();
button.setOnClickListener(onClickListener);
OnDoubleClickListener onDoubleClickListener = OnDoubleClickListener();
button.setOnDoubleClickListener(onDoubleClickListener);
OnPressListener onPressListener = OnPressListener();
button.setOnPressListener(onPressListener);
// Optionally, set additional attributes for the button
button.setDebounceTicks(10);
...
Having an listener as a C++ object allows us to initialize ObjectButton
instance internally inside this listener and encapsulate the button in internal logic of the listener. Here is a recommended approach to use.
#include <ObjectButton.h>
#include <interfaces/IOnClickListener.h>
class OnClickListener : private virtual IOnClickListener {
public:
// Initialize the listener
void init();
// Update the listener
void update();
....
private:
// Store button object internally
ObjectButton button = ObjectButton(INPUT_PIN);
...
};
void OnClickListener::init() {
button.setDebounceTicks(10);
button.setOnClickListener(this);
}
void OnClickListener::update() {
button.tick();
}
/* Create a listener instance, which will internally
initialize a button */
OnClickListener onClickListener = OnClickListener();
void setup() {
// Setup logic encapsulated inside object
onClickListener.init();
}
void loop() {
/* Update logic encapsulated inside object;
internally button.onTick() function is called */
onClickListener.update();
}
If you want to receive onClick
events, but also onPress
events, you could implement just one listener. This will inherit both from IOnClickListener
and IOnPressListener
classes. Here is an example of an listener, which is able to receive all kinds of events.
#include <ObjectButton.h>
#include <interfaces/IOnClickListener.h>
#include <interfaces/IOnDoubleClickListener.h>
#include <interfaces/IOnPressListener.h>
class CompositeListener : private virtual IOnClickListener,
private virtual IOnDoubleClickListener, private virtual IOnPressListener {
public:
CompositeListener() = default;
...
private:
// Implement functions from all inherited classes
void onClick(ObjectButton &button) override;
void onDoubleClick(ObjectButton &button) override;
void onPress(ObjectButton &button) override;
....
};
...
// Register a listener for all events
ObjectButton button = ObjectButton(...);
CompositeListener listener = CompositeListener();
button.setOnClickListener(this);
button.setOnDoubleClickListener(this);
button.setOnPressListener(this);