Simple GUI Library
gui_event_dispatching.h
Go to the documentation of this file.
1/**
2 * The event proccessing is split into several stages.
3 *
4 * -# Creating @ref GuiEvent.
5 * In most cases, this is done internally by the system. The system registers a
6 * system event (e.g. MouseMoved, KeyPressed, etc.).
7 * -# Determining the @ref EventTarget.
8 * Then the system determines to which component the event should be sent. Some
9 * examples include:
10 * - A keyboard event is sent to the currently focused component.
11 * - A mouse event is sent to the component on which the cursor is pointed.
12 *
13 * -# Building a @ref GuiEventDispatchChain from event target.
14 * The system then calls @ref fireEvent(GuiEvent*) function with the event target
15 * determined by the previous stage. @ref fireEvent(GuiEvent*) builds a dispatch
16 * chain and sends the event through it.
17 * -# Capturing phase.
18 * /------\ /------------\ /------------------\
19 * | Root | --> | Component1 | --> ... --> | Target component |
20 * \------/ \------------/ \------------------/
21 * Dispatcher Dispatcher Dispatcher
22 * Filter1 Filter1 Filter1
23 * ... ... ...
24 * FilterN FilterN FilterN
25 *
26 * The next stage is moving the event from the root to the target. Each component
27 * has its own @ref GuiEventDispatcher which calls filters on the event. A filter
28 * can consume the event and then the dispatching proccess terminates (though all
29 * of the current dispatcher's filters are called nonetheless).
30 *
31 * -# Bubbling phase.
32 * /------\ /------------\ /------------------\
33 * | Root | --> | Component1 | --> ... --> | Target component |
34 * \------/ \------------/ \------------------/
35 * Dispatcher Dispatcher Dispatcher
36 * Handler1 Handler1 Handler1
37 * ... ... ...
38 * HandlerN HandlerN HandlerN
39 *
40 * The next stage is moving the event from the target to the root. Here each
41 * dispatcher calls handlers on the event. A handler can consume the event and then
42 * the dispatching proccess terminates (though all of the current dispatcher's
43 * handlers are called nonetheless). Most target components consume the event and
44 * the bubbling phase doesn't occur.
45 *
46 * @author Nikita Mochalov (github.com/tralf-strues)
47 * @file gui_event_dispatching.h
48 * @date 2021-11-06
49 *
50 * @copyright Copyright (c) 2021
51 */
52
53#pragma once
54
55#include <vector>
56#include "sml/events/event_dispatching.h"
57#include "sml/events/listener_notifier.h"
58#include "sml/events/system_events.h"
59#include "gui_event.h"
60
62
63class GuiEventDispatcher : public Sml::EventDispatcher
64{
65public:
66 ~GuiEventDispatcher() = default;
67
68 /* Listeners */
69 void attachFilter(const std::initializer_list<Sml::EventType>& types, Sml::Listener* filter);
70 void detachFilter(Sml::Listener* filter);
71 void attachHandler(const std::initializer_list<Sml::EventType>& types, Sml::Listener* handler);
72 void detachHandler(Sml::Listener* handler);
73
74 /* EventDispatcher */
75 virtual Sml::Event* dispatchEvent(Sml::Event* event, Sml::EventDispatchChain* chain) override;
76
77protected:
78 Sml::Notifier m_FiltersNotifier;
79 Sml::Notifier m_HandlersNotifier;
80
81 virtual Sml::Event* dispatchCapturingEvent(Sml::Event* event);
82 virtual Sml::Event* dispatchBubblingEvent(Sml::Event* event);
83};
84
85class GuiEventDispatchChain : public Sml::EventDispatchChain
86{
87public:
88 GuiEventDispatchChain(size_t defaultDispatchersCount = 8);
89
90 void reset();
91
92 /* EventDispatchChain */
93 /// @warning Must be Sgl::GuiEventDispatcher type!
94 virtual void prependDispatcher(Sml::EventDispatcher* dispatcher) override;
95 virtual Sml::Event* sendThroughChain(Sml::Event* event) override;
96
97private:
98 std::vector<GuiEventDispatcher*> m_Dispatchers;
99 uint32_t m_ActiveCount;
100};
101
102/**
103 * @brief Fire the @ref event from the specified @code event->target @endcode.
104 *
105 * Build a @ref GuiEventDispatchChain from target to the root component and send
106 * the event through it.
107 *
108 * @param event
109 *
110 * @return The return event or nullptr if the event has been consumed.
111 */
112Sml::Event* fireEvent(Sml::Event* event);
virtual void prependDispatcher(Sml::EventDispatcher *dispatcher) override
Sml::Event * fireEvent(Sml::Event *event)
Fire the event from the specified.