# Programming model

An app is a set of entities. Some of them are views: they implement `Render` and return an element
tree. When an entity changes it calls `cx.notify()`, and the framework runs `render` again for that
view only. Everything runs in one process on the main thread; there is no IPC layer to cross.

> **Example: Hello.** Source in [examples/hello](https://github.com/FormalSnake/NativeDesktop/blob/main/examples/hello). Live on the web and captured on macOS, Linux and Windows in the docs app.


## Views and render

```rust
pub struct Counter {
    count: u32,
}

impl Render for Counter {
    fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
        let theme = cx.theme();
        scaffold()
            .toolbar(toolbar().item(button("add", "Add one").on_click(cx.listener(
                |this, _: &ClickEvent, _window, cx| {
                    this.count += 1;
                    cx.notify();
                },
            ))))
            .content(
                v_flex()
                    .size_full()
                    .items_center()
                    .justify_center()
                    .gap_2()
                    .child(window_controls().at(point(px(16.), px(10.))))
                    .child(text(self.count.to_string()).text_size(px(48.)).tabular_nums())
                    .child(text("clicks").text_color(theme.text.secondary)),
            )
    }
}
```

<sub>From [examples/hello/src/lib.rs](https://github.com/FormalSnake/NativeDesktop/blob/main/examples/hello/src/lib.rs), line 4.</sub>


`Counter` is a plain struct. `impl Render` gives it one method, `render(&mut self, window, cx)`,
which returns `impl IntoElement`. `render` describes the window as it should look now; it does not
mutate anything on screen. Keep it cheap and free of side effects, because the framework calls it
whenever the view is notified.

`cx` is a `Context<Counter>`. It dereferences to `App`, so everything an `App` can do (open a
window, read the theme, set a global) works through it, and it adds what is specific to this
entity:

- `cx.notify()` marks this view dirty. The next frame re-renders it.
- `cx.listener(|this, event, window, cx| ..)` turns a closure over `&mut Counter` into the handler
  an element stores. The entity is updated when the event is delivered.
- `cx.observe(&other, |this, other, cx| ..)` runs when `other` notifies. See [state](https://nativedesktop.formalsnake.dev/concepts/state.md).
- `cx.weak_entity()` gives a handle that a callback can hold without keeping the view alive.

## Entities

`cx.new(|cx| value)` builds an `Entity<T>`, a shared handle to a `T` that the app owns. An entity is
read with `entity.read(cx)` and changed with `entity.update(cx, |value, cx| ..)`. An `update` leases
the value, so reading or updating the same entity from inside its own `update` panics. Views are
entities; so are models that hold data and have no `render`. A `WeakEntity` returns `None` from
`update` once the entity is gone, which is why callbacks use it.

```rust
pub fn app() -> Application {
    Application::new(nd::manifest!())
}

pub fn open(cx: &mut App) -> WindowHandle<Counter> {
    cx.open_window(WindowOptions::main("main").title("Hello"), |_window, cx| cx.new(|_cx| Counter { count: 0 }))
}
```

<sub>From [examples/hello/src/lib.rs](https://github.com/FormalSnake/NativeDesktop/blob/main/examples/hello/src/lib.rs), line 35.</sub>


`open_window` builds the root view with a closure and returns a `WindowHandle<Counter>`.
`handle.id()` is the window id; `handle.root()` is the root entity. An entity is not bound to a
window, so a view can move to another window and keep its state.

## Invalidation is per view

`cx.notify()` re-runs `render` of that one view. A child that is itself an `Entity` is a boundary:
parent and child render only when each is notified, so a keystroke in a text editor does not
re-render the list next to it. The cost of a change is the size of the dirty view, not the window.

After `render`, the framework compares the new element description with the retained tree and sends
the backend only what changed: create, insert, move, remove, update, and for retained backends a
frame. Event handlers sit on the retained node and are swapped without a backend call, so a new
closure on every render costs nothing. [Elements](https://nativedesktop.formalsnake.dev/concepts/elements.md) explains how a child is matched to
its previous self.

## The backend seam

The framework talks to a platform through one `Backend` trait. The AppKit backend, the GPUI
backend and the test backend implement it, and the app never sees which one it has.

- One transaction per window per frame: `begin`, the ops in a fixed order (creates, structure
  with parents first, updates, frames, focus, releases), then `commit`. On AppKit that is one
  `CATransaction` with implicit animations off.
- The backend holds one strong reference per node and drops it on `release`.
- Layout is Taffy everywhere. On AppKit the framework runs Taffy and pushes frames to the native
  views. On GPUI, Taffy runs inside GPUI's element tree.
- Everything happens on the main thread.

Native controls never call into your code while the framework is applying changes. AppKit fires
delegate methods inside setters and during layout, and an app entity can be mid-update at that
moment. A native control pushes its events onto a per-window queue instead, and the queue drains
after the transaction, outside every entity lease. This is why a handler can safely change any
entity.

## Tests use the same tree

`TestApp` is an `App` over a `TestBackend` that records the ops and exposes the semantic tree. The
test for the counter opens the real `hello::open` and clicks the button by id; see the
[hello tutorial](https://nativedesktop.formalsnake.dev/getting-started.md#the-hello-app) and the [testing page](https://nativedesktop.formalsnake.dev/tooling/testing.md).
