"""Status strip -- persistent 1-row connection/position/signal bar.""" from rich.text import Text from textual.reactive import reactive from textual.widgets import Static # Firmware prompt → display color mapping. _MENU_COLORS: dict[str, str] = { "TRK>": "#00d4aa", "MOT>": "#00e060", "DVB>": "#2080d0", "NVS>": "#e8a020", "A3981>": "#00b8c8", "STEP>": "#40c0a0", "EE>": "#e8a020", "OS>": "#8090a0", "ADC>": "#00b8c8", "GPIO>": "#40c0a0", "PEAK>": "#e8c020", } class StatusStrip(Static): """Persistent status bar showing connection, position, signal, and motor state. Docked below the header on every screen. Updated by the app-level position poll and signal monitors. """ connected: reactive[bool] = reactive(False) demo: reactive[bool] = reactive(False) port: reactive[str] = reactive("/dev/ttyUSB0") azimuth: reactive[float] = reactive(0.0) elevation: reactive[float] = reactive(0.0) rssi: reactive[int] = reactive(-1) # -1 means no data motor_state: reactive[str] = reactive("IDLE") fw_menu: reactive[str] = reactive("TRK>") def render(self) -> Text: result = Text() sep = Text(" \u2502 ", style="#1a2a38") # Connection status if self.demo: result.append(" DEMO", style="#e8a020 bold italic") elif self.connected: result.append(" CONNECTED", style="#00e060 bold") result.append(f" {self.port}", style="#506878") else: result.append(" OFFLINE", style="#e04040 bold") result.append_text(sep) # Position result.append("AZ ", style="#506878") result.append(f"{self.azimuth:7.2f}", style="#00d4aa bold") result.append(" EL ", style="#506878") result.append(f"{self.elevation:6.2f}", style="#00d4aa bold") result.append_text(sep) # Signal (RSSI) if self.rssi >= 0: result.append("RSSI ", style="#506878") result.append(f"{self.rssi}", style="#00b8c8 bold") else: result.append("RSSI ", style="#384858") result.append("---", style="#384858") result.append_text(sep) # Motor state state = self.motor_state if state == "MOVING": result.append(state, style="#e8c020 bold") elif state == "ENGAGED": result.append(state, style="#00e060") else: result.append(state, style="#506878") result.append_text(sep) # Firmware context menu_color = _MENU_COLORS.get(self.fw_menu, "#506878") result.append(self.fw_menu, style=f"{menu_color}") return result def watch_connected(self, _value: bool) -> None: self.refresh() def watch_demo(self, _value: bool) -> None: self.refresh() def watch_port(self, _value: str) -> None: self.refresh() def watch_azimuth(self, _value: float) -> None: self.refresh() def watch_elevation(self, _value: float) -> None: self.refresh() def watch_rssi(self, _value: int) -> None: self.refresh() def watch_motor_state(self, _value: str) -> None: self.refresh() def watch_fw_menu(self, _value: str) -> None: self.refresh()