faststep 0.1.0

UIKit-inspired embedded UI framework built on embedded-graphics
Documentation
# Developer Guide

## Goal

`faststep` should behave more like a small UIKit-style framework than a loose widget bundle.

The intended authoring flow is:

1. Keep `main` thin.
2. Provide a root view implementation.
3. Let an OEM adapter construct the board/display/touch side.
4. Start the app with `run_ui_system(...)`.
5. Let the root view configure its children and metadata.
6. Use container views for stack/tab/split/alert behavior.
7. Let controls own their own interaction state.
8. Build scrolling surfaces from `ScrollView`.
9. Use datasource/delegate protocols for data-driven views such as lists.

## Entry Point

The framework entry points are `UiSystem` and `run_ui_system(...)`.

`UiSystem` owns:

- the OEM display port
- the root view instance
- theme and i18n
- the root `ViewRegistration`

`FsTheme` is the global semantic palette for the system. Configure it once at startup and let views consume semantic colors such as:

- neutral surfaces
- primary/accent
- warning
- danger
- text-on-accent
- text-on-danger

`run_ui_system(...)` owns:

- the update/touch/present loop
- tick pacing
- feeding touch into the root view
- calling the OEM presenter when a redraw is pending

The intended startup shape is:

```rust
run_ui_system(display, RootView::new(), theme, i18n, driver, presenter)?;
```

That keeps hardware setup in the OEM adapter and keeps the runtime loop inside `faststep`.

## View Contract

`UiView<'text, ViewId, Message, N>` is the core view trait.

Every view can:

- `configure(...)`: declare title, alpha, hidden state, clipping, and child views
- `update(...)`: produce redraw/message output during tick
- `handle_touch(...)`: react to input and emit messages/redraws
- `draw(...)`: render itself using `embedded-graphics`

`ViewRegistration` is the setup/configuration object passed into `configure(...)`.

Useful registration methods:

- `set_title(...)`
- `set_alpha(...)`
- `set_hidden(...)`
- `set_clips_to_bounds(...)`
- `set_user_interaction_enabled(...)`
- `add_child(...)`

Child views are declared with `ChildView`, which carries:

- a child id
- a `ViewKind`
- a frame
- view properties

This is how a root view states what it contains.

## View Metadata

`ViewProperties` carries UIKit-like view attributes:

- `title`
- `alpha`
- `hidden`
- `clips_to_bounds`
- `user_interaction_enabled`

Those properties are part of the framework contract, not ad hoc app state.

## OEM Abstraction

The framework does not hardcode ESP-IDF display plumbing.

The OEM-facing traits are:

- `DisplayPort`
- `UiRuntimeDriver`
- `UiRuntimePresenter`

This is the seam for turning `faststep` into an OEM-ready solution instead of coupling it to one board implementation.

An OEM project should not need to rewrite the framework to fit a new panel, touch controller, or a future simulator backend. The hardware boundary stays trait-based, and the runtime loop stays in `faststep` rather than in the final app binary.

### Display

Implement `DisplayPort` for the target display backend.

Required pieces:

- `bounds() -> Rectangle`
- `draw_frame(...)`

Optional optimization:

- override `draw_dirty(...)` if the backend supports partial redraw efficiently

This is the place to connect:

- framebuffer ownership
- DMA / flush
- dirty-rect presentation
- double buffering

### Runtime Driver

Implement `UiRuntimeDriver` for the board or simulator runtime side.

This trait owns:

- touch polling in terms of `TouchEvent`
- poll cadence decisions
- sleep or delay
- clock reads

That keeps gesture, list, and container code portable across devices while moving the event loop out of `main`.

### Presenter

Implement `UiRuntimePresenter` for the panel or backend-specific presentation policy.

This is where redraw scheduling belongs:

- full redraw vs dirty redraw
- motion frame throttling
- platform-specific partial-present optimizations
- tracking previous dirty geometry when required

### Expected Main Layout

Typical `main` structure should now be:

1. initialize system patches or logging
2. hand off to an OEM adapter
3. let that adapter call `faststep::run_ui_system(...)`

The important boundary is:

- the board or simulator crate owns hardware construction and backend-specific adapters
- `faststep` owns the UI contracts and the runtime loop
- the app or root view owns only UI structure and behavior

## Container Views

The first foundation layer includes thin container/state wrappers:

- `StackView`
- `TabView`
- `SplitView`
- `AlertHost`

These are not yet a full retained view tree, but they establish the correct direction:

- stack mechanics belong to a stack container
- tab organization belongs to a tab container
- split-pane layout belongs to a split container
- alert presentation belongs to an alert host

## Controls

Leaf controls should keep their own interaction state inside `faststep`.

For example:

- `Button` owns pressed/highlighted/captured touch state
- `ImageView` owns image frame/alignment/inset presentation instead of making each screen hand-place raw images
- `TextView` and `RichTextView` own mono-font layout for single-line and multiline text blocks
- app/root code should keep button actions and layout, not a parallel `ButtonTouchState`
- this keeps application views closer to UIKit view-controller structure instead of pushing control bookkeeping upward

## Lists

`ScrollView` is the base scrolling primitive.

It owns:

- inertial scrolling
- overscroll/snap-back behavior
- transient vertical scroll indicator state

The indicator should behave like a mobile scroll surface:

- stay hidden on touch-down
- reveal only after drag slop is crossed and content is actually moving
- stay visible during drag/fling/snap-back
- fade after motion ends

`ListView` builds on `ScrollView` and adds separate roles:

- `ListDataSource`: count, item id, item size
- `ListDelegate`: row drawing plus highlight/select callbacks

Rows are described with `ListRow` and `ListRowState`.

That means a row renderer can change appearance when:

- the row is highlighted
- the row is selected

This is the current bridge toward UIKit-like reusable row/cell behavior.

That means the list itself owns scrolling and selection mechanics, while application code owns data and row appearance/selection responses.

This is the shape new screens should follow.

## Examples

The crate ships with compile-checked examples for each major API family:

- `examples/buttons.rs`
- `examples/text_and_image.rs`
- `examples/scroll_and_list.rs`
- `examples/containers.rs`
- `examples/alerts.rs`
- `examples/runtime_shell.rs`
- `examples/uikit_root.rs`
- `examples/root_delegate.rs`

These examples are packaged with the crate and are intended to show up cleanly on docs.rs.

## Redraw Model

The new foundation uses `ViewRedraw`:

- `None`
- `Dirty(Rectangle)`
- `Full`

`ViewEvent<Message>` carries:

- redraw request
- capture state
- optional message

This keeps view behavior explicit and testable.

## Compatibility Layer

`UiApp` still exists because current projects use it, but it should be treated as transitional.

Use `UiApp` only when maintaining existing demos.
Use `UiSystem` + `UiView` + container/data-source APIs for new work.