"""Gerenciador de temas para a interface do usuário.""" from typing import Dict, Any from enum import Enum class ThemeType(Enum): """Tipos de tema disponíveis.""" LIGHT = "light" DARK = "dark" class ThemeManager: """Gerenciador de temas da aplicação.""" def __init__(self, default_theme: ThemeType = ThemeType.DARK): """Inicializa o gerenciador de temas. Args: default_theme: Tema padrão a ser usado """ self.current_theme = default_theme self._themes = { ThemeType.LIGHT: self._get_light_theme(), ThemeType.DARK: self._get_dark_theme() } def get_current_theme(self) -> Dict[str, Any]: """Retorna o tema atual. Returns: Dicionário com as configurações do tema atual """ return self._themes[self.current_theme] def set_theme(self, theme: ThemeType) -> None: """Define o tema atual. Args: theme: Tipo de tema a ser definido """ self.current_theme = theme def toggle_theme(self) -> ThemeType: """Alterna entre os temas disponíveis. Returns: O novo tema ativo """ if self.current_theme == ThemeType.LIGHT: self.current_theme = ThemeType.DARK else: self.current_theme = ThemeType.LIGHT return self.current_theme def _get_light_theme(self) -> Dict[str, Any]: """Configurações do tema claro. Returns: Dicionário com as configurações do tema claro """ return { 'name': 'light', 'colors': { 'primary': '#667eea', 'secondary': '#764ba2', 'background': '#ffffff', 'surface': '#f8f9fa', 'card_background': '#ffffff', 'text_primary': '#495057', 'text_secondary': '#6c757d', 'text_muted': '#adb5bd', 'border': '#dee2e6', 'success': '#28a745', 'success_background': '#d4edda', 'success_border': '#c3e6cb', 'success_text': '#155724', 'warning': '#ffc107', 'warning_background': '#fff3cd', 'warning_border': '#ffeaa7', 'warning_text': '#856404', 'error': '#dc3545', 'info': '#007bff', 'gradient_start': '#667eea', 'gradient_end': '#764ba2', 'shadow': 'rgba(0,0,0,0.1)', 'shadow_hover': 'rgba(0,0,0,0.2)' }, 'css_variables': { '--bg-primary': '#ffffff', '--bg-secondary': '#f8f9fa', '--bg': '#ffffff', '--surface': '#f8f9fa', '--text-primary': '#495057', '--text-secondary': '#6c757d', '--border-color': '#dee2e6', '--shadow': '0 2px 4px rgba(0,0,0,0.1)', '--gradient': 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' } } def _get_dark_theme(self) -> Dict[str, Any]: """Configurações do tema escuro. Returns: Dicionário com as configurações do tema escuro """ return { 'name': 'dark', 'colors': { 'primary': '#4f46e5', 'secondary': '#7c3aed', 'background': '#0f172a', 'surface': '#1e293b', 'card_background': '#334155', 'text_primary': '#f1f5f9', 'text_secondary': '#cbd5e1', 'text_muted': '#94a3b8', 'border': '#475569', 'success': '#10b981', 'success_background': '#064e3b', 'success_border': '#065f46', 'success_text': '#34d399', 'warning': '#f59e0b', 'warning_background': '#451a03', 'warning_border': '#92400e', 'warning_text': '#fbbf24', 'error': '#ef4444', 'info': '#3b82f6', 'gradient_start': '#4f46e5', 'gradient_end': '#7c3aed', 'shadow': 'rgba(0,0,0,0.3)', 'shadow_hover': 'rgba(0,0,0,0.5)' }, 'css_variables': { '--bg-primary': '#0f172a', '--bg-secondary': '#1e293b', '--bg': '#0f172a', '--surface': '#1e293b', '--text-primary': '#f1f5f9', '--text-secondary': '#cbd5e1', '--border-color': '#475569', '--shadow': '0 4px 8px rgba(0,0,0,0.3)', '--gradient': 'linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%)' } } def get_css_variables(self) -> str: """Retorna as variáveis CSS do tema atual. Returns: String com as variáveis CSS formatadas """ theme = self.get_current_theme() variables = [] for var_name, var_value in theme['css_variables'].items(): variables.append(f" {var_name}: {var_value};") return ":root {\n" + "\n".join(variables) + "\n}" def get_custom_css(self) -> str: """Retorna o CSS customizado para o tema atual. Returns: String com o CSS customizado completo """ theme = self.get_current_theme() colors = theme['colors'] return f""" {self.get_css_variables()} /* Tema {theme['name'].title()} */ body {{ background-color: {colors['background']} !important; color: {colors['text_primary']} !important; }} body[data-theme="{theme['name']}"] {{ background-color: {colors['background']} !important; color: {colors['text_primary']} !important; }} .gradio-container {{ max-width: 1200px !important; margin: auto !important; background-color: {colors['background']} !important; color: {colors['text_primary']} !important; }} /* Botões */ .gr-button {{ transition: all 0.3s ease !important; background: {colors['gradient_start']} !important; border: none !important; color: white !important; border-radius: 8px !important; font-weight: 600 !important; }} .gr-button:hover {{ transform: translateY(-2px) !important; box-shadow: 0 8px 16px {colors['shadow_hover']} !important; background: {colors['gradient_end']} !important; }} /* Inputs e TextAreas */ .gr-textbox, .gr-number, .gr-dropdown {{ background-color: {colors['surface']} !important; border: 1px solid {colors['border']} !important; color: {colors['text_primary']} !important; border-radius: 8px !important; }} .gr-textbox textarea, .gr-textbox input {{ font-family: 'Courier New', monospace !important; background-color: {colors['surface']} !important; color: {colors['text_primary']} !important; border: none !important; }} /* Tabs */ .gr-tab-nav {{ background: {colors['surface']} !important; border-bottom: 1px solid {colors['border']} !important; }} .gr-tab-nav button {{ border-radius: 8px 8px 0 0 !important; background: {colors['card_background']} !important; color: {colors['text_primary']} !important; border: 1px solid {colors['border']} !important; border-bottom: none !important; }} .gr-tab-nav button.selected {{ background: {colors['primary']} !important; color: white !important; }} /* Cards e Containers */ .gr-panel, .gr-box {{ background-color: {colors['card_background']} !important; border: 1px solid {colors['border']} !important; border-radius: 12px !important; box-shadow: {colors['shadow']} !important; }} /* HTML Components */ .gr-html {{ background-color: transparent !important; }} /* JSON Viewer */ .gr-json {{ background-color: {colors['surface']} !important; border: 1px solid {colors['border']} !important; border-radius: 8px !important; color: {colors['text_primary']} !important; }} /* Scrollbars */ ::-webkit-scrollbar {{ width: 8px; height: 8px; }} ::-webkit-scrollbar-track {{ background: {colors['surface']}; border-radius: 4px; }} ::-webkit-scrollbar-thumb {{ background: {colors['border']}; border-radius: 4px; }} ::-webkit-scrollbar-thumb:hover {{ background: {colors['text_muted']}; }} /* Animações */ * {{ transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease !important; }} /* Loading Spinner */ .loading {{ border: 3px solid {colors['border']}; border-top: 3px solid {colors['primary']}; border-radius: 50%; animation: spin 1s linear infinite; }} @keyframes spin {{ 0% {{ transform: rotate(0deg); }} 100% {{ transform: rotate(360deg); }} }} """ # Instância global do gerenciador de temas theme_manager = ThemeManager(ThemeType.DARK)