Documentation
¶
Overview ¶
Package geom carries the geometry primitives shared by pkg/layout and the components it places. It is a leaf: nothing in tuilib is imported here, so both the layout engine and the components it sizes can depend on it without pointing at each other.
A Rect is what the layout engine hands a component during render — where it sits in absolute terminal coordinates, not just how big it is. Components store the rect they were last given and use it to answer "was this click mine?" without any marker injection into the rendered string.
Typical use inside a component:
func (m *Model) SetRect(r geom.Rect) { m.rect = r; … }
func (m *Model) Update(msg tea.Msg) (Model, tea.Cmd) {
if e, ok := msg.(tea.MouseMsg); ok && m.rect.Hit(e.X, e.Y) {
…
}
}
Generations ¶
A component that wasn't drawn in the last frame still holds the rect it had when it was last visible — a hidden tab body, a modal that's been dismissed. Hit-testing against that stale rect would let an invisible component claim a click.
Every rect therefore carries the render generation it was stamped with. The root of a render calls NextGen once per frame and seeds its rect with it; children inherit the value as it propagates down the tree. Hit reports false unless the rect's generation is the current one, so anything not drawn last frame silently declines every click.
The counter is package-level because bubbletea's View has a value receiver and so cannot thread per-program state. Two concurrently-running programs in one process would share it and invalidate each other's rects; that is not a shape tuilib supports. Tests that build rects by hand get generation 0, which matches the counter's initial value, so hit-testing works without rendering.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NextGen ¶
func NextGen() uint64
NextGen advances the render generation and returns the new value. The root of a render tree calls it exactly once per frame, before rendering; nested roots (a tab body's layout, say) must not — they inherit the generation from the rect they were handed so the whole frame shares one value.
Types ¶
type Rect ¶
type Rect struct {
X, Y, W, H int
// Gen is the render generation this rect was produced in. See the
// package doc — Hit uses it to reject rects from earlier frames.
Gen uint64
}
Rect is a component's absolute position and size in terminal cells, plus the render generation it was stamped with. X/Y are the top-left corner, measured from the top-left of the terminal.
func AnchorIn ¶ added in v0.21.0
AnchorIn returns the rect a w×h child occupies when its top-left is placed at (x, y) inside outer, pushed back inside outer when it would overflow.
This is the positioned counterpart to CenterIn, and it is what a context menu needs: opened by a right-click near the bottom-right corner, the box flips up and to the left instead of hanging off the edge. A child larger than outer clamps to outer's origin, so it is clipped from the far edge rather than sliding out of view at the near one.
func CenterIn ¶
CenterIn returns the rect a w×h child occupies when centered inside outer. It mirrors lipgloss.Place's centering exactly — the gap is split with integer division, biasing the remainder to the right and bottom — so a component that draws itself with Place can hit-test against the result. Offsets clamp at zero when the child is larger than outer.
func New ¶
New returns a rect stamped with the current generation. Layout uses it when seeding a render root; callers building a rect for a child should copy the parent's Gen instead so a single frame stays internally consistent.
func (Rect) Contains ¶
Contains reports whether the cell at (x, y) falls inside r, ignoring generation. Use Hit for click routing; this is the pure geometry test.