Layout widget engine
Summary
Custom 2D/3D layout engine for Fennel widgets, built from scratch in Fennel starting 2025-09-01. The engine uses explicit Layout objects with measurer and layouter closures, dirty propagation, and depth offsets. It underpins everything visual in Space — HUD, dialogs, canvas panels, graph views, agent transcripts, and board items.
Motivation
The Python prototype had a manual layout system where nodes were assembled by hand without a uniform widget hierarchy. Each object tracked its own children for teardown. The Fennel layout system provides:
- Declarative widget composition (Flex, Stack, Grid, Padding, Sized)
- Automatic measure/layout passes with dirty tracking
- Proper ownership: composite widgets own their children; teardown cascades through the widget tree
- Depth offsets for z-ordering without z-fighting
Design
- Layout objects:
Layoutinstances withmeasurer(compute desired size) andlayouter(assign child positions) - Dirty rules:
mark-measure-dirtypropagates to descendants;mark-layout-dirtyis subtree-local - Depth offsets:
layout.depth-offset-indexfor ordering; backgrounds at parent, content at parent+1 - Widget composition:
Flex,Stack,Grid,Padding,Sizedas layout primitives;Rectangle,TextSpan,Buttonas leaf widgets - Build pattern: Each widget exports a constructor returning a
buildclosure;buildreceives renderer context, instantiates children, returns entity withlayoutanddrop
Tasks
- [x] Measure/layout pass with dirty propagation
- [x] Flex, Stack, Grid, Padding, Sized layout primitives
- [x] Rectangle, TextSpan, Image, Button, Input leaf widgets
- [x] Depth offsets and z-ordering
- [x] Widget ownership and recursive teardown
- [x] Layout contract tests
