Skip to content

cyypherus/backer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Backer

rust crates.io downloads license

A library for straight-forward UI layout.

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).

Features ✨

  • 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.

Quick Start

1. Create a Layout struct with your layout function.

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!() }

2. Implement a draw node

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.
    })
}

3. Combine nodes to define & customize your layout

let mut layout = Layout::new(dynamic(|state| {
    row(vec![
        my_drawable(state),
    ])
}));

4. Draw your layout

// 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);

Preview

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.

stretched

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.)

Status

The crate is currently usable but new! Breaking changes may be relatively frequent as the crate matures.

Contributing

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 🤗

About

A library for straight-forward UI layout.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages