183 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			183 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from textual.screen import ModalScreen
 | |
| from textual.widgets import Label, Select, TabbedContent, TabPane, Switch, Input, Rule, Static
 | |
| from textual.containers import Vertical, HorizontalGroup, VerticalGroup, VerticalScroll
 | |
| 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;
 | |
|         }
 | |
| 
 | |
|         Rule {
 | |
|             color: $boost;
 | |
|         }
 | |
| 
 | |
|         .thingy {
 | |
|             margin-top: 2;
 | |
|             text-style: bold;
 | |
|         }
 | |
| 
 | |
|         .setting {
 | |
|             padding: 0 2;
 | |
|             content-align: center middle;
 | |
|             margin-bottom: 1;
 | |
| 
 | |
|             .setting-name {
 | |
|                 text-style: bold;
 | |
|             }
 | |
| 
 | |
|             .setting-desc {
 | |
|                 text-style: dim;
 | |
|                 width: 100%;
 | |
|                 min-width: 30;
 | |
|             }
 | |
| 
 | |
|             VerticalGroup {
 | |
|                 width: 50%;
 | |
|                 min-width: 20;
 | |
|                 margin-right: 1;
 | |
|             }
 | |
| 
 | |
|             Select, Input {
 | |
|                 max-width: 30;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     """
 | |
| 
 | |
|     BINDINGS = [
 | |
|         Binding("escape", "close", "Close")
 | |
|     ]
 | |
| 
 | |
|     def __init__(self):
 | |
|         super().__init__()
 | |
| 
 | |
|     def action_close(self):
 | |
|         self.dismiss()
 | |
| 
 | |
|     def on_switch_changed(self, event: Switch.Changed):
 | |
|         if event.switch.id == "word-wrap":
 | |
|             self.app.query_one("#code-editor").soft_wrap = event.value
 | |
|             self.app.config_handler.set("editor", "word_wrap", str(int(event.value)))
 | |
|         elif event.switch.id == "line-numbers":
 | |
|             self.app.query_one("#code-editor").show_line_numbers = event.value
 | |
|             self.app.config_handler.set("editor", "line_numbers", str(int(event.value)))
 | |
|         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")
 | |
|         elif event.switch.id == "plugins-log":
 | |
|             self.app.config_handler.set("plugins", "log", str(int(event.value)))
 | |
|         elif event.switch.has_class("plugin-option"):
 | |
|             if event.switch.berry_changed_func != None:
 | |
|                 event.switch.berry_changed_func(event.switch.value)
 | |
| 
 | |
|     def on_select_changed(self, event: Select.Changed):
 | |
|         if event.select.id == "colour-theme":
 | |
|             self.app.theme = event.value
 | |
|             self.app.config_handler.set("appearance", "colour_theme", str(event.value))
 | |
| 
 | |
|     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))
 | |
|         elif event.input.has_class("plugin-option"):
 | |
|             if event.input.berry_changed_func != None:
 | |
|                 event.input.berry_changed_func(event.input.value)
 | |
| 
 | |
|     def compose(self):
 | |
|         with Vertical(id="window") as window:
 | |
|             window.border_title = "Settings"
 | |
|             with TabbedContent():
 | |
|                 with TabPane("Appearance"):
 | |
|                     with VerticalScroll():
 | |
|                         with HorizontalGroup(classes="setting"):
 | |
|                             with VerticalGroup():
 | |
|                                 yield Label("Colour Theme", classes="setting-name")
 | |
|                                 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
 | |
|                             )
 | |
| 
 | |
| 
 | |
|                 with TabPane("Editor"):
 | |
|                     with VerticalScroll():
 | |
|                         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")
 | |
|                             yield Switch(value=bool(int(self.app.config_handler.get("editor", "word_wrap"))), id="word-wrap")
 | |
|                         
 | |
|                         with HorizontalGroup(classes="setting"):
 | |
|                             with VerticalGroup():
 | |
|                                 yield Label("Line Numbers", classes="setting-name")
 | |
|                                 yield Label("Show line numbers in the editor.", classes="setting-desc")
 | |
|                             yield Switch(value=bool(int(self.app.config_handler.get("editor", "line_numbers"))), id="line-numbers")
 | |
|                 with TabPane("Plugins"):
 | |
|                     with VerticalScroll():
 | |
|                     
 | |
|                         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")
 | |
|                             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")
 | |
|                                 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")
 | |
|                             yield Input(value=self.app.config_handler.get("plugins", "log_timeout"), id="log-timeout", type="integer")
 | |
|                             
 | |
|                         yield Static("Plugin-defined Settings", classes="thingy")
 | |
|                         yield Rule(line_style="double")
 | |
| 
 | |
|                         for plugin_section, plugin_settings in self.app.config_handler.plugin_defined_settings.items():
 | |
|                             yield Static(f"{plugin_section}", classes="thingy")
 | |
|                             yield Rule()
 | |
| 
 | |
|                             for setting_name, setting in plugin_settings.items():
 | |
|                                 with HorizontalGroup(classes="setting"):
 | |
|                                     with VerticalGroup():
 | |
|                                         yield Label(setting_name, classes="setting-name")
 | |
|                                         yield Label(setting["description"], classes="setting-desc")
 | |
| 
 | |
|                                     value = self.app.config_handler.get(f"plugin_{plugin_section}", setting["option_name"])
 | |
| 
 | |
|                                     new_widget = None
 | |
|                                     if setting["type"] == bool:
 | |
|                                         value = bool(int(value))
 | |
|                                         new_widget = Switch(value=value)
 | |
|                                     elif setting["type"] == int:
 | |
|                                         new_widget = Input(value=value, type="integer", placeholder=setting["default_value"])
 | |
|                                     elif setting["type"] == float:
 | |
|                                         new_widget = Input(value=value, type="number", placeholder=setting["default_value"])
 | |
|                                     elif setting["type"] == str:
 | |
|                                         new_widget = Input(value=value, placeholder=setting["default_value"])
 | |
|                                     
 | |
|                                     new_widget.add_class("plugin-option")
 | |
|                                     setattr(new_widget, "berry_changed_func", setting['on_changed_func'])
 | |
|                                     yield new_widget | 
