WARNING: Cushy is in early alpha. This guide doubly so.

Welcome to the Cushy User's Guide

This is a user's guide for Cushy, a Rust GUI crate. The documentation is a great resource for finding information about specific functionality quickly. This guide is aimed to providing an example-rich walkthrough of how to use and extend Cushy.

A "Hello, World" Example

Here's the simplest "Hello, World" example:

use cushy::Run;

fn main() -> cushy::Result {
    "Hello, World!".run()
}

When run, the app just displays the text as one would hope:

Hello World Example

That was a little too easy. Let's take it a step further by letting a user type in their name and have a label display "Hello, {name}!":

use cushy::value::{Dynamic, Source};
use cushy::widget::MakeWidget;
use cushy::widgets::input::{Input, InputValue};
use cushy::Run;

fn main() -> cushy::Result {
    // Create storage for user to enter a name.
    let name: Dynamic<String> = Dynamic::default();

    // Create our label by using `map_each` to format the name, first checking
    // if it is empty.
    let greeting: Dynamic<String> = name.map_each(|name| {
        let name = if name.is_empty() { "World" } else { name };
        format!("Hello, {name}!")
    });

    // Create the input widget with a placeholder.
    let name_input: Input = name.into_input().placeholder("Name");

    // Stack our widgets as rows, and run the app.
    name_input.and(greeting).into_rows().run()
}

This app looks like this when executed:

Hello Ferris Example

In this example, both name and greeting are Dynamic<String>s. A Dynamic<T> is an Arc<Mutex<T>>-like type that is able to invoke a set of callbacks when its contents is changed. This simple feature is the core of Cushy's reactive data model.

Each time name is changed, the map_each closure will be executed and greeting will be updated with the result. Now that we have the individual pieces of data our user interface is going to work with, we can start assembling the interface.

First, we create name_input by converting the Dynamic<String> into a text input widget (Input<String>). Since Dynamic<String> can be used as a Label, all that's left is laying out our two widgets.

To layout name_input and greeting, we use a Stack to lay out the widgets as rows.

Don't worry if this example seems a bit magical or confusing as to how it works. Cushy can feel magical to use. But, it should never be a mystery. The goal of this guide is to try and explain how and why Cushy works the way it does.