# Copyright (C) 2025 James Brotosky, Brandon Wickline # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . """ Policy Selector Screen Module Provides a Textual Screen wrapper for the PolicySelector widget that manages the policy selection workflow. """ import logging from textual.app import ComposeResult from textual.binding import Binding from textual.screen import Screen from textual.widgets import Footer, Header from TUI.Widgets.policyselector import PolicySelector logger = logging.getLogger(__name__) class PolicySelectorScreen(Screen): """ A Textual Screen for policy selection in agent move operations. This screen wraps the PolicySelector widget and manages the workflow of selecting a target policy for bulk agent movements. Attributes: policies: List of available policies (Policy objects or DataFrame). agent_move_operations: Reference to the parent AgentMoveOperations widget. """ BINDINGS = [ Binding("escape", "go_back", "Back"), Binding("q", "main_menu", "Main Menu"), ] CSS = """ Screen { layout: vertical; background: $surface; } """ def __init__( self, policies, agent_move_operations=None, ): """ Initialize the PolicySelectorScreen. Args: policies: List of available policies to display. agent_move_operations: Reference to parent AgentMoveOperations widget. Used to call back when policy selection is confirmed. """ super().__init__() self.policies = policies self.agent_move_operations = agent_move_operations def compose(self) -> ComposeResult: """Create the PolicySelector widget.""" yield Header(show_clock=True) yield PolicySelector(self.policies) yield Footer() def action_go_back(self) -> None: """Handle escape key to go back one screen.""" self.app.pop_screen() def action_main_menu(self) -> None: """Handle q key to go back to main menu.""" while len(self.app.screen_stack) > 2: self.app.pop_screen() def on_policy_selector_policy_selected( self, message: PolicySelector.PolicySelected ) -> None: """ Handle policy selection from the PolicySelector widget. When a policy is selected, this handler: 1. Closes the selector screen 2. Calls the parent AgentMoveOperations to execute the move Args: message (PolicySelector.PolicySelected): Contains the selected policy. """ # Pop this screen to return to AgentMoveOperations self.app.pop_screen() # Call parent widget's method to execute the move if self.agent_move_operations: self.agent_move_operations._execute_move_to_policy(message.policy)