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.