Dependency free & framework-agnostic. Backer can be used in an index-based layout approach or with inline drawing code.
This library only implements layout & would be most useful along with a GUI library that can do GUI things (like macroquad or egui).
- Declarative API: The code should look like the structure it defines
- Minimal interface: No confusing overloads or magic, cascading effects
- Intuitive constraints: Backer adheres to & smoothly resolves size constraints with an advanced algorithm
- Performant: Layout can be comfortably recalculated every frame
- Easy integration & compatibility: Backer should work with just about any UI library with a bit of glue - so it isn't really fine-tuned for any specific UI solution.
This project intends to be a flexible layout tool & not much else.
use backer::layout::Layout;
use backer::layout::Node;
let layout = Layout::new(my_layout_fn);
fn my_layout_fn(state: &mut MyState) -> Node<MyState> { todo!() }
For reuse, you can construct your drawable in a function
fn my_drawable<'a>(state: &'_ mut MyState) -> Node<'a, MyState> {
draw(move |area: Area, state: &mut MyState| {
// The `area` parameter is the space alotted for your view after layout is calculated
// The `state` parameter is *your* mutable state that you pass when you call layout.
// This closure should draw UI based on the alotted area or update state so that drawing can be performed later.
})
}
let mut layout = Layout::new(dynamic(|state| {
row(vec![
my_drawable(state),
])
}));
// UI libraries generally will expose methods to get the available screen size
// In a real implementation this should use the real screen size!
let available_area = Area {
x: todo!(),
y: todo!(),
width: todo!(),
height: todo!(),
};
let mut my_state = MyState;
// Perform layout & draw all of your drawable nodes.
layout.draw(available_area, &mut my_state);
Check out the demo site: a mock page showcasing layout capabilities in a realistic interface. Built with egui!
Backer relies on simple rules that can compose to create complex, flexible layouts.
See some code
column_spaced(
10.,
vec![
draw_a(ui),
row_spaced(
10.,
vec![
draw_b(ui).width(180.).align(Align::Leading),
column_spaced(10., vec![draw_a(ui), draw_b(ui), draw_c(ui)]),
],
),
draw_c(ui),
],
)
.pad(10.)
The crate is currently usable but new! Breaking changes may be relatively frequent as the crate matures.
Note
This repo uses cargo insta
to snapshot test the public API.
If your PR changes the public API, one of the checks will fail by default.
If the changes to the public API were intentional you can update the snapshot by running:
INSTA_UPDATE=always && cargo test --features test-api
Contributions are always welcome 🤗