libstp.ui.step¶
UIStep - Base class for Steps that show UI screens.
The Step orchestrates the flow, screens handle their own UI/events.
Attributes¶
Classes¶
Base class for Steps that show UI screens. |
Module Contents¶
- libstp.ui.step.T¶
- class libstp.ui.step.UIStep¶
Bases:
libstp.step.base.Step,abc.ABCBase class for Steps that show UI screens.
The Step is responsible for orchestrating the flow by showing screens and collecting their results. Each screen handles its own events and state.
Example
- class MyCalibration(UIStep):
- async def _execute_step(self, robot):
# Show first screen, wait for result off_value = await self.show(MeasureScreen(is_on=False))
# Show second screen on_value = await self.show(MeasureScreen(is_on=True))
# Show confirmation result = await self.show(ConfirmScreen(off_value, on_value))
- if not result.confirmed:
# Retry return await self._execute_step(robot)
self.result = result
- async show(screen: libstp.ui.screen.UIScreen[T]) T¶
Show a screen and wait for it to close.
The screen’s event handlers will be called as the user interacts. When the screen calls close(result), this method returns that result.
- Parameters:
screen – The UIScreen instance to display
- Returns:
Whatever the screen passed to close()
- async run_step(robot: libstp.robot.api.GenericRobot) None¶
Run the step with automatic UI cleanup.
Ensures the UI is closed even if the step fails or is cancelled.
- async display(screen: libstp.ui.screen.UIScreen) None¶
Show a screen without waiting for it to close.
Use this when you want to run background logic while the UI is visible. Events will still be dispatched to the screen’s handlers.
Example
await self.display(StatusScreen(“Processing…”)) for i in range(100):
await self.update_progress(i) await asyncio.sleep(0.1)
await self.close_ui()
- async pump_events(timeout: float = 0) None¶
Process pending UI events without blocking.
Call this periodically in your background loop to handle user input.
Example
await self.display(MyScreen()) while running:
await self.pump_events() # … do background work … await asyncio.sleep(0.05)
- async showing(screen: libstp.ui.screen.UIScreen[T])¶
Context manager for displaying a screen while running code.
Events are automatically pumped. Screen closes when exiting context.
Example
- async with self.showing(ProgressScreen()) as ctx:
- for i in range(100):
ctx.screen.progress = i await ctx.screen.refresh() await asyncio.sleep(0.1)
- async run_with_ui(screen: libstp.ui.screen.UIScreen, task: Callable[[], Awaitable[Any]] | Awaitable[Any], poll_interval: float = 0.05) Any¶
Run a background task while showing a screen.
Events are pumped automatically. Returns when task completes.
- Parameters:
screen – The screen to display while task runs
task – Either a coroutine or a callable that returns a coroutine
poll_interval – How often to pump UI events (seconds)
Example
# With callable: result = await self.run_with_ui(
LoadingScreen(“Calibrating…”), self.do_calibration
)
# With coroutine directly: result = await self.run_with_ui(
LoadingScreen(“Calibrating…”), self.do_calibration()
)
- async message(text: str, title: str = 'Info', button_label: str = 'OK') None¶
Show a simple message and wait for acknowledgment.
Example
await self.message(“Calibration complete!”) await self.message(“Error occurred”, title=”Error”)
- async confirm(text: str, title: str = 'Confirm', yes_label: str = 'Yes', no_label: str = 'No') bool¶
Show a yes/no confirmation dialog.
Example
- if await self.confirm(“Start calibration?”):
await self.do_calibration()
- async input_number(prompt: str, title: str = 'Input', default: float = 0, unit: str = '', min_value: float | None = None, max_value: float | None = None) float | None¶
Get a numeric value from the user.
Returns None if cancelled.
Example
distance = await self.input_number(“Enter distance:”, unit=”cm”) speed = await self.input_number(“Speed:”, min_value=0, max_value=100)
- async choose(prompt: str, options: List[str], title: str = 'Choose') str | None¶
Let user choose from a list of options.
Returns None if cancelled.
Example
mode = await self.choose(“Select mode:”, [“Fast”, “Normal”, “Precise”])
- async wait_for_button(text: str = 'Press button to continue', title: str = 'Ready') None¶
Wait for physical button press.
Example
await self.wait_for_button(“Position robot and press button”)