2025-10-29 13:11:51 +11:00
from textual . screen import ModalScreen
2025-10-30 07:53:19 +11:00
from textual . widgets import Label , Select , TabbedContent , TabPane , Switch , Input
2025-10-29 13:11:51 +11:00
from textual . containers import Vertical , HorizontalGroup , VerticalGroup
from textual . binding import Binding
class SettingsScreen ( ModalScreen ) :
border_title = " Settings "
DEFAULT_CSS = """
SettingsScreen {
align : center middle ;
#window {
border : panel $ primary ;
background : $ background ;
width : 65 % ;
height : 65 % ;
padding : 1 ;
}
TabPane {
padding : 1 ;
}
. setting {
padding : 0 2 ;
2025-10-29 21:06:34 +11:00
content - align : center middle ;
2025-10-30 07:53:19 +11:00
margin - bottom : 1 ;
2025-10-29 21:06:34 +11:00
2025-10-29 13:11:51 +11:00
. setting - name {
text - style : bold ;
}
2025-10-29 21:06:34 +11:00
2025-10-29 13:11:51 +11:00
. setting - desc {
text - style : dim ;
2025-10-29 15:31:56 +11:00
width : 100 % ;
min - width : 30 ;
2025-10-29 13:11:51 +11:00
}
2025-10-29 21:06:34 +11:00
2025-10-29 13:11:51 +11:00
VerticalGroup {
2025-10-29 15:31:56 +11:00
width : 50 % ;
min - width : 20 ;
2025-10-30 07:53:19 +11:00
margin - right : 1 ;
2025-10-29 15:31:56 +11:00
}
2025-10-30 07:53:19 +11:00
Select , Input {
2025-10-29 21:06:34 +11:00
max - width : 30 ;
2025-10-29 13:11:51 +11:00
}
}
}
"""
BINDINGS = [
Binding ( " escape " , " close " , " Close " )
]
2025-10-30 06:59:20 +11:00
def __init__ ( self ) :
super ( ) . __init__ ( )
2025-10-29 13:11:51 +11:00
def action_close ( self ) :
self . dismiss ( )
2025-10-30 06:59:20 +11:00
def on_switch_changed ( self , event : Switch . Changed ) :
if event . switch . id == " word-wrap " :
self . app . query_one ( " #code-editor " ) . soft_wrap = event . value
2025-10-30 07:20:01 +11:00
self . app . config_handler . set ( " editor " , " word_wrap " , str ( int ( event . value ) ) )
2025-10-30 07:53:19 +11:00
elif event . switch . id == " plugins-enabled " :
self . app . config_handler . set ( " plugins " , " enabled " , str ( int ( event . value ) ) )
self . notify ( " Restart for changes to apply. " , title = " Restart Required " , severity = " warning " )
2025-10-30 12:38:14 +11:00
elif event . switch . id == " plugins-log " :
self . app . config_handler . set ( " plugins " , " log " , str ( int ( event . value ) ) )
2025-10-30 06:59:20 +11:00
def on_select_changed ( self , event : Select . Changed ) :
if event . select . id == " colour-theme " :
self . app . theme = event . value
2025-10-30 07:20:01 +11:00
self . app . config_handler . set ( " appearance " , " colour_theme " , str ( event . value ) )
2025-10-30 06:59:20 +11:00
2025-10-30 12:38:14 +11:00
def on_input_changed ( self , event : Input . Changed ) :
if not event . input . is_valid : return
if event . input . id == " log-timeout " :
self . app . config_handler . set ( " plugins " , " log_timeout " , str ( event . input . value ) )
2025-10-29 13:11:51 +11:00
def compose ( self ) :
with Vertical ( id = " window " ) as window :
window . border_title = " Settings "
with TabbedContent ( ) :
2025-10-29 15:31:56 +11:00
with TabPane ( " Appearance " ) :
with HorizontalGroup ( classes = " setting " ) :
with VerticalGroup ( ) :
yield Label ( " Colour Theme " , classes = " setting-name " )
2025-10-30 06:59:20 +11:00
yield Label ( " Colour theme used for the entire Berry app. You can get more themes with plugins! " , classes = " setting-desc " )
yield Select . from_values (
( theme_name for theme_name in self . app . _registered_themes . keys ( ) if theme_name != " textual-ansi " ) ,
allow_blank = False ,
id = " colour-theme " ,
value = self . app . theme
)
2025-10-29 13:11:51 +11:00
with TabPane ( " Editor " ) :
with HorizontalGroup ( classes = " setting " ) :
with VerticalGroup ( ) :
yield Label ( " Word Wrap " , classes = " setting-name " )
yield Label ( " Enable word wrap in the code editor. " , classes = " setting-desc " )
2025-10-30 07:20:01 +11:00
yield Switch ( value = bool ( int ( self . app . config_handler . get ( " editor " , " word_wrap " ) ) ) , id = " word-wrap " )
2025-10-29 21:06:34 +11:00
with TabPane ( " Plugins " ) :
2025-10-30 07:53:19 +11:00
2025-10-29 21:06:34 +11:00
with HorizontalGroup ( classes = " setting " ) :
with VerticalGroup ( ) :
yield Label ( " Plugins Enabled " , classes = " setting-name " )
yield Label ( " Enable or disable Lua plugins. This requires a restart. " , classes = " setting-desc " )
2025-10-30 07:53:19 +11:00
yield Switch ( value = bool ( int ( self . app . config_handler . get ( " plugins " , " enabled " ) ) ) , id = " plugins-enabled " )
with HorizontalGroup ( classes = " setting " ) :
with VerticalGroup ( ) :
yield Label ( " Plugins Log " , classes = " setting-name " )
yield Label ( " Show the plugin loader log on startup. " , classes = " setting-desc " )
yield Switch ( value = bool ( int ( self . app . config_handler . get ( " plugins " , " log " ) ) ) , id = " plugins-log " )
with HorizontalGroup ( classes = " setting " ) :
with VerticalGroup ( ) :
yield Label ( " Log Timeout " , classes = " setting-name " )
2025-10-30 12:38:14 +11:00
yield Label ( " How many seconds before the log automatically closes. This gets overriden by the [b]Plugins Log[/] option. The window doesn ' t automatically close if there was an error. If this is set to -1, the log will not close automatically. " , classes = " setting-desc " )
2025-10-30 07:53:19 +11:00
yield Input ( value = self . app . config_handler . get ( " plugins " , " log_timeout " ) , id = " log-timeout " , type = " integer " )