Back to Projects
TUIX v0.1Alpha

Last Updated: 2026-05-20

Layout & Render Lifecycle

Understanding how TUIX Core computes layout and renders components is key to building effective terminal UIs. This page describes the lifecycle from engine.render.draw() through screen output.

Render Cycle Overview

  1. Screen clear — os.system('cls'/'clear') wipes the terminal
  2. Layout computation — LayoutEngine._compute_all() reads terminal size and computes pixel positions for all components
  3. Component rendering — RenderEngine draws borders, label text, and interactive buttons
  4. Input loop — InputHandler.listen() starts a blocking loop for keyboard navigation
  5. Re-render on change — Arrow key presses trigger RenderEngine._refresh() which clears and redraws

Layout Computation

The LayoutEngine reads the current terminal size via shutil.get_terminal_size() on every render. It converts proportional modifiers (0.0–1.0) into actual character coordinates. Each component gets computed x, y (width/height in chars), margin_top, margin_left, and corner coordinates.

Custom vs Centered Margins

In 'custom' mode, margins are computed as modifier * terminal_size. In 'centered' mode, margins are auto-calculated as (terminal_size - component_size) // 2, placing the component in the center of the terminal.

Computed Layout Properties

PropertyDescription
xComponent width in characters (width_modifier * terminal_cols)
yComponent height in characters (height_modifier * terminal_rows)
margin_topTop offset in rows (computed based on mode)
margin_leftLeft offset in columns (computed based on mode)
corners.top_leftTuple (col, row) of top-left corner
corners.bottom_rightTuple (col, row) of bottom-right corner

Rendering Phase

The RenderEngine draws the component using Unicode box-drawing characters (━, ┃, ┏, ┓, ┗, ┛). For choice components, it: (1) draws the top border, (2) renders the label text with word-wrap and centering via _wrap_and_center(), (3) draws interactive buttons via _draw_buttons(), (4) draws the bottom border.

Text Wrapping

The _wrap_and_center() method splits text into lines that fit within the component's inner width, then centers the text block horizontally within the available space. It respects explicit newlines in the label text.

Button Rendering

The _draw_buttons() method renders choice buttons vertically aligned and horizontally centered. The currently selected button is highlighted using the selected_background and selected_text colors from the active style. Long button text is automatically wrapped based on visual_width() calculations.

Refresh Cycle

When the user presses an arrow key, InputHandler updates selected_row and selected_index, then calls RenderEngine._refresh(). This clears the screen and calls draw() again, which recomputes layout and redraws all components with the updated selection state.

Full RedrawEvery input event triggers a full screen clear and redraw. There is no partial/differential rendering — the entire UI is redrawn from scratch on each interaction.

Input Phase

After rendering, _draw_choice() calls engine.input.listen(choices) to start a blocking input loop. The InputHandler polls for keyboard events, updates selected_row and selected_index, and triggers _refresh() on each navigation. Enter exits the loop.

Engine Structure Summary

TuixEngine aggregates all subsystems:

  • engine.styles — manages themes and visual properties
  • engine.components — manages component creation and updates
  • engine.layout — calculates dimensions and positions
  • engine.render — draws components to the terminal
  • engine.input — handles keyboard events

Components data is shared between ComponentAPI and LayoutEngine via a common objects dictionary. The render engine reads computed layout and cached styles to produce terminal output.

Current Limitations

  • Only single choice component rendering is fully implemented
  • Multi-component layouts raise NotImplementedError
  • No partial/differential updates — full redraw on every interaction
  • Input handling only supports arrow keys and Enter
FuturePlanned: multi-component layouts with collision detection, rendering for all component types, additional key bindings, and multi-component focus management.