Early days: oxframe is under very active development. The API is not stable yet and may change from version to version. Pin the exact version in your Cargo.toml and check the changelog before upgrading.

6. Groups and layout

Put shapes inside other shapes, and let a layout arrange them for you.

Loading live preview…

Source of learn_06_groups — edit in the playground
//! Lesson 6 — Groups and layout.
//!
//! Nodes can have children. Children move, rotate and fade with their parent,
//! and their positions are relative to it. A `Layout` places its children in
//! a row or a column for you.

use oxframe::prelude::*;

#[oxframe::scene]
pub async fn groups(view: View) {
    // A tiny solar system: the moon orbits the planet, the planet the sun.
    let sun = view.add(
        Group::new()
            .x(-350.0)
            .child(Circle::new().size(120.0).fill(color!("#f5c242"))),
    );
    let planet = sun.add(Group::new().x(220.0));
    planet.add(Circle::new().size(50.0).fill(color!("#68abdf")));
    planet.add(Circle::new().size(18.0).x(60.0).fill(Color::WHITE));

    // A row of cards laid out automatically.
    let row = view.add(
        Layout::new()
            .gap(16.0)
            .padding(16.0)
            .radius(16.0)
            .fill(color!("#26282e"))
            .position((380.0, 0.0)),
    );
    for c in ["#e13238", "#f5c242", "#68abdf"] {
        row.add(
            Rect::new()
                .size(70.0)
                .radius(10.0)
                .fill(Color::from_hex(c).unwrap()),
        );
    }

    all((
        sun.rotation().to(360.0, 3.0).ease(presets::LINEAR),
        planet.rotation().to(720.0, 3.0).ease(presets::LINEAR),
        // Growing the gap re-flows the row.
        row.gap().to(40.0, 1.5),
    ))
    .await;
}

// Try: add a fourth card with `.grow(1.0)` and give the row `.width(500.0)`.

pub fn project() -> Project {
    Project::new("groups").scene(groups())
}

Children

So far everything was added to the view. You can also add shapes to other shapes: sun.add(...). A child's position is measured from its parent, and it moves, rotates and fades along with it. Rotate the sun, and the planet orbits; rotate the planet, and its moon orbits the planet.

Group is a shape that draws nothing — a container for others.

Layout

Placing ten cards by hand is tedious. A Layout places its children in a row (or .column()), with .gap() between them and .padding() around. It works like flexbox on the web: children can .grow(1.0) to fill space, the row can .wrap(true), and .grid(3) makes a three-column grid.

Layout settings are animatable like everything else. Animate the gap and the cards slide apart; remove a card and the others close the gap.