Crates.io | egui_flex |
lib.rs | egui_flex |
version | 0.1.1 |
source | src |
created_at | 2024-10-03 09:28:30.650237 |
updated_at | 2024-10-03 12:07:47.291035 |
description | A flexbox-like layout system for egui. |
homepage | https://lucasmerlin.github.io/hello_egui/#/example/flex |
repository | https://github.com/lucasmerlin/hello_egui/tree/main/crates/egui_flex |
max_upload_size | |
id | 1395026 |
size | 174,300 |
I was curious how much of flexbox I could implement in egui in a single-pass layout, by just remembering the sizes of widgets from the previous frame. Turns out it's quite a lot!
First of all, here is a good refresher of what all the different flex keywords mean.
flex-direction: row and column work as expected (I've named them horizontal and vertical to match egui's layout names)
flex-grow: you can give items a grow factor and they will grow to exactly fill the available space. An item with grow: 2 will grow twice as much as an item with grow: 1
align-items / align-self:
align-items-content / align-self-content: egui-specific property I added to help align an item's content if it
has grow > 0.0 || align_self == Stretch
nested flex containers work and will grow as expected as long as they don't wrap:
Every group in the screenshot represents a flex container or flex item so this shows flexes nested three levels deep.
You can't arbitrarily nest flexes in child ui's, you have to use a special method on the flex builder to add nested flexes, because it needs to communicate it's minimal size to the parent flex.
flex-wrap wrap and no-wrap works, wrap-reverse is not implemented
wrap
, items will fill the row and wrap once they reach Ui::available_width()Here's a demo showing how nice things flow into the next row when resizing the window:
https://github.com/user-attachments/assets/3f8d324e-7e51-4f4b-9415-f2d61e24d322
Finally, I wanted to share a real world example how flex can improve the ui by a lot. In the hello_egui demo app I have a list of crates displayed as small tags in the sidebar. When just shown with ui.horizontal_wrapped it looks really weird:
When updated to use egui_flex it looks much nicer:
Here is a simple example of how to use egui_flex:
use eframe::NativeOptions;
use egui::{Button, CentralPanel};
use egui_flex::{item, Flex, FlexAlignContent};
fn main() -> eframe::Result {
eframe::run_simple_native(file!(), NativeOptions::default(), |ctx, _frame| {
CentralPanel::default().show(ctx, |ui| {
Flex::horizontal().show(ui, |flex| {
flex.add(item().grow(1.0), Button::new("Growing button"));
flex.add(item(), Button::new("Non-growing button"));
// Nested flex
flex.add_flex(
item().grow(1.0),
// We need the FlexAlignContent::Stretch to make the buttons fill the space
Flex::vertical().align_content(FlexAlignContent::Stretch),
|flex| {
flex.add(item(), Button::new("Vertical button"));
flex.add(item(), Button::new("Another Vertical button"));
},
);
});
});
})
}