0.8
Events

This chapter discusses the event model and how events are handled.

Event Loop

The EventLoop is the inner loop of the framework. Its basic operation is demonstrated with the following pseudo code:

while (true)
{
wait for events
dispatch events
draw
}

It does this until the event loop is told to exit, and in turn, this usually means the application exits. For example, a call to EventLoop::quit() would cause the event loop to exit.

The event loop in EGT is implemented with the Asio library. Asio is a cross-platform C++ library for network and low-level I/O programming that provides developers with a consistent asynchronous model using a modern C++ approach. Asio can be used as part of the boost or standalone, and EGT comes with the standalone version built in. Asio provides more features than what is directly used by EGT.

Asio

EGT abstracts out any required direct involvement with Asio; however, should you choose to use it directly, it is available for use in, for example, networking and multi-threaded applications. Asio Documentation is a good reference point if you want to start using the Asio API directly.

Event Propagation

Every time a user touches the screen, clicks a button, or presses a key, an event is generated and sent to the event loop and then dispatched to appropriate handlers. Events can also come from other things like a window manager, timers, or networking sockets.

Events are usually propagated from the top level widget down. There are exceptions to this, for example, when a widget grabs the pointer or keyboard, since this natural flow is short circuited. For example, when a TextBox has keyboard focus.

Event

Event Data

Each event handler, like Widget::handle(), is called with an event object. This object maintains the unique egt::v1::eventid of the event, and any data associated with the event such as pointer or key event data.

Handling Events

When implementing a widget that needs to handle events, overriding the the Widget::handle() virtual method is the expected method to handle events. However, when using an existing widget, it can be a burden to the subclass just to handle events. So, to handle events when using a widget, the Widget::on_event() method can be used to register any number of callbacks. A lambda function may also be used.

ImageButton settings("@cog.png");
settings.on_event([this](Event& event)
{
if (event.id() == eventid::pointer_click)
{
if (m_popup.visible())
m_popup.hide();
else
m_popup.show(true);
}
});

Another variation of the Widget::on_event() function allows for specifying what events to filter as a second parameter.

ImageButton settings("@cog.png");
settings.on_event([this](Event&)
{
if (m_popup.visible())
m_popup.hide();
else
m_popup.show(true);

Widget::on_event() can be called any number of times to register any number of callbacks.

Timers

Timers are an intrinsic part of the EventLoop. There are two main classes for working with timers: Timer and PeriodicTimer.

Creating a timer is straightforward, and you can register any number of callbacks with the Timer::on_timeout() function of a Timer or a PeriodicTimer.

PeriodicTimer timer(std::chrono::seconds(1));
timer.on_timeout([]()
{
cout << "timer fired" << endl;
});
timer.start();
egt::v1::eventid::pointer_click
Pointer event.