SXXXXXXX_PyMsc/pymsc/gui/main_window.py

110 lines
4.1 KiB
Python

# -*- coding: utf-8 -*-
import tkinter as tk
from tkinter import ttk, messagebox
import logging
from typing import Dict, Any, Type
from pymsc.core.mission_logic import MissionLogic
from pymsc.utils.logger import CustomLogger
from pymsc.gui.script_manager import get_script_manager
from pymsc.gui.components.command_widgets import (
CommandFrameCheckBox, CommandFrameComboBox, CommandFrameSpinBox,
CommandFrameLabels, CommandFrameControls
)
class MainWindow:
"""
Main Application Window.
Uses a ttk.Notebook for real tab management.
"""
def __init__(self, root: tk.Tk):
self.root = root
self.root.title("PyMsc - Mission Computer Radar Control")
# Core Components
self.logic = MissionLogic()
self.logger = CustomLogger()
self.script_manager = get_script_manager()
# Tab management
self.tabs: Dict[str, tk.Frame] = {}
self._setup_layout()
# Start GUI refresh loop (Main Thread)
self.root.after(100, self.gui_refresh_loop)
def _setup_layout(self):
"""Organizes the main UI with a Top Toolbar, Central Notebook, and Bottom Log."""
# 1. Top Toolbar (for global buttons like Script Manager)
self.toolbar = ttk.Frame(self.root, relief="flat", padding=5)
self.toolbar.pack(side=tk.TOP, fill=tk.X)
self.script_btn = ttk.Button(
self.toolbar,
text="SCRIPT MANAGER",
command=lambda: self.script_manager.open_manager_gui(self.root)
)
self.script_btn.pack(side=tk.RIGHT, padx=5)
# 2. Main Tabbed Interface (Notebook)
self.notebook = ttk.Notebook(self.root)
self.notebook.pack(side=tk.TOP, fill=tk.BOTH, expand=True, padx=5, pady=5)
# 3. Log Area (Bottom)
self.log_container = ttk.Frame(self.root, relief="sunken", borderwidth=1)
self.log_container.pack(side=tk.BOTTOM, fill=tk.X, padx=5, pady=5)
self.logger.setup_tkinter_logging(self.log_container)
def add_page(self, title: str, page_class: Type[tk.Frame]):
"""
Instantiates a page class and adds it as a new tab in the Notebook.
"""
page_instance = page_class(parent=self.notebook, controller=self)
self.notebook.add(page_instance, text=title.upper())
self.tabs[title] = page_instance
def gui_refresh_loop(self):
"""
Periodically refreshes widgets only in the currently active tab.
"""
# Get the currently selected tab widget
current_tab_id = self.notebook.select()
if current_tab_id:
# The notebook.select() returns the widget name,
# we need to find the widget instance
current_tab_widget = self.root.nametowidget(current_tab_id)
self._refresh_widgets_recursive(current_tab_widget)
self.root.after(100, self.gui_refresh_loop)
def _refresh_widgets_recursive(self, container: tk.Widget):
"""Traverses the widget tree to find and update PyMsc custom components."""
for child in container.winfo_children():
# Check if it's one of our custom command widgets
is_custom = isinstance(child, (
CommandFrameCheckBox, CommandFrameComboBox,
CommandFrameSpinBox, CommandFrameLabels,
CommandFrameControls
))
if is_custom:
child.check_updated_value()
# Continue searching if the child has its own children (like sub-frames)
if child.winfo_children():
self._refresh_widgets_recursive(child)
def start_mission(self):
"""Initializes 1553 and starts sync threads."""
config = {"ip": "127.0.0.1", "send_port": 5001, "recv_port": 5002}
success = self.logic.initialize_system(config)
if success:
self.logic.start_mission()
else:
self.logger.get_logger().error("Hardware initialization failed.")
def on_close(self):
"""Stops background logic before closing the window."""
self.logic.stop_mission()
self.root.destroy()