"""Adapter wrapping Display as a Stage.""" from typing import Any from engine.pipeline.core import PipelineContext, Stage class DisplayStage(Stage): """Adapter wrapping Display as a Stage.""" def __init__(self, display, name: str = "terminal", positioning: str = "mixed"): self._display = display self.name = name self.category = "display" self.optional = False self._initialized = False self._init_width = 80 self._init_height = 24 self._positioning = positioning def save_state(self) -> dict[str, Any]: """Save display state for restoration after pipeline rebuild. Returns: Dictionary containing display state that can be restored """ return { "initialized": self._initialized, "init_width": self._init_width, "init_height": self._init_height, "width": getattr(self._display, "width", 80), "height": getattr(self._display, "height", 24), } def restore_state(self, state: dict[str, Any]) -> None: """Restore display state from saved state. Args: state: Dictionary containing display state from save_state() """ self._initialized = state.get("initialized", False) self._init_width = state.get("init_width", 80) self._init_height = state.get("init_height", 24) # Restore display dimensions if the display supports it if hasattr(self._display, "width"): self._display.width = state.get("width", 80) if hasattr(self._display, "height"): self._display.height = state.get("height", 24) @property def capabilities(self) -> set[str]: return {"display.output"} @property def dependencies(self) -> set[str]: # Display needs rendered content and camera transformation return {"render.output", "camera"} @property def inlet_types(self) -> set: from engine.pipeline.core import DataType return {DataType.TEXT_BUFFER} # Display consumes rendered text @property def outlet_types(self) -> set: from engine.pipeline.core import DataType return {DataType.NONE} # Display is a terminal stage (no output) def init(self, ctx: PipelineContext) -> bool: w = ctx.params.viewport_width if ctx.params else 80 h = ctx.params.viewport_height if ctx.params else 24 # Try to reuse display if already initialized reuse = self._initialized result = self._display.init(w, h, reuse=reuse) # Update initialization state if result is not False: self._initialized = True self._init_width = w self._init_height = h return result is not False def process(self, data: Any, ctx: PipelineContext) -> Any: """Output data to display.""" if data is not None: # Check if positioning mode is specified in context params positioning = self._positioning if ctx and ctx.params and hasattr(ctx.params, "positioning"): positioning = ctx.params.positioning # Pass positioning to display if supported if ( hasattr(self._display, "show") and "positioning" in self._display.show.__code__.co_varnames ): self._display.show(data, positioning=positioning) else: # Fallback for displays that don't support positioning parameter self._display.show(data) return data def cleanup(self) -> None: self._display.cleanup()