morph 0.1.0
Asynchronous bridge between GUI thread and business models
Loading...
Searching...
No Matches
frontend.hpp File Reference

The frontend seam: main picks a frontend at runtime, and the frontend runs whatever an AppSource opens. More...

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <exception>
#include <expected>
#include <functional>
#include <map>
#include <memory>
#include <optional>
#include <ranges>
#include <span>
#include <stdexcept>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "../core/executor.hpp"
#include "../reactive/runtime.hpp"
#include "../reactive/scheduler.hpp"

Go to the source code of this file.

Classes

class  morph::ui::AppContext
 What a frontend lends the source it opens and the screens it mounts. More...
struct  morph::ui::Bundle
 What an open source hands the frontend: the application's screens, verified. More...
struct  morph::ui::ConnectError
 Why a source could not be opened. More...
struct  morph::ui::Backend
 The application's opaque handle for one of its backends. Its name is what {"env": "backend"} reads. More...
class  morph::ui::AppSource
 Where the screens and the models are: a server (remote) or the application linked in-process (local). More...
class  morph::ui::Frontend
 A frontend: owns an event loop and a renderer, and runs one source's screens. More...
struct  morph::ui::FrontendOption
 One frontend a binary was built with. More...
struct  morph::ui::FrontendError
 Why no frontend was selected. More...
struct  morph::ui::detail::CommandLineChoice
 The command line's choice of frontend, and the arguments that made it. More...
class  morph::ui::MountedShell
 What a frontend mounts once its source is open: the app shell and its screens, or a view of why the source did not open. Destroying it unmounts all of it. More...

Typedefs

using morph::ui::Scheduler = reactive::Scheduler
 Timers on the frontend's owner executor; see reactive::Scheduler.
using morph::ui::TimerHandle = reactive::TimerHandle
 Owns one scheduled timer and cancels it when destroyed; see reactive::TimerHandle.
using morph::ui::EnvironmentReader = std::function<std::optional<std::string>(std::string_view name)>
 Reads an environment variable: its value, or nullopt when it is unset.
using morph::ui::ShellFactory
 Mounts the shell for what the source delivered. Called once, on the owner; it may return null to mount nothing (after calling AppContext::quit, for example).

Functions

EnvironmentReader morph::ui::processEnvironment ()
 The process environment, read through std::getenv.
CommandLineChoice morph::ui::detail::readCommandLine (std::span< std::string const > args)
 Reads --ui=<name> and --ui <name> from the arguments, up to a --.
std::expected< std::unique_ptr< Frontend >, FrontendError > morph::ui::selectFrontend (std::span< FrontendOption const > built, std::vector< std::string > &args, EnvironmentReader const &env=processEnvironment())
 Picks the frontend to run: the last --ui=<name> (or --ui <name>) before a --, else a non-empty MORPH_UI, else the first option in the given order whose usable() holds.
int morph::ui::runApp (AppContext &context, AppSource &source, ShellFactory const &mountShell, std::function< int()> const &loop)
 Runs one source inside a frontend: opens it, mounts the shell when it is ready, runs the loop, and tears down in order.

Detailed Description

The frontend seam: main picks a frontend at runtime, and the frontend runs whatever an AppSource opens.

Specified in docs/spec/ui/frontend.md.

Definition in file frontend.hpp.

Typedef Documentation

◆ Scheduler

using morph::ui::Scheduler = reactive::Scheduler

Timers on the frontend's owner executor; see reactive::Scheduler.

Definition at line 41 of file frontend.hpp.

◆ TimerHandle

using morph::ui::TimerHandle = reactive::TimerHandle

Owns one scheduled timer and cancels it when destroyed; see reactive::TimerHandle.

Definition at line 44 of file frontend.hpp.

◆ EnvironmentReader

using morph::ui::EnvironmentReader = std::function<std::optional<std::string>(std::string_view name)>

Reads an environment variable: its value, or nullopt when it is unset.

Definition at line 251 of file frontend.hpp.

◆ ShellFactory

Initial value:
std::function<std::unique_ptr<MountedShell>(AppContext& context, std::expected<Bundle, ConnectError> opened)>
What a frontend lends the source it opens and the screens it mounts.
Definition frontend.hpp:50

Mounts the shell for what the source delivered. Called once, on the owner; it may return null to mount nothing (after calling AppContext::quit, for example).

Definition at line 405 of file frontend.hpp.

Function Documentation

◆ processEnvironment()

EnvironmentReader morph::ui::processEnvironment ( )
inlinenodiscard

The process environment, read through std::getenv.

Returns
A reader over the process environment.

Definition at line 255 of file frontend.hpp.

◆ readCommandLine()

CommandLineChoice morph::ui::detail::readCommandLine ( std::span< std::string const > args)
inlinenodiscard

Reads --ui=<name> and --ui <name> from the arguments, up to a --.

The last one wins. An argument starting with -- is never taken as the name after --ui: it is the next option, and the --ui before it has no name.

Parameters
argsThe arguments; a program name among them is never a --ui flag.
Returns
The choice.

Definition at line 298 of file frontend.hpp.

◆ selectFrontend()

std::expected< std::unique_ptr< Frontend >, FrontendError > morph::ui::selectFrontend ( std::span< FrontendOption const > built,
std::vector< std::string > & args,
EnvironmentReader const & env = processEnvironment() )
inlinenodiscard

Picks the frontend to run: the last --ui=<name> (or --ui <name>) before a --, else a non-empty MORPH_UI, else the first option in the given order whose usable() holds.

A frontend named on the command line or in MORPH_UI is used even when its usable() is false: the user asked for it. On success every --ui argument (with the name after a bare --ui) is removed from args, and the rest keep their order, for the caller to pass on; on an error args is left as it was.

Parameters
builtThe frontends this binary was built with, in order of preference.
argsThe command-line arguments, with or without the program name first.
envReads MORPH_UI; the process environment by default. An empty reader reads nothing.
Returns
The frontend, made; or why there is none.

Definition at line 338 of file frontend.hpp.

◆ runApp()

int morph::ui::runApp ( AppContext & context,
AppSource & source,
ShellFactory const & mountShell,
std::function< int()> const & loop )
inlinenodiscard

Runs one source inside a frontend: opens it, mounts the shell when it is ready, runs the loop, and tears down in order.

The order is fixed here so that every frontend keeps it. When the loop returns, or throws, the shell is destroyed first, while the source's connections that its screens use are still open, and the source is closed next, while the runtime and the executor its handlers were made with are still alive; the frontend destroys those after this returns.

The source's ready may come during open (a local source) or later from the loop (a remote one). A second ready is ignored, and one that comes after the run has ended does nothing. A mountShell that throws quits the context with exit code 1, and its exception leaves this call once everything is torn down.

Parameters
contextThe frontend's context; its runtime must outlive this call.
sourceThe source to open; closed before this returns.
mountShellMounts the shell for what the source delivered.
loopRuns the frontend's event loop and returns the exit code once AppContext::quit ends it.
Returns
What loop returns.
Exceptions
std::invalid_argumentwhen mountShell or loop is empty; whatever open, mountShell, loop or close throws, the first of them.

Definition at line 426 of file frontend.hpp.