Back to Projects
TUIX v0.4Beta

Last Updated: 2026-05-20

Widgets

Widgets are the interactive elements rendered to the terminal. Each widget is an instance of a builder type, lives in a scene, and has a unique integer UID.

Builder System

Widget types are defined by builders — a polymorphic pattern implemented in C. Each builder provides five callbacks: create_state (allocate per-widget state), destroy_state (free state), handler_func (per-frame update logic), build_content (render state to pixel buffer), and on_resize (optional geometry notification).

TUIX ships thirteen built-in builders, registered by calling builders.register_standard(). The builder constants are byte strings used when creating widgets:

ConstantValueWidget Type
builders.PROGRESSBARb"ProgressBarBuilder"Horizontal fill bar with custom chars and colours
builders.CHOICEb"ChoiceBuilder"Keyboard-navigable list menu
builders.INPUTb"InputBuilder"Single-line text input with placeholder support
builders.CANVASb"CanvasBuilder"Free-draw surface for pixels, lines, rects, circles, text, and sprites
builders.TEXTb"TextBuilder"Inline text content with runtime fg/bg updates
builders.BOXb"BoxBuilder"Framed container with title and color controls
builders.DIVIDERb"DividerBuilder"Horizontal or vertical divider with custom symbol and color
builders.BADGEb"BadgeBuilder"Compact label with foreground/background palette
builders.BUTTONb"ButtonBuilder"Clickable and keyboard-activatable button state
builders.ICONb"IconBuilder"Centered symbol/icon with configurable colours
builders.TAGb"TagBuilder"Chip-style label with configurable brackets
builders.STATUSb"StatusBuilder"IDLE/OK/WARN/ERROR status display widget
builders.MENUb"MenuBuilder"Interactive menu with keyboard and mouse selection
builders.SCROLL_CONTAINERb"ScrollContainerBuilder"Scrollable viewport over virtual content

Creating a Widget

uid = objects.create_object(
    builders.CHOICE,   # builder name (bytes)
    b"main",           # scene name (bytes)
    0.4,               # width_mod: fraction of terminal width
    0.5,               # height_mod: fraction of terminal height
    0.25,              # margin_top_mod: fraction from top
    0.3                # margin_left_mod: fraction from left
)

All six parameters are required. The four float modifiers (width_mod, height_mod, margin_top_mod, margin_left_mod) are proportional values between 0.0 and 1.0, multiplied by the terminal dimensions each frame.

Proportional Geometry

Widget dimensions are not fixed pixel counts. They are fractions of the terminal size, resolved every frame by the geometry resolver:

buffer.width       = terminal_width  × object.width_mod
buffer.height      = terminal_height × object.height_mod
buffer.margin_left = terminal_width  × object.margin_left_mod
buffer.margin_top  = terminal_height × object.margin_top_mod

This means widgets automatically resize when the terminal is resized. A widget with width_mod=0.5 always occupies half the terminal width.

Accessing Widget Objects

To call widget-specific functions (set options, feed input, etc.), you need the TuixObject pointer. Retrieve it through the buffer:

buf = buffers.get_buffer_by_uid(uid)
obj = buf.contents.obj.contents

# Now use widget-specific functions
objects.tuix_choice_set_options(obj, [b"A", b"B", b"C"])

Widget Lifecycle

  1. Create: objects.create_object() → allocates object, buffer, and registers subcycle handler
  2. Configure: call widget-specific set functions (set_options, set_value, set_placeholder, etc.)
  3. Render: engine.main_loop() resolves geometry, calls build_content, composites, renders
  4. Input: handled automatically in the v0.4 frame loop for built-in builders
  5. Query: check is_confirmed/is_submitted, get_selected/get_text/get_result
  6. Reset (optional): widget-specific reset() to reuse without recreating
  7. Destroy: buffers.free_buffer(scene, uid) to free the buffer and state

Internal Frame Handlers

Each widget has an internal handler callback that runs every frame. It controls state updates, redraw signaling, and input processing behavior for the builder. These control objects are internal implementation details in v0.4.

Focus Routing (v0.4)v0.4 supports scene-level focus routing and hitmap-based mouse click picking. When multiple interactive widgets are present, use scenes.set_focus(scene_name, uid) to select which widget should handle keyboard input. Use scenes.set_previous_focus(scene_name) to restore the previous target.