# 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 . from textual.containers import Vertical from textual.message import Message from textual.widget import Widget from textual.widgets import Button, Static class ThemeSelector(Widget): """Widget for selecting and applying Textual themes.""" class ThemeSelected(Message): """Message posted when a theme is selected.""" def __init__(self, theme_name: str): super().__init__() self.theme_name = theme_name AVAILABLE_THEMES = [ ("Textual Dark", "textual-dark"), ("Textual Light", "textual-light"), ("Nord", "nord"), ("Gruvbox", "gruvbox"), ("Catppuccin Mocha", "catppuccin-mocha"), ("Dracula", "dracula"), ("Tokyo Night", "tokyo-night"), ("Monokai", "monokai"), ("Flexoki", "flexoki"), ("Catppuccin Latte", "catppuccin-latte"), ("Solarized Light", "solarized-light"), ("Retro Terminal", "retro-terminal"), ("Amber Terminal", "amber-terminal"), # your custom theme ] def compose(self): yield Static("Theme Options", id="theme_title") with Vertical() as column: column.styles.width = "1fr" column.styles.height = "auto" for label, btn_id in self.AVAILABLE_THEMES: yield Button(label, id=f"set_theme_{btn_id}", compact=True) def on_button_pressed(self, event: Button.Pressed) -> None: button_id = event.button.id if button_id and button_id.startswith("set_theme_"): theme_name = button_id.replace("set_theme_", "") self.post_message(self.ThemeSelected(theme_name))