S1005403_RisCC/target_simulator/gui/connection_panel.py
2025-11-03 13:51:44 +01:00

104 lines
4.0 KiB
Python

import tkinter as tk
from tkinter import ttk
from typing import Callable, Optional, Dict, Any
class ConnectionPanel(ttk.LabelFrame):
"""Reusable connection panel used by MainView.
This encapsulates the small UI that shows connection type/summary and
exposes simple hooks so the outer view can attach handlers for Connect
and Settings.
"""
def __init__(self, parent, initial_config: Optional[Dict[str, Any]] = None):
super().__init__(parent, text="Connection")
self._on_connect: Optional[Callable[[], None]] = None
self._on_open_settings: Optional[Callable[[], None]] = None
self.conn_type_var = tk.StringVar(value=(initial_config or {}).get("target", {}).get("type", "-"))
self.conn_info_var = tk.StringVar(value=self._format_summary((initial_config or {}).get("target", {})))
ttk.Label(self, text="Type:").pack(side=tk.LEFT, padx=(6, 2))
ttk.Label(self, textvariable=self.conn_type_var, width=10).pack(side=tk.LEFT)
ttk.Label(self, textvariable=self.conn_info_var).pack(side=tk.LEFT, padx=(8, 4))
# Buttons
self.connect_button = ttk.Button(self, text="Connect", command=self._handle_connect)
self.connect_button.pack(side=tk.RIGHT, padx=(4, 6))
self.conn_settings_button = ttk.Button(self, text="Settings...", command=self._handle_open_settings)
self.conn_settings_button.pack(side=tk.RIGHT, padx=(4, 0))
def _format_summary(self, cfg: Dict[str, Any]) -> str:
try:
t = cfg.get("type")
if not t:
return "-"
if t == "sfp":
sfp = cfg.get("sfp", {})
ip = sfp.get("ip") or sfp.get("host") or "?"
remote = sfp.get("port") or sfp.get("remote_port")
if isinstance(remote, (list, tuple)):
remote_str = ",".join(str(int(p)) for p in remote)
else:
try:
remote_str = str(int(remote)) if remote is not None else "?"
except Exception:
remote_str = str(remote)
local = sfp.get("local_port")
if local is not None:
try:
local_str = str(int(local))
except Exception:
local_str = str(local)
return f"{ip} (remote:{remote_str} local:{local_str})"
return f"{ip} (remote:{remote_str})"
if t == "serial":
s = cfg.get("serial", {})
port = s.get("port") or s.get("device") or "?"
baud = s.get("baudrate") or s.get("baud") or "?"
return f"{port} @{baud}"
if t == "tftp":
tftp = cfg.get("tftp", {})
host = tftp.get("host") or tftp.get("server") or "?"
return f"{host}"
return "-"
except Exception:
return "-"
def set_connect_handler(self, cb: Callable[[], None]):
self._on_connect = cb
def set_open_settings_handler(self, cb: Callable[[], None]):
self._on_open_settings = cb
def _handle_connect(self):
if self._on_connect:
try:
self._on_connect()
except Exception:
# Handler should manage its own errors
raise
def _handle_open_settings(self):
if self._on_open_settings:
try:
self._on_open_settings()
except Exception:
raise
def update_summary(self, conn_config: Dict[str, Any]):
try:
self.conn_type_var.set((conn_config or {}).get("target", {}).get("type", "-"))
self.conn_info_var.set(self._format_summary((conn_config or {}).get("target", {})))
except Exception:
pass
def update_toggle_state(self, is_connected: bool):
try:
self.connect_button.config(text="Disconnect" if is_connected else "Connect")
except Exception:
pass