110 lines
4.1 KiB
Python
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() |