SXXXXXXX_Radalyze/radalyze/gui/dialogs.py
2025-06-13 14:13:29 +02:00

123 lines
4.3 KiB
Python

import tkinter as tk
from tkinter import filedialog, messagebox
from typing import Optional, Dict, Any
class DataFileSelectorDialog(tk.Toplevel):
"""
A modal dialog window for selecting a data file and its type.
This dialog prompts the user to browse for a file and specify whether
it contains a "Vector" or a "Matrix".
"""
def __init__(self, master: tk.Tk, initial_dir: str):
"""
Initializes the dialog.
Args:
master: The parent tk.Tk window.
initial_dir: The initial directory for the file browser.
"""
super().__init__(master)
self.title("Select Data File")
self.transient(master) # Keep dialog on top of the main window
self.grab_set() # Make the dialog modal
# --- Internal state ---
self._file_path = tk.StringVar()
self._data_type = tk.StringVar(value="Vector") # Default selection
self._initial_dir = initial_dir
self.result: Optional[Dict[str, Any]] = None
self._create_widgets()
self._center_window()
# This call blocks until the window is destroyed
self.wait_window(self)
def _create_widgets(self) -> None:
"""Creates and arranges the widgets in the dialog."""
main_frame = tk.Frame(self, padx=15, pady=15)
main_frame.pack(expand=True, fill=tk.BOTH)
# --- File Path Selection ---
file_frame = tk.Frame(main_frame)
file_frame.pack(fill=tk.X, pady=(0, 10))
lbl_file = tk.Label(file_frame, text="File Path:")
lbl_file.pack(side=tk.LEFT, padx=(0, 5))
entry_file = tk.Entry(file_frame, textvariable=self._file_path, width=40)
entry_file.pack(side=tk.LEFT, fill=tk.X, expand=True)
btn_browse = tk.Button(file_frame, text="Browse...", command=self._browse_file)
btn_browse.pack(side=tk.LEFT, padx=(5, 0))
# --- Data Type Selection ---
type_frame = tk.LabelFrame(main_frame, text="Data Type", padx=10, pady=10)
type_frame.pack(fill=tk.X, pady=5)
rb_vector = tk.Radiobutton(
type_frame, text="Vector (Single Column)", variable=self._data_type, value="Vector"
)
rb_vector.pack(anchor=tk.W)
rb_matrix = tk.Radiobutton(
type_frame, text="Matrix (Header + Data)", variable=self._data_type, value="Matrix"
)
rb_matrix.pack(anchor=tk.W)
# --- Action Buttons ---
button_frame = tk.Frame(main_frame)
button_frame.pack(fill=tk.X, pady=(15, 0))
btn_load = tk.Button(button_frame, text="Load", command=self._load_data)
btn_load.pack(side=tk.RIGHT)
btn_cancel = tk.Button(button_frame, text="Cancel", command=self._cancel)
btn_cancel.pack(side=tk.RIGHT, padx=(0, 10))
def _center_window(self) -> None:
"""Centers the dialog on the screen."""
self.update_idletasks() # Ensure window size is calculated
# Get screen and window dimensions
screen_width = self.winfo_screenwidth()
screen_height = self.winfo_screenheight()
window_width = self.winfo_width()
window_height = self.winfo_height()
# Calculate position
pos_x = (screen_width // 2) - (window_width // 2)
pos_y = (screen_height // 2) - (window_height // 2)
self.geometry(f"{window_width}x{window_height}+{pos_x}+{pos_y}")
self.resizable(False, False)
def _browse_file(self) -> None:
"""Opens the system's file browser dialog."""
filename = filedialog.askopenfilename(
initialdir=self._initial_dir,
title="Select a CSV data file",
filetypes=(("CSV files", "*.csv"), ("All files", "*.*"))
)
if filename:
self._file_path.set(filename)
def _load_data(self) -> None:
"""Validates the inputs and sets the result."""
file_path = self._file_path.get()
if not file_path:
messagebox.showwarning("Input Missing", "Please select a file path.", parent=self)
return
self.result = {
"file_path": file_path,
"data_type": self._data_type.get()
}
self.destroy()
def _cancel(self) -> None:
"""Closes the dialog without setting a result."""
self.result = None
self.destroy()