Skip to content

Commit 82700a2

Browse files
authored
Merge pull request #116 from NuiCpp/fix/inline-injector
Fix/inline injector
2 parents 6cfb6e3 + bbeffa9 commit 82700a2

27 files changed

+2634
-2117
lines changed

.clang-tidy

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,50 @@ Checks: '-*,
3232
-hicpp-vararg,
3333
-hicpp-member-init,
3434
misc-*,
35-
-misc-non-private-member-variables-in-classes,
35+
-misc-non-private-member-variables-in-classes'
36+
37+
# Disabled Options Explanation:
38+
# CppCoreGuidelines:
39+
# cppcoreguidelines-pro-bounds-constant-array-index: requires use of guideline support library
40+
# cppcoreguidelines-pro-type-vararg: Mostly triggers for functions we didn't write in acceptable
41+
# situations.
42+
# cppcoreguidelines-pro-type-member-init: Even though this rule is useful, it cannot be uphold in
43+
# some cases with generated constructors and would break a lot of code.
44+
# cppcoreguidelines-non-private-member-variables-in-classes: This rule cannot be followed because
45+
# of testing requirements to make some members protected.
46+
47+
# Llvm:
48+
# llvm-header-guard: pragma once allowed
49+
# llvm-include-order: Clang format sorts the includes, should maybe fixed in clang-format file.
50+
51+
# Modernize:
52+
# modernize-use-nodiscard: wants nodiscard for every function.
53+
# modernize-avoid-c-arrays: duplicate rule.
54+
# modernize-use-using: Cannot apply to SDK.
55+
56+
# Performance:
57+
# performance-noexcept-move-constructor: This is cannot be generally applied and is
58+
# potentially dangerous if applied wrongly.
59+
# Performance improvement from this is questionable and less relevant.
60+
61+
# Readability:
62+
# readability-redundant-member-init: Initializing all members of a class even if unnecessary is
63+
# not bad style
64+
# readability-uppercase-literal-suffix
65+
# readability-else-after-return: Rule cannot be followed
66+
# readability-named-parameter: Breaks builds with unused variables
67+
# readability-redundant-access-specifiers: Redundant access specifiers (public, private) can
68+
# actually increase readability by introducing visual barriers
69+
# readability-magic-numbers: cppcoreguidelines has a rule for it, no duplicate needed.
70+
71+
# Hicpp:
72+
# hicpp-uppercase-literal-suffix
73+
# hicpp-noexcept-move: This cannot be generally applied and is potentially dangerous if applied
74+
# wrongly. Performance improvement from this is questionable and less relevant.
75+
# hicpp-vararg: Mostly triggers for functions we didn't write in acceptable situations.
76+
# hicpp-member-init: Even though this rule is useful, it cannot be uphold in some cases with
77+
# generated constructors and would break a lot of code.
78+
# hicpp-avoid-c-arrays: duplicate rule.
79+
80+
# Misc:
81+
# misc-non-private-member-variables-in-classes: Public members should be allowed in structs
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#pragma once
2+
3+
#include <functional>
4+
#include <memory>
5+
#include <vector>
6+
7+
namespace Nui
8+
{
9+
struct EventImpl
10+
{
11+
virtual bool call(std::size_t eventId) = 0;
12+
virtual bool valid() const = 0;
13+
virtual ~EventImpl() = default;
14+
};
15+
16+
struct TwoFunctorEventImpl : public EventImpl
17+
{
18+
TwoFunctorEventImpl(std::function<bool(std::size_t eventId)> action, std::function<bool()> valid)
19+
: action_{std::move(action)}
20+
, valid_{std::move(valid)}
21+
{}
22+
23+
bool call(std::size_t eventId) override
24+
{
25+
auto result = action_(eventId);
26+
return result;
27+
}
28+
29+
bool valid() const override
30+
{
31+
return valid_();
32+
}
33+
34+
private:
35+
std::function<bool(std::size_t eventId)> action_;
36+
std::function<bool()> valid_;
37+
};
38+
39+
class Event
40+
{
41+
public:
42+
Event(
43+
std::function<bool(std::size_t eventId)> action,
44+
std::function<bool()> valid =
45+
[] {
46+
return true;
47+
})
48+
: impl_{std::make_unique<TwoFunctorEventImpl>(std::move(action), std::move(valid))}
49+
{}
50+
Event(Event const&) = delete;
51+
Event(Event&&) = default;
52+
Event& operator=(Event const&) = delete;
53+
Event& operator=(Event&&) = default;
54+
55+
operator bool() const
56+
{
57+
return impl_->valid();
58+
}
59+
bool operator()(std::size_t eventId) const
60+
{
61+
return impl_->call(eventId);
62+
}
63+
64+
private:
65+
std::unique_ptr<EventImpl> impl_;
66+
};
67+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#pragma once
2+
3+
#include <nui/frontend/event_system/event_registry.hpp>
4+
5+
#include <memory>
6+
7+
namespace Nui
8+
{
9+
class EventEngine
10+
{
11+
public:
12+
EventEngine() = default;
13+
EventEngine(const EventEngine&) = default;
14+
EventEngine(EventEngine&&) = default;
15+
EventEngine& operator=(const EventEngine&) = default;
16+
EventEngine& operator=(EventEngine&&) = default;
17+
virtual ~EventEngine() = default;
18+
19+
virtual EventRegistry& eventRegistry() = 0;
20+
};
21+
22+
class DefaultEventEngine : public EventEngine
23+
{
24+
public:
25+
EventRegistry& eventRegistry() override
26+
{
27+
return eventRegistry_;
28+
}
29+
30+
private:
31+
EventRegistry eventRegistry_;
32+
};
33+
34+
/**
35+
* @brief This object can be copied with low cost.
36+
*/
37+
class EventContext
38+
{
39+
public:
40+
using EventIdType = EventRegistry::EventIdType;
41+
42+
EventContext()
43+
: impl_{std::make_shared<DefaultEventEngine>()}
44+
{}
45+
EventContext(EventContext const&) = default;
46+
EventContext(EventContext&&) = default;
47+
EventContext& operator=(EventContext const&) = default;
48+
EventContext& operator=(EventContext&&) = default;
49+
~EventContext() = default;
50+
51+
EventIdType registerEvent(Event event)
52+
{
53+
return impl_->eventRegistry().registerEvent(std::move(event));
54+
}
55+
auto activateEvent(EventIdType id)
56+
{
57+
return impl_->eventRegistry().activateEvent(id);
58+
}
59+
void executeActiveEventsImmediately()
60+
{
61+
impl_->eventRegistry().executeActiveEvents();
62+
}
63+
void executeEvent(EventIdType id)
64+
{
65+
impl_->eventRegistry().executeEvent(id);
66+
}
67+
EventIdType registerAfterEffect(Event event)
68+
{
69+
return impl_->eventRegistry().registerAfterEffect(std::move(event));
70+
}
71+
void cleanInvalidEvents()
72+
{
73+
impl_->eventRegistry().cleanInvalidEvents();
74+
}
75+
void reset()
76+
{
77+
impl_->eventRegistry().clear();
78+
}
79+
80+
private:
81+
std::shared_ptr<EventEngine> impl_;
82+
};
83+
84+
extern thread_local EventContext globalEventContext;
85+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#pragma once
2+
3+
#include <nui/data_structures/selectables_registry.hpp>
4+
#include <nui/frontend/event_system/event.hpp>
5+
#include <nui/utility/visit_overloaded.hpp>
6+
7+
#include <functional>
8+
#include <limits>
9+
#include <map>
10+
11+
namespace Nui
12+
{
13+
class EventRegistry
14+
{
15+
public:
16+
using RegistryType = SelectablesRegistry<Event>;
17+
using EventIdType = SelectablesRegistry<Event>::IdType;
18+
constexpr static EventIdType invalidEventId = std::numeric_limits<EventIdType>::max();
19+
20+
public:
21+
EventRegistry() = default;
22+
EventRegistry(const EventRegistry&) = delete;
23+
EventRegistry(EventRegistry&&) = default;
24+
EventRegistry& operator=(const EventRegistry&) = delete;
25+
EventRegistry& operator=(EventRegistry&&) = default;
26+
~EventRegistry() = default;
27+
28+
EventIdType registerEvent(Event event)
29+
{
30+
return registry_.append(std::move(event));
31+
}
32+
33+
/**
34+
* @brief Returns a pointer to the selected event (only valid until the next activation or event execution). May
35+
* return nullptr when the event id was not found.
36+
*
37+
* @param id
38+
* @return auto*
39+
*/
40+
RegistryType::SelectionResult activateEvent(EventIdType id)
41+
{
42+
return registry_.select(id);
43+
}
44+
45+
EventIdType registerAfterEffect(Event event)
46+
{
47+
return afterEffects_.append(std::move(event));
48+
}
49+
50+
void executeEvent(EventIdType id)
51+
{
52+
registry_.deselect(id, [](SelectablesRegistry<Event>::ItemWithId const& itemWithId) -> bool {
53+
if (!itemWithId.item)
54+
return false;
55+
return itemWithId.item.value()(itemWithId.id);
56+
});
57+
}
58+
59+
void executeActiveEvents()
60+
{
61+
registry_.deselectAll([](SelectablesRegistry<Event>::ItemWithId const& itemWithId) -> bool {
62+
if (!itemWithId.item)
63+
return false;
64+
return itemWithId.item.value()(itemWithId.id);
65+
});
66+
afterEffects_.deselectAll([](SelectablesRegistry<Event>::ItemWithId const& itemWithId) -> bool {
67+
if (!itemWithId.item)
68+
return false;
69+
return itemWithId.item.value()(itemWithId.id);
70+
});
71+
}
72+
73+
void cleanInvalidEvents()
74+
{
75+
std::vector<EventIdType> invalidIds;
76+
for (auto const& itemWithId : registry_.rawRange())
77+
{
78+
if (!itemWithId.item)
79+
continue;
80+
if (!static_cast<bool>(itemWithId.item.value()))
81+
invalidIds.push_back(itemWithId.id);
82+
}
83+
84+
for (auto const& id : invalidIds)
85+
registry_.erase(id);
86+
}
87+
88+
void clear()
89+
{
90+
registry_.clear();
91+
afterEffects_.clear();
92+
}
93+
94+
private:
95+
RegistryType registry_;
96+
RegistryType afterEffects_;
97+
};
98+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#pragma once
2+
3+
#include <nui/event_system/event_context.hpp>
4+
#include <nui/event_system/observed_value.hpp>
5+
6+
#include <utility>
7+
#include <memory>
8+
#include <functional>
9+
10+
namespace Nui
11+
{
12+
template <typename ValueT>
13+
void listen(EventContext& eventContext, Observed<ValueT> const& obs, std::function<bool(ValueT const&)> onEvent)
14+
{
15+
const auto eventId = eventContext.registerEvent(Event{
16+
[obs = Detail::CopyableObservedWrap{obs}, onEvent = std::move(onEvent)](auto) {
17+
return onEvent(obs.value());
18+
},
19+
[]() {
20+
return true;
21+
}});
22+
obs.attachEvent(eventId);
23+
}
24+
25+
template <typename ValueT>
26+
void listen(EventContext& eventContext, Observed<ValueT> const& obs, std::function<void(ValueT const&)> onEvent)
27+
{
28+
return listen(eventContext, obs, [onEvent = std::move(onEvent)](ValueT const& value) {
29+
onEvent(value);
30+
return true;
31+
});
32+
}
33+
34+
template <typename ValueT, typename FunctionT>
35+
void listen(EventContext& eventContext, Observed<ValueT> const& obs, FunctionT onEvent)
36+
{
37+
return listen(eventContext, obs, std::function(std::move(onEvent)));
38+
}
39+
40+
template <typename ValueT>
41+
void listen(
42+
EventContext& eventContext,
43+
std::shared_ptr<Observed<ValueT>> const& obs,
44+
std::function<bool(ValueT const&)> onEvent)
45+
{
46+
const auto eventId = eventContext.registerEvent(Event{
47+
[weak = std::weak_ptr<Observed<ValueT>>{obs}, onEvent = std::move(onEvent)](auto) {
48+
if (auto obs = weak.lock(); obs)
49+
return onEvent(obs->value());
50+
return false;
51+
},
52+
[weak = std::weak_ptr<Observed<ValueT>>{obs}]() {
53+
return !weak.expired();
54+
}});
55+
obs->attachEvent(eventId);
56+
}
57+
58+
template <typename ValueT>
59+
void listen(
60+
EventContext& eventContext,
61+
std::shared_ptr<Observed<ValueT>> const& obs,
62+
std::function<void(ValueT const&)> onEvent)
63+
{
64+
return listen(eventContext, obs, [onEvent = std::move(onEvent)](ValueT const& value) {
65+
onEvent(value);
66+
return true;
67+
});
68+
}
69+
70+
template <typename ValueT, typename FunctionT>
71+
void listen(EventContext& eventContext, std::shared_ptr<Observed<ValueT>> const& obs, FunctionT onEvent)
72+
{
73+
return listen(eventContext, obs, std::function(std::move(onEvent)));
74+
}
75+
}

0 commit comments

Comments
 (0)