August 19, 2021 by Olivier Goffart and Simon Hausmann

Announcing SixtyFPS 0.1Blog RSS

We're proud to announce the SixtyFPS 0.1 series. The 0.1 series, to us, signifies that our toolkit is graduating from "lab mode" to "development mode". We are now confident that our toolkit can be used in products. Based on semantic versioning principles, all 0.1.x releases will maintain compatibility.


The 0.1 Series

We've implemented plenty of new features and fixed many bugs. Thank you to all the early adopters who provided high-quality bug reports and feedback. We also reached 1000 stars on GitHub 🤩.

What's SixtyFPS

SixtyFPS is a fresh, new graphical toolkit for desktop apps and embedded devices.

We're building a product to make UI development faster and easier, no matter what programming language, platform, or form-factor. Our toolkit consists of the following key components:

  • A design-friendly markup language for UI elements
  • A run-time library with APIs in C++, Rust and JavaScript
  • An optimizing compiler to compile designs to native C++/Rust code

SixtyFPS is actively developed on GitHub. We provide three options for licensing:

Highlights

We last caught up with you on the 0.0.6 release. Here are the highlights between then and the just released v0.1.1; full details available in our change log.

A new style

We've written a new, beautiful widget style that implements Microsoft's fluent design. This replaces our previous attempt at a distinct style, jokingly called the "ugly" style.

SixtyFPS can also style widgets according to the platform's native look, if you have Qt installed.

These screenshots also show the new TabWidget.

New API for custom rendering

When working with images, the Image element's source specifies where it's stored. When this property is exposed to Rust or C++, the type is sixtyfps::Image. You can create sixtyfps::Image from a file system path or from a pixel buffer. Use this API to create images dynamically at run-time with Rust code or integrate other crates that produce graphics into your SixtyFPS UI. Our new plotter example demonstrates this use-case with the plotters crate:

SixtyFPS plotter example

Various improvements to the .60 markup language

Our markup language is used by designers and developers, and it's intuitive and type-safe. We observed that when declaring two-way bindings to forward a property, it can be cumbersome to repeat the property type. Now, we've gotten rid of this requirement - you can declare two-way bindings for properties and callbacks using a shorter syntax:

export Application := Window {
    property action <=> button.text;
    callback triggered <=> button.clicked;
    button := Button { }
}
Layout improvements

For consistency across all items, layout elements now have their own x and y properties. We've changed the default spacing and padding to be zero. The style-provided counterparts HorizontalBox, VerticalBox, and GridBox come with defaults that give a natural spacing and padding between widgets.

The layout constraints of elements, such as their minimum or maximum size, are now consistently propagated throughout the hierarchy of elements. This includes support for "height-for-width" for Text and Image elements.

To set the preferred size when a Window is first shown, use the preferred-width and preferred-height properties. Setting the width and height properties locks the window's size; free resizing by the user is then disabled.

Threading support improvements

To keep the application GUI fluid, it's important to perform long lasting operations in a different thread and not block the GUI thread. For platform specific reasons, the SixtyFPS UI must "live" in the main thread, other threads need to synchronize or communicate with it. In SixtyFPS version 0.1, we added helper functions in the Rust and C++ API to help to communicate between worker threads and the UI thread. Here's how to use them in Rust:

// Create a handle to `MyWindow`, the type generated by the `sixtyfps!` macro
let window_handle = MyWindow::new();
// ... set properties and callbacks on window_handle ...

// pass a weak handle to the window to a worker thread
let handle_weak = window_handle.as_weak();
let thread = std::thread::spawn(move || {
    // ... Do some computation in the thread ...
    let result = { /* ... */ };

    // now forward the data to the main thread using sixtyfps::weak::upgrade_in_event_loop
    handle_weak.upgrade_in_event_loop(move |handle| {
      // this code here is run in the main UI thread
      handle.set_status_text(result);
    });
});

// run the event loop in the UI thread
handle.run();
// Create a handle to `MyWindow`, the type
// generated by the `sixtyfps!` macro
let window_handle = MyWindow::new();
// ...
// set properties and callbacks on
// window_handle ...

// pass a weak handle to the window to a
// worker thread
let handle_weak = window_handle.as_weak();
let thread = std::thread::spawn(move || {
  // ... Do some computation in the
  // thread ...
  let result = { /* ... */ };

  // now forward the data to the main
  // thread using
  // sixtyfps::weak::upgrade_in_event_loop
  handle_weak.upgrade_in_event_loop(
    move |handle| {
      // this code here is run in the main
      // UI thread
      handle.set_status_text(result);
    });
});

// run the event loop in the UI thread
handle.run();

For more details, check out the documentation for Rust and for C++. For real threaded application code, check out Cargo-UI.

What’s next?

SixtyFPS is already happily used by customers on embedded devices. We plan on building up the Desktop support in subsequent releases to reach the level of integration we're aiming for.

Rust

If you're using Rust, then you can use our crate directly by editing Cargo.toml.

Rust Crate crates.io badge
C++

For use with C++ we provide a CMake integration that takes care of the installation.

C++/CMake Install Docs
Visual Studio Code

Install for VS Code that provides syntax highlighting, a live preview and more.

Install Extension
Video Tutorial

If you'd like to learn SixtyFPS by watching a video, check out our tutorial on YouTube.

Watch 🎥

We hope you'll enjoy developing with SixtyFPS and we look forward to your feedback. You can post a message in our GitHub Discussions Forum or chat with us on our Mattermost instance. For fresh news follow us on Twitter: @sixtyfpsui.


Comments

Slint is a Rust-based toolkit for creating reactive and fluent user interfaces across a range of targets, from embedded devices with limited resources to powerful mobile devices and desktop machines. Supporting Android, Windows, Mac, Linux, and bare-metal systems, Slint features an easy-to-learn domain-specific language (DSL) that compiles into native code, optimizing for the target device's capabilities. It facilitates collaboration between designers and developers on shared projects and supports business logic development in Rust, C++, JavaScript, or Python.