139 lines
4.2 KiB
Python
139 lines
4.2 KiB
Python
# -*- 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
|