Behaviour for Plushie apps following the Elm architecture.
Implement this behaviour to define a desktop application. The runtime calls
init/1 once at startup, then repeatedly calls update/2 and view/1 as
events arrive from the renderer and subscriptions.
Minimal example
defmodule MyApp do
use Plushie.App
alias Plushie.Event.WidgetEvent
def init(_opts), do: %{count: 0}
def update(model, %WidgetEvent{type: :click, id: "increment"}), do: %{model | count: model.count + 1}
def update(model, _event), do: model
def view(model) do
import Plushie.UI
window "counter", title: "Counter" do
column do
text("count", "Count: #{model.count}")
button("increment", "Increment")
end
end
end
endReturn values
init/1 and update/2 both accept two return shapes:
- Bare model -- no side effects needed.
{model, command}or{model, [command]}-- schedule async work, widget operations, window management, or timers. SeePlushie.Commandfor the full command API.
Returning commands
update/2 can return a {model, command} tuple to schedule side effects:
def update(model, %WidgetEvent{type: :click, id: "save"}) do
{model, Command.async(fn -> save_to_disk(model) end, :save_result)}
endSee Plushie.Command for the full command API and result delivery mechanisms.
Error handling
Exceptions in update/2 and view/1 are caught by the runtime and logged;
the model reverts to its pre-exception state. You do not need to wrap your
callbacks in try/rescue. After 100 consecutive errors, the runtime suppresses
further log messages to prevent log flooding.
Optional callbacks
subscribe/1 and handle_renderer_exit/2 are optional. use Plushie.App
provides default implementations that can be overridden.
Summary
Callbacks
Called when the renderer process exits unexpectedly. Return the model to use when the renderer restarts. Default: return model unchanged.
Called once at startup. Returns the initial model, optionally with commands.
Called once at startup to provide application-level settings to the renderer.
Called after every update. Returns the list of active subscriptions.
The runtime diffs this list and starts or stops subscriptions as needed.
Default: [].
Called on every event. Returns the next model, optionally with commands.
Called after every update. Returns a window node or a list of window nodes.
Called on runtime startup to configure window properties. Also called on renderer restart whenever windows need re-opening. Per-window props set in the view tree override these defaults.
Types
@type command() :: Plushie.Command.t() | [Plushie.Command.t()]
@type event() :: Plushie.Event.t() | term()
@type model() :: term()
@type window_view() :: Plushie.Widget.Window.t() | map() | [Plushie.Widget.Window.t() | map()] | nil
Callbacks
Called when the renderer process exits unexpectedly. Return the model to use when the renderer restarts. Default: return model unchanged.
Called once at startup. Returns the initial model, optionally with commands.
@callback settings() :: keyword()
Called once at startup to provide application-level settings to the renderer.
Supported keys:
default_font-- a font specification map (same format as font props)default_text_size-- a number (pixels)antialiasing-- booleanvsync-- boolean (defaults totrue). When enabled, the renderer synchronizes frame presentation with the display refresh rate. Disabling it can improve rendering performance on some platforms.scale_factor-- number (defaults to1.0). Multiplier on top of OS DPI scaling. Setting2.0on a 2x HiDPI display gives 4x physical pixels per logical pixel. Per-window overrides are supported via thescale_factorprop on window nodes.theme-- built-in theme atom (e.g.:dark,:nord),:systemto follow the OS light/dark preference, or a custom palette map. SeePlushie.Type.Theme.fonts-- list of font paths to loaddefault_event_rate-- integer, maximum events per second for coalescable event types. Omit for unlimited (default). Affects mouse moves, scroll, animation frames, slider drags, etc. Set to 60 for most apps, lower for dashboards or remote rendering. Per-subscriptionmax_rateand per-widgetevent_rateoverride this default.
Default: [] (renderer uses its own defaults).
@callback subscribe(model()) :: [Plushie.Subscription.t()]
Called after every update. Returns the list of active subscriptions.
The runtime diffs this list and starts or stops subscriptions as needed.
Default: [].
Called on every event. Returns the next model, optionally with commands.
In addition to Plushie.Event structs from the renderer and subscriptions,
update/2 may receive internal tuple events (e.g. async results, stream
chunks, effect responses). Pattern match broadly or include a catch-all clause.
@callback view(model()) :: window_view()
Called after every update. Returns a window node or a list of window nodes.
The top level must be explicit windows. Single-window apps return one
window(...) node. Multi-window apps return a list of window(...) nodes.
nil or [] is allowed when the app intentionally has no open windows.
Called on runtime startup to configure window properties. Also called on renderer restart whenever windows need re-opening. Per-window props set in the view tree override these defaults.
Supported keys
title, size, width, height, position, min_size, max_size,
maximized, fullscreen, visible, resizable, closeable,
minimizable, decorations, transparent, blur, level,
exit_on_close_request.
See Plushie.Widget.Window for details on each property.
Example
def window_config(_model) do
%{title: "My App", width: 800, height: 600, min_size: {400, 300}}
endDefault: empty config (the renderer uses its own defaults).