SXXXXXXX_Radian/radian_plugins/test_component/adapter.py
2025-11-12 13:36:07 +01:00

115 lines
4.6 KiB
Python

# C:/radian_plugins/test_component/adapter.py
import tkinter as tk
from tkinter import ttk
from typing import Optional
from pathlib import Path
# This import works because RADIAN was installed in editable mode.
from radian.components.base_component import BaseComponent, ConfigType
from radian.utils import logger
# Each component should have its own logger instance.
log = logger.get_logger(__name__)
class RadianAdapter(BaseComponent):
"""
A dummy component adapter for testing the RADIAN loading mechanism.
This class implements the full BaseComponent contract.
"""
def __init__(self):
log.info("TestComponent's adapter is being initialized...")
# The call to super().__init__() is important as it sets up
# the initial configuration by calling get_default_config().
super().__init__()
# NOTE: Tkinter variables are now created inside get_config_ui
# to ensure they are fresh each time the UI is built.
def get_name(self) -> str:
"""Returns the user-friendly name of the component."""
return "Test Component"
def get_description(self) -> str:
"""Returns a brief description of what the component does."""
return "A dummy component for demonstrating and testing the plugin system."
def get_default_config(self) -> ConfigType:
"""Defines the default configuration parameters for this component."""
return {
"test_parameter_1": "default_string_value",
"test_parameter_2": True
}
def get_icon_path(self) -> Optional[str]:
"""Returns the path to this component's icon."""
# The icon is expected to be in the same directory as this adapter file.
icon_path = Path(__file__).parent / "test_component.png"
if icon_path.exists():
return str(icon_path)
log.warning(f"Icon not found at: {icon_path}")
return None
def get_config_ui(self, parent: tk.Frame) -> Optional[tk.Frame]:
"""Creates the configuration UI for this test component."""
log.debug(f"Creating config UI for '{self.get_name()}'")
frame = ttk.Frame(parent, padding="10")
frame.columnconfigure(1, weight=1)
# --- Initialize Tkinter variables locally within this method ---
# This ensures they are new for each UI creation and avoids conflicts
# with previously destroyed widgets.
param1_var = tk.StringVar()
param2_var = tk.BooleanVar()
# --- UI Widgets ---
label1 = ttk.Label(frame, text="Test Parameter 1 (String):")
label1.grid(row=0, column=0, padx=5, pady=5, sticky="w")
entry1 = ttk.Entry(frame, textvariable=param1_var)
entry1.grid(row=0, column=1, padx=5, pady=5, sticky="ew")
check2 = ttk.Checkbutton(frame, text="Enable Test Feature", variable=param2_var)
check2.grid(row=1, column=0, columnspan=2, padx=5, pady=5, sticky="w")
# --- Nested helper functions to manage UI state ---
# These functions have access to the local tkinter variables.
def update_ui_from_config():
"""Helper to sync the UI with the current self.config state."""
param1_var.set(self.config.get("test_parameter_1", ""))
param2_var.set(self.config.get("test_parameter_2", False))
def update_config_from_ui(*args):
"""Helper to sync self.config with the current UI state."""
self.config["test_parameter_1"] = param1_var.get()
self.config["test_parameter_2"] = param2_var.get()
log.info(f"TestComponent config updated from UI: {self.config}")
# --- Load current config into UI variables ---
update_ui_from_config()
# --- Bind UI changes back to the config dictionary ---
param1_var.trace_add("write", update_config_from_ui)
param2_var.trace_add("write", update_config_from_ui)
return frame
def run(self, input_data: Optional[any] = None) -> any:
"""Executes the dummy logic of this component."""
log.info(f"--- Running '{self.get_name()}' ---")
if input_data:
log.info(f"Received input data: {input_data}")
log.info(f"Using configuration: {self.config}")
if self.config.get("test_parameter_2"):
log.info("Test Feature is ENABLED.")
else:
log.info("Test Feature is DISABLED.")
output_message = f"Output from {self.get_name()} with param1='{self.config.get('test_parameter_1')}'"
log.info("--- Finished running ---")
return output_message