Pure Rust GUI Landscape
Published: 2022-11-24 23:12:02

Out of all programming languages, aside from javascript, Rust is currently seeing a flurry of crossplatform gui frameworks.
This is due to a combination of factors such as Rust's safety guarantees as well as its high performance.
In this article, we'll be looking at the most promising frameworks out there. Non-pure gui such libraries will not be discussed here.
The reason is that pure Rust guis are easier to build, since they don't require external C/C++ libraries. They are also safer by default given Rust's safety guarantees, and probably faster than frameworks written in other languages since Rust offers greater optimizability due to its guarantees.

## [Orbtk](https://github.com/redox-os/orbtk)
Orbtk started its development with the redox operating system, an operating system written entirely in Rust. It's based on an ECS (entity-component system) and provides a functional reactive api.
It has above 3k stars on Github.
A code sample:
```rust
use orbtk::prelude::*;

fn main() {
	  Application::new()
		.window(|ctx| {
			Window::new()
				.title("OrbTk - minimal example")
				.position((100.0, 100.0))
				.size(420.0, 730.0)
				.child(TextBlock::new().text("OrbTk").build(ctx))
				.build(ctx)
		})
		.run();
}
```

And an example of the look of the toolkit:
![image](https://user-images.githubusercontent.com/37966791/203868411-34e8acfd-0fe7-423f-8545-481dcc50c415.png)

## [slint](https://github.com/slint-ui/slint)
Allows developing fluid graphical user interfaces for any display, including embedded devices. It was started by 2 lead Qt developers. 
It has 5k stars on Github. It's charactarized by having its own markup language.
Example:
```
HelloWorld := Window {
    width: 400px;
    height: 400px;

    Text {
       y: parent.width / 2;
       x: parent.x + 200px;
       text: "Hello, world";
       color: blue;
    }
}
```
It aims to be as close as possible to native look and feel. 

![image](https://user-images.githubusercontent.com/37966791/203871644-604983d7-5b38-4225-8570-8a0776ae711c.png)

One downside of slint is its licensing model. It has a dual license, a permissive license for free open source projects, and a paid license for closed-source projects. The licensing fee is also quite steep last I checked

## [Dioxus](https://github.com/DioxusLabs/dioxus)
Dioxus is probably the only Rust gui framework which can target web, mobile and desktop platforms. It can also be used for terminal apps!
It has 5k stars on Github. 
The api is similar to React:
```rust
fn app(cx: Scope) -> Element {
    let mut count = use_state(&cx, || 0);

    cx.render(rsx! {
        h1 { "High-Five counter: {count}" }
        button { onclick: move |_| count += 1, "Up high!" }
        button { onclick: move |_| count -= 1, "Down low!" }
    })
}
```
Which should make it easy to onboard webdevelopers into Rust.

## [azul](https://github.com/fschutt/azul)
Azul is a free, functional, reactive GUI framework. It uses firefox's WebRender rendering engine, written in Rust, and thus html5 and javascript can be used for the frontend.
It also has 5k stars on Github. 

Example code:
```rust
use azul::prelude::*;
use azul::widgets::{button::Button, label::Label};

struct DataModel {
    counter: usize,
}

extern "C" 
fn render_dom(data: &mut RefAny, _: &mut LayoutInfo) -> StyledDom {

    let data = data.downcast_ref::<DataModel>()?;

    let label = Dom::text(format!("{}", data.counter))
        .with_inline_style("font-size: 50px;");
        
    let button = Button::new("Increment counter")
        .onmouseup(increment_counter, data.clone());

    Dom::body()
    .with_child(label)
    .with_child(button.dom())
    .style(Css::empty())
}

extern "C" 
fn increment_counter(data: &mut RefAny, _: &mut CallbackInfo) -> Update {
    let mut data = data.downcast_mut::<DataModel>()?;
    data.counter += 1;
    Update::RefreshDom // call render_dom() again
}

fn main() {
    let initial_data = RefAny::new(DataModel { counter: 0 });
    let app = App::new(initial_data, AppConfig::default());
    app.run(WindowCreateOptions::new(render_dom));
}
```

Example look:
![image](https://user-images.githubusercontent.com/37966791/203871032-d17defec-bd51-43ca-83f8-64aeaa3bafc9.png)

## [Druid](https://github.com/linebender/druid)
By world-renouned developer Raph levien, who's an authority on gui programming and creating gui frameworks. 
The project has 8k stars on Github. It's used by some high profile and highly successful applications (also by Raph) such as piet, xi-editor and lapce editor.
It's charactarized by being "data-first".
Example api:
```rust
use druid::widget::{Button, Flex, Label};
use druid::{AppLauncher, LocalizedString, PlatformError, Widget, WidgetExt, WindowDesc};

fn main() -> Result<(), PlatformError> {
    let main_window = WindowDesc::new(ui_builder());
    let data = 0_u32;
    AppLauncher::with_window(main_window)
        .log_to_console()
        .launch(data)
}

fn ui_builder() -> impl Widget<u32> {
    // The label text will be computed dynamically based on the current locale and count
    let text =
        LocalizedString::new("hello-counter").with_arg("count", |data: &u32, _env| (*data).into());
    let label = Label::new(text).padding(5.0).center();
    let button = Button::new("increment")
        .on_click(|_ctx, data, _env| *data += 1)
        .padding(5.0);

    Flex::column().with_child(label).with_child(button)
}
```

Example screenshots:
![image](https://user-images.githubusercontent.com/37966791/203869631-581c513a-2d55-4a1d-983f-fe618476d88a.png)

## [egui](https://github.com/emilk/egui)
Is an easy-to-use immediate mode GUI in Rust that runs on both web and native. It's light on resources and very high performance. Usually immediate-mode guis are used for games, however egui is a very viable option for general purpose gui.
It currently has 11k stars on Github.

Example code:
```rust
ui.heading("My egui Application");
ui.horizontal(|ui| {
    ui.label("Your name: ");
    ui.text_edit_singleline(&mut name);
});
ui.add(egui::Slider::new(&mut age, 0..=120).text("age"));
if ui.button("Click each year").clicked() {
    age += 1;
}
ui.label(format!("Hello '{}', age {}", name, age));
```

Example look:
![image](https://user-images.githubusercontent.com/37966791/203870411-4a622707-29d6-4187-acba-e1d64253fbcc.png)

However, to myself, the most impressive is egui's online [demo](https://www.egui.rs/#demo).

## [Iced](https://github.com/iced-rs/iced)
Is an elm-inspired framework. It currently has 17k stars on Github. It's a high performance gui which uses wgpu for rendering. wgpu also allows it to run in your browser.
Example api:
```rust
use iced::widget::{button, column, text, Column};

impl Counter {
    pub fn view(&self) -> Column<Message> {
        // We use a column: a simple vertical layout
        column![
            // The increment button. We tell it to produce an
            // `IncrementPressed` message when pressed
            button("+").on_press(Message::IncrementPressed),

            // We show the value of the counter here
            text(self.value).size(50),

            // The decrement button. We tell it to produce a
            // `DecrementPressed` message when pressed
            button("-").on_press(Message::DecrementPressed),
        ]
    }
}
```

Example look:
![image](https://user-images.githubusercontent.com/37966791/203869838-9eb7d973-3b70-424e-b44b-6e685283aa35.png)

This framework is probably the most mature and functional in the Rust ecosystem and is very actively developed, it's used in cryptowatch desktop:
![image](https://user-images.githubusercontent.com/37966791/203869938-0bda06f8-713c-4df7-a2da-d3ea8153cca2.png)

## [Tauri](https://github.com/tauri-apps/tauri)
Tauri is a better alternative to Electron, where the backend is written purely in Rust. For the frontend, html5 and javascript can be used.
It has a whopping 54k stars on github. It offers better performance than electron and a smaller binary size. There is also work on adding an iOS and android target, which electron doesn't support.

![image](https://user-images.githubusercontent.com/37966791/203871933-c93706b9-be1b-43be-8b9a-84e896a6e281.png)

Starting a Tauri project is also easier than the previously mentioned frameworks:
```
npm create tauri-app
```

The tauri cli tool also allows you to easily create installers for your binary.

## Conclusion
It seems all the stars aligned and currently point at Tauri. If you have a webdev background, it would be the perfect choice for getting started with gui programming in Rust.
That said, don't miss out on the other listed projects. Personally, I'm keeping an eye on Druid, which seems to be the most successful non-webtech project, that's also being developed by Mr Levien.
If however you're targetting a game engine, then your only option at the moment is egui.