102 lines
3.2 KiB
Python
102 lines
3.2 KiB
Python
import tkinter as tk
|
|
from tkinter import ttk
|
|
from datetime import datetime
|
|
import typing
|
|
|
|
from shared_libs.common_tools import IconManager
|
|
|
|
if typing.TYPE_CHECKING:
|
|
from tkinter import Event
|
|
|
|
|
|
class LogWindow(ttk.Frame):
|
|
"""A Tkinter frame that provides a scrollable text widget for logging messages."""
|
|
|
|
def __init__(self, parent: tk.Misc, copy: str = "Copy") -> None:
|
|
"""
|
|
Initializes the LogWindow widget.
|
|
|
|
Args:
|
|
parent: The parent widget.
|
|
copy: The text label for the 'Copy' context menu item.
|
|
"""
|
|
super().__init__(parent)
|
|
|
|
self.icon_manager = IconManager()
|
|
|
|
log_container = tk.Frame(self)
|
|
# Let the main app control padding via the grid options
|
|
log_container.pack(fill="both", expand=True, padx=0, pady=0)
|
|
|
|
self.log_text: tk.Text = tk.Text(
|
|
log_container,
|
|
wrap=tk.WORD,
|
|
font=("Consolas", 9),
|
|
bg="#1e1e1e",
|
|
fg="#d4d4d4",
|
|
insertbackground="white",
|
|
selectbackground="#264f78",
|
|
height=10 # Give it a default height
|
|
)
|
|
|
|
log_scrollbar = ttk.Scrollbar(
|
|
log_container, orient="vertical", command=self.log_text.yview
|
|
)
|
|
self.log_text.configure(yscrollcommand=log_scrollbar.set)
|
|
|
|
self.log_text.pack(side="left", fill="both", expand=True)
|
|
log_scrollbar.pack(side="right", fill="y")
|
|
|
|
self.context_menu: tk.Menu = tk.Menu(self, tearoff=0)
|
|
self.context_menu.add_command(
|
|
label=copy, command=self.copy_text, image=self.icon_manager.get_icon('copy'), compound='left')
|
|
self.log_text.bind("<Button-3>", self.show_context_menu)
|
|
|
|
def log_message(self, message: str) -> None:
|
|
"""
|
|
Adds a timestamped message to the log view.
|
|
|
|
Args:
|
|
message: The message string to add.
|
|
"""
|
|
timestamp = datetime.now().strftime("%H:%M:%S")
|
|
log_entry = f"[{timestamp}] {message}\n"
|
|
self.log_text.insert(tk.END, log_entry)
|
|
self.log_text.see(tk.END)
|
|
self.log_text.update()
|
|
|
|
def show_text_menu(self, event: 'Event') -> None:
|
|
"""
|
|
Displays the context menu at the event's coordinates.
|
|
(Note: This seems to be a remnant, show_context_menu is used).
|
|
|
|
Args:
|
|
event: The tkinter event that triggered the menu.
|
|
"""
|
|
try:
|
|
self.context_menu.tk_popup(event.x_root, event.y_root)
|
|
finally:
|
|
self.context_menu.grab_release()
|
|
|
|
def copy_text(self) -> None:
|
|
"""Copies the currently selected text in the log widget to the clipboard."""
|
|
try:
|
|
selected_text = self.log_text.selection_get()
|
|
self.clipboard_clear()
|
|
self.clipboard_append(selected_text)
|
|
except tk.TclError:
|
|
# No Text selected
|
|
pass
|
|
|
|
def show_context_menu(self, event: 'Event') -> None:
|
|
"""
|
|
Shows the right-click context menu.
|
|
|
|
Args:
|
|
event: The tkinter Button-3 event.
|
|
"""
|
|
try:
|
|
self.context_menu.tk_popup(event.x_root, event.y_root)
|
|
finally:
|
|
self.context_menu.grab_release()
|