Expand description
An infinite, pannable/zoomable whiteboard canvas for GPUI.
Host-agnostic — depends only on gpui, serde, and ttf-parser (no
gpui-component, no native libraries). Two layers: a serializable scene model
(Scene / Element) the host persists as opaque JSON, and a
WhiteboardView entity that renders the board and its editing UI (toolbar,
color picker, flyouts, templates gallery, context menu) and drives all
interaction. The host supplies a theme (WhiteboardStyle) and optional
callbacks (persist on change, open a page, fetch an image bitmap, read/write the
clipboard, store templates); with none installed it’s still a working board.
Elements: freehand pen, rect / ellipse / diamond / triangle / rounded-rect /
hexagon / star, line, arrow, text, images, and page-cards — sharing one select /
move / resize / rotate / fill / z-order machinery, plus copy-paste, templates,
and undo/redo. Text renders as vector outlines (the font module, via
ttf-parser) rather than gpui overlay glyphs, so it rotates + scales with the
camera and a host can supply a custom face (Font). See README.md for the
full API and usage; design notes in docs/whiteboard-architecture.md.
Perf note: element geometry is re-tessellated when painted (as GPUI’s own
painting/brush examples do), but rendering is viewport-culled and text
glyph layouts are cached. A built-Path cache remains a further optimization
for extremely dense visible scenes.
Structs§
- Board
Embed View - A read-only whiteboard embedding surface for use inside rich-text editors and other host containers. It overlays a small “edit / maximize” affordance and delegates the actual expansion behavior back to the host.
- Board
Thumbnail View - A lightweight, chrome-free thumbnail renderer for embedding a local board snapshot in documents, lists, and rich-text blocks.
- BoxGeom
- A box (rectangle / ellipse), world-space.
x,y,w,hdescribe the unrotated box;rotation(radians, clockwise) spins it about its center at paint time. - Camera
- The viewport: a world-space pan offset and a zoom factor. The offset is the
world point that maps to the canvas’s top-left corner, so a screen point
s(relative to the canvas) is the world pointoffset + s / zoom. - Element
- One board element: a stable id plus its geometry/kind.
- Embed
Geom - A page-card: a titled box anchored at
(x, y)that links to a host page (page_id). The crate is page-agnostic — the host supplies the id + title and handles opening it; this just stores and draws the card. - Font
- A font backing whiteboard text. Holds raw TTF/OTF bytes (parsed on demand) so it’s cheap to clone and a host can supply its own face.
- Image
Geom - An image: a box anchored at
(x, y)referencing a host-managed file (src, e.g.images/<name>). The crate is storage-agnostic — the host imports the file and supplies the decoded bitmap (seeImageFn); this stores the reference + geometry and draws it as an overlay. - Local
Thumbnail Snapshot - Local
Thumbnail Spec - Mind
MapNode Meta - RunStyle
- The formatting of a run of characters;
default()is plain text. - Scene
- The board document: everything persisted for a whiteboard. Owned and
(de)serialized here; the host stores
Scene::to_jsonopaquely (for Zorite, in thecontentcolumn of akind = 'whiteboard'page). - SegGeom
- Segment
Anchor - A directed segment (line / arrow), world-space.
- Stroke
- A freehand pen stroke: world-space points and a world-space width.
- Style
Span - A
RunStyleover the byte range[start, end)of an element’s text. Runs are kept sorted, non-overlapping, and non-plain. SeeElement::styles. - Template
- A reusable group of elements the user can stamp onto a board. Element
positions are normalized so the group’s bounding box starts at the origin;
applying re-bases them to the viewport. The host owns persistence and the
id; the crate renders the preview + instantiates on click. - Text
Geom - A text label: a top-left anchor, its content, and a world-space font size.
- Whiteboard
Style - Theme colors, read at paint time (via
WhiteboardStyleFn) so the board follows live theme changes per window. - Whiteboard
View - The whiteboard view entity. The host holds it in an
Entity<WhiteboardView>(keyed by board id) and renders it into a tab.
Enums§
- Element
Kind - The kinds of thing a board can hold.
- Font
Pick - Which face the Font flyout offers — upload one from disk or revert to the bundled default.
- Format
- A toggleable boolean format. (Highlight is a color, toggled on its own.)
- Local
Thumbnail Mode - Mind
MapConnector Style - Mind
MapRoot Direction - Mind
MapSide - Segment
Style - Tool
- The active tool. UI state — not part of the persisted scene.
Type Aliases§
- Change
Fn - Called when the board changes (an element committed/moved/deleted, the camera moved), with the serialized scene JSON, so the host can persist it.
- CopyFn
- Called on ⌘C / ⌘X with the selection serialized (same format as
SaveTemplateFn); the host writes it to the system clipboard. Paste is the reverse: the host reads the clipboard and callsWhiteboardView::paste_elements. - Delete
Template Fn - Called to delete a stored template by its host id (right-click a card).
- Drop
Files Fn - Called when files are dropped onto the canvas at world
(x, y)— the host imports any images and places them viaWhiteboardView::add_image_at. - Expand
Embed Fn - Host callback fired by an embed view when the user requests “open / maximize for editing”. The host owns the actual layout transition.
- ImageFn
- Called each render to fetch the decoded bitmap for an image element’s
src, rotated byrotationradians (0 = upright). The host serves it from its image cache, decoding/rotating on demand (returningNoneuntil ready, then re-rendering the board); a steady angle hits the cache, so it only re-rotates when the angle changes. - Move
Toolbar Fn - Called when the toolbar is moved, reset, or re-oriented, with its new
board-relative top-left (
None= default top-center) and whether it’s vertical. The host persists both and feeds them back viaWhiteboardView::set_toolbar_pos/set_toolbar_vertical. Without it, the layout is per-session. - Open
Page Fn - Called to open a page (double-clicking a card) — the host opens it in a tab.
- PasteFn
- Called by the context-menu Paste: the host reads the clipboard and returns
previously copied whiteboard elements (the JSON a
CopyFnwrote — same format asSaveTemplateFn), orNoneif it holds no board elements. Pass the JSON toWhiteboardView::paste_elements. (Keyboard ⌘V is handled internally.) - Pick
Font Fn - Called when the user picks from the Font flyout. The host loads the face and
calls
WhiteboardView::set_font(and persists the per-board choice). Without it, the Font toolbar button is hidden. - Place
Embed Fn - Called when the page-card tool is clicked at world
(x, y)— the host picks a page and callsWhiteboardView::add_embed. - Place
Image Fn - Called when the image tool is clicked at world
(x, y)— the host picks a file and callsWhiteboardView::add_image_at. - Save
Template Fn - Called when the user saves the current selection as a template, with the
selected elements serialized (normalized to origin). The host names + stores
it, then feeds the updated list back via
WhiteboardView::set_templates. - Saved
Colors Fn - Called when the user’s saved-color palette changes (a swatch added or removed),
with the full list (packed
0xRRGGBBAA). The host persists it and feeds it back viaWhiteboardView::set_saved_colors. Without it, the palette is per-session. - Whiteboard
Style Fn - A
() -> WhiteboardStylethe host supplies; called each paint so the board tracks theme changes without the host pushing updates.