keypresser/controller/ui_controller.py

112 lines
4.9 KiB
Python

import tkinter as tk
from tkinter import messagebox
import logging
logger = logging.getLogger(__name__)
class UIController:
def __init__(self, controller_main, view):
# controller_main is a reference to the main KeyPressController instance
self.controller_main = controller_main
self.view = view
logger.info("UIController: Initialized.")
def initial_ui_setup_after_view_is_ready(self):
"""
Performs UI-specific setup that relies on the view being fully initialized.
Called from controller.py after view reference is available.
"""
if self.view is None:
logger.error("UIController: initial_ui_setup_after_view_is_ready called but view is None!")
return
logger.info("UIController: Performing post-view-initialization UI setup.")
# Any view-dependent setup that was previously in KeyPressController's init_setup
# that directly interacts with self.view now lives here.
# Link View's StringVar traces for key input change
self.view.key_to_press_var.trace_add("write", lambda name, index, mode: self._on_key_input_change())
# Initial refresh of windows list for the UI
self.refresh_windows_ui()
# Initial check of start button state based on UI inputs
self._check_start_button_state_ui()
def _on_key_input_change(self):
"""Handles changes in the key input field, informs main controller."""
self.controller_main.set_key_input_from_ui(self.view.get_key_input())
self._check_start_button_state_ui()
def refresh_windows_ui(self):
"""
Refreshes the list of available windows in the View and updates Controller.
Calls model via controller_main to get window titles.
"""
current_selection = self.view.get_selected_window_title()
window_titles = self.controller_main.get_available_window_titles() # Get from model via main controller
display_window_titles = ["--- Select a Window ---"] + window_titles
if "--- Global Input (No Specific Window) ---" not in display_window_titles:
display_window_titles.insert(1, "--- Global Input (No Specific Window) ---")
new_selection = current_selection
if new_selection not in display_window_titles:
new_selection = "--- Select a Window ---"
elif current_selection == "--- Global Input (No Specific Window) ---":
new_selection = "--- Global Input (No Specific Window) ---"
self.view.update_window_list(display_window_titles, new_selection)
# Inform the main controller about the updated window selection
self.controller_main.set_window_selection_from_ui(new_selection)
logger.info(f"UIController: Refreshed window list. Found {len(window_titles)} active windows.")
self._check_start_button_state_ui()
def on_window_selected_ui(self):
"""Handles combobox selection event from View, informs main controller."""
selected_title = self.view.get_selected_window_title()
self.controller_main.set_window_selection_from_ui(selected_title)
self._check_start_button_state_ui()
def _check_start_button_state_ui(self):
"""
Determines if the start button should be enabled based on UI input validation.
Updates validation labels in the View directly.
"""
key_input_present = bool(self.view.get_key_input())
self.view.set_key_validation_visibility(not key_input_present)
selected_option = self.view.get_selected_window_title()
is_real_window_selected = (selected_option != "--- Select a Window ---" and selected_option in self.controller_main.get_available_window_titles())
is_global_input_selected = (selected_option == "--- Global Input (No Specific Window) ---")
valid_window_selected_for_start = is_real_window_selected or is_global_input_selected
self.view.set_window_validation_visibility(not valid_window_selected_for_start)
if key_input_present and valid_window_selected_for_start:
# Only enable the button if both are valid
self.view.start_button.config(state=tk.NORMAL)
logger.debug("UIController: Start button enabled.")
else:
self.view.start_button.config(state=tk.DISABLED)
logger.debug("UIController: Start button disabled (validation error).")
def show_ui_error_message(self, message):
"""Displays a messagebox error to the user via View."""
self.view.show_input_error(message)
def set_ui_running_state(self):
"""Updates UI elements to reflect running state."""
self.view.set_ui_state_running()
def set_ui_idle_state(self):
"""Updates UI elements to reflect idle state."""
self.view.set_ui_state_idle()
self._check_start_button_state_ui() # Re-check after returning to idle to ensure proper button state