from dataclasses import dataclass import tkinter as tk from tkinter import ttk, messagebox @dataclass class ExportSettings: orientation: str = "horizontal" spacing: int = 0 margin: int = 0 rows: int = 0 columns: int = 0 output_name: str = "flipbook.png" class ExportSettingsDialog(tk.Toplevel): def __init__(self, parent: tk.Misc, initial_settings: ExportSettings | None = None) -> None: super().__init__(parent) self.title("Default Export Settings") self.resizable(False, False) self.transient(parent) self.grab_set() self.result: ExportSettings | None = None settings = initial_settings or ExportSettings() self.orientation_var = tk.StringVar(value=settings.orientation) self.spacing_var = tk.StringVar(value=str(settings.spacing)) self.margin_var = tk.StringVar(value=str(settings.margin)) self.rows_var = tk.StringVar(value=str(settings.rows)) self.columns_var = tk.StringVar(value=str(settings.columns)) self.output_name_var = tk.StringVar(value=settings.output_name) container = ttk.Frame(self, padding=10) container.grid(row=0, column=0, sticky="nsew") container.columnconfigure(1, weight=1) ttk.Label(container, text="Orientation").grid(row=0, column=0, sticky="w", pady=4) orientation_combo = ttk.Combobox( container, state="readonly", values=["horizontal", "vertical"], textvariable=self.orientation_var, width=20, ) orientation_combo.grid(row=0, column=1, sticky="ew", pady=4) ttk.Label(container, text="Frame Spacing (px)").grid(row=1, column=0, sticky="w", pady=4) ttk.Spinbox(container, from_=0, to=999, textvariable=self.spacing_var, width=10).grid( row=1, column=1, sticky="w", pady=4 ) ttk.Label(container, text="Margin (px)").grid(row=2, column=0, sticky="w", pady=4) ttk.Spinbox(container, from_=0, to=999, textvariable=self.margin_var, width=10).grid( row=2, column=1, sticky="w", pady=4 ) ttk.Label(container, text="Rows (0 = auto)").grid(row=3, column=0, sticky="w", pady=4) ttk.Spinbox(container, from_=0, to=999, textvariable=self.rows_var, width=10).grid( row=3, column=1, sticky="w", pady=4 ) ttk.Label(container, text="Columns (0 = auto)").grid(row=4, column=0, sticky="w", pady=4) ttk.Spinbox(container, from_=0, to=999, textvariable=self.columns_var, width=10).grid( row=4, column=1, sticky="w", pady=4 ) ttk.Label(container, text="Default File Name").grid(row=5, column=0, sticky="w", pady=4) ttk.Entry(container, textvariable=self.output_name_var, width=24).grid(row=5, column=1, sticky="ew", pady=4) actions = ttk.Frame(container) actions.grid(row=6, column=0, columnspan=2, sticky="e", pady=(10, 0)) ttk.Button(actions, text="Cancel", command=self._cancel).grid(row=0, column=0, padx=4) ttk.Button(actions, text="Apply", command=self._apply).grid(row=0, column=1, padx=4) self.protocol("WM_DELETE_WINDOW", self._cancel) def show(self) -> ExportSettings | None: self.wait_window(self) return self.result def _apply(self) -> None: try: spacing = int(self.spacing_var.get()) margin = int(self.margin_var.get()) rows = int(self.rows_var.get()) columns = int(self.columns_var.get()) except ValueError: messagebox.showerror( "Invalid settings", "Spacing, margin, rows, and columns must be valid whole numbers.", parent=self, ) return if spacing < 0 or margin < 0 or rows < 0 or columns < 0: messagebox.showerror("Invalid settings", "Spacing, margin, rows, and columns cannot be negative.", parent=self) return orientation = self.orientation_var.get() if orientation not in {"horizontal", "vertical"}: messagebox.showerror("Invalid settings", "Orientation must be horizontal or vertical.", parent=self) return output_name = self.output_name_var.get().strip() or "flipbook.png" if not output_name.lower().endswith(".png"): output_name = f"{output_name}.png" self.result = ExportSettings( orientation=orientation, spacing=spacing, margin=margin, rows=rows, columns=columns, output_name=output_name, ) self.destroy() def _cancel(self) -> None: self.result = None self.destroy()