Skip to main content

App

Struct App 

Source
pub struct App<D: Document> { /* private fields */ }
Expand description

An app: name, document type and format, commands, views. run() opens the window; the same definition serves the CLI and MCP (App::cli) and tests (App::headless).

use ashlar_app::{App, Cx, Session};
use ashlar_command::{CommandError, CommandSpec};

#[derive(Clone, Default, serde::Serialize, serde::Deserialize)]
struct Doc { count: i64 }

fn bump(s: &mut Session<Doc>, _: &serde_json::Value) -> Result<serde_json::Value, CommandError> {
    s.edit("Bump", |d| d.count += 1);
    Ok(serde_json::Value::Null)
}

fn main() -> Result<(), ashlar_app::Error> {
    App::<Doc>::new("counter", "0.1.0")
        .command(CommandSpec::new("count.bump", "Bump", bump).menu(&["Edit"]).shortcut("Mod+B"))
        .view(|ui, cx: &mut Cx<'_, Doc>| {
            ui.label(format!("{}", cx.doc().count));
            if ui.button("Bump").clicked() {
                cx.dispatch("count.bump", serde_json::json!({}));
            }
        })
        .run()
}

Implementations§

Source§

impl<D: Document> App<D>

Source

pub fn new(name: impl Into<String>, version: impl Into<String>) -> Self

An app called name (lower case, used for folders, env vars and the CLI).

Source

pub fn organization( self, qualifier: impl Into<String>, org: impl Into<String>, ) -> Self

Reverse-domain qualifier and organisation for the OS folders ("com", "Acme").

Source

pub fn title(self, title: impl Into<String>) -> Self

Window title (default: the name).

Source

pub fn format(self, format: Format<D>) -> Self

The document’s file format, with its migrations.

Source

pub fn file_extension(self, ext: impl Into<String>) -> Self

A file extension offered by Open and Save dialogs (without the dot).

Source

pub fn commands( self, specs: impl IntoIterator<Item = CommandSpec<Session<D>>>, ) -> Self

Add commands (menus follow declaration order).

Source

pub fn command(self, spec: CommandSpec<Session<D>>) -> Self

Source

pub fn view(self, view: impl FnMut(&mut Ui, &mut Cx<'_, D>) + 'static) -> Self

The UI, drawn inside the window’s central area each frame.

Source

pub fn setup(self, f: impl FnOnce(&Context) + 'static) -> Self

Runs once before the first frame (install fonts, tokens).

Source

pub fn autosave(self, every: Option<Duration>) -> Self

Autosave interval (None: no autosave or recovery). Default 60 s.

Source

pub fn telemetry(self, key: impl Into<String>, endpoint: Option<&str>) -> Self

Telemetry (with the telemetry feature): write key and server. Always on when endpoint is set (no notice, no switches); TRACER_DISABLED in the environment turns it off.

Source

pub fn instructions(self, text: impl Into<String>) -> Self

What MCP clients are told about the app.

Source

pub fn dirs(self, dirs: AppDirs) -> Self

Put config, data, cache and logs here instead of the OS folders (tests, portable).

Source

pub fn canvas_id(self, id: impl Into<String>) -> Self

On the web, the id of the <canvas> the app runs in (default: the app’s name, then ashlar). When the app cannot start (no such canvas, no WebGL), a visible error appears next to the canvas (or at the top of the page) as well as in the console. Ignored on the desktop.

Source

pub fn window_size(self, width: f32, height: f32) -> Self

Source

pub fn frame_latency(self, frames: u32) -> Self

Frames the GPU may queue ahead of the screen, 1 to 3 (default 1: the lowest input latency, and one swapchain image fewer, about 10 MB for a 960×640 window on a Retina screen). Apps that draw heavy GPU scenes every frame may prefer 2 for smoother throughput.

Source

pub fn control_port(self, port: u16) -> Self

Serve the control port on this port (also --control <port> and <APP>_CONTROL_PORT).

Source

pub fn follow_system_accent(self, follow: bool) -> Self

Recolour the accent (hover, focus, selection) from the OS accent colour (default on). Off pins the built-in accent. Tokens the app installs itself always win over the OS.

Source

pub fn motion(self, prefs: MotionPrefs) -> Self

Motion settings that win over the OS “reduce motion” setting (an app’s own motion preference). Without this the app follows the OS, at normal speed.

Source

pub fn single_instance(self, on: bool) -> Self

One window per app (default off). A second launch hands its arguments (the files to open) to the running one and exits; the running one opens them with file.open and comes to the front. The endpoint is named after the app (see App::organization); desktop only.

Source

pub fn accept_drops(self, on: bool) -> Self

Open files dropped on the window (default on when the app sets a App::format or a App::file_extension). The first file with a known extension opens with file.open (a dirty document asks to save first); the others reach the view as Cx::dropped_files. Off leaves drops to the view’s own input.

Source

pub fn run_toast_actions(self, on: bool) -> Self

Run a toast’s action when it is clicked (default off). With it on, a clicked ToastAction whose command is a registered command id runs like a menu pick, with empty params, after the frame’s toasts are drawn; errors become toasts. Actions naming anything else stay queued for the view’s Toasts::take_actions.

Source

pub fn viewport( self, f: impl FnOnce(ViewportBuilder) -> ViewportBuilder + 'static, ) -> Self

Change the window before it opens: a minimum size, decorations, transparency… f gets the builder ashlar made (title, size, app id, the restored placement) and returns it. Desktop only; the headless driver has no window.

App::<i64>::new("notes", "0.1.0").viewport(|b| b.with_min_inner_size([480.0, 320.0]));
Source

pub fn icon(self, png: impl Into<Vec<u8>>) -> Self

The window and taskbar icon, as PNG bytes (include_bytes!("icon.png")). An image that does not decode is logged and the default icon stays. Desktop only.

Source

pub fn remember_window(self, on: bool) -> Self

Remember where the window was (default on): its position, size, maximized and full screen state go to the settings under "window" when they change and on close, and the next launch opens the window there, kept on a visible monitor. Ignored without a window (--headless, crate::Driver) and without an app folder (App::dirs).

Source

pub fn scene( self, name: impl Into<String>, setup: impl Fn(&mut Session<D>) + Send + Sync + 'static, ) -> Self

A named starting state: setup runs on the session (load a fixture, fill a list, set the theme…) when the scene is applied, with --scene NAME (in a window or --headless), the ui.scene {name} control method, the MCP tool ui_scene or crate::Driver::scene. --list-scenes prints the names. A name declared twice keeps the first.

App::<Doc>::new("notes", "0.1.0").scene("two-notes", |s: &mut Session<Doc>| {
    s.edit("Two notes", |d| d.notes = vec!["a".into(), "b".into()]);
});
Source

pub fn scene_names(&self) -> Vec<String>

The names of the app’s scenes, in declaration order.

Source

pub fn headless(self) -> Headless<D>

A session without a window, driving the same commands (tests, scripts).

Source

pub fn runtime(self) -> Runtime<D>

The runtime without a window, for tests and benches: drive it with crate::Driver. It ignores the OS preferences (see Runtime::set_preferences) so runs match on every machine.

Source

pub fn cli(self) -> Cli

The app’s -cli binary: commands, exec, run, mcp, serve, version, each on a fresh headless session (or the running app with --connect PORT). Add app verbs to the returned ashlar_cli::Cli before run().

Source

pub fn run(self) -> Result<(), Error>

Open the window and run until it closes.

With --headless on the command line, run with no window instead: a virtual-clock crate::Driver in a temporary folder that writes --snap out.png and --tree tree.json (after --script file.ui and --at SECONDS, at --size WxH, --scale S, --theme light|dark, --scene NAME), then exits with 0 (done), 1 (a step failed) or 2 (bad arguments). (--headless needs the headless feature, on by default.) --scene NAME also works with a window; --list-scenes prints the scenes.

Auto Trait Implementations§

§

impl<D> !RefUnwindSafe for App<D>

§

impl<D> !Send for App<D>

§

impl<D> !Sync for App<D>

§

impl<D> !UnwindSafe for App<D>

§

impl<D> Forget for App<D>

§

impl<D> Freeze for App<D>
where Option<Format<D>>: Freeze, Vec<CommandSpec<Session<D>>>: Freeze, Option<Box<dyn FnMut(&mut Ui, &mut Cx<'_, D>)>>: Freeze, Vec<(String, Arc<dyn Fn(&mut Session<D>) + Send + Sync>)>: Freeze,

§

impl<D> Move for App<D>

§

impl<D> Unpin for App<D>
where Option<Format<D>>: Unpin, Vec<CommandSpec<Session<D>>>: Unpin, Option<Box<dyn FnMut(&mut Ui, &mut Cx<'_, D>)>>: Unpin, Vec<(String, Arc<dyn Fn(&mut Session<D>) + Send + Sync>)>: Unpin,

§

impl<D> UnsafeUnpin for App<D>
where Option<Format<D>>: UnsafeUnpin, Vec<CommandSpec<Session<D>>>: UnsafeUnpin, Option<Box<dyn FnMut(&mut Ui, &mut Cx<'_, D>)>>: UnsafeUnpin, Vec<(String, Arc<dyn Fn(&mut Session<D>) + Send + Sync>)>: UnsafeUnpin,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T, S> SimdFrom<T, S> for T
where S: Simd,

Source§

fn simd_from(_simd: S, value: T) -> T

Source§

impl<F, T, S> SimdInto<T, S> for F
where T: SimdFrom<F, S>, S: Simd,

Source§

fn simd_into(self, simd: S) -> T

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> Upcast<T> for T

Source§

fn upcast(&self) -> Option<&T>

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more