Foundations

Layout and Cell Management

NAppGUI's layout system is a recursive grid composer. Layout owns the rows, columns, and cells; Cell stores per-item visibility, alignment, sizing, padding, and DBind state; Panel and Window host the final composed tree.

The source comment above _layout_compose() explicitly describes the engine as a constraint-satisfaction algorithm with separate compose and locate phases.

Relevant Source Files

Layout and Cell Model

A Layout is created with a fixed grid size and each position is represented by a Cell. A cell can hold either a GuiComponent, another nested Layout, or remain empty. The public surface reflects that model through paired setters/getters such as layout_button(...) and layout_get_button(...).

Beyond content, each cell tracks enabled/visible state, tabstop participation, per-axis alignment, forced size, computed final size/origin, and padding. The surrounding Layout tracks line sizes, expand weights, margins, background/stroke colors, DBind metadata, and a pointer back to its owning panel.

Compose Algorithm

Composition happens in two distinct phases. First, _layout_natural() walks the tree to compute the natural width and height. Then _layout_expand() grows or shrinks each dimension to satisfy an externally required size. Only after that does _layout_locate() assign final origins and call the component-specific frame setters.

Width is solved before height because some widgets have height that depends on width, especially multi-line text. The code comment is explicit about the intent: compose manipulates numbers only, so it stays fast and defers native window/control updates to the locate pass.

Sizing, Alignment, and Visibility Controls

Area Representative API Effect
Grid shape layout_insert_col, layout_remove_row Changes the logical matrix after creation.
Explicit sizing layout_hsize, layout_vsize, cell_force_size Overrides natural size for lines or individual cells.
Expansion layout_hexpand*, layout_vexpand* Assigns resize weights when a window or panel is larger than natural size.
Alignment and padding layout_halign, layout_valign, cell_padding* Controls where the composed content sits inside each partition.
Visibility and tab order layout_show_col, layout_show_row, layout_taborder, layout_tabstop Removes lines from layout flow and controls keyboard navigation order.

Panels Are Layout Hosts, Not Just Containers

A Panel does not own just one layout. Internally it keeps an ArrPt(Layout) plus visible_layout and active_layout indices. panel_layout(...) appends layouts, and panel_visible_layout(...) switches which one is active. When the active layout changes, the panel re-attaches the right children and composes the new tree.

That matters because it means panel-level view switching is a first-class feature of the library, not a user-built convention. Scroll sizes, invalidation, and child attachment are all managed at the panel layer.

Window Integration

window_panel(...) does not attach a panel directly. It creates an internal 1x1 layout, places the panel in cell (0, 0), and makes that layout the window's main_layout. On resize, the window asks _layout_compose() to negotiate a constrained content size and then runs _layout_locate() to push frames into the real controls.

This explains why layout behavior is the same whether the tree is nested inside another layout, mounted into a panel, or used as the root content of a top-level window.