buoyant 0.7.0

SwiftUI-like UIs in Rust for embedded devices
Documentation
# App

`App` is initialized with an initial state, display size, and a view function. The view
function takes a reference to your state and returns a view:

```rust
# extern crate buoyant;
# extern crate embedded_graphics;
use buoyant::app::App;
# use buoyant::view::prelude::*;
# use buoyant::primitives::Size;
# use embedded_graphics::pixelcolor::Rgb888;

#[derive(Clone, Default)]
struct State {
    count: i32,
}
#
# fn counter_view(state: &State) -> impl View<Rgb888, State> + use<> {
#     let count = state.count;
#     Button::new(
#         |state: &mut State| state.count += 1,
#         move |_| EmptyView,
#     )
# }
#

let mut app = App::new(State::default(), Size::new(200, 100), counter_view);

```

```rust,ignore
{{#include event-loops.rs:view}}
```

## Handling Events

The `Harness` trait, implemented by `App`, provides `Harness::send()`, which can be used
to send events to the app. In addition to `send()`, a number of convenience methods are
provided for constructing common events.

Here, events generated by the `embedded-graphics-simulator` window are mapped into Buoyant
events using a `MouseTracker`, then sent to the app with `App::send()`:

```rust,ignore
    loop {
{{#include event-loops.rs:handle_events}}

        // rendering...
    }
```

## Rendering

To determine whether rendering a new frame is necessary, two fields should be checked:

- `App::should_redraw()`: This flag is set when the state changes or a view modifies the
  render tree during event handling, such as on a `ScrollView` drag.

- `RenderTarget::clear_animation_status()`:
  Render tree nodes, such as animations, set a flag on the render target when they're drawn
  and animation is in progress. This flag is initially set to `true`.

```rust,ignore
    loop {
        // event handling...

{{#include event-loops.rs:render_idle}}
    }
```

## Mutating State Outside the View

Generally, state changed as a direct result of user input (e.g. button taps) will
cause the view to be rebuilt automatically. To access the state outside the view,
you can use `App::state_mut()` which returns a (wrapped) mutable reference to the app state.
Mutably dereferencing this object will automatically trigger a view rebuild with the
updated state. This is a handy convenience to prevent missing an update, but be aware
of the potential to accidentally trigger rebuilds when no state actually changed.

```rust
# extern crate buoyant;
# extern crate embedded_graphics;
# use buoyant::app::App;
# use buoyant::view::prelude::*;
# use buoyant::primitives::Size;
# use embedded_graphics::pixelcolor::Rgb888;
#
# #[derive(Clone, Default)]
# struct State { count: i32 }
#
# fn counter_view(state: &State) -> impl View<Rgb888, State> + use<> {
#     Button::new(
#         |state: &mut State| state.count += 1,
#         move |_| EmptyView,
#     )
# }
#
# let mut app = App::new(State::default(), Size::new(200, 100), counter_view);
#
// The state can be read and a mutable reference obtained
// without triggering a rebuild:

let count = app.state().count;
let mut s = app.state_mut();

// Mutably dereferencing triggers a view rebuild:

s.count = 42;
```

Render trees are rebuilt lazily upon calling `App::render_animated()` or `App::finalize_view()`
if the state may have changed.

> `App::force_rebuild()` can be used to force the
> view to rebuild if the state has changed without Buoyant's knowledge, like through
> interior mutability.

## Complete Example

```rust,no_run
# extern crate buoyant;
# extern crate embedded_graphics;
# extern crate embedded_graphics_simulator;
{{#include event-loops.rs:all}}
```