Skip to content

audulus/rui

main
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

* add a horizontal list

* rm my duplicate fn

I should read code every once in a while

* layout from left to right

* order orientations
15273d1

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
Aug 18, 2022
Feb 26, 2022
Mar 1, 2022

logo

rui

build status

Experimental Rust UI library, inspired by SwiftUI. Early days, but some stuff already works. rui will be used for a future version of Audulus

rui is immediate mode (there is no retained tree of views), GPU rendered, updates reactively (when your state changes), and has richer layout options than other immediate mode UIs.

discord server

Examples

obligatory Counter (cargo run --example counter):

use rui::*;

fn main() {
    rui(state(
        || 1,
        |count, cx| {
            vstack((
                cx[count].padding(Auto),
                button("increment", move |cx| {
                    cx[count] += 1;
                })
                .padding(Auto),
            ))
        },
    ));
}

counter screenshot

some shapes (cargo run --example shapes):

use rui::*;

fn main() {
    rui(vstack((
        circle()
            .color(RED_HIGHLIGHT)
            .padding(Auto),
        rectangle()
            .corner_radius(5.0)
            .color(AZURE_HIGHLIGHT)
            .padding(Auto)
    )));
}

shapes screenshot

canvas for gpu drawing (cargo run --example canvas):

use rui::*;

fn main() {
    rui(canvas(|_, rect, vger| {
        vger.translate(rect.center() - LocalPoint::zero());

        let paint = vger.linear_gradient(
            [-100.0, -100.0],
            [100.0, 100.0],
            AZURE_HIGHLIGHT,
            RED_HIGHLIGHT,
            0.0,
        );

        let radius = 100.0;
        vger.fill_circle(LocalPoint::zero(), radius, paint);
    }));
}

canvas screenshot

slider with map (cargo run --example slider):

use rui::*;

#[derive(Default)]
struct MyState {
    value: f32,
}

/// A slider with a value.
fn my_slider(s: impl Binding<f32>) -> impl View {
    with_ref(s, move |v| {
        vstack((
            v.to_string().font_size(10).padding(Auto),
            hslider(s).thumb_color(RED_HIGHLIGHT).padding(Auto),
        ))
    })
}

fn main() {
    rui(state(MyState::default, |state, cx| 
        map(
            cx[state].value,
            move |v, cx| cx[state].value = v,
            |s, _| my_slider(s),
        ),
    ));
}

slider screenshot

widget gallery (cargo run --example gallery):

widgets gallery screenshot

Goals

  • Encode UI in types to ensure stable identity.
  • Optimize to reduce redraw.
  • Use vger-rs for rendering.
  • Minimal boilerplate.
  • Good looking.
  • No unsafe.
  • Accessibility for assistive technologies.

Optional Features

  • winit - (enabled by default) use winit for windowing.
  • tao - use tao for windowing.
  • Use default-features = false if you are embedding rui (see https://github.com/audulus/rui-ios).

Why?

In the long term, I'd like to move Audulus over to Rust. After looking at other available UI options, it seemed best to implement something resembling the existing immediate mode UI system I already have working in Audulus, but better.

Status

  • basic shapes: circle, rounded rectangle
  • basic gestures: tap, drag
  • hstack/vstack
  • text
  • padding
  • offsets
  • state
  • zstack
  • canvas (GPU vector graphics with vger)
  • bindings
  • list
  • sliders
  • knobs
  • editable text (still a bit rough)
  • any_view (view type erasure)
  • layout feedback
  • animation

References

Towards principled reactive UI

Towards a unified theory of reactive UI

Flutter's Rendering Pipeline

Static Types in SwiftUI

How Layout Works in SwiftUI

Xilem: an architecture for UI in Rust