Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added factory for elements not in dom. #119

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion nui/include/nui/event_system/event_context.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include <nui/frontend/event_system/event_registry.hpp>
#include <nui/event_system/event_registry.hpp>

#include <memory>

Expand Down Expand Up @@ -38,6 +38,7 @@ namespace Nui
{
public:
using EventIdType = EventRegistry::EventIdType;
constexpr static auto invalidEventId = EventRegistry::invalidEventId;

EventContext()
: impl_{std::make_shared<DefaultEventEngine>()}
Expand Down
158 changes: 156 additions & 2 deletions nui/include/nui/event_system/observed_value.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

#include <iterator>
#include <nui/concepts.hpp>
#include <nui/frontend/event_system/range_event_context.hpp>
#include <nui/frontend/event_system/event_context.hpp>
#include <nui/event_system/range_event_context.hpp>
#include <nui/event_system/event_context.hpp>
#include <nui/utility/assert.hpp>
#include <nui/utility/meta/pick_first.hpp>

Expand All @@ -17,6 +17,7 @@
#include <string>
#include <cassert>
#include <set>
#include <memory>

namespace Nui
{
Expand Down Expand Up @@ -298,6 +299,12 @@ namespace Nui
return ModificationProxy{*this, true};
}

explicit operator bool() const
requires std::convertible_to<ContainedT, bool>
{
return static_cast<bool>(contained_);
}

ContainedT& value()
{
return contained_;
Expand Down Expand Up @@ -396,6 +403,26 @@ namespace Nui
std::size_t pos_;
T& ref_;
};

template <typename T, typename ContainerT>
auto& unwrapReferenceWrapper(ReferenceWrapper<T, ContainerT>& wrapper)
{
return wrapper.get();
}
template <typename T, typename ContainerT>
auto const& unwrapReferenceWrapper(ReferenceWrapper<T, ContainerT> const& wrapper)
{
return wrapper.get();
}
auto& unwrapReferenceWrapper(auto& ref)
{
return ref;
}
auto const& unwrapReferenceWrapper(auto const& ref)
{
return ref;
}

template <typename T, typename ContainerT>
class PointerWrapper
{
Expand Down Expand Up @@ -1259,6 +1286,37 @@ namespace Nui
{
static constexpr bool value = true;
};

template <typename T>
struct IsWeakObserved
{
static constexpr bool value = false;
};

template <typename T>
struct IsWeakObserved<std::weak_ptr<Observed<T>>>
{
static constexpr bool value = true;
};

template <typename T>
struct IsSharedObserved
{
static constexpr bool value = false;
};

template <typename T>
struct IsSharedObserved<std::shared_ptr<Observed<T>>>
{
static constexpr bool value = true;
};

template <typename T>
struct IsObservedLike
{
static constexpr bool value =
IsObserved<T>::value || IsWeakObserved<T>::value || IsSharedObserved<T>::value;
};
}

template <typename T>
Expand Down Expand Up @@ -1299,6 +1357,12 @@ namespace Nui

template <typename T>
concept IsObserved = Detail::IsObserved<std::decay_t<T>>::value;
template <typename T>
concept IsSharedObserved = Detail::IsSharedObserved<std::decay_t<T>>::value;
template <typename T>
concept IsWeakObserved = Detail::IsWeakObserved<std::decay_t<T>>::value;
template <typename T>
concept IsObservedLike = Detail::IsObservedLike<std::decay_t<T>>::value;

namespace Detail
{
Expand Down Expand Up @@ -1328,5 +1392,95 @@ namespace Nui
private:
Observed<T> const* observed_;
};

template <typename T>
struct ObservedAddReference
{
using type = T const&;
};
template <>
struct ObservedAddReference<void>
{
using type = void;
};
template <typename T>
struct ObservedAddReference<std::weak_ptr<Observed<T>>>
{
using type = std::weak_ptr<Observed<T>>;
};
template <typename T>
struct ObservedAddReference<std::shared_ptr<Observed<T>>>
{
using type = std::weak_ptr<Observed<T>>;
};
template <typename T>
struct ObservedAddReference<std::weak_ptr<const Observed<T>>>
{
using type = std::weak_ptr<const Observed<T>>;
};
template <typename T>
struct ObservedAddReference<std::shared_ptr<const Observed<T>>>
{
using type = std::weak_ptr<const Observed<T>>;
};

template <typename T>
struct ObservedAddMutableReference
{
using type = T&;
};
template <>
struct ObservedAddMutableReference<void>
{
using type = void;
};
template <typename T>
struct ObservedAddMutableReference<std::weak_ptr<Observed<T>>>
{
using type = std::weak_ptr<Observed<T>>;
};
template <typename T>
struct ObservedAddMutableReference<std::shared_ptr<Observed<T>>>
{
using type = std::weak_ptr<Observed<T>>;
};

template <typename T>
using ObservedAddReference_t = typename ObservedAddReference<std::decay_t<T>>::type;
template <typename T>
using ObservedAddMutableReference_t = typename ObservedAddMutableReference<std::remove_reference_t<T>>::type;
}

template <typename T>
struct UnpackObserved
{
using type = T;
};
template <typename T>
struct UnpackObserved<Observed<T>>
{
using type = T;
};
template <typename T>
struct UnpackObserved<std::weak_ptr<Observed<T>>>
{
using type = T;
};
template <typename T>
struct UnpackObserved<std::shared_ptr<Observed<T>>>
{
using type = T;
};
template <typename T>
struct UnpackObserved<std::weak_ptr<const Observed<T>>>
{
using type = T;
};
template <typename T>
struct UnpackObserved<std::shared_ptr<const Observed<T>>>
{
using type = T;
};
template <typename T>
using UnpackObserved_t = typename UnpackObserved<T>::type;
}
101 changes: 75 additions & 26 deletions nui/include/nui/event_system/observed_value_combinator.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#pragma once

#include <nui/frontend/event_system/event_context.hpp>
#include <nui/event_system/event_context.hpp>
#include <nui/event_system/observed_value.hpp>
#include <nui/utility/tuple_for_each.hpp>
#include <nui/utility/overloaded.hpp>
#include <nui/concepts.hpp>

#include <tuple>
Expand All @@ -12,51 +14,92 @@ namespace Nui
class ObservedValueCombinatorBase
{
public:
explicit constexpr ObservedValueCombinatorBase(ObservedValues const&... observedValues)
: observedValues_{observedValues...}
explicit constexpr ObservedValueCombinatorBase(
Detail::ObservedAddReference_t<ObservedValues>&&... observedValues)
: observedValues_{std::forward<Detail::ObservedAddReference_t<ObservedValues>>(observedValues)...}
{}
explicit constexpr ObservedValueCombinatorBase(std::tuple<ObservedValues const&...> observedValues)
explicit constexpr ObservedValueCombinatorBase(
std::tuple<Detail::ObservedAddReference_t<ObservedValues>...> observedValues)
: observedValues_{std::move(observedValues)}
{}

constexpr void attachEvent(auto eventId) const
{
tupleForEach(observedValues_, [eventId](auto const& observed) {
observed.attachEvent(eventId);
});
tupleForEach(
observedValues_,
Nui::overloaded{
[eventId](IsObserved auto const& observed) {
observed.attachEvent(eventId);
},
[eventId](IsWeakObserved auto const& observed) {
if (auto shared = observed.lock(); shared)
shared->attachEvent(eventId);
},
});
}

constexpr void attachOneshotEvent(auto eventId) const
{
tupleForEach(observedValues_, [eventId](auto const& observed) {
observed.attachOneshotEvent(eventId);
});
tupleForEach(
observedValues_,
Nui::overloaded{
[eventId](IsObserved auto const& observed) {
observed.attachOneshotEvent(eventId);
},
[eventId](IsWeakObserved auto const& observed) {
if (auto shared = observed.lock(); shared)
shared->attachOneshotEvent(eventId);
},
});
}

constexpr void detachEvent(auto eventId) const
{
tupleForEach(observedValues_, [eventId](auto const& observed) {
observed.detachEvent(eventId);
});
tupleForEach(
observedValues_,
Nui::overloaded{
[eventId](IsObserved auto const& observed) {
observed.detachEvent(eventId);
},
[eventId](IsWeakObserved auto const& observed) {
if (auto shared = observed.lock(); shared)
shared->detachEvent(eventId);
},
});
}

std::tuple<ObservedValues const&...> const& observedValues() &
std::tuple<Detail::ObservedAddReference_t<ObservedValues>...> const& observedValues() &
{
return observedValues_;
}

std::tuple<ObservedValues const&...>&& observedValues() &&
std::tuple<Detail::ObservedAddReference_t<ObservedValues>...>&& observedValues() &&
{
return std::move(const_cast<std::tuple<ObservedValues const&...>&>(observedValues_));
return std::move(
const_cast<std::tuple<Detail::ObservedAddReference_t<ObservedValues>...>&>(observedValues_));
}

bool isAnyExpired() const
{
const auto isExpired = Nui::overloaded{
[](IsObserved auto const&) {
return false;
},
[](IsWeakObserved auto const& observed) {
return observed.expired();
},
};

return std::apply(
[isExpired](auto const&... observed) {
return (isExpired(observed) || ...);
},
observedValues_);
}

protected:
const std::tuple<ObservedValues const&...> observedValues_;
const std::tuple<Detail::ObservedAddReference_t<ObservedValues>...> observedValues_;
};
template <typename... ObservedValues>
ObservedValueCombinatorBase(std::tuple<ObservedValues const&...>) -> ObservedValueCombinatorBase<ObservedValues...>;
template <typename... ObservedValues>
ObservedValueCombinatorBase(ObservedValues const&...) -> ObservedValueCombinatorBase<ObservedValues...>;

template <typename... ObservedValues>
class ObservedValueCombinator;
Expand All @@ -66,7 +109,7 @@ namespace Nui
{
public:
constexpr ObservedValueCombinatorWithGenerator(
std::tuple<ObservedValues const&...> observedValues,
std::tuple<Detail::ObservedAddReference_t<ObservedValues>...> observedValues,
RendererType generator)
: ObservedValueCombinatorBase<ObservedValues...>{std::move(observedValues)}
, generator_{std::move(generator)}
Expand Down Expand Up @@ -138,12 +181,18 @@ namespace Nui
}
};
template <typename... ObservedValues>
ObservedValueCombinator(ObservedValues const&...) -> ObservedValueCombinator<ObservedValues...>;
ObservedValueCombinator(ObservedValues&&...)
-> ObservedValueCombinator<std::decay_t<Detail::ObservedAddReference_t<ObservedValues>>...>;
template <typename... ObservedValues>
ObservedValueCombinator(std::tuple<Detail::ObservedAddReference_t<ObservedValues>...>)
-> ObservedValueCombinator<std::decay_t<Detail::ObservedAddReference_t<ObservedValues>>...>;

template <typename... ObservedValues>
requires(Detail::IsObserved<ObservedValues>::value && ...)
ObservedValueCombinator<ObservedValues...> observe(ObservedValues const&... observedValues)
requires(IsObservedLike<ObservedValues> && ...)
ObservedValueCombinator<std::decay_t<Detail::ObservedAddReference_t<ObservedValues>>...>
observe(ObservedValues&&... observedValues)
{
return ObservedValueCombinator(observedValues...);
return ObservedValueCombinator<std::decay_t<Detail::ObservedAddReference_t<ObservedValues>>...>{
std::forward<Detail::ObservedAddReference_t<ObservedValues>>(observedValues)...};
}
}
Loading
Loading