# -*- coding: utf-8 -*- """ DockFrame: Base class for dockable panels in Tkinter. Provides minimize, maximize, and close functionality. """ import tkinter as tk from tkinter import ttk from typing import Optional, Callable class DockFrame(ttk.Frame): """ Base class for dockable panels in the ARTOS GUI. Features: - Title bar with controls (minimize/maximize/close) - Content area for child widgets - State management (visible/hidden/minimized) - Callbacks for dock events """ def __init__(self, parent: tk.Widget, title: str, on_close: Optional[Callable] = None, closable: bool = True, **kwargs): """ Args: parent: Parent widget title: Dock window title on_close: Optional callback when dock is closed closable: Whether the dock can be closed **kwargs: Additional Frame options """ super().__init__(parent, **kwargs) self.title = title self.on_close_callback = on_close self.closable = closable self.is_minimized = False self.is_visible = True self._create_ui() def _create_ui(self): """Create the dock frame UI components.""" # Title bar self.title_bar = ttk.Frame(self, relief=tk.RAISED, borderwidth=1) self.title_bar.pack(side=tk.TOP, fill=tk.X) # Title label self.title_label = ttk.Label( self.title_bar, text=self.title, font=('Arial', 10, 'bold'), padding=(5, 2) ) self.title_label.pack(side=tk.LEFT) # Control buttons frame btn_frame = ttk.Frame(self.title_bar) btn_frame.pack(side=tk.RIGHT) # Minimize button self.min_btn = ttk.Button( btn_frame, text="−", width=3, command=self.toggle_minimize ) self.min_btn.pack(side=tk.LEFT, padx=1) # Close button (if closable) if self.closable: self.close_btn = ttk.Button( btn_frame, text="✕", width=3, command=self.close ) self.close_btn.pack(side=tk.LEFT, padx=1) # Separator ttk.Separator(self, orient=tk.HORIZONTAL).pack(side=tk.TOP, fill=tk.X) # Content area - subclasses will populate this self.content_frame = ttk.Frame(self, padding=5) self.content_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True) def toggle_minimize(self): """Toggle between minimized and normal state.""" if self.is_minimized: self.restore() else: self.minimize() def minimize(self): """Minimize the dock (hide content, keep title bar).""" if not self.is_minimized: self.content_frame.pack_forget() self.is_minimized = True self.min_btn.configure(text="□") def restore(self): """Restore from minimized state.""" if self.is_minimized: self.content_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True) self.is_minimized = False self.min_btn.configure(text="−") def close(self): """Close the dock (hide completely).""" if self.closable: self.pack_forget() self.is_visible = False if self.on_close_callback: self.on_close_callback(self) def show(self): """Show the dock if hidden.""" if not self.is_visible: self.pack(side=tk.TOP, fill=tk.BOTH, expand=True) self.is_visible = True if self.is_minimized: self.restore() def set_title(self, new_title: str): """Update the dock title.""" self.title = new_title self.title_label.configure(text=new_title) # Override this in subclasses to populate content def populate_content(self): """ Override this method in subclasses to add widgets to content_frame. Called after the dock is initialized. """ pass