From 979c748ae46ce548ce00cbd77d477b71c94f84f0 Mon Sep 17 00:00:00 2001 From: Henry Wallace Date: Thu, 13 Feb 2025 11:14:20 +0000 Subject: [PATCH 1/4] Install path was wrong for configuration --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 3477a54..e61b98f 100644 --- a/setup.py +++ b/setup.py @@ -9,5 +9,5 @@ "rich", ], extras_require={"develop": ["ipdb", "ipython" "black"]}, - package_data={"": ["*.tcss", "*.json"]}, + package_data={"": ["*.tcss", "*.yml"]}, ) From 046f6d5edf8f7edf2b5391b4e1cbf8069be1e880 Mon Sep 17 00:00:00 2001 From: Henry Wallace Date: Thu, 13 Feb 2025 12:08:45 +0000 Subject: [PATCH 2/4] Add additional detector view --- .../configuration/np02_configuration.yml | 8 +++ src/cider/screens/quit_screen.py | 5 +- src/cider/screens/shifter_view_screen.py | 41 +++++++++-- src/cider/utils/daq_conf_tree.py | 21 ++++-- src/cider/widgets/options_panel.py | 71 ++++++++++++------- 5 files changed, 109 insertions(+), 37 deletions(-) diff --git a/src/cider/configuration/np02_configuration.yml b/src/cider/configuration/np02_configuration.yml index aacf9f5..2e209d8 100644 --- a/src/cider/configuration/np02_configuration.yml +++ b/src/cider/configuration/np02_configuration.yml @@ -50,6 +50,7 @@ DetectorSystemMap: id: crp4-segment enabled_state: true disabled_state: false + enabled: true @@ -60,6 +61,13 @@ DetectorSystemMap: id: crp5-segment enabled_state: true disabled_state: false + - id: tp_generation_enabled + type: attribute + class: ReadoutApplication + affected_objects: [runp02srv002eth0, runp02srv003eth0] + enabled_state: true + disabled_state: false + enabled: true PDS: diff --git a/src/cider/screens/quit_screen.py b/src/cider/screens/quit_screen.py index 6d234b9..240ff49 100644 --- a/src/cider/screens/quit_screen.py +++ b/src/cider/screens/quit_screen.py @@ -68,7 +68,8 @@ def on_button_pressed(self, event: Button.Pressed) -> None: options = main_screen.query_one("OptionPanel") if event.button.id == "quit_screen_savequit_button": # HACK: This is a hack to save correctly - options.save_copy() + options.save_main() + options.save_backup() self._saved_configuration_name = options.saved_configuration self.app.exit(self.message()) @@ -79,7 +80,9 @@ def on_button_pressed(self, event: Button.Pressed) -> None: if options.saved_configuration is None: self.app.exit("[bold red]Exited without saving.") else: + options.save_backup() self._saved_configuration_name = options.saved_configuration + # To be sure! self.app.exit(self.message(True)) else: self.app.pop_screen() diff --git a/src/cider/screens/shifter_view_screen.py b/src/cider/screens/shifter_view_screen.py index 631ecb5..91d2965 100644 --- a/src/cider/screens/shifter_view_screen.py +++ b/src/cider/screens/shifter_view_screen.py @@ -5,7 +5,6 @@ from textual.css.query import NoMatches from textual.reactive import reactive - from cider.interfaces.controller.config_wrapper import ConfigurationWrapper from cider.widgets.single_component_panel import SingleComponentEnableDisablePanel from cider.widgets.multicomponent_panel import MultiComponentEnableDisablePanel @@ -14,7 +13,7 @@ from cider.widgets.file_io_panel import FileIOPanel from cider.utils.consolidate_file import ConsolidateFile from cider.utils.daq_conf_tree import DaqConfTree, ComponentLevelTree - +from cider.screens.quit_screen import QuitScreen from pathlib import Path import os @@ -34,7 +33,7 @@ def remove_popup(self): class ShifterViewScreen(Screen): - + TMP_CONFIG = Path(f"/tmp/shifter_configs-{os.getlogin()}/tmp_config.data.xml") changed_session = False @@ -64,6 +63,9 @@ def __init__( self._config_folder = config_folder self._output_directory = output_directory + self._configuration = None + self._session = None + def compose(self): """ Generate the screen layout @@ -102,7 +104,7 @@ def compose(self): id="systematic_map_tabs", classes="systematic_map_tabs", ): - with TabPane("Detector View", id="full_system_map_tab"): + with TabPane("Configuration View", id="full_system_map_tab"): yield ScrollableContainer( Static( DaqConfTree(None, None).print_tree(), @@ -111,6 +113,18 @@ def compose(self): id="tree_view_full_container", classes="tree_view_full_container", ) + with TabPane("Detector System View", id="det_system_tab"): + yield ScrollableContainer( + Static( + ComponentLevelTree( + None, None, self.detector_system_map + ).print_tree(), + id="tree_view_det", + ), + id="det_view_trigger_container", + ) + + with TabPane("Trigger View", id="trigger_system_tab"): yield ScrollableContainer( Static( @@ -200,6 +214,10 @@ def open_new_file(self): if not session_name or not buffer_config: pass + self._configuration = buffer_config + self._session = session_name + + for a in self.query("EnableDisablePanel"): a.open_new_session(buffer_config, session_name) a.refresh(recompose=True) @@ -218,11 +236,22 @@ def update_trees(self, configuration: ConfigurationWrapper, session: str): self.query_one("#tree_view_full").update(main_tree.print_tree()) # For trigger info we need to hack disabled = main_tree.disabled_objs + + # We can also do a component level tree + + detector_states = self.query_one("#detector_subsystem_panel").get_full_state_info() + detector_tree = ComponentLevelTree( + configuration, session, detector_states, "Detector Systems", disabled + ) + + self.query_one("#tree_view_det").update(detector_tree.print_tree()) + + # We also want trigger states trigger_states = self.query_one("#trigger_panel").get_full_state_info() - trigger_tree = ComponentLevelTree( - configuration, session, trigger_states, disabled + configuration, session, trigger_states, "Triggers", disabled ) + self.query_one("#tree_view_trigger").update(trigger_tree.print_tree()) diff --git a/src/cider/utils/daq_conf_tree.py b/src/cider/utils/daq_conf_tree.py index 3582ffc..7906da2 100644 --- a/src/cider/utils/daq_conf_tree.py +++ b/src/cider/utils/daq_conf_tree.py @@ -157,16 +157,18 @@ def __init__( configuration: ConfigurationWrapper | None = None, session: str | None = None, system_info: dict = {}, + label: str = "", disabled_items=[], ): self._system_info = system_info self._disabled_items = disabled_items self._extractor = SystemInfoExtractor(configuration, session) - + self._label = label + super().__init__(configuration, session) def generate_tree(self): - self._tree = Tree("[bold deep_pink4] Triggers") + self._tree = Tree(f"[bold deep_pink4] {self._label}") trigger_labels = list(self._system_info.keys()) @@ -193,9 +195,16 @@ def generate_tree(self): # Okay now we can grab each component - specific_comps = GetObjectsInSessionAction(self._configuration)( - session_dal, subsystem["class"], subsystem["affected_objects"] - ) + if subsystem['type']=='attribute': + specific_comps = GetObjectsInSessionAction(self._configuration)( + session_dal, subsystem["class"], subsystem["affected_objects"] + ) + + system_name = subsystem['id'] + + else: + specific_comps = [ca.GetDalObjectAction(self._configuration)(subsystem["id"], subsystem["class"])] + system_name = "" for c in specific_comps: if enabled and c not in self._disabled_items: @@ -206,7 +215,7 @@ def generate_tree(self): text = "[bold]DISABLED" trigger_tree.add( - f"[{colour}]{ca.GetAttributeAction(self._configuration)(c, 'id')} {text}" + f"[{colour}]{ca.GetAttributeAction(self._configuration)(c, 'id')} {system_name} {text}" ) return self._tree diff --git a/src/cider/widgets/options_panel.py b/src/cider/widgets/options_panel.py index 25ce7e4..9abe9e5 100644 --- a/src/cider/widgets/options_panel.py +++ b/src/cider/widgets/options_panel.py @@ -72,30 +72,53 @@ def compose(self): classes="options_panel", ) - def save_copy(self): - # Check output directory - main_output_path = Path(f"{self._output_directory}/current_config") - backup_output_path = Path( - f"{self._output_directory}/old_configs/run_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}" - ) - - if main_output_path.is_dir(): - shutil.rmtree(main_output_path) - - main_output_path.mkdir(parents=True, exist_ok=True) - backup_output_path.mkdir(parents=True, exist_ok=True) - - main_copy = f"{main_output_path}/{self.generate_output_name()}" - backup_copy = f"{backup_output_path}/{self.generate_output_name()}" - - # Make current copy - ca.CopyFullConfigurationAction(self._configuration)(main_copy) - self.generate_change_log(main_copy) - # Make backup copy - ca.CopyFullConfigurationAction(self._configuration)(backup_copy) - self.generate_change_log(backup_copy) - self._saved_configuration = main_copy + def save_to_path(self, dir_path, name): + dir_path = Path(dir_path) + + # Clear it + if dir_path.is_dir(): + shutil.rmtree(dir_path) + + dir_path.mkdir(parents=True, exist_ok=True) + + output_file_path = f"{dir_path}/{name}" + ca.CopyFullConfigurationAction(self._configuration)(output_file_path) + self.generate_change_log(output_file_path) + + return output_file_path + + # Wrappers + def save_main(self): + self._saved_configuration = self.save_to_path(f"{self._output_directory}/current_config", self.generate_output_name()) + + def save_backup(self): + self.save_to_path(f"{self._output_directory}/old_configs/run_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}", self.generate_output_name()) + + # def save_copy(self): + # # Check output directory + # main_output_path = Path(f"{self._output_directory}/current_config") + # backup_output_path = Path( + # f"{self._output_directory}/old_configs/run_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}" + # ) + + # if main_output_path.is_dir(): + # shutil.rmtree(main_output_path) + + # main_output_path.mkdir(parents=True, exist_ok=True) + # backup_output_path.mkdir(parents=True, exist_ok=True) + + # main_copy = f"{main_output_path}/{self.generate_output_name()}" + # backup_copy = f"{backup_output_path}/{self.generate_output_name()}" + + # # Make current copy + # ca.CopyFullConfigurationAction(self._configuration)(main_copy) + # self.generate_change_log(main_copy) + # # Make backup copy + # ca.CopyFullConfigurationAction(self._configuration)(backup_copy) + # self.generate_change_log(backup_copy) + + # self._saved_configuration = main_copy def generate_output_name(self): if self._configuration is None: @@ -143,7 +166,7 @@ def on_button_pressed(self, event: Button.Pressed): self.app.push_screen(HelpScreen(classes="pop_up_screen")) elif event.button.id == "create_button": try: - self.save_copy() + self.save_main() except Exception as e: raise e From 3d3db64b01b781e9a8148d63cf2cda8bbc610d67 Mon Sep 17 00:00:00 2001 From: Henry Wallace Date: Thu, 13 Feb 2025 14:30:39 +0000 Subject: [PATCH 3/4] Fixes bug where buttons were still pressable when no session selected. --- src/cider/apps/shifter_view.tcss | 9 ++- .../configuration/np02_configuration.yml | 24 +++---- src/cider/screens/shifter_view_screen.py | 15 +---- src/cider/widgets/file_io_panel.py | 30 +++++---- src/cider/widgets/options_panel.py | 63 +++++++++++-------- src/cider/widgets/popup_message.py | 13 ++++ 6 files changed, 86 insertions(+), 68 deletions(-) create mode 100644 src/cider/widgets/popup_message.py diff --git a/src/cider/apps/shifter_view.tcss b/src/cider/apps/shifter_view.tcss index 03bbcd8..ce5edae 100644 --- a/src/cider/apps/shifter_view.tcss +++ b/src/cider/apps/shifter_view.tcss @@ -186,8 +186,15 @@ SelectCurrent{ width: 100%; height: auto; padding: 1; - background: $error; text-style: bold; layer: overlay; content-align: center middle; } + +.popup_failure{ + background: $error; +} + +.popup_success{ + background: $success +} \ No newline at end of file diff --git a/src/cider/configuration/np02_configuration.yml b/src/cider/configuration/np02_configuration.yml index 2e209d8..a69bcdb 100644 --- a/src/cider/configuration/np02_configuration.yml +++ b/src/cider/configuration/np02_configuration.yml @@ -1,24 +1,21 @@ # Triggers TriggerMap: - TPG Enabled CRP4: + TPG Enabled CRP 4 and 5: subsystems: - id: tp_generation_enabled type: attribute class: ReadoutApplication affected_objects: [runp02srv001eth0, runp02srv003eth1] enabled_state: true - disabled_state: false - enabled: true - - TPG Enabled CRP5: - subsystems: + disabled_state: false - id: tp_generation_enabled type: attribute class: ReadoutApplication affected_objects: [runp02srv002eth0, runp02srv003eth0] enabled_state: true disabled_state: false - + + enabled: true TPG Enabled APA: @@ -31,12 +28,12 @@ TriggerMap: disabled_state: false enabled: true - TA Enabled: + TPG Enabled PDS: subsystems: - - id: ta_generation_enabled + - id: tp_generation_enabled type: attribute class: ReadoutApplication - affected_objects: null + affected_objects: [runp04srv026flx4] enabled_state: true disabled_state: false enabled: true @@ -61,13 +58,6 @@ DetectorSystemMap: id: crp5-segment enabled_state: true disabled_state: false - - id: tp_generation_enabled - type: attribute - class: ReadoutApplication - affected_objects: [runp02srv002eth0, runp02srv003eth0] - enabled_state: true - disabled_state: false - enabled: true PDS: diff --git a/src/cider/screens/shifter_view_screen.py b/src/cider/screens/shifter_view_screen.py index 91d2965..45389b6 100644 --- a/src/cider/screens/shifter_view_screen.py +++ b/src/cider/screens/shifter_view_screen.py @@ -13,23 +13,12 @@ from cider.widgets.file_io_panel import FileIOPanel from cider.utils.consolidate_file import ConsolidateFile from cider.utils.daq_conf_tree import DaqConfTree, ComponentLevelTree -from cider.screens.quit_screen import QuitScreen from pathlib import Path import os import yaml - -class PopupMessage(Static): - """A custom widget for displaying pop-up messages.""" - - def on_mount(self): - # Automatically remove the pop-up after 3 seconds - self.set_timer(10.0, self.remove_popup) - - def remove_popup(self): - """Remove the pop-up from the DOM.""" - self.remove() +from cider.widgets.popup_message import PopupMessage class ShifterViewScreen(Screen): @@ -170,7 +159,7 @@ def show_popup(self, message: str): self.remove_popup() # Create and mount the pop-up - popup = PopupMessage(message, classes="popup") + popup = PopupMessage(message, classes="popup popup_failure") self.query_one("#main_container").mount(popup) def remove_popup(self): diff --git a/src/cider/widgets/file_io_panel.py b/src/cider/widgets/file_io_panel.py index 393b7e0..2c5b44e 100644 --- a/src/cider/widgets/file_io_panel.py +++ b/src/cider/widgets/file_io_panel.py @@ -125,10 +125,15 @@ def get_number_of_sessions(cls, config_file_path: str) -> int: return n_sessions def on_select_changed(self, event: Select.Changed): - if event.value == Select.BLANK: - return if event.select.id == "select_file": + if event.value == Select.BLANK: + self._selected_config_name = None + self._selected_session_name = None + self.query_one("#select_session").set_options([]) + return + + self._selected_config_name: str = event.value self._configuration = ConfigurationWrapper(self._selected_config_name) session_list = [ @@ -169,18 +174,21 @@ class Deconfigured(Message): def __init__(self): super().__init__() + def deconfigure(self): + self._selected_config_name = "" + self._configuration = None + self._selected_session_name = Select.BLANK + self.query_one("#select_session").set_options([]) + self.query_one("#file_io_panel_message").update( + "[bold medium_violet_red] No file loaded\n " + ) + self.post_message(self.Deconfigured()) + + def on_button_pressed(self): if self._selected_config_name and self._selected_session_name: self.query_one("#file_io_panel_message").update( f" [bold green]Current Config[/bold green]: [deep_pink4]{self._configuration.file_name}[/deep_pink4]\n [bold green]Session[/bold green]: [deep_pink4]{self._selected_session_name}" ) else: - self._selected_config_name = "" - self._configuration = None - self._selected_session_name = Select.BLANK - self.query_one("#select_session").set_options([]) - self.query_one("#file_io_panel_message").update( - "[bold medium_violet_red] No file loaded\n " - ) - self.post_message(self.Deconfigured()) - return + self.deconfigure() \ No newline at end of file diff --git a/src/cider/widgets/options_panel.py b/src/cider/widgets/options_panel.py index 9abe9e5..7e9e655 100644 --- a/src/cider/widgets/options_panel.py +++ b/src/cider/widgets/options_panel.py @@ -1,9 +1,12 @@ import cider.interfaces.actions.actions as ca from cider.interfaces.controller.config_wrapper import ConfigurationWrapper - from cider.screens.quit_screen import QuitScreen from cider.screens.help_screen import HelpScreen +from cider.widgets.popup_message import PopupMessage + +from textual.reactive import reactive +from textual.css.query import NoMatches from textual.containers import Vertical from textual.visual import SupportsVisual from textual.widgets import Button, Static @@ -13,6 +16,8 @@ class OptionPanel(Static): + show_popup = reactive(False) + def __init__( self, configuration: ConfigurationWrapper | None, @@ -48,6 +53,32 @@ def __init__( def saved_configuration(self): return self._saved_configuration + def show_popup(self, message: str): + """ + Display a pop-up message on the screen. + """ + # Remove any existing pop-up to avoid duplicates + self.remove_popup() + + # Create and mount the pop-up + popup = PopupMessage(message, classes="popup popup_success") + + main_screen = self.app.get_screen("shifter_view_screen") + main_screen.query_one("#main_container").mount(popup) + + def remove_popup(self): + """ + Remove any existing pop-up from the screen. + """ + try: + # Find and remove any existing pop-up + existing_popup = self.query_one(".popup", expect_type=PopupMessage) + existing_popup.remove() + except NoMatches: + # No pop-up to remove + pass + + def compose(self): disable_buttons = self._configuration is None or self._session_name is None @@ -86,6 +117,11 @@ def save_to_path(self, dir_path, name): ca.CopyFullConfigurationAction(self._configuration)(output_file_path) self.generate_change_log(output_file_path) + self.show_popup( + f"[white]Configuration saved to [bold grey3]{output_file_path}[/bold grey3]" + ) + + return output_file_path # Wrappers @@ -95,31 +131,6 @@ def save_main(self): def save_backup(self): self.save_to_path(f"{self._output_directory}/old_configs/run_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}", self.generate_output_name()) - # def save_copy(self): - # # Check output directory - # main_output_path = Path(f"{self._output_directory}/current_config") - # backup_output_path = Path( - # f"{self._output_directory}/old_configs/run_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}" - # ) - - # if main_output_path.is_dir(): - # shutil.rmtree(main_output_path) - - # main_output_path.mkdir(parents=True, exist_ok=True) - # backup_output_path.mkdir(parents=True, exist_ok=True) - - # main_copy = f"{main_output_path}/{self.generate_output_name()}" - # backup_copy = f"{backup_output_path}/{self.generate_output_name()}" - - # # Make current copy - # ca.CopyFullConfigurationAction(self._configuration)(main_copy) - # self.generate_change_log(main_copy) - # # Make backup copy - # ca.CopyFullConfigurationAction(self._configuration)(backup_copy) - # self.generate_change_log(backup_copy) - - # self._saved_configuration = main_copy - def generate_output_name(self): if self._configuration is None: return diff --git a/src/cider/widgets/popup_message.py b/src/cider/widgets/popup_message.py new file mode 100644 index 0000000..216c3dd --- /dev/null +++ b/src/cider/widgets/popup_message.py @@ -0,0 +1,13 @@ +from textual.widgets import Static + + +class PopupMessage(Static): + """A custom widget for displaying pop-up messages.""" + + def on_mount(self): + # Automatically remove the pop-up after 3 seconds + self.set_timer(5.0, self.remove_popup) + + def remove_popup(self): + """Remove the pop-up from the DOM.""" + self.remove() \ No newline at end of file From 470e26b48c73faa3ebf69c5d76f8dd31a65bb4a2 Mon Sep 17 00:00:00 2001 From: Henry Wallace Date: Thu, 13 Feb 2025 14:58:00 +0000 Subject: [PATCH 4/4] update help --- src/cider/screens/help_screen.py | 33 +++++++++++++++--------- src/cider/screens/shifter_view_screen.py | 6 ++--- src/cider/widgets/enable_disable_base.py | 19 ++++++++++++++ 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/src/cider/screens/help_screen.py b/src/cider/screens/help_screen.py index 45747d6..ae55783 100644 --- a/src/cider/screens/help_screen.py +++ b/src/cider/screens/help_screen.py @@ -25,18 +25,27 @@ def message(self): """\ [bold]Hello and welcome to the DAQ Shifter interface!![/bold] - To get started, please select a file from the dropdown menu and then select a session. - The configuration will be copied, and you can start enabling/disabling things in the detector. - - Currently, 3 options are available: - - [bold]Detector Subsystem[/bold] - - [bold]Dataflow Applications[/bold] - - [bold]Triggers[/bold] - - You can enable/disable these options by clicking on the buttons. - When you're happy, you can save/copy + quit the configuration editor and run it through DRUNC. - - In addition, you can reset all changes by pressing the reset button. + To get started, please select a file from the dropdown menu and then select a session to modify. Press "open" to load the session. + + Currently there are 3 categories of objects that can be enabled or disabled: + - [bold]Detector subsystems[/bold]: For example the APAs, PDS, etc. + - [bold]The Trigger System[/bold]: Triggers to enable/disable including trigger primitive generation + - [bold]Dataflow applications[/bold]: Objects that control dataflow + + To disable/enable items simply press the buttons on the left side of the screen. Each set of objects is given its own tab. + In addition, we provide 3 views of the detector configuration, although this is mostly intended for expert use. + - [bold]Configuration view[/bold]: View a tree describing detector configuration + - [bold]Detector system view[/bold]: Summary of detector subsystems which are enabled/disabled + - [bold]Trigger View[/bold]: A summary of triggers/trigger objects which are enabled/disabled + + Once you have made the desired changes, press the "Create" button to save the configuration. By default the current configuration is saved in the /current_config directory. + Older configurations are automatically moved to /old_configs/run_ when a new configuration is saved. + + If you are unhappy with changes + want to revert to the original configuration, press the "Reset" button. + + Finally to quit the interface, press the "Quit" button. The configuration can be run in drunc using the command provided after quitting. + + If you have any questions, please contact the DAQ shifter on duty. Enjoy your shift!gi """ ) diff --git a/src/cider/screens/shifter_view_screen.py b/src/cider/screens/shifter_view_screen.py index 45389b6..2803e7b 100644 --- a/src/cider/screens/shifter_view_screen.py +++ b/src/cider/screens/shifter_view_screen.py @@ -64,7 +64,7 @@ def compose(self): with Grid(id="enable_disable_panel_container"): with TabbedContent(id="selection_tabs"): - with TabPane("Detector Component", id="detector_subsystem_tab"): + with TabPane("Detector Subsystems", id="detector_subsystem_tab"): yield MultiComponentEnableDisablePanel( None, None, @@ -216,8 +216,8 @@ def open_new_file(self): def on_enable_disable_panel_changed(self, message: EnableDisablePanel.Changed): for a in self.query("EnableDisablePanel"): - a.refresh(recompose=True) - + a.update_button_styles() + self.update_trees(message.configuration, message.session) def update_trees(self, configuration: ConfigurationWrapper, session: str): diff --git a/src/cider/widgets/enable_disable_base.py b/src/cider/widgets/enable_disable_base.py index f2d7ad8..c588844 100644 --- a/src/cider/widgets/enable_disable_base.py +++ b/src/cider/widgets/enable_disable_base.py @@ -102,6 +102,7 @@ def on_button_pressed(self, event: Button.Pressed): return self._button_action(objs_affected, button_name) + self.update_button_styles() self.post_message(self.Changed(self._configuration, self._session_name)) def _button_action(self, objs_affected, button_name): @@ -145,3 +146,21 @@ def get_current_states(self): def get_full_state_info(self): return self._button_list + + def update_button_styles(self): + """Update the styles of the buttons based on their current state.""" + for button, information in self._button_list.items(): + button_id = button.replace(" ", "_") + "_button" + try: + button_widget = self.query_one(f"#{button_id}", Button) + except: + return + + if self.check_is_disabled(button, information): + button_widget.remove_class("detector_subsystem_button_enabled") + button_widget.add_class("detector_subsystem_button_disabled") + button_widget.label = f"{button} (Disabled)" + else: + button_widget.remove_class("detector_subsystem_button_disabled") + button_widget.add_class("detector_subsystem_button_enabled") + button_widget.label = f"{button} (Enabled)" \ No newline at end of file