Simple GUI Library
gui_event_dispatching.cpp
Go to the documentation of this file.
1/**
2 * @author Nikita Mochalov (github.com/tralf-strues)
3 * @file gui_event_dispatching.cpp
4 * @date 2021-10-24
5 *
6 * @copyright Copyright (c) 2021
7 */
8
9#include <assert.h>
11#include "scene/component.h"
12
13Sml::Event* fireEvent(Sml::Event* event)
14{
15 assert(event);
16 assert(event->getTarget());
17
18 static GuiEventDispatchChain baseDispatchChain;
19
20 GuiEventDispatchChain* targetDispatchChain =
21 dynamic_cast<GuiEventDispatchChain*>(event->getTarget()->buildEventDispatchChain(&baseDispatchChain));
22
23 Sml::Event* returnEvent = targetDispatchChain->sendThroughChain(event);
24 baseDispatchChain.reset();
25
26 return returnEvent;
27}
28
29//------------------------------------------------------------------------------
30// GuiEventDispatcher
31//------------------------------------------------------------------------------
32void GuiEventDispatcher::attachFilter(const std::initializer_list<Sml::EventType>& types,
33 Sml::Listener* filter)
34{
35 assert(filter);
36 m_FiltersNotifier.attachListener(types, filter);
37}
38
39void GuiEventDispatcher::detachFilter(Sml::Listener* filter)
40{
41 assert(filter);
42 m_FiltersNotifier.detachListener(filter);
43}
44
45void GuiEventDispatcher::attachHandler(const std::initializer_list<Sml::EventType>& types,
46 Sml::Listener* handler)
47{
48 assert(handler);
49 m_HandlersNotifier.attachListener(types, handler);
50}
51
52void GuiEventDispatcher::detachHandler(Sml::Listener* handler)
53{
54 assert(handler);
55 m_HandlersNotifier.detachListener(handler);
56}
57
58Sml::Event* GuiEventDispatcher::dispatchEvent(Sml::Event* event, Sml::EventDispatchChain* chain)
59{
60 assert(event);
61 assert(chain);
62
63 event = dispatchCapturingEvent(event);
64
65 if (event->isConsumed())
66 {
67 return nullptr;
68 }
69
70 // Send forward down the chain
71 event = chain->sendThroughChain(event);
72
73 // If the event hasn't been consumed
74 if (event != nullptr)
75 {
76 event = dispatchBubblingEvent(event);
77
78 if (event->isConsumed())
79 {
80 return nullptr;
81 }
82 }
83
84 return event;
85}
86
87Sml::Event* GuiEventDispatcher::dispatchCapturingEvent(Sml::Event* event)
88{
89 assert(event);
90 m_FiltersNotifier.notify(event);
91
92 return event;
93}
94
95Sml::Event* GuiEventDispatcher::dispatchBubblingEvent(Sml::Event* event)
96{
97 assert(event);
98 m_HandlersNotifier.notify(event);
99
100 return event;
101}
102
103//------------------------------------------------------------------------------
104// GuiEventDispatchChain
105//------------------------------------------------------------------------------
106GuiEventDispatchChain::GuiEventDispatchChain(size_t defaultDispatchersCount)
107 : m_Dispatchers(defaultDispatchersCount), m_ActiveCount(0) {}
108
109void GuiEventDispatchChain::reset()
110{
111 for (auto it = m_Dispatchers.begin(); it != m_Dispatchers.end(); ++it)
112 {
113 *it = nullptr;
114 }
115
116 m_Dispatchers.clear();
117 m_ActiveCount = 0;
118}
119
120void GuiEventDispatchChain::prependDispatcher(Sml::EventDispatcher* dispatcher)
121{
122 assert(dispatcher);
123
124 if (m_ActiveCount >= m_Dispatchers.size())
125 {
126 m_Dispatchers.push_back(dynamic_cast<GuiEventDispatcher*>(dispatcher));
127 }
128 else
129 {
130 m_Dispatchers[m_ActiveCount] = dynamic_cast<GuiEventDispatcher*>(dispatcher);
131 }
132
133 ++m_ActiveCount;
134}
135
136Sml::Event* GuiEventDispatchChain::sendThroughChain(Sml::Event* event)
137{
138 assert(event);
139
140 if (m_ActiveCount == 0)
141 {
142 return event;
143 }
144
145 uint32_t savedActiveCount = m_ActiveCount;
146
147 GuiEventDispatcher* nextDispatcher = m_Dispatchers[--m_ActiveCount];
148 Sml::Event* returnEvent = nextDispatcher->dispatchEvent(event, this);
149
150 m_ActiveCount = savedActiveCount;
151
152 return returnEvent;
153}
virtual void prependDispatcher(Sml::EventDispatcher *dispatcher) override
Sml::Event * fireEvent(Sml::Event *event)
Fire the event from the specified.