Skip to content

Grid, Flexbox, Block layout support for egui using taffy

License

Notifications You must be signed in to change notification settings

PPakalns/egui_taffy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

egui_taffy: Egui Taffy Ui

egui_version taffy_version Latest version Documentation unsafe forbidden License

Flexible egui layout library that supports CSS Block, Flexbox, Grid layouts. It uses high-performance taffy library under the hood.

Egui version compatibility

egui_taffy egui taffy
0.1 0.29 0.6

To use add egui_taffy to your project dependencies in Cargo.toml file.

Examples

Check out ./examples/demo.rs (cargo run --example demo).

Flex wrap demo example:

egui::Window::new("Flex wrap demo").show(ctx, |ui| {
    tui(ui, ui.id().with("demo"))
        .reserve_available_space() // Reserve full space of this window for layout
        .style(Style {
            flex_direction: taffy::FlexDirection::Column,
            align_items: Some(taffy::AlignItems::Stretch),
            ..default_style()
        })
        .show(|tui| {
            // Add egui ui as node
            tui.ui(|ui| {
                ui.label("Hello from egui ui!");
                ui.button("Egui button");
            });

            // Add egui widgets directly to UI that implements [`TuiWidget`] trait
            tui.ui_add(egui::Label::new("label"));
            tui.ui_add(egui::Button::new("button"));
            // Or use couple of supported helper function
            tui.separator();
            tui.label("Text");

            // You can add custom style or unique id to every element that is added to the ui
            // by calling id, style, mut_style methods on it first using builder pattern

            // Provide full style
            tui.style(Style {
                align_self: Some(taffy::AlignItems::Center),
                ..Default::default()
            })
            .label("Centered text");

            tui.style(default_style())
                .mut_style(|style| {
                    // Modify one field of the style
                    style.align_self = Some(taffy::AlignItems::End);
                })
                .label("Right aligned text");

            // You can add elements with custom background using add_with_ family of methods
            tui.add_with_border(|tui| {
                tui.label("Text with border");
            });

            tui.separator();

            tui.style(Style {
                flex_wrap: taffy::FlexWrap::Wrap,
                justify_items: Some(taffy::AlignItems::Stretch),
                ..default_style()
            })
            .add(|tui| {
                for word in FLEX_ITEMS {
                    tui.style(default_style()).add_with_border(|tui| {
                        tui.label(word);
                    });
                }
            });
        });
});

Preview:

flex_wrap_demo

Grid example

grid_demo

Flex example

flex_demo

Grow demo

grow_demo

Egui options

For best visual look you should enable egui multiple passes support so layout can be immediately recalculated upon some changes.

ctx.options_mut(|options| {
    options.max_passes = std::num::NonZeroUsize::new(2).unwrap();
});

If integrating with egui implementations such as bevy_egui, for egui multipass (request_discard) functionality to work you need to use special approach. See bevy_egui simple_multipass example for such case.

Inspiration

This crate is inspired by lucasmerlin previous exploration in this direction by such crates as:

It combines ideas from both crates and builds upon them to provide easy to use egui like API to write your UI with modern layout support.

It uses egui 0.29 new features intrinsic size and request_discard to request immediate frame redraw (without even drawing the current frame) if layout has changed.

Contributing

Contributions are welcome. Please add your improvements to examples so that it is easy to see and validate.