import tkinter as tk from tkinter import ttk from typing import Optional class StatusBar(ttk.Frame): """Status bar widget containing connection indicators and rate/status text. Exposes small API so MainView can delegate status updates without managing layout details. """ def __init__(self, parent): super().__init__(parent, relief=tk.SUNKEN) ttk.Label(self, text="Target:").pack(side=tk.LEFT, padx=(5, 2)) self.target_status_canvas = tk.Canvas(self, width=16, height=16, highlightthickness=0) self.target_status_canvas.pack(side=tk.LEFT, padx=(0, 10)) self._draw_status_indicator(self.target_status_canvas, "#e74c3c") ttk.Label(self, text="LRU:").pack(side=tk.LEFT, padx=(5, 2)) self.lru_status_canvas = tk.Canvas(self, width=16, height=16, highlightthickness=0) self.lru_status_canvas.pack(side=tk.LEFT, padx=(0, 10)) self._draw_status_indicator(self.lru_status_canvas, "#e74c3c") self.status_var = tk.StringVar(value="Ready") ttk.Label(self, textvariable=self.status_var, anchor=tk.W).pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5) # Small rate indicator showing incoming real-state rate and PPI update rate try: self.rate_status_var = tk.StringVar(value="") ttk.Label(self, textvariable=self.rate_status_var, anchor=tk.E).pack(side=tk.RIGHT, padx=(4, 8)) except Exception: self.rate_status_var = None # Id for scheduled status clear; used by show_status_message self._status_after_id: Optional[str] = None def _draw_status_indicator(self, canvas, color): try: canvas.delete("all") canvas.create_oval(2, 2, 14, 14, fill=color, outline="black") except Exception: pass def set_target_connected(self, is_connected: bool): color = "#2ecc40" if is_connected else "#e74c3c" try: self._draw_status_indicator(self.target_status_canvas, color) except Exception: pass def set_lru_connected(self, is_connected: bool): color = "#2ecc40" if is_connected else "#e74c3c" try: self._draw_status_indicator(self.lru_status_canvas, color) except Exception: pass def show_status_message(self, text: str, timeout_ms: int = 3000): try: try: if self._status_after_id is not None: self.after_cancel(self._status_after_id) except Exception: pass self.status_var.set(text) def _clear(): try: self.status_var.set("Ready") except Exception: pass self._status_after_id = self.after(timeout_ms, _clear) except Exception: # Fallback: set the var and do not schedule clear try: self.status_var.set(text) except Exception: pass class StatusBar(ttk.Frame): """Status bar widget containing connection indicators and rate/status text. Exposes small API so MainView can delegate status updates without managing layout details. """ def __init__(self, parent): super().__init__(parent, relief=tk.SUNKEN) ttk.Label(self, text="Target:").pack(side=tk.LEFT, padx=(5, 2)) self.target_status_canvas = tk.Canvas(self, width=16, height=16, highlightthickness=0) self.target_status_canvas.pack(side=tk.LEFT, padx=(0, 10)) self._draw_status_indicator(self.target_status_canvas, "#e74c3c") ttk.Label(self, text="LRU:").pack(side=tk.LEFT, padx=(5, 2)) self.lru_status_canvas = tk.Canvas(self, width=16, height=16, highlightthickness=0) self.lru_status_canvas.pack(side=tk.LEFT, padx=(0, 10)) self._draw_status_indicator(self.lru_status_canvas, "#e74c3c") self.status_var = tk.StringVar(value="Ready") ttk.Label(self, textvariable=self.status_var, anchor=tk.W).pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5) # Small rate indicator showing incoming real-state rate and PPI update rate try: self.rate_status_var = tk.StringVar(value="") ttk.Label(self, textvariable=self.rate_status_var, anchor=tk.E).pack(side=tk.RIGHT, padx=(4, 8)) except Exception: self.rate_status_var = None # Id for scheduled status clear; used by show_status_message self._status_after_id: Optional[str] = None def _draw_status_indicator(self, canvas, color): try: canvas.delete("all") canvas.create_oval(2, 2, 14, 14, fill=color, outline="black") except Exception: pass def set_target_connected(self, is_connected: bool): color = "#2ecc40" if is_connected else "#e74c3c" try: self._draw_status_indicator(self.target_status_canvas, color) except Exception: pass def set_lru_connected(self, is_connected: bool): color = "#2ecc40" if is_connected else "#e74c3c" try: self._draw_status_indicator(self.lru_status_canvas, color) except Exception: pass def show_status_message(self, text: str, timeout_ms: int = 3000): try: try: if self._status_after_id is not None: self.after_cancel(self._status_after_id) except Exception: pass self.status_var.set(text) def _clear(): try: self.status_var.set("Ready") except Exception: pass self._status_after_id = self.after(timeout_ms, _clear) except Exception: # Fallback: set the var and do not schedule clear try: self.status_var.set(text) except Exception: pass