Expand description
§1. Hello, window
Create a binary crate, open its first window, and render a title. This shell stays intact as later chapters add state, input, layout, and tests.
§Create the project
Make a new binary crate and add GPUI to it:
cargo new todos
cd todos[dependencies]
gpui = { package = "gpui-ce", version = "0.2" }
gpui_platform = { package = "gpui_ce_platform", version = "0.1" }gpui contains the application, window, element, and styling APIs.
gpui_platform supplies the platform runner for macOS, Windows, Linux, and the
web. Cargo uses the package name gpui-ce; Rust imports it as gpui.
§Write the app
Replace src/main.rs with this:
use gpui::{App, Context, QuitMode, Window, WindowOptions, colors::Colors, div, prelude::*};
struct Todos;
impl Render for Todos {
fn render(&mut self, window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
let colors = Colors::for_appearance(window);
div()
.size_full()
.p_8()
.bg(colors.background)
.text_color(colors.text)
.text_3xl()
.child("Todos")
}
}
fn main() {
gpui_platform::application()
.with_quit_mode(QuitMode::LastWindowClosed)
.run(|cx: &mut App| {
cx.open_window(WindowOptions::default(), |_window, cx| {
cx.new(|_cx| Todos)
})
.unwrap();
cx.activate(true);
});
}Run it with cargo run. The window shows “Todos” in large type. Closing the
last window ends the process because this example selects
QuitMode::LastWindowClosed.
§What the code does
main starts the application. gpui_platform::application() creates an
Application for the platform you built for, and run
starts its event loop. The closure runs once the platform is ready, and receives
an App: the object that owns everything in your program. run doesn’t
return until the program quits. QuitMode::LastWindowClosed makes it quit
when its last window closes, which is how most apps behave on Windows and
Linux; on macOS, apps normally keep running until you quit them.
open_window creates a window. It takes WindowOptions, which control
the window’s size, title bar and more, and a closure that builds the window’s
root view. activate brings the app to the front.
A view is a struct that can render. Todos implements Render. GPUI
calls its render method whenever the window needs to be drawn, and render
returns a tree of elements describing what to show. Here the tree is a single
div containing some text.
cx.new hands the view to GPUI. The app owns your views and the rest of your
state. cx.new(|_cx| Todos) gives the app a Todos and returns an
Entity<Todos>, a handle you use to reach it. The ownership and data
flow concept page explains why
GPUI keeps views behind entities.
§Styling elements
Each method called on div() sets one style property:
size_fullmakes the element fill its parent, here the whole window.p_8adds padding. The numbers follow the scale from Tailwind CSS, where each step is a quarter of a rem, the window’s base font size of 16 pixels. Sop_8is two rems, or 32 pixels.bgandtext_colorset the background and text colors. Text properties apply to all the text inside an element, including its children’s.text_3xlsets a large font size.
Colors::for_appearance selects a small
palette for the window’s light or dark appearance. Passing those colors through
the element tree keeps this first example readable; later chapters use the same
palette for rows and controls.
These methods come from the Styled trait, imported through
gpui::prelude::*. The layout and style
concept page explains how those properties become layout and paint.
In the next chapter you give the view some todos, and make them respond to clicks.