"""Tkinter UI adapter skeleton for the installer runner.""" from __future__ import annotations import threading import tkinter as tk from ..runner import InstallerRunner from ..state import InstallerState from ..milestone import Milestone class TkinterUI: """Minimal Tkinter adapter that listens to runner events.""" def __init__(self, runner: InstallerRunner, root: tk.Tk | None = None): self.runner = runner self.root = root or tk.Tk() self._bind_runner() def _bind_runner(self) -> None: self.runner.on("on_enter_milestone", self.on_enter_milestone) self.runner.on("on_validation_error", self.on_validation_error) self.runner.on("on_progress", self.on_progress) self.runner.on("on_complete", self.on_complete) # Event handlers (override in concrete UI) def on_enter_milestone(self, milestone: Milestone, state: InstallerState) -> None: pass def on_validation_error( self, milestone: Milestone | None, state: InstallerState, errors: list[str] ) -> None: pass def on_progress( self, milestone: Milestone, state: InstallerState, message: str, percent: float | None, ) -> None: pass def on_complete(self, milestone: Milestone | None, state: InstallerState) -> None: pass def start(self, start_id: str | None = None) -> None: """Start the runner in a background thread and enter Tk mainloop.""" threading.Thread( target=self.runner.run, kwargs={"start_id": start_id}, daemon=True ).start() self.root.mainloop()