Encapsulated user action with an optional CanExecute predicate.
More...
#include <command.hpp>
template<typename... Args>
class aria::Command< Args >
Encapsulated user action with an optional CanExecute predicate.
Two flavours:
- Command<> (parameterless) — the predicate is a () -> bool closure. On construction the command installs a reactive Effect that re-runs the predicate whenever any reactive value it reads changes, and emits a can_execute signal with the new truth value. Bound buttons auto-update enabled with no manual plumbing.
- Command<Args...> (parameterised) — the predicate takes the same arguments the View supplies at click time. Because those arguments are only known at invocation, we cannot run the predicate eagerly to register reactive dependencies; callers that want enabled to reflect model state changes must call notify_can_execute_changed(args...) explicitly. (The BindingEngine::bind_command helper will also re-evaluate on demand for fixed args.)
Lifetime contract (READ BEFORE CAPTURING REFERENCES)
- Declare Command<> AFTER every Property / Computed its predicate reads. The no-arg specialisation runs the predicate once at construction to register its reactive dependency set; reading a not-yet-constructed member is undefined behaviour.
- Keep the predicate pure and side-effect free. The internal Effect may re-run it any time an upstream changes, and re-runs are coalesced by the reactive graph; observable side effects will appear non-deterministic.
- A Property freed before the Command it feeds is undefined behaviour — avoid it. Normal ViewModel usage co-owns both, so they die together at the owning scope's end. The reactive graph detaches the Effect's source edge when Property's ~Node runs, so the Command does not crash on destruction, but re-reading the predicate (via notify_can_execute_changed()) after an upstream was freed is UB (the predicate captures a reference to freed storage). See the test Command<>: Property freed before Command for the one case that IS safe: don't touch the command again, just let it destruct.
◆ Action
template<typename... Args>
| using aria::Command< Args >::Action = std::function<void(Args...)> |
◆ Predicate
template<typename... Args>
| using aria::Command< Args >::Predicate = std::function<bool(const Args&...)> |
◆ CanExecuteSignal
template<typename... Args>
| using aria::Command< Args >::CanExecuteSignal = detail::TypedSignal<bool> |
◆ Command() [1/4]
template<typename... Args>
template<std::invocable< Args... > A>
◆ Command() [2/4]
template<typename... Args>
template<std::invocable< Args... > A, std::predicate< const Args &... > P>
◆ Command() [3/4]
template<typename... Args>
◆ Command() [4/4]
template<typename... Args>
◆ ~Command()
template<typename... Args>
◆ operator=() [1/2]
template<typename... Args>
◆ operator=() [2/2]
template<typename... Args>
◆ execute()
template<typename... Args>
Invoke the action if can_execute(args...) is true.
◆ operator()()
template<typename... Args>
◆ can_execute()
template<typename... Args>
| bool aria::Command< Args >::can_execute |
( |
const Args &... | args | ) |
const |
|
inlinenodiscard |
◆ notify_can_execute_changed()
template<typename... Args>
| void aria::Command< Args >::notify_can_execute_changed |
( |
const Args &... | args | ) |
const |
|
inline |
Manually notify observers that can_execute may have changed.
For Command<Args...> this is the primary mechanism (we cannot auto-track a predicate whose inputs we do not know). For Command<> callers normally never need to call this – the built-in Effect already re-evaluates automatically – but it is retained for force-refresh scenarios (e.g. external state that isn't expressed as a Property).
◆ observe_can_execute()
template<typename... Args>
◆ binding::BindingEngine
template<typename... Args>
The documentation for this class was generated from the following file: