diff --git a/config/settings.toml b/config/settings.toml index e5996e8e..c0f0413d 100644 --- a/config/settings.toml +++ b/config/settings.toml @@ -1,18 +1,24 @@ -theme="default" -font="firacode" -font_size=13 - +theme = "dark" +font = "Fira Code" +font_size = 13 +cursor_style = "line" +auto_save = false +tab_size = 4 +show_minimap = false +render_indent_guides = false +show_breadcrumbs = false +show_line_numbers = false [testing] -font_size=14 -tab_size=4 -theme="light" -auto_save=false -auto_closing_pairs=true -auto_closing_delete=true -auto_indent=true -auto_surround=true -cursor_style="line" -word_wrap=false -exclude_dirs=[".git"] -exclude_types=["__pycache__"] +font_size = 14 +tab_size = 4 +theme = "light" +auto_save = false +auto_closing_pairs = true +auto_closing_delete = true +auto_indent = true +auto_surround = true +cursor_style = "line" +word_wrap = false +exclude_dirs = [ ".git",] +exclude_types = [ "__pycache__",] diff --git a/src/biscuit/common/fixedstack.py b/src/biscuit/common/fixedstack.py index 4f30c0eb..e6f72fe9 100644 --- a/src/biscuit/common/fixedstack.py +++ b/src/biscuit/common/fixedstack.py @@ -1,7 +1,6 @@ from __future__ import annotations import os -import sqlite3 class FixedSizeStack: @@ -45,27 +44,13 @@ def __len__(self): def clear(self): self.stack.clear() - def dump_sqlite(self, cursor: sqlite3.Cursor) -> None: - """Dump the stack to the database. + def dump(self) -> None: + """Dump the stack to the file.""" + return self.stack - Args: - cursor (sqlite3.Cursor): the cursor to the database""" - - # print(self.name, self.stack) - cursor.execute(f"DELETE FROM {self.name};") - cursor.executemany( - f"INSERT INTO {self.name} (path) VALUES (?);", - [(item,) for item in self.stack], - ) - - def load_sqlite(self, cursor: sqlite3.Cursor) -> FixedSizeStack: - """Load the stack from the database. - - Args: - cursor (sqlite3.Cursor): the cursor to the database""" - - cursor.execute(f"SELECT path FROM {self.name};") - self.stack = [item[0] for item in cursor.fetchall()] + def load(self, data) -> FixedSizeStack: + """Load the stack from the file.""" + self.stack = data return self def open_item(self, item): diff --git a/src/biscuit/common/ui/scrollableframe.py b/src/biscuit/common/ui/scrollableframe.py index a90bc64c..5ce94d45 100644 --- a/src/biscuit/common/ui/scrollableframe.py +++ b/src/biscuit/common/ui/scrollableframe.py @@ -45,6 +45,12 @@ def _configure_canvas(self, event) -> None: def _on_mousewheel(self, event) -> None: self.canvas.yview_scroll(int(-1 * (event.delta / 120)), "units") + def bind_scroll(self, widget): + widget.bind("", self._on_mousewheel) + for child in widget.winfo_children(): + self.bind_scroll(child) + def add(self, content, *args, **kwargs) -> None: content.pack(in_=self.content, *args, **kwargs) self.items.append(content) + self.bind_scroll(content) diff --git a/src/biscuit/config.py b/src/biscuit/config.py index c0a6abac..0b66e786 100644 --- a/src/biscuit/config.py +++ b/src/biscuit/config.py @@ -3,6 +3,7 @@ import os import sys import typing +import tkinter as tk from pathlib import Path from biscuit.layout.statusbar.statusbar import Statusbar @@ -154,7 +155,49 @@ def set_tab_spaces(self, spaces: int) -> None: if e.content and e.content.editable: e.content.text.set_tab_size(spaces) self.statusbar.set_spaces(spaces) + + def refresh_editors(self) -> None: + self.tab_spaces = self.config.tab_size + self.wrap_words = self.config.word_wrap + self.block_cursor = self.config.cursor_style == "block" + self.relative_line_numbers = self.config.relative_line_numbers + self.show_minimap = self.config.show_minimap + self.show_linenumbers = self.config.show_linenumbers + self.theme = self.config.theme + for editor in self.editorsmanager.active_editors: + if editor.content and editor.content.editable: + editor.content.text.configure( + tabs=(self.settings.font.measure(" " * self.tab_spaces),), + blockcursor=self.block_cursor, + wrap=tk.WORD if self.wrap_words else tk.NONE, + **self.theme.editors.text + ) + editor.content.text.relative_line_numbers = self.relative_line_numbers + editor.content.linenumbers.redraw() + + if self.show_minimap: + editor.content.minimap.grid() + else: + editor.content.minimap.grid_remove() + + if self.show_linenumbers: + editor.content.linenumbers.grid() + else: + editor.content.linenumbers.grid_remove() + + if self.config.show_breadcrumbs: + self.editorsmanager.editorsbar.show_breadcrumbs() + else: + self.editorsmanager.editorsbar.hide_breadcrumbs() + + # Update indent guides for all active text editors + # This requires manually triggering an update/refresh in the text widget + # providing the render_indent_guides flag is used in update_indent_guides + for editor in self.editorsmanager.active_editors: + if editor.content and editor.content.editable: + editor.content.text.refresh() + @property def active_workspace(self): return self.workspaces.workspace diff --git a/src/biscuit/editor/text/text.py b/src/biscuit/editor/text/text.py index 1b619df8..f4bf067f 100644 --- a/src/biscuit/editor/text/text.py +++ b/src/biscuit/editor/text/text.py @@ -303,7 +303,7 @@ def diagnostic_hover(self, severity: int) -> str: self.base.diagnostic.show(self, start, message, severity) def update_indent_guides(self) -> None: - if self.minimalist: + if self.minimalist or not self.base.config.render_indent_guides: return self.tag_remove("indent_guide", "1.0", "end") diff --git a/src/biscuit/gui.py b/src/biscuit/gui.py index eb1bcbf6..66cabe55 100644 --- a/src/biscuit/gui.py +++ b/src/biscuit/gui.py @@ -1,5 +1,4 @@ import platform -import sqlite3 from tkinterDnD import Tk diff --git a/src/biscuit/history.py b/src/biscuit/history.py index 35b2d2fb..bf65c1f0 100644 --- a/src/biscuit/history.py +++ b/src/biscuit/history.py @@ -1,42 +1,34 @@ from __future__ import annotations import os -import sqlite3 +import toml import typing - from .common import ActionSet, FixedSizeStack if typing.TYPE_CHECKING: from . import App - class HistoryManager: """Manages the history of opened files and folders. Manages the history of opened files and folders. - Uses an sqlite3 database to store the history. + Uses a TOML file to store the history. """ def __init__(self, base: App) -> None: self.base = base - self.path = self.base.datadir / "history.db" - - self.db = sqlite3.connect(self.path) - self.cursor = self.db.cursor() + self.path = self.base.datadir / "history.toml" + self.history = {} - self.cursor.executescript( - """ - CREATE TABLE IF NOT EXISTS file_history (path TEXT NOT NULL); - CREATE TABLE IF NOT EXISTS folder_history (path TEXT NOT NULL); - """ - ) + if self.path.exists(): + try: + self.history = toml.load(self.path) + except Exception as e: + self.base.logger.error(f"History load failed: {e}") + self.history = {} - self.file_history = FixedSizeStack(self, "file_history").load_sqlite( - self.cursor - ) - self.folder_history = FixedSizeStack(self, "folder_history").load_sqlite( - self.cursor - ) + self.file_history = FixedSizeStack(self, "file_history").load(self.history.get("file_history", [])) + self.folder_history = FixedSizeStack(self, "folder_history").load(self.history.get("folder_history", [])) def generate_actionsets(self) -> None: self.base.palette.register_actionset( @@ -53,9 +45,14 @@ def register_folder_history(self, path: str) -> None: self.folder_history.push(path) def dump(self) -> None: - self.file_history.dump_sqlite(self.cursor) - self.folder_history.dump_sqlite(self.cursor) - self.db.commit() + try: + with open(self.path, 'w') as f: + toml.dump({ + "file_history": self.file_history.dump(), + "folder_history": self.folder_history.dump(), + }, f) + except Exception as e: + self.base.logger.error(f"History save failed: {e}") def clear_history(self) -> None: self.file_history.clear() diff --git a/src/biscuit/session.py b/src/biscuit/session.py index 73ce45c7..287dd024 100644 --- a/src/biscuit/session.py +++ b/src/biscuit/session.py @@ -2,65 +2,54 @@ from __future__ import annotations -import sqlite3 as sq -import typing - -if typing.TYPE_CHECKING: - from biscuit import App - +import toml class SessionManager: def __init__(self, base: App): self.base = base + self.session_path = self.base.datadir / "session.toml" + self.session = {} - # Initialize the session database connection - self.base_dir = self.base.datadir - self.session_db_path = self.base.datadir / "session.db" - self.db = sq.connect(self.session_db_path) - self.cursor = self.db.cursor() - - # Ensure the session table is created - self._create_session_table() - - def _create_session_table(self): - self.cursor.executescript( - """ - CREATE TABLE IF NOT EXISTS session ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - file_path TEXT, - folder_path TEXT - ); - """ - ) + if self.session_path.exists(): + try: + self.session = toml.load(self.session_path) + except Exception as e: + self.base.notifications.error(f"Failed to load session: {e}") + self.session = {} def restore_session(self): - opened_files = [] - active_directory = "" + if not self.session: + return - self.cursor.execute("SELECT * FROM session") - for row in self.cursor.fetchall(): - if row[1]: - opened_files.append(row[1]) - elif row[2]: - active_directory = row[2] + active_directory = self.session.get("active_directory") + opened_files = self.session.get("opened_files", []) - self.base.open_directory(active_directory) + if active_directory: + self.base.open_directory(active_directory) + self.base.open_files(opened_files) def clear_session(self): - self.cursor.execute("DELETE FROM session") + self.session = {} + if self.session_path.exists(): + try: + # Create empty file or just empty dict + with open(self.session_path, 'w') as f: + toml.dump({}, f) + except Exception as e: + self.base.logger.error(f"Failed to clear session: {e}") def save_session(self, opened_files, active_directory): - for file_path in opened_files: - self.cursor.execute( - "INSERT INTO session (file_path) VALUES (?)", (file_path,) - ) - - self.cursor.execute( - "INSERT INTO session (folder_path) VALUES (?)", (active_directory,) - ) - - self.db.commit() + self.session = { + "active_directory": active_directory, + "opened_files": opened_files + } + + try: + with open(self.session_path, 'w') as f: + toml.dump(self.session, f) + except Exception as e: + self.base.logger.error(f"Failed to save session: {e}") def close(self): - self.db.close() + pass diff --git a/src/biscuit/settings/config.py b/src/biscuit/settings/config.py index b0a15ca5..46873e0d 100644 --- a/src/biscuit/settings/config.py +++ b/src/biscuit/settings/config.py @@ -1,12 +1,9 @@ import os - import toml from .theme.catppuccin_mocha import CatppuccinMocha from .theme.gruvbox_dark import GruvboxDark -# from .theme import Dark, Light, Theme - class Config: """Loads and manages configurations for biscuit.""" @@ -14,12 +11,9 @@ class Config: def __init__(self, master) -> None: self.base = master.base - self.theme = GruvboxDark() - self.font = ("Fira Code", 12) - self.uifont = ("Fira Code", 10) - - self.auto_save_enabled = False - self.auto_save_timer_ms = 10000 + self.config_path = self.get_config_path("settings.toml") + self.data = {} + self.load_data() def get_config_path(self, relative_path: str) -> str: """Get the absolute path to the resource @@ -27,15 +21,78 @@ def get_config_path(self, relative_path: str) -> str: Args: relative_path (str): path relative to the config directory""" - return os.path.join(self.base.configdir, relative_path) + path = os.path.join(self.base.configdir, relative_path) + if not os.path.exists(path): + # fallback to the default config in the repo + path = os.path.join(self.base.parentdir, "config", relative_path) + + return path - def load_config(self) -> dict: - with open(self.get_config_path("settings.toml"), "r") as settingsfile: - config = toml.load(settingsfile) + def load_data(self) -> None: + """Load configurations from the config file.""" + if os.path.exists(self.config_path): + with open(self.config_path, "r") as configfile: + self.data = toml.load(configfile) + else: + self.data = {} - return config + self.setup_properties() - def load_data(self) -> None: - # TODO testing - self.theme = GruvboxDark() - self.font = (self.config["font"], self.config["font_size"]) + def setup_properties(self) -> None: + """Setup properties based on the loaded data.""" + # TODO add more properties + # Editor + self.font = (self.get_value("font", "Fira Code"), self.get_value("font_size", 12)) + self.uifont = (self.get_value("uifont", "Fira Code"), self.get_value("uifont_size", 10)) + + # Theme + theme_name = self.get_value("theme", "dark") + from .theme import VSCodeDark, VSCodeLight + if theme_name == "dark": + self.theme = VSCodeDark() + elif theme_name == "light": + self.theme = VSCodeLight() + elif theme_name == "gruvbox_dark": + self.theme = GruvboxDark() + elif theme_name == "catppuccin_mocha": + self.theme = CatppuccinMocha() + else: + self.theme = VSCodeDark() + + # Text Editor + self.auto_save_enabled = self.get_value("auto_save", False) + self.auto_closing_pairs = self.get_value("auto_closing_pairs", True) + self.auto_closing_delete = self.get_value("auto_closing_delete", True) + self.auto_indent = self.get_value("auto_indent", True) + self.auto_surround = self.get_value("auto_surround", True) + self.word_wrap = self.get_value("word_wrap", False) + self.tab_size = self.get_value("tab_size", 4) + self.cursor_style = self.get_value("cursor_style", "line") + self.relative_line_numbers = self.get_value("relative_line_numbers", False) + + # Display + self.show_minimap = self.get_value("show_minimap", True) + self.show_breadcrumbs = self.get_value("show_breadcrumbs", True) + self.show_linenumbers = self.get_value("show_line_numbers", True) + self.render_indent_guides = self.get_value("render_indent_guides", True) + + def get_value(self, key: str, default: any) -> any: + """Get a value from the config data.""" + return self.data.get(key, default) + + def set_value(self, key: str, value: any) -> None: + """Set a value in the config data and save it.""" + self.data[key] = value + self.save() + self.setup_properties() + + self.base.refresh_editors() + if "font" in key: + self.base.settings.update_font() + + def save(self) -> None: + """Save the current config data to the config file.""" + # ensure config directory exists + os.makedirs(os.path.dirname(self.config_path), exist_ok=True) + with open(self.config_path, "w") as configfile: + toml.dump(self.data, configfile) diff --git a/src/biscuit/settings/editor/editor.py b/src/biscuit/settings/editor/editor.py index 42b3b09a..cb5092ed 100644 --- a/src/biscuit/settings/editor/editor.py +++ b/src/biscuit/settings/editor/editor.py @@ -51,21 +51,57 @@ def add_commonly_used(self): commonly_used = self.add_section(f"Commonly Used") - commonly_used.add_dropdown("Color Theme", ("dark", "light")) - commonly_used.add_intvalue("Font Size", 14) - commonly_used.add_stringvalue("Font Family", "Consolas") - commonly_used.add_intvalue("Tab Size", 4) + commonly_used.add_dropdown("Color Theme", ("dark", "light", "gruvbox_dark", "catppuccin_mocha"), + self.base.config.get_value("theme", "dark"), + lambda v: self.base.config.set_value("theme", v)) + commonly_used.add_intvalue("Font Size", self.base.config.get_value("font_size", 12), + lambda v: self.base.config.set_value("font_size", int(v) if v else 12)) + commonly_used.add_intvalue("UI Font Size", self.base.config.get_value("uifont_size", 10), + lambda v: self.base.config.set_value("uifont_size", int(v) if v else 10)) + commonly_used.add_stringvalue("Font Family", self.base.config.get_value("font", "Fira Code"), + lambda v: self.base.config.set_value("font", v)) + commonly_used.add_intvalue("Tab Size", self.base.config.get_value("tab_size", 4), + lambda v: self.base.config.set_value("tab_size", int(v) if v else 4)) def add_text_editor(self): """Add text editor settings to the settings editor""" - commonly_used = self.add_section(f"Text Editor") - commonly_used.add_checkbox("Auto Save", False) - commonly_used.add_checkbox("Auto Closing Pairs", True) - commonly_used.add_checkbox("Auto Closing Delete", True) - commonly_used.add_checkbox("Auto Indent", True) - commonly_used.add_checkbox("Auto Surround", True) - commonly_used.add_checkbox("Word Wrap", False) + text_editor = self.add_section(f"Text Editor") + text_editor.add_checkbox("Relative Line Numbers", self.base.config.get_value("relative_line_numbers", False), + lambda v: self.base.config.set_value("relative_line_numbers", v)) + text_editor.add_checkbox("Auto Save", self.base.config.get_value("auto_save", False), + lambda v: self.base.config.set_value("auto_save", v)) + text_editor.add_checkbox("Auto Closing Pairs", self.base.config.get_value("auto_closing_pairs", True), + lambda v: self.base.config.set_value("auto_closing_pairs", v)) + text_editor.add_checkbox("Auto Closing Delete", self.base.config.get_value("auto_closing_delete", True), + lambda v: self.base.config.set_value("auto_closing_delete", v)) + text_editor.add_checkbox("Auto Indent", self.base.config.get_value("auto_indent", True), + lambda v: self.base.config.set_value("auto_indent", v)) + text_editor.add_checkbox("Auto Surround", self.base.config.get_value("auto_surround", True), + lambda v: self.base.config.set_value("auto_surround", v)) + text_editor.add_checkbox("Word Wrap", self.base.config.get_value("word_wrap", False), + lambda v: self.base.config.set_value("word_wrap", v)) + text_editor.add_dropdown("Cursor Style", ("line", "block", "underline"), + self.base.config.get_value("cursor_style", "line"), + lambda v: self.base.config.set_value("cursor_style", v)) + + text_editor.add_checkbox("Minimap", self.base.config.get_value("show_minimap", True), + lambda v: self.base.config.set_value("show_minimap", v)) + text_editor.add_checkbox("Breadcrumbs", self.base.config.get_value("show_breadcrumbs", True), + lambda v: self.base.config.set_value("show_breadcrumbs", v)) + text_editor.add_checkbox("Line Numbers", self.base.config.get_value("show_line_numbers", True), + lambda v: self.base.config.set_value("show_line_numbers", v)) + text_editor.add_checkbox("Render Indent Guides", self.base.config.get_value("render_indent_guides", True), + lambda v: self.base.config.set_value("render_indent_guides", v)) + + def add_section(self, name: str) -> Section: + """Add a section to the settings editor + + Args: + name (str): name of the section + + Returns: + Section: section to add items to""" def add_section(self, name: str) -> Section: """Add a section to the settings editor @@ -80,21 +116,56 @@ def add_section(self, name: str) -> Section: section.pack(fill=tk.X, expand=True) self.sections.append(section) - shortcut = Button(self.tree, name, anchor=tk.W) + shortcut = Button(self.tree, name, anchor=tk.W, command=lambda *_: self.scroll_to_section(section)) shortcut.pack(fill=tk.X) shortcut.config(**self.base.theme.editors.button) return section - def show_result(self, items): + def scroll_to_section(self, section: Section): + """Scrolls to the specified section.""" + # Using update_idletasks to ensure geometry is up to date + self.update_idletasks() + + # Calculate the y-position of the section relative to the content frame + y_pos = section.winfo_y() + + # Calculate the total height of the scrollable content + total_height = self.container.content.winfo_height() + + # Avoid division by zero + if total_height == 0: + return + + # Calculate the scroll fraction (0.0 to 1.0) + fraction = y_pos / total_height + + # Scroll the canvas + self.container.canvas.yview_moveto(fraction) + + def show_result(self, term: str): """Show the search results in the settings editor Args: - items (list): list of items to show in the settings editor""" - - if not any(items): - return self.show_no_results() + term (str): the search term""" + + term = term.lower() + + for section in self.sections: + visible_items = 0 + for item in section.items: + if term in item.name.lower(): + item.pack(fill=tk.X, expand=True) + visible_items += 1 + else: + item.pack_forget() + + if visible_items > 0: + section.pack(fill=tk.X, expand=True) + else: + section.pack_forget() def show_no_results(self): """Show no results found message in the settings editor""" - ... + # TODO implement this + pass diff --git a/src/biscuit/settings/editor/items.py b/src/biscuit/settings/editor/items.py index 7a019a69..7058e2dd 100644 --- a/src/biscuit/settings/editor/items.py +++ b/src/biscuit/settings/editor/items.py @@ -5,10 +5,11 @@ class Item(Frame): - def __init__(self, master, name="Example", *args, **kwargs) -> None: + def __init__(self, master, name="Example", callback=None, *args, **kwargs) -> None: super().__init__(master, *args, **kwargs) self.name = name + self.callback = callback self.description = None # TODO add descriptions self.bg, self.fg, self.highlightbg, _ = self.base.theme.editors.section.values() @@ -24,16 +25,9 @@ def __init__(self, master, name="Example", *args, **kwargs) -> None: ) self.lbl.pack(fill=tk.X, expand=True) - # self.bind("", self.hoverin) - # self.bind("", self.hoveroff) - - # def hoverin(self, *_): - # self.config(bg=self.highlightbg) - # self.lbl.config(bg=self.highlightbg) - - # def hoveroff(self, *_): - # self.config(bg=self.bg) - # self.lbl.config(bg=self.bg) + def change(self, *_) -> None: + if self.callback: + self.callback(self.value) class DropdownItem(Item): @@ -43,12 +37,21 @@ def __init__( name="Example", options=["True", "False"], default=0, + callback=None, *args, **kwargs ) -> None: - super().__init__(master, name, *args, **kwargs) + super().__init__(master, name, callback, *args, **kwargs) + + if isinstance(default, str): + try: + default = options.index(default) + except ValueError: + default = 0 self.var = tk.StringVar(self, value=options[default]) + self.var.trace_add("write", self.change) + m = ttk.OptionMenu(self, self.var, options[default], *options) m.config(width=30) m.pack(side=tk.LEFT) @@ -59,8 +62,8 @@ def value(self) -> str: class IntegerItem(Item): - def __init__(self, master, name="Example", default="0", *args, **kwargs) -> None: - super().__init__(master, name, *args, **kwargs) + def __init__(self, master, name="Example", default="0", callback=None, *args, **kwargs) -> None: + super().__init__(master, name, callback, *args, **kwargs) self.base.register(self.validate) self.entry = ttk.Entry( @@ -70,8 +73,10 @@ def __init__(self, master, name="Example", default="0", *args, **kwargs) -> None validate="key", validatecommand=(self.register(self.validate), "%P"), ) - self.entry.insert(0, default) + self.entry.insert(0, str(default)) self.entry.pack(side=tk.LEFT) + self.entry.bind("", self.change) + self.entry.bind("", self.change) def validate(self, value) -> None: return bool(value.isdigit() or value == "") @@ -83,13 +88,15 @@ def value(self) -> str: class StringItem(Item): def __init__( - self, master, name="Example", default="placeholder", *args, **kwargs + self, master, name="Example", default="placeholder", callback=None, *args, **kwargs ) -> None: - super().__init__(master, name, *args, **kwargs) + super().__init__(master, name, callback, *args, **kwargs) self.entry = ttk.Entry(self, font=self.base.settings.uifont, width=30) self.entry.insert(tk.END, default) self.entry.pack(side=tk.LEFT) + self.entry.bind("", self.change) + self.entry.bind("", self.change) @property def value(self) -> str: @@ -97,10 +104,12 @@ def value(self) -> str: class CheckboxItem(Item): - def __init__(self, master, name="Example", default=True, *args, **kwargs) -> None: - super().__init__(master, name, *args, **kwargs) + def __init__(self, master, name="Example", default=True, callback=None, *args, **kwargs) -> None: + super().__init__(master, name, callback, *args, **kwargs) self.var = tk.BooleanVar(self, value=default) + self.var.trace_add("write", self.change) + ttk.Checkbutton(self, text=name, variable=self.var, cursor="hand2").pack( fill=tk.X, anchor=tk.W ) diff --git a/src/biscuit/settings/editor/searchbar.py b/src/biscuit/settings/editor/searchbar.py index b51b29cc..14b0a440 100644 --- a/src/biscuit/settings/editor/searchbar.py +++ b/src/biscuit/settings/editor/searchbar.py @@ -41,21 +41,4 @@ def get_search_term(self) -> str: def filter(self, *args) -> str: term = self.get_search_term() - return - new = [ - i for i in self.master.active_set if i[0].lower().startswith(term.lower()) - ] - new += [ - i - for i in self.master.active_set - if any( - [ - f.lower() in i[0].lower() - or i[0].lower() in f.lower() - and i not in new - for f in term.lower().split() - ] - ) - ] - - self.master.show_result(new) + self.master.show_result(term) diff --git a/src/biscuit/settings/editor/section.py b/src/biscuit/settings/editor/section.py index b4fc92a9..22939779 100644 --- a/src/biscuit/settings/editor/section.py +++ b/src/biscuit/settings/editor/section.py @@ -32,7 +32,7 @@ def __init__(self, master, title="", *args, **kwargs) -> None: ).pack(fill=tk.X, expand=True) def add_dropdown( - self, name="Example", options=["True", "False"], default=0 + self, name="Example", options=["True", "False"], default=0, callback=None ) -> None: """Add a dropdown item to the section @@ -40,44 +40,48 @@ def add_dropdown( name (str, optional): name of the dropdown. Defaults to "Example". options (list, optional): list of options for the dropdown. Defaults to ["True", "False"]. default (int, optional): default value of the dropdown. Defaults to 0. + callback (function, optional): callback function to be called when the value is changed. """ - dropdown = DropdownItem(self, name, options, default) + dropdown = DropdownItem(self, name, options, default, callback) dropdown.pack(fill=tk.X, expand=True) self.items.append(dropdown) - def add_stringvalue(self, name="Example", default="placeholder") -> None: + def add_stringvalue(self, name="Example", default="placeholder", callback=None) -> None: """Add a string text box item to the section Args: name (str, optional): name of the string. Defaults to "Example". default (str, optional): default value of the string. Defaults to "placeholder". + callback (function, optional): callback function to be called when the value is changed. """ - string = StringItem(self, name, default) + string = StringItem(self, name, default, callback) string.pack(fill=tk.X, expand=True) self.items.append(string) - def add_intvalue(self, name="Example", default="0") -> None: + def add_intvalue(self, name="Example", default="0", callback=None) -> None: """Add an integer text box item to the section Args: name (str, optional): name of the integer. Defaults to "Example". default (int, optional): default value of the integer. Defaults to "0". + callback (function, optional): callback function to be called when the value is changed. """ - int = IntegerItem(self, name, default) + int = IntegerItem(self, name, default, callback) int.pack(fill=tk.X, expand=True) self.items.append(int) - def add_checkbox(self, name="Example", default=True) -> None: + def add_checkbox(self, name="Example", default=True, callback=None) -> None: """Add a checkbox item to the section Args: name (str, optional): name of the checkbox. Defaults to "Example". default (bool, optional): default value of the checkbox. Defaults to True. + callback (function, optional): callback function to be called when the value is changed. """ - dropdown = CheckboxItem(self, name, default) + dropdown = CheckboxItem(self, name, default, callback) dropdown.pack(fill=tk.X, expand=True) self.items.append(dropdown) diff --git a/src/biscuit/settings/settings.py b/src/biscuit/settings/settings.py index b3987112..ef5b0960 100644 --- a/src/biscuit/settings/settings.py +++ b/src/biscuit/settings/settings.py @@ -105,6 +105,13 @@ def setup_font(self) -> None: family=self.config.uifont[0], size=self.config.uifont[1], weight="bold" ) + def update_font(self) -> None: + self.font.configure(family=self.config.font[0], size=self.config.font[1]) + self.font_bold.configure(family=self.config.font[0], size=self.config.font[1], weight="bold") + self.autocomplete_font.configure(family=self.config.font[0], size=self.config.font[1] - 1) + self.uifont.configure(family=self.config.uifont[0], size=self.config.uifont[1]) + self.uifont_bold.configure(family=self.config.uifont[0], size=self.config.uifont[1], weight="bold") + def late_setup(self) -> None: """Configurations that require full initialization of editor"""