# Untitled Embedded Rust GUI

## What is This?
This is a new GUI library for no_std embedded Rust. I currently have it running on
the ESP32-S3 based [Lilygo T-Deck](https://github.com/Xinyuan-LilyGO/T-Deck/tree/master), but it should run on anything
that
uses the [embedded_graphics traits](https://docs.rs/embedded-graphics/latest/embedded_graphics/).
It focuses on bandwidth limited devices, such as SPI displays.
## Features
* Incremental redrawing using layout and dirty rect tracking.
* Built in components for buttons, labels, text input, toggles, and panels.
* Theming with colors and fonts
* Scene to manage a tree of View structs
* Fast single pass layout algorithm
## Anti-Features
* **event loop:** To make it flexible, the lib **does not** impose its own event loop. Instead, the application
should send events to the scene and then redraw in its own loop. **Better documentation coming**.
* **animation:** The library has no support for animation or transparency because those will perform horribly on
bandwidth
limited SPI displays.
## Usage
Build the library with `cargo build`.
Run the simulator example with `cargo run --example simulator --features std`. Note that
the simulator needs
SDL2. [Install instructions](https://docs.rs/embedded-graphics-simulator/latest/embedded_graphics_simulator/).
Run the unit tests with `cargo test --features std`.
The library has not yet been released as a published crate because I still need
a name and need to fix some bugs.
## Views
`View`s are rendered using a `Theme` which can be customized for different
colors and font sizes. Views carry their own internal state using an
optional `state` struct. Application state should remain outside the scene/view structure
and be handled by processing actions emitted from the scene when events happen.
Instead of implementing a trait you create components by
allocating a `View` is with optional fields for functions to handle
input, state, layout, and drawing. This is the code that creates a button (as implemented in the
library provided `make_button`):
```rust
pub fn make_button(name: &ViewId, title: &str) -> View {
View {
name: name.clone(),
title: title.to_string(),
// the button will determine its own width
h_flex: Intrinsic,
// the button will determine its own height
v_flex: Intrinsic,
// on tap, requested to be focused
input: Some(|e| {
if let EventType::Tap(_pt) = &e.event_type {
e.scene.set_focused(e.target);
return Some(Action::Generic);
}
None
}),
// size self based on the font and the title text
layout: Some(|e| {
if let Some(view) = e.scene.get_view_mut(&e.target) {
view.bounds.size = util::calc_size(e.theme.bold_font, &view.title);
}
}),
// delegate drawing to a draw_button function
draw: Some(draw_button),
..Default::default()
}
}
fn draw_button(e: &mut DrawEvent) {
e.ctx.fill_rect(&e.view.bounds, &e.theme.bg);
e.ctx.stroke_rect(&e.view.bounds, &e.theme.fg);
if let Some(focused) = e.focused {
if focused == &e.view.name {
e.ctx.stroke_rect(&e.view.bounds.contract(2), &e.theme.fg);
}
}
draw_centered_text(
e.ctx,
&e.view.title,
&e.view.bounds,
&e.theme.bold_font,
&e.theme.fg,
);
}
```
## Themes
`Theme` is a struct passed to every View's `draw` function. It stores the standard colors and fonts for drawing.
However, these are just guidelines. A view can feel free to ignore them and draw whatever it wants.
The theme fields should be used for:
* **bg**: the background of components like buttons and text inputs.
* **fg**: the foreground of components, which usually means the text color.
* **panel_bg**: the background of panels and other containers. Depending on the theme this may or may not be the same as
*bg*.
* **font**: the default font used for all text.
* **bold_font**: the bold variant of the current font. Used for button titles.
* **selected_bg**: a background color used to indicate something is selected.
* **selected_fg**: a text color used to indicate something is selected. Usually used with `selected_bg`.
## Roadmap
### 0.1
- [x] Remove generics for color and font. Just use embedded graphics directly.
- [x] use simulator for interactive tests
- [x] use MockDisplay for automated tests
- [x] support layout using font size. needs padding in the widgets.
- [x] add hbox and vbox layouts
- [x] make children drawn and picked relative to the parent.
- [x] general
- [x] setup CI on github actions.
- [x] more components
- [x] add menu view
- [x] add list view
- [x] drawing
- [x] redo fill_text api.
- [x] just text. support bg color?
- [x] proper alignment. provide center point and draw centered
- [x] draw line
- [x] remove clear
- [x] consolidate Display impls
- [x] layout & rendering
- [x] calculating dirty rect needs to be converted back to global
- [x] common view padding
- [x] new layout algoritm
- [x] form layout -> grid layout
- [x] debug lines
- [x] alignment within grid cells
- [x] span grid cells
- [ ] pick final name
### 0.2
- [ ] input improvements
- [ ] cleanup event types and action command signatures.
- [ ] document how to make your own event & draw loop
- [ ] text input
- [ ] move cursor within text
- [ ] forward and backward delete
- [ ] selection?
- [ ] focus management
- [ ] use scroll events to jump between focused elements and perform selection.
- [ ] spec out how focus management works.
- [ ] focus groups
- [ ] improved custom view support
- [ ] view can define the children it uses
- [ ] let tab panel define its own children using a toggle group
- [ ] let tab panel switch its own tabs instead of using external handle action
- [ ] theme accent colors?