160 lines
5.9 KiB
Python
160 lines
5.9 KiB
Python
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
|