[][src]Crate pixel_widgets

pixel-widgets is a user interface library focused on use for games. It's architecture is inspired by elm, since it's very fitting for rusts mutability patterns.

Features

  • Very compact and easy API
  • Render agnostic rendering
  • wgpu based renderer included
  • Styling using stylesheets
  • Built in widgets

Check out the examples to get started quickly.

Overview

User interfaces in pixel-widgets are all defined by implementing a Model, serving as the data model for your user interface. The model then has to implement some methods:

  • view - for generating a tree of ui widgets. These are retained for as long as the model is not mutated. Ui widgets generate messages when they are interacted with, which leads us to the next method:
  • update - modifies the model based on a message that was generated by the view

Other ways of updating the ui, such as futures and subscriptions will be be coming in the future.

Quick start

Setting up a ui with pixel-widgets is easy. You start with defining a model.

use pixel_widgets::prelude::*;

pub struct Counter {
    // a state manager, used for remembering the state of our buttons
    state: ManagedState<String>,
    // the counter value
    count: i32,
}

Then, we have to define a message type. The message type should be able to tell us what happend in the ui.

pub enum Message {
    UpClicked,
    DownClicked,
}

And finally, we must implement Model on our state

use pixel_widgets::prelude::*;

pub struct Counter {
    state: ManagedState<String>,
    count: i32,
}

pub enum Message {
    UpClicked,
    DownClicked,
}

impl Model for Counter {
    // define our message type
    type Message = Message;

    fn update(&mut self, message: Message) -> Vec<Command<Message>> {
        match message {
            Message::UpClicked => self.count += 1,
            Message::DownClicked => self.count -= 1,
        }
        Vec::new()
    }

    // Note that the view is allowed to keep mutable references to the model.
    // As soon as the model is accessed mutably, the `Ui` will destroy the existing view.
    fn view(&mut self) -> Node<Message> {
        let mut state = self.state.tracker();
        Column::new()
            .push(Button::new(state.get("up"), Text::new("Up"))
                .on_clicked(Message::UpClicked)
            )
            .push(Text::new(format!("Count: {}", self.count)))
            .push(Button::new(state.get("down"), Text::new("Down"))
                .on_clicked(Message::DownClicked)
            )
            .into_node()
    }
}

// Now that we have a model that can be used with pixel-widgets,
// we can pass it to the sandbox to quickly see some results!
#[tokio::main]
async fn main() {
    let model = Counter {
        state: ManagedState::default(),
        count: 0,
    };

    let window = winit::window::WindowBuilder::new()
        .with_title("Counter")
        .with_inner_size(winit::dpi::LogicalSize::new(240, 240));

   let loader = pixel_widgets::loader::FsLoader::new("./examples".into()).unwrap();

    let mut sandbox = Sandbox::new(model, loader, window).await;
    sandbox.ui.set_stylesheet("counter.pwss").await.unwrap();
    sandbox.run().await;
}

Modules

backend

Backend specific code

cache

Texture cache for styles and text

draw

Primitives used for drawing

event

User input events

graphics

Graphics loader

layout

Primitives used for layouts

loader

Asynchronous resource loading

prelude

prelude module for convenience

sandbox

Simple windowing system for those who want to render just widgets.

stylesheet

Styling system

text

Primitives for rendering text

tracker

Utility for tracking state conveniently.

widget

User interface widgets

Structs

Ui

Entry point for pixel-widgets.

Enums

Command

Some asynchronous work that will update the ui later.

Traits

EventLoop

Trait for sending custom events to the event loop of the application

Model

A model that keeps track of the state of your GUI. Serves to control the behaviour and DOM of your GUI. Styling is handled separately. Once you implemented a model, you can run your GUI using a Ui.