build_tools.tui_common.controls.inputs

Seed input and radio option widgets.

This module provides input widgets for seed/random value entry and radio-button style option selection.

Widgets:

  • SeedInput - Two-box seed input with random mode support

  • RadioOption - Checkbox-style radio button for option groups

Example Usage:

from build_tools.tui_common.controls import SeedInput, RadioOption
from textual import on

class MyApp(App):
    def compose(self) -> ComposeResult:
        # Seed input with random default
        yield SeedInput(id="seed-input")

        # Radio options for mode selection
        yield RadioOption("fast", "Quick processing", is_selected=True, id="opt-fast")
        yield RadioOption("thorough", "Deep analysis", id="opt-thorough")

    @on(SeedInput.Changed)
    def on_seed_changed(self, event: SeedInput.Changed) -> None:
        print(f"Using seed: {event.value}")

    @on(RadioOption.Selected)
    def on_option_selected(self, event: RadioOption.Selected) -> None:
        # Update other options to deselect them
        for opt in self.query(RadioOption):
            opt.set_selected(opt.option_name == event.option_name)

Classes

SeedInput

Seed input widget with two-box design.

RadioOption

Radio button style option widget.

Module Contents

class build_tools.tui_common.controls.inputs.SeedInput(value=None, *args, **kwargs)[source]

Bases: textual.widgets.Static

Seed input widget with two-box design.

Displays an input field for entering a seed value and a display showing the actual seed being used. Supports random mode when input is empty or “-1”.

Layout:

[Seed:] [Input Field] [->] [Actual Seed Used]

Modes:

  • Manual mode: Enter a specific integer seed value

  • Random mode: Enter “-1” or leave empty to auto-generate

value

Current seed value being used (always a valid integer)

user_input

User’s raw input (-1 means random mode)

Keybindings:
  • r: Set to random mode (-1)

Messages:
  • Changed: Posted when seed changes, includes actual seed value

CSS Classes:
  • .seed-label: “Seed:” label (width: 15)

  • Input: Text input field (width: 13)

  • .arrow: Arrow indicator “->” (width: 3)

  • .seed-used-value: Actual seed display (width: 12, muted)

Initialize seed input with two-box design.

Parameters:
  • value (int | None) – Initial seed value. If None, generates a random seed using SystemRandom for cryptographic randomness.

  • *args – Additional positional arguments passed to Static

  • **kwargs – Additional keyword arguments passed to Static

BINDINGS = [('r', 'random', 'Random')]

A list of key bindings.

class Changed(value, widget_id)[source]

Bases: textual.message.Message

Message posted when the seed value changes.

value

The actual seed value being used (always valid integer)

widget_id

The ID of the widget that posted this message, or None

Initialize the Changed message.

Parameters:
  • value (int) – The actual seed value

  • widget_id (str | None) – ID of the seed input widget that changed

value
widget_id
DEFAULT_CSS = Multiline-String
Show Value
"""
    SeedInput {
        layout: horizontal;
        height: 3;
        width: 100%;
    }

    SeedInput .seed-label {
        width: 15;
        text-align: right;
        padding-right: 1;
        height: 3;
        content-align: center middle;
    }

    SeedInput Input {
        width: 13;
        height: 3;
        border: solid $primary;
    }

    SeedInput .arrow {
        width: 3;
        text-align: center;
        height: 3;
        content-align: center middle;
    }

    SeedInput .seed-used-value {
        width: 12;
        height: 3;
        text-align: left;
        content-align: center middle;
        color: $text-muted;
        background: $boost;
        padding-left: 1;
    }
    """

Default TCSS.

user_input = -1
compose()[source]

Create two-box seed input in single horizontal row.

Layout: [Label] [Input] [Arrow] [Actual Value]

Yields:

Label and Input widgets for the two-box design

action_random()[source]

Set input to random mode (-1).

Bound to ‘r’ key. Generates a new random seed.

on_input_changed(event)[source]

Handle user typing in the seed input.

Parameters:

event (textual.widgets.Input.Changed) – Input change event from Textual

class build_tools.tui_common.controls.inputs.RadioOption(option_name, description, is_selected=False, *args, **kwargs)[source]

Bases: textual.widgets.Static

Radio button style option widget.

Displays as a checkbox-style option that can be selected with keyboard or mouse. Used in groups where only one option should be selected at a time (managed by parent).

Display Format:

  • Selected: [x] Label: Description (green, bold)

  • Unselected: [ ] Label: Description (muted)

option_name

Internal name for this option (e.g., “fast”, “thorough”)

description

Brief description shown after the label

is_selected

Whether this option is currently selected

Keybindings:
  • Enter or Space: Select this option

Messages:
  • Selected: Posted when this option is selected (only if not already selected)

CSS Classes:
  • Default styles handle hover and focus states

  • .profile-selected / .profile-unselected: Selection state classes

Note

This widget only posts a message when selected. The parent is responsible for deselecting other options in the group by calling set_selected() on each.

Initialize radio option.

Parameters:
  • option_name (str) – Internal name for this option (e.g., “fast”)

  • description (str) – Brief description to show after the label

  • is_selected (bool) – Whether this option starts selected

  • *args – Additional positional arguments passed to Static

  • **kwargs – Additional keyword arguments passed to Static

BINDINGS = [('enter', 'select', 'Select Option'), ('space', 'select', 'Select Option')]

A list of key bindings.

class Selected(option_name, widget_id)[source]

Bases: textual.message.Message

Message posted when this option is selected.

Only posted if the option was not already selected.

option_name

The name of the selected option

widget_id

The ID of the widget that posted this message, or None

profile_name

Alias for option_name (backward compatibility)

Initialize the Selected message.

Parameters:
  • option_name (str) – Name of the option that was selected

  • widget_id (str | None) – ID of the radio option widget

option_name
widget_id
property profile_name: str

Alias for option_name (backward compatibility with ProfileOption).

DEFAULT_CSS = Multiline-String
Show Value
"""
    RadioOption {
        height: 1;
        width: 100%;
    }

    RadioOption:hover {
        background: $boost;
    }

    RadioOption:focus {
        background: $accent;
    }

    .profile-selected {
        color: $success;
        text-style: bold;
    }

    .profile-unselected {
        color: $text-muted;
    }
    """

Default TCSS.

option_name
description
is_selected = False
on_mount()[source]

Configure widget after mounting.

Makes the widget focusable for keyboard navigation.

render()[source]

Render the option as text with Rich markup.

Returns:

Rich Text object with checkbox, label, and description

action_select()[source]

Select this option (Enter/Space).

Only posts Selected message if not already selected. Does not blur focus - keeps focus on selected option like standard radio button behavior.

on_click()[source]

Handle click on this option.

Same behavior as action_select - posts message if not selected.

set_selected(selected)[source]

Update selection state and refresh display.

Called by parent to manage radio group state. Does not post any message.

Parameters:

selected (bool) – Whether this option should be selected