"""Application composition root.""" from __future__ import annotations import tkinter as tk from .color_picker import ColorPickerMixin from .constants import DEFAULTS from .exclusions import ExclusionMixin from .image_processing import ImageProcessingMixin from .reset import ResetMixin from .theme import ThemeMixin from .ui import UIBuilderMixin class PurpleTunerApp( ThemeMixin, UIBuilderMixin, ImageProcessingMixin, ExclusionMixin, ColorPickerMixin, ResetMixin, ): """Tkinter based application for highlighting purple hues in images.""" def __init__(self, root: tk.Tk): self.root = root self.root.title("Purple Tuner — Bild + Overlay") try: self.root.state("zoomed") except Exception: pass self.root.configure(bg="#f2f2f7") # Theme and styling self.init_theme() # Tkinter state variables self.DEFAULTS = DEFAULTS.copy() self.hue_min = tk.DoubleVar(value=self.DEFAULTS["hue_min"]) self.hue_max = tk.DoubleVar(value=self.DEFAULTS["hue_max"]) self.sat_min = tk.DoubleVar(value=self.DEFAULTS["sat_min"]) self.val_min = tk.DoubleVar(value=self.DEFAULTS["val_min"]) self.val_max = tk.DoubleVar(value=self.DEFAULTS["val_max"]) self.alpha = tk.IntVar(value=self.DEFAULTS["alpha"]) self.ref_hue = None # Debounce for heavy preview updates self.update_delay_ms = 400 self._update_job = None # Exclusion rectangles (preview coordinates) self.exclude_rects: list[tuple[int, int, int, int]] = [] self._rubber_start = None self._rubber_id = None self.pick_mode = False # Image references self.image_path = None self.orig_img = None self.preview_img = None self.preview_tk = None self.overlay_tk = None # Build UI self.setup_ui() self._init_copy_menu() self.bring_to_front() def start_app() -> None: """Entry point used by the CLI script.""" root = tk.Tk() app = PurpleTunerApp(root) root.mainloop() __all__ = ["PurpleTunerApp", "start_app"]