Skip to main content

gpui_authoring/
_authoring.rs

1//! # Authoring GPUI
2//!
3//! UI is written at one of two levels: composing the built-in elements into
4//! components, or writing a custom element when nothing built in emits what you
5//! need. Both levels are public, so code written against them today should keep
6//! compiling across minor releases.
7//!
8//! ## Composing components
9//!
10//! Most UI is built from [`div()`](crate::div) and the other element
11//! constructors, refined with style and interaction builders:
12//!
13//! - [`Styled`](crate::Styled) for layout and appearance: `.p_4()`, `.bg()`,
14//!   `.w_full()`, and the rest of the utility-style methods.
15//! - [`InteractiveElement`](crate::InteractiveElement) for listeners:
16//!   `.on_click()`, `.on_mouse_down()`, `.on_key_down()`.
17//! - [`Render`](crate::Render) and [`RenderOnce`](crate::RenderOnce) to turn
18//!   your own types into elements.
19//! - [`Entity`](crate::Entity) and [`Context`](crate::Context) for the state
20//!   that drives them.
21//!
22//! This level composes; it does not draw. Painting is decided by the elements
23//! being composed.
24//!
25//! ## Writing custom elements
26//!
27//! When nothing built in draws what you need, implement
28//! [`Element`](crate::Element). Its lifecycle runs in three phases:
29//!
30//! 1. [`Element::request_layout`](crate::Element::request_layout) asks the layout
31//!    engine for a [`LayoutId`](crate::LayoutId), through
32//!    [`Window::request_layout`](crate::Window::request_layout) or, for leaf
33//!    content whose size only its own measurements know,
34//!    [`Window::request_measured_layout`](crate::Window::request_measured_layout).
35//! 2. [`Element::prepaint`](crate::Element::prepaint) runs once the element's
36//!    [`Bounds`](crate::Bounds) are known. This is where you register hitboxes
37//!    with [`Window::insert_hitbox`](crate::Window::insert_hitbox) and stash
38//!    whatever state painting will need.
39//! 3. [`Element::paint`](crate::Element::paint) emits the drawing:
40//!    - [`Window::paint_quad`](crate::Window::paint_quad) draws a
41//!      [`PaintQuad`](crate::PaintQuad), the same primitive a `div()` uses for
42//!      its background, border and corner radii.
43//!    - [`Window::paint_path`](crate::Window::paint_path) draws arbitrary vector
44//!      geometry, built with [`PathBuilder`](crate::PathBuilder) into an
45//!      engine-level [`Path`](crate::Path).
46//!    - [`Window::paint_drop_shadows`](crate::Window::paint_drop_shadows) and
47//!      [`Window::paint_inset_shadows`](crate::Window::paint_inset_shadows) draw
48//!      [`BoxShadow`](crate::BoxShadow)s, before and after the element's fill
49//!      respectively.
50//!    - [`Window::paint_image`](crate::Window::paint_image) draws an image.
51//!    - [`Window::layout_bounds`](crate::Window::layout_bounds) reads a child's
52//!      computed bounds.
53//!
54//! None of these name a GPU API or an operating system. Each call appends a
55//! record to the frame's scene, and the engine's
56//! [`SceneRenderer`](crate::SceneRenderer) turns those records into whatever the
57//! backend draws, so a custom element keeps working when the renderer is
58//! replaced. [`LayoutId`](crate::LayoutId) is likewise an opaque token, so a
59//! custom element keeps working when the layout engine is replaced.
60//!
61//! Compositing pixels produced outside GPUI is the one place a platform-specific
62//! payload reaches the window. It goes through [`gpu_canvas`](crate::gpu_canvas),
63//! whose callback receives a [`GpuCanvasContext`](crate::GpuCanvasContext): the
64//! context's `paint_surface` takes a CoreVideo buffer, a Direct3D texture or
65//! view, or a dma-buf, and its `paint_texture` takes a texture made on the
66//! window renderer's own device.
67//!
68//! ## What is not authoring API
69//!
70//! Part of [`Window`](crate::Window)'s public surface exists for the runtime and
71//! for test harnesses rather than for elements:
72//!
73//! - Frame orchestration: `compute_layout`, `present_if_needed`, damage diffing
74//!   and `draw`. `draw` stays public because the visual test harnesses render
75//!   frames with it, and is hidden from these docs.
76//! - Element storage: the erased `ElementObject`, the element arena, and the
77//!   stack-safety wrapper around it.
78//! - Frame double-buffering and the retained hit-test tree.
79//! - The inspector: the runtime publishes the identity of the element it is
80//!   laying out or painting, so elements never handle it themselves.
81//!
82//! Depend on the authoring surface instead. If something in that list is the
83//! only way to express what you need, that is a gap worth reporting.
84//!
85//! ## The rest of `Window` is runtime API
86//!
87//! The remaining methods on [`Window`](crate::Window) are public on purpose, and
88//! they are not authoring API: window management, input, focus, event
89//! subscriptions, element state and assets. Whether a *component* or an
90//! *element* needs them is a judgement each call site makes, so they are neither
91//! hidden here nor treated as a frozen contract.