12#include "../attributes.hpp"
13#include "../core/bridge.hpp"
14#include "../core/callback_scope.hpp"
15#include "../core/registry.hpp"
23namespace morph::reactive {
31template <
typename Update,
typename ViewState,
typename Msg>
38template <
typename Update,
typename ViewState,
typename... Alts>
40 : std::bool_constant<(std::invocable<Update&, ViewState&, Alts const&> && ...)> {};
55 if (!_frame->storeDied) {
74template <
typename Update,
typename ViewState,
typename Msg>
92template <
typename ViewState,
typename Msg>
100 template <
typename Init,
typename Update>
101 requires std::invocable<Init&, Runtime&> && std::same_as<std::invoke_result_t<Init&, Runtime&>, ViewState> &&
105 _state{init(runtime)},
106 _update{std::make_shared<Update>(std::move(update))},
107 _apply{&applyUpdate<Update>} {}
111 if (_updating !=
nullptr) {
112 _updating->storeDied =
true;
125 auto& core = *_rt->core();
126 if (!core.checkOwner()) {
129 if (_updating !=
nullptr) {
136 std::shared_ptr<void>
const update = _update;
137 void (*
const apply)(
void*, ViewState&, Msg
const&) = _apply;
138 ViewState&
state = _state;
146 apply(update.get(),
state, msg);
153 [[nodiscard]] ViewState
const&
state() const noexcept {
return _state; }
158 [[nodiscard]] std::function<void()>
action(Msg msg) {
159 return [
this, msg = std::move(msg)] {
send(msg); };
163 template <
typename Update>
164 static void applyUpdate(
void* update, ViewState&
state, Msg
const& msg) {
165 std::visit([&](
auto const& alternative) { (*
static_cast<Update*
>(update))(
state, alternative); }, msg);
171 std::shared_ptr<void> _update;
172 void (*_apply)(
void*, ViewState&, Msg
const&);
173 detail::UpdateFrame* _updating =
nullptr;
200template <
typename ViewState,
typename Msg,
typename Model,
typename Sharing,
typename Action,
typename ToMsg,
205 handler.
execute(std::move(action))
206 .then(scope, [&store, toMsg = std::move(toMsg)](Result
const& result) { store.
send(Msg{toMsg(result)}); })
207 .onError(scope, [&store, toFailMsg = std::move(toFailMsg)](std::exception_ptr
const& error) {
208 store.
send(Msg{toFailMsg(error)});
Owned lifetime-and-stop gate for asynchronous callbacks — a data member, not a base class.
RAII wrapper that binds a single model type to a Bridge.
::morph::async::Completion< typename ::morph::model::ActionTraits< Action >::Result > execute(Action action)
Dispatches action via the underlying Bridge and returns a Completion.
The owner of a signal graph: every node takes one, and every operation runs on its owner.
decltype(auto) batch(F &&fn)
Runs fn as one batch: every write inside it is one flush.
decltype(auto) untracked(F &&fn) const
Runs fn with tracking off: reads inside it subscribe nothing.
User-intent view state — what is selected, typed, open — changed only by messages.
~Store()
Destroys the state, and tells an update still running that the Store is gone.
void send(Msg msg)
Applies msg in one batch. Refused off the owner, and inside an update.
Store(Runtime &runtime, Init init, Update update)
ViewState const & state() const noexcept
The state, for reading. A field's get() tracks exactly that field.
std::function< void()> action(Msg msg)
A callable that sends msg each time it is called — what a button binds to.
Marks a Store as inside its update for the guard's lifetime.
~UpdateGuard()
Clears the Store's in-update slot, also when the update throws, unless the Store died.
UpdateGuard(UpdateFrame *&slot, UpdateFrame &frame) noexcept
An update that handles every message: Update& is invocable as (ViewState&, Alt const&) for each alter...
constexpr char const * kSendInUpdate
Store::send was called from inside an update; the message is dropped.
morph::reactive::Runtime: the owner, batching and flush scheduling of a signal graph.
void request(Store< ViewState, Msg > &store, bridge::BridgeHandler< Model, Sharing > &handler, async::CallbackScope const &scope, Action action, ToMsg toMsg, ToFailMsg toFailMsg)
Executes action and sends its result, or its failure, to store as one message.
Traits specialisation that maps an action type to its id, JSON codec, and result type.
Whether Update handles every alternative of the variant Msg.
One update in progress, on the stack of the send() running it.
bool storeDied
Set by the Store's destructor while the update is still running.
std::function< void()> Action
A widget event handler taking no arguments.