morph 0.1.0
Asynchronous bridge between GUI thread and business models
Loading...
Searching...
No Matches
morph::ui::Mounted Class Reference

A view tree mounted on a backend: its widgets, built once, and the bindings that keep them current. More...

#include <mount.hpp>

Public Member Functions

 Mounted (reactive::Runtime &runtime, IViewBackend &backend, Node root, ContainerWidget *parent=nullptr, std::size_t depth=0)
 Mounted (Mounted const &)=delete
Mounted & operator= (Mounted const &)=delete
 Mounted (Mounted &&)=delete
Mounted & operator= (Mounted &&)=delete
Widget & root () const noexcept
 The root node's widget.
bool focus (std::string_view focusId)
 Moves keyboard focus to the mounted widget whose Common::focusId is focusId, at any depth, including the content of a Switch case, a Tabs page, a Dialog and every row mounted now.

Detailed Description

A view tree mounted on a backend: its widgets, built once, and the bindings that keep them current.

Destroying it destroys every binding before the widget it drives and every child before its parent. The runtime, the backend and every signal a binding reads must outlive it; the owner of the runtime constructs and destroys it. Non-copyable and non-movable: bindings point into it.

Every widget callback, a drop's accepts predicate included, runs as a reactive::Runtime::widgetEvent and untracked, so a binding whose setter makes the backend call a handler does not subscribe to what the handler reads. An exception a callback throws is reported (detail::site::kCallbackThrew) and goes no further: the backend's call returns normally, a predicate that threw refuses the drop, and what the callback wrote before throwing still flushes.

An input whose value is a slot is controlled: a text input's text, a checkbox's state, a select's key, a slider's, date-time input's or file picker's value, a collapsible panel's state, a Tabs index, a Dialog's open and a Table's selection. After a user's request, and after the flush it caused, a posted turn shows the slot's value if the widget shows anything else: a refused request snaps back, an accepted one costs no setter call, and a transformed one shows the request for that one turn. That holds with no handler too, which makes a slot without one read-only. A constant is not a slot: the widget keeps what the user did to it.

A mount that throws goes no further than the content it was building, and leaves none of it behind. A node mounted directly, a constant Switch selector, Tabs index or Dialog open included, throws out of the constructor. Content a binding mounts, which a bound selector, index or open does in an Effect even during the constructor, is reported (reactive::detail::site::kEffectThrew) instead: a Switch shows nothing for that key, having torn the old case down first; a Tabs keeps the previous page shown and selected; a Dialog stays closed. A Tabs then calls its onSelect with the page still shown, and a Dialog its onDismiss, each as a widget callback and as the last thing the mount does, so the application's state follows the widget and its next pick of the failed tab, or opening of the dialog, mounts again. A Switch selector is equality-gated, so its next change of key mounts again. A Tabs index and a Dialog open are not: while one still names content that failed — no onSelect or onDismiss moved it — every run of its binding, a change to any signal the binding reads included, tries that mount again, once per run, reporting each failure and calling onSelect or onDismiss again.

A ForEach or a Table mounts its rows in an Effect too, one row at a time: a row that fails is reported, leaves nothing behind and is left out, the other rows are mounted and ordered all the same, and the next change of the rows mounts it again. A key repeated in one snapshot is reported (detail::site::kDuplicateKey), and only its first row is shown.

Bindings run in owner order. The tree's own bindings are at the depth the mount was given; the content of a Switch case, a Tabs page or a Dialog, and every ForEach or Table row, is in a scope one level deeper than the binding that mounted it. So an Effect that removes content runs before the content's own bindings in the same flush, and a binding never evaluates against state its owner is about to take away. A mount placed under an outer scope (a screen's, a row's) takes that scope's depth plus one, so the outer scope's Effects run first too.

A mount must run to completion: nothing it calls, a backend factory or setter or a binding's evaluation, may destroy this object, its runtime or its backend. Widget callbacks are events, not part of a mount, and may.

Definition at line 1727 of file mount.hpp.

Constructor & Destructor Documentation

◆ Mounted()

morph::ui::Mounted::Mounted ( reactive::Runtime & runtime,
IViewBackend & backend,
Node root,
ContainerWidget * parent = nullptr,
std::size_t depth = 0 )
inline
Parameters
runtimeThe runtime the bindings are made in. Borrowed.
backendMakes the widgets. Borrowed.
rootThe tree; kept alive as long as the mount.
parentThe container the root widget is appended to, or null for a backend root.
depthThe scope depth of the tree's own bindings (reactive::Scope::depth): zero for a mount no other scope owns, one more than the owner's for a mount placed under a scope.
Exceptions
std::invalid_argumentwhen root is null.

Definition at line 1736 of file mount.hpp.

Member Function Documentation

◆ root()

Widget & morph::ui::Mounted::root ( ) const
inlinenodiscardnoexcept

The root node's widget.

Returns
The widget; valid as long as this object.

Definition at line 1752 of file mount.hpp.

◆ focus()

bool morph::ui::Mounted::focus ( std::string_view focusId)
inline

Moves keyboard focus to the mounted widget whose Common::focusId is focusId, at any depth, including the content of a Switch case, a Tabs page, a Dialog and every row mounted now.

Of several such widgets, the one mounted first is taken; one whose content has since been unmounted is not found.

Parameters
focusIdThe name.
Returns
Whether a mounted widget has that name.

Definition at line 1761 of file mount.hpp.


The documentation for this class was generated from the following file: