Преглед на файлове

automatically resize button label size + remove fontsize config subentry + add icon + add borderless config

Noah Vogt преди 6 месеца
родител
ревизия
d37df7db67
променени са 6 файла, в които са добавени 96 реда и са изтрити 14 реда
  1. 7 4
      VulcanBoard.py
  2. 1 0
      config/classes.py
  3. 12 10
      config/load.py
  4. BIN
      icon.jpg
  5. 16 0
      ui/__init__.py
  6. 60 0
      ui/button.py

+ 7 - 4
VulcanBoard.py

@@ -22,22 +22,26 @@ import sys
 import colorama
 
 from kivy.app import App
-from kivy.uix.button import Button
 from kivy.uix.gridlayout import GridLayout
 from kivy.utils import get_color_from_hex
 
 from util import log, error_exit_gui
 from config import get_config_path, ConfigLoader, Config
+from ui import AutoResizeButton
 
 
 class VulcanBoardApp(App):
     def build(self):
+        self.icon = "icon.jpg"
         config_loader = ConfigLoader(get_config_path())
         config = config_loader.get_config()  # pyright: ignore
         if isinstance(config, str):
             error_exit_gui(config)
         else:
             config: Config = config
+
+            self.Borderless = config.borderless
+
             button_map = {
                 (btn["position"][0], btn["position"][1]): btn
                 for btn in config.buttons
@@ -55,7 +59,7 @@ class VulcanBoardApp(App):
                 for col in range(config.columns):
                     defined_button = button_map.get((row, col))
                     if defined_button:
-                        btn = Button(
+                        btn = AutoResizeButton(
                             text=defined_button.get("txt", ""),
                             background_color=get_color_from_hex(
                                 defined_button.get("bg_color", "aaaaff")
@@ -63,7 +67,6 @@ class VulcanBoardApp(App):
                             color=get_color_from_hex(
                                 defined_button.get("fg_color", "ffffff")
                             ),
-                            font_size=defined_button.get("fontsize", 14),
                             halign="center",
                             valign="middle",
                             background_normal="",
@@ -77,7 +80,7 @@ class VulcanBoardApp(App):
                             )
                         )
                     else:
-                        btn = Button(
+                        btn = AutoResizeButton(
                             background_color=get_color_from_hex("cccccc"),
                         )
                     layout.add_widget(btn)

+ 1 - 0
config/classes.py

@@ -23,3 +23,4 @@ class Config:
     buttons: list[dict]
     spacing: int
     padding: int
+    borderless: bool

+ 12 - 10
config/load.py

@@ -28,11 +28,12 @@ class ConfigLoader:
     config_path: str
 
     def __post_init__(self) -> None:
+        self.buttons = []
         self.columns = 0
         self.rows = 0
-        self.buttons = []
         self.padding = 0
         self.spacing = 0
+        self.borderless = False
 
     def get_config(self) -> Config | str:
         try:
@@ -43,6 +44,7 @@ class ConfigLoader:
                 self.buttons = yaml_config.get("buttons")
                 self.padding = yaml_config.get("padding", 5)
                 self.spacing = yaml_config.get("spacing", 5)
+                self.borderless = yaml_config.get("borderless", False)
                 return self.__interpret_config()
         except (FileNotFoundError, PermissionError, IOError) as error:
             return f"Error: Could not access config file at {self.config_path}. Reason: {error}"
@@ -55,7 +57,12 @@ class ConfigLoader:
         self.__validate_styling()
 
         return Config(
-            self.columns, self.rows, self.buttons, self.spacing, self.padding
+            self.columns,
+            self.rows,
+            self.buttons,
+            self.spacing,
+            self.padding,
+            self.borderless,
         )
 
     def __validate_buttons(self) -> None:
@@ -100,14 +107,6 @@ class ConfigLoader:
                     f"invalid button 'fg_color' subentry: '{fg_color}'"
                 )
 
-            if (
-                not isinstance(fontsize := button.get("fontsize", ""), int)
-                or 0 > fontsize
-            ):
-                raise CustomException(
-                    f"invalid button 'fontsize' subentry: '{fontsize}'"
-                )
-
     def __validate_dimensions(self) -> None:
         for dimension in (self.columns, self.rows):
             if not isinstance(dimension, int) or (dimension <= 0):
@@ -117,3 +116,6 @@ class ConfigLoader:
         for styling in (self.spacing, self.padding):
             if not isinstance(styling, int) or (styling <= 0):
                 raise CustomException(f"invalid styling: {styling}")
+
+        if not isinstance(self.borderless, bool):
+            raise CustomException("invalid borderless value, should be boolean")

BIN
icon.jpg


+ 16 - 0
ui/__init__.py

@@ -0,0 +1,16 @@
+# Copyright © 2024 Noah Vogt <noah@noahvogt.com>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from .button import AutoResizeButton

+ 60 - 0
ui/button.py

@@ -0,0 +1,60 @@
+# Copyright © 2024 Noah Vogt <noah@noahvogt.com>
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU 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 General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+from kivy.uix.button import Button
+from kivy.properties import ListProperty  # pylint: disable=no-name-in-module
+
+
+class AutoResizeButton(Button):
+    """A button that adjusts its label font size dynamically."""
+
+    original_pos = ListProperty([0, 0])
+
+    def __init__(self, **kwargs):
+        super().__init__(**kwargs)
+        self.dragged = False
+        # pylint: disable=no-member
+        self.bind(  # type: ignore
+            size=self.adjust_font_size, text=self.adjust_font_size
+        )
+
+    def adjust_font_size(self, *args):
+        """Dynamically adjusts font size to fit the button's bounds."""
+        if not self.text:
+            return
+
+        # Define the minimum and maximum font size
+        min_font_size = 10
+        max_font_size = min(self.width, self.height) * 0.5
+
+        # Perform a binary search to find the best font size
+        best_font_size = min_font_size
+        while min_font_size <= max_font_size:
+            current_font_size = (min_font_size + max_font_size) // 2
+            self.font_size = current_font_size
+            self.texture_update()  # Update texture to get new texture_size
+
+            # Check if the text fits within the button's bounds
+            if (
+                self.texture_size[0] <= self.width * 0.9
+                and self.texture_size[1] <= self.height * 0.9
+            ):
+                best_font_size = current_font_size
+                min_font_size = current_font_size + 1
+            else:
+                max_font_size = current_font_size - 1
+
+        # Apply the best font size
+        self.font_size = best_font_size