8#include "../utility/utility.hpp"
9#include "../dispatch/dispatch.hpp"
11#include "../macros.hpp"
19hi_export_module(hikogui.observer : observer_intf);
21hi_export
namespace hi {
inline namespace v1 {
35 using notifier_type = notifier<void(value_type)>;
36 using callback_type = notifier_type::callback_type;
37 using awaiter_type = notifier_type::awaiter_type;
47 using reference = value_type &;
48 using const_reference = value_type
const &;
49 using pointer = value_type *;
50 using const_pointer = value_type
const *;
59 if (_observer !=
nullptr) {
60 hi_axiom_not_null(_ptr);
61 if (_original_value) {
62 if constexpr (
requires(value_type
const& a, value_type
const& b) { a != b; }) {
63 if (*_original_value != *_ptr) {
77 _observer(std::exchange(
other._observer,
nullptr)),
78 _ptr(std::exchange(
other._ptr,
nullptr)),
79 _original_value(std::exchange(
other._original_value, std::nullopt))
85 _observer = std::exchange(
other._observer,
nullptr);
89 _ptr = std::exchange(
other._ptr,
nullptr);
90 _original_value = std::exchange(
other._original_value, std::nullopt);
101 _observer(observer), _ptr(ptr), _original_value(std::nullopt)
103 hi_axiom_not_null(_observer);
104 hi_axiom_not_null(_ptr);
114 _observer(
nullptr), _ptr(
nullptr), _original_value(
std::nullopt)
138 hi_axiom_not_null(_ptr);
164 hi_axiom_not_null(_ptr);
190 hi_axiom_not_null(_ptr);
198 template<typename Rhs> \
199 decltype(auto) operator op() noexcept \
200 requires requires(value_type& a) { op a; } \
212 template<typename Rhs> \
213 auto operator op(int) noexcept \
214 requires requires(value_type& a) { a op; } \
226 template<typename Rhs> \
227 decltype(auto) operator op(Rhs const& rhs) noexcept \
228 requires requires(value_type& a, Rhs const& b) { a op b; } \
231 return (*_ptr) op rhs; \
248 template<typename Rhs> \
249 auto operator op() const noexcept \
250 requires requires(value_type const& a) { op a; } \
252 hi_axiom_not_null(_ptr); \
264 template<typename Rhs> \
265 auto operator op(Rhs const& rhs) const noexcept \
266 requires requires(value_type const& a, Rhs const& b) { a op b; } \
268 hi_axiom_not_null(_ptr); \
269 return (*_ptr) op rhs; \
287 template<
typename... Args>
288 auto operator()(Args &&... args)
const noexcept
289 requires requires(value_type
const & a, Args &&...args) { a(
std::forward<Args>(args)...); }
291 hi_axiom_not_null(_ptr);
295 template<
typename... Args>
296 decltype(
auto)
operator()(Args &&... args)
noexcept
305 template<
typename Arg>
306 auto operator[](Arg && arg)
const noexcept
307 requires requires(value_type
const & a, Arg &&arg) { a[
std::forward<Arg>(arg)]; }
309 hi_axiom_not_null(_ptr);
318 std::optional<value_type> _original_value;
320 void start_write() noexcept
322 if (not _original_value) {
323 hi_axiom_not_null(_ptr);
324 _original_value = *_ptr;
328 friend class observer;
331 using const_reference = value_type
const &;
333 using const_pointer = value_type
const *;
335 constexpr ~observer() =
default;
341 template<forward_of<std::shared_ptr<hi::observed_base>> Observed>
357 template<std::convertible_to<value_type> Value>
389 _observed =
other._observed;
391 _convert =
other._convert;
394 update_state_callback();
395 _observed->notify_group_ptr(
observable_msg{_observed->get(), _path});
414 update_state_callback();
415 _observed->notify_group_ptr(
observable_msg{_observed->get(), _path});
427 _convert = [](
void *base) {
430 update_state_callback();
437 [[nodiscard]] const_pointer
get() const noexcept
439 return convert(_observed->get());
446 [[nodiscard]] pointer
get() noexcept
448 return proxy_type{
this, convert(_observed->get())};
457 template<forward_of<
void(value_type)> Func>
458 [[nodiscard]]
callback<void(value_type)>
subscribe(Func &&func, callback_flags flags = callback_flags::synchronous)
noexcept
463 awaiter_type
operator co_await()
const noexcept
465 return _notifier.operator
co_await();
473 [[nodiscard]]
auto sub(
auto const& index)
const noexcept
476 using result_type = std::decay_t<decltype(std::declval<value_type>()[index])>;
478 auto new_path = _path;
479 new_path.
push_back(std::format(
"[{}]", index));
481 _observed,
std::move(new_path), [convert_copy = this->_convert, index](
void *base) ->
void * {
482 return std::addressof((*std::launder(
static_cast<value_type *
>(convert_copy(base))))[index]);
492 template<fixed_
string Name>
493 [[nodiscard]]
auto sub() const noexcept
497 auto new_path = _path;
503 [convert_copy = this->_convert](
void *base) ->
void * {
505 *std::launder(
static_cast<value_type *
>(convert_copy(base)))));
518 template<
typename Rhs>
535 const_pointer operator&() const noexcept
556 template<typename Rhs> \
557 observer& operator op() noexcept \
558 requires requires(value_type& a) { op a; } \
570 template<typename Rhs> \
571 auto operator op(int) noexcept \
572 requires requires(value_type& a) { a op; } \
583 template<typename Rhs> \
584 observer& operator op(Rhs const& rhs) noexcept \
585 requires requires(value_type& a, Rhs const& b) { a op b; } \
605 template<typename Rhs> \
606 auto operator op() const noexcept \
607 requires requires(value_type const& a) { op a; } \
620 template<typename Rhs> \
621 auto operator op(Rhs const& rhs) const noexcept \
622 requires requires(value_type const& a, Rhs const& b) { a op b; } \
624 return *get() op rhs; \
642 template<
typename... Args>
643 auto operator()(Args &&... args)
const noexcept
644 requires requires(value_type
const & a, Args &&...args) { a(
std::forward<Args>(args)...); }
651 template<
typename Arg>
652 auto operator[](Arg && arg)
const noexcept
653 requires requires(value_type
const & a, Arg &&arg) { a[
std::forward<Arg>(arg)]; }
661 using observed_type = group_ptr<observed_base>;
662 observed_type _observed = {};
663 path_type _path = {};
664 std::function<
void *(
void *)> _convert = {};
665 notifier_type _notifier;
667 value_type _debug_value;
672 template<forward_of<observed_type> ObservedBase, forward_of<path_type> Path, forward_of<
void *(
void *)> Converter>
676 Converter&& converter) noexcept :
679 update_state_callback();
682 void notify() const noexcept
684 _observed->notify_group_ptr(
observable_msg{_observed->get(), _path});
687 value_type *convert(
void *base)
const noexcept
689 return std::launder(
static_cast<value_type *
>(_convert(base)));
692 value_type
const *convert(
void const *base)
const noexcept
694 return std::launder(
static_cast<value_type
const *
>(_convert(
const_cast<void *
>(base))));
697 void update_state_callback() noexcept
699 _observed.subscribe([
this](observable_msg
const& msg) {
700 auto const [msg_it, this_it] =
std::mismatch(msg.path.cbegin(), msg.path.cend(), _path.cbegin(), _path.cend());
703 if (msg_it == msg.path.cend() or this_it == _path.cend()) {
705 _debug_value = *convert(msg.ptr);
707 _notifier(*convert(msg.ptr));
712 _debug_value = *convert(_observed->get());
718 friend class observer;
735 using type = std::remove_cvref_t<T>;
749template<
typename Context,
typename Expected>
751 std::conditional_t<std::is_convertible_v<Context, observer<Expected>>, std::true_type, std::false_type> {};
754template<
typename Context,
typename Expected>
Functions and types for accessing operating system threads.
@ other
The gui_event does not have associated data.
Definition gui_event_variant.hpp:24
The HikoGUI namespace.
Definition array_generic.hpp:21
The HikoGUI API version 1.
Definition array_generic.hpp:22
Definition callback.hpp:77
Definition observed.hpp:17
std::vector< std::string > path_type
The type of the path used for notifying observers.
Definition observed.hpp:20
An abstract observed object.
Definition observed.hpp:30
Definition observed.hpp:53
A observer pointing to the whole or part of a observed_base.
Definition observer_intf.hpp:32
void reset() noexcept
Reset the observer.
Definition observer_intf.hpp:423
const_pointer get() const noexcept
Read the observed_base value.
Definition observer_intf.hpp:437
observer & operator=(Rhs &&rhs) noexcept
Assign a new value to the observed_base value.
Definition observer_intf.hpp:519
observer(Observed &&observed_base) noexcept
Create an observer from an observed_base.
Definition observer_intf.hpp:342
const_pointer operator->() const noexcept
Constant pointer-to-member of the value being observed_base.
Definition observer_intf.hpp:542
pointer operator->() noexcept
Constant pointer-to-member of the value being observed_base.
Definition observer_intf.hpp:549
constexpr observer(observer &&other) noexcept
Move construct.
Definition observer_intf.hpp:375
constexpr observer & operator=(observer &&other) noexcept
Move assign.
Definition observer_intf.hpp:406
constexpr observer(Value &&value) noexcept
Create a observer linked to an anonymous observed_base-value.
Definition observer_intf.hpp:358
pointer get() noexcept
Make a copy of the observed_base value for modification.
Definition observer_intf.hpp:446
auto sub() const noexcept
Create a sub-observer by selecting a member-variable of the value.
Definition observer_intf.hpp:493
const_reference operator*() const noexcept
Get the value being observed_base.
Definition observer_intf.hpp:528
constexpr observer & operator=(observer const &other) noexcept
Copy assign.
Definition observer_intf.hpp:387
callback< void(value_type)> subscribe(Func &&func, callback_flags flags=callback_flags::synchronous) noexcept
Subscribe a callback to this observer.
Definition observer_intf.hpp:458
constexpr observer(observer const &other) noexcept
Copy construct.
Definition observer_intf.hpp:368
constexpr observer() noexcept
Create a observer linked to an anonymous default initialized observed_base-value.
Definition observer_intf.hpp:353
observer(ObservedBase &&observed_base, Path &&path, Converter &&converter) noexcept
Construct an observer from an observed_base.
Definition observer_intf.hpp:673
auto sub(auto const &index) const noexcept
Create a sub-observer by indexing into the value.
Definition observer_intf.hpp:473
A proxy object of the observer.
Definition observer_intf.hpp:45
reference operator*() noexcept
Dereference the value.
Definition observer_intf.hpp:124
proxy_type() noexcept
Create a proxy object.
Definition observer_intf.hpp:113
pointer operator&() noexcept
Pointer dereference the value.
Definition observer_intf.hpp:175
const_pointer operator&() const noexcept
Pointer dereference the value.
Definition observer_intf.hpp:188
~proxy_type() noexcept
Commits and destruct the proxy object.
Definition observer_intf.hpp:57
pointer operator->() noexcept
Pointer dereference the value.
Definition observer_intf.hpp:149
const_pointer operator->() const noexcept
Pointer dereference the value.
Definition observer_intf.hpp:162
const_reference operator*() const noexcept
Dereference the value.
Definition observer_intf.hpp:136
proxy_type(observer *observer, value_type *ptr) noexcept
Create a proxy object.
Definition observer_intf.hpp:100
A type-trait for observer arguments.
Definition observer_intf.hpp:734
Is context a form of the expected type.
Definition type_traits.hpp:593
This selector allows access to member variable by name.
Definition type_traits.hpp:691
Definition observer_intf.hpp:755
True if T is a forwarded type of Forward.
Definition concepts.hpp:137