]> git.mar77i.info Git - zenbook_gui/commitdiff
make ui key_methods great again.
authormar77i <mar77i@protonmail.ch>
Sun, 11 May 2025 16:34:36 +0000 (18:34 +0200)
committermar77i <mar77i@protonmail.ch>
Sun, 11 May 2025 16:34:36 +0000 (18:34 +0200)
13 files changed:
bookpaint/book_manager.py
bookpaint/bookpaint.py
bookpaint/color_menu.py
bookpaint/line_menu.py
bookpaint/menu.py
bookpaint/page_menu.py
memory.py
ui/child.py
ui/drop_down.py
ui/event_method_dispatcher.py
ui/root.py
ui/text_input.py
ui/utils.py [new file with mode: 0644]

index e0dd84e4e7970dec55b1ed42da160c907e951188..dbe0ec3cab1de648ed41b6e06a046c92b7159a16 100644 (file)
@@ -55,27 +55,31 @@ class BookManager:
         LAST = auto()
         NEW = auto()
 
+    def get_current_index(self):
+        try:
+            return self.pages.index(self.current_file)
+        except ValueError:
+            return len(self.pages)
+
     def _get_index_for_page(self, nav):
-        if nav is self.Nav.NEW or len(self.pages) == 0:
+        len_pages = len(self.pages)
+        if nav is self.Nav.NEW or len_pages == 0:
             return -1
         elif nav is self.Nav.FIRST:
             return 0
         elif nav is self.Nav.LAST:
-            return len(self.pages) - 1
-        try:
-            current_index = self.pages.index(self.current_file)
-        except ValueError:
-            current_index = -1
+            return len_pages - 1
+        current_index = self.get_current_index()
         if nav is self.Nav.PREV:
-            if current_index == -1:
-                return len(self.pages) - 1
+            if current_index == len_pages:
+                return len_pages - 1
             elif current_index > 0:
                 return current_index - 1
             return None
         elif nav is self.Nav.NEXT:
-            if current_index == -1:
+            if current_index == len_pages:
                 return None
-            elif current_index < len(self.pages) - 1:
+            elif current_index < len_pages - 1:
                 return current_index + 1
             return -1
         raise IndexError(nav)
@@ -84,7 +88,9 @@ class BookManager:
         if self.parent.draw_image.image_dirty:
             self.save_file()
         i = self._get_index_for_page(nav)
-        if i >= 0:
+        if i is None:
+            return
+        elif i >= 0:
             self.current_file = self.pages[i]
             self.parent.draw_image.set_image(pygame.image.load(self.current_file))
         elif self.current_file in self.pages:
index e68de1d9ed43a7f928ddfeac2f5a9b5f2088e861..addb0d02aff4a8b9f82884b899a8d67db037bcff 100644 (file)
@@ -12,12 +12,16 @@ from .line_menu import LineMenu
 from .menu import Menu
 from .page_menu import PageMenu
 
-# - page menu; browse through next and prev pages using stylus
-
 
 class BookPaint(Root):
     BACKGROUND_COLOR = "black"
 
+    def setup_deactivate_keys(self):
+        for key, value in self.key_methods[frozenset()].items():
+            menu = getattr(self, value.keywords["menu_attr"])
+            if key not in menu.key_methods[frozenset()]:
+                menu.key_methods[frozenset()][key] = menu.deactivate.__func__
+
     def __init__(self):
         pygame.init()
         super().__init__(
@@ -30,6 +34,8 @@ class BookPaint(Root):
         self.page_menu = PageMenu(self)
         self.menu = Menu(self)
         self.book_manager = BookManager(self, Path("book"))
+        self.page_menu.update_label()
+        self.setup_deactivate_keys()
 
     def show_menu(self, menu_attr):
         getattr(self, menu_attr).activate()
@@ -39,8 +45,9 @@ class BookPaint(Root):
 
     def nav(self, nav):
         self.book_manager.nav(nav)
+        self.page_menu.update_label()
 
-    KEY_METHODS = {
+    key_methods = {
         frozenset(): {
             pygame.K_ESCAPE: partial(show_menu, menu_attr="menu"),
             pygame.K_c: partial(show_menu, menu_attr="color_menu"),
index 892b13bb5d685586abe913cb3fb36361a7c71c8d..4067db6d2ee7bb0b12963fc989b8e0ba4aa06b1a 100644 (file)
@@ -64,9 +64,4 @@ class ColorMenu(Modal):
             ),
         )
 
-    KEY_METHODS = {
-        frozenset(): {
-            pygame.K_ESCAPE: Modal.deactivate,
-            pygame.K_c: Modal.deactivate,
-        }
-    }
+    key_methods = {frozenset(): {pygame.K_ESCAPE: Modal.deactivate}}
index 705d85efab07a6a8fb9d309720b7cb9387faa6b6..21536ad6b94369dadbfbc84e391a0f39d97c90f4 100644 (file)
@@ -76,9 +76,4 @@ class LineMenu(Modal):
         pygame.draw.rect(self.surf, "black", rect)
         pygame.draw.rect(self.surf, "gray", rect, 1)
 
-    KEY_METHODS = {
-        frozenset(): {
-            pygame.K_ESCAPE: Modal.deactivate,
-            pygame.K_l: Modal.deactivate,
-        }
-    }
+    key_methods = {frozenset(): {pygame.K_ESCAPE: Modal.deactivate}}
index 0f3ff7217bda979f208eac6240333836524a0366..f471025c85cba73e6e50b686513a29119c3c3c6b 100644 (file)
@@ -68,4 +68,4 @@ class Menu(Modal):
         pygame.draw.rect(self.surf, "black", rect)
         pygame.draw.rect(self.surf, "gray", rect, 1)
 
-    KEY_METHODS = {frozenset(): {pygame.K_ESCAPE: Modal.deactivate}}
+    key_methods = {frozenset(): {pygame.K_ESCAPE: Modal.deactivate}}
index d68eb1b25e57c681bc24341cf9ea0242781e0304..e1b08524ecb9054b37f67389804523e3cf2b6a92 100644 (file)
@@ -14,13 +14,13 @@ class PageMenu(Modal):
         button_height = 128
         self.base_rect = pygame.Rect(
             (size[0] // 4, size[1] * 6 // 8),
-            (size[0] // 2, max(size[1] // 8, button_height * 2 + 16)),
+            (size[0] // 2, button_height * 2 + 16),
         )
         y = self.base_rect.top
-        Label(
+        self.label = Label(
             self,
             pygame.Rect((self.base_rect.left, y), (self.base_rect.width, button_height)),
-            "Page Menu",
+            "",
             Label.HAlign.CENTER,
         )
         y += button_height + 16
@@ -48,15 +48,12 @@ class PageMenu(Modal):
         pygame.draw.rect(self.surf, "black", rect)
         pygame.draw.rect(self.surf, "gray", rect, 1)
 
-    def first(self):
-        pass
+    key_methods = {frozenset(): {pygame.K_ESCAPE: Modal.deactivate}}
 
-    def last(self):
-        pass
-
-    KEY_METHODS = {
-        frozenset(): {
-            pygame.K_ESCAPE: Modal.deactivate,
-            pygame.K_p: Modal.deactivate,
-        }
-    }
+    def update_label(self):
+        self.label.value = " / ".join(
+            (
+                str(self.parent.book_manager.get_current_index() + 1),
+                str(len(self.parent.book_manager.pages)),
+            )
+        )
\ No newline at end of file
index a1611f0334c6217574e3b13d275a4239c481b5b0..950bc2a7a97fa6ab49b37e0ee52c97fb6febbe3d 100755 (executable)
--- a/memory.py
+++ b/memory.py
@@ -13,7 +13,7 @@ class QuittableModal(Modal):
     def handle_quit(self, ev):
         self.parent.handle_quit(ev)
 
-    KEY_METHODS = {frozenset(): {pygame.K_ESCAPE: handle_quit}}
+    key_methods = {frozenset(): {pygame.K_ESCAPE: handle_quit}}
 
 
 class NameMenu(QuittableModal):
index 6d9ecfeb7bdb93b4743a6eb67b92f8f8db62f37f..d197021cb3a0bb635c5789d1405158e2402759bd 100644 (file)
@@ -6,6 +6,7 @@ from .root import Root
 
 class Child(EventMethodDispatcher):
     def __init__(self, parent, enabled=True):
+        super().__init__()
         self.parent = parent
         parent.children.append(self)
         self.enabled = enabled
index f78fe0f8e2cf8cfa2caa95463d8485cb2ed1fc50..2d857b188d320eb8268752ddb4c0034eb6e9fd72 100644 (file)
@@ -23,7 +23,7 @@ class DropDownMenu(Modal):
             rect.bottomleft, (rect.width, rect.height * len(entries))
         )
 
-    KEY_METHODS = {frozenset(): {pygame.K_ESCAPE: Modal.deactivate}}
+    key_methods = {frozenset(): {pygame.K_ESCAPE: Modal.deactivate}}
 
     def choose(self, i=None):
         self.deactivate()
index 8e548545e461673aaaea284d97eb894780a1aa1d..2bdd8d7da14680d9b721d9a1b6c75bbc14ec0a78 100644 (file)
@@ -2,24 +2,26 @@ from functools import partial
 
 import pygame
 
+from .utils import CowDict
+
 
 class EventMethodDispatcher:
     MODS = (pygame.KMOD_CTRL, pygame.KMOD_ALT, pygame.KMOD_META, pygame.KMOD_SHIFT)
-    KEY_METHODS = {}
+
+    def __init__(self):
+        self.key_methods = CowDict(getattr(type(self), "key_methods", {}))
 
     def get_key_method(self, key, mod):
         mods = set()
         for mask in self.MODS:
             if mod & mask:
                 mods.add(mask)
-        method = self.KEY_METHODS.get(frozenset(mods), {}).get(key)
+        method = self.key_methods.get(frozenset(mods), {}).get(key)
         if method is not None:
             return partial(method, self)
         return None
 
     def handle_keydown(self, ev):
-        if not self.KEY_METHODS:
-            return
         key_method = self.get_key_method(ev.key, ev.mod)
         if key_method is not None:
             key_method()
index 1403fdca02c2e80e18b23aa554e7b0ef7828c405..d561d84e2f657f303c04e1ec4f543a2c6bf06de5 100644 (file)
@@ -7,8 +7,6 @@ class Root(Parent):
     BACKGROUND_COLOR: pygame.Color
 
     def __init__(self, surf, font=None):
-        from .child import Child
-
         super().__init__()
         self.font = font
         self.running = True
@@ -17,12 +15,12 @@ class Root(Parent):
         self.clock = pygame.time.Clock()
         self.stop_event = False
         self.root = self
-        self.focus_stack: list[Root | Child] = [self]
+        self.focus_stack: list[Parent] = [self]
 
     def handle_quit(self, _=None):
         self.running = False
 
-    KEY_METHODS = {frozenset(): {pygame.K_ESCAPE: handle_quit}}
+    key_methods = {frozenset(): {pygame.K_ESCAPE: handle_quit}}
 
     @property
     def focused(self):
index 7b5d5c8b97b9358cb05f85ba056265b647397f19..325ca1e0d440613865a7112f5efcc9b79aa733bc 100644 (file)
@@ -272,7 +272,7 @@ class TextInput(Focusable, Child):
         self.cursor = None
         super().deactivate()
 
-    KEY_METHODS = {
+    key_methods = {
         frozenset(): {
             pygame.K_LEFT: key_left,
             pygame.K_RIGHT: key_right,
diff --git a/ui/utils.py b/ui/utils.py
new file mode 100644 (file)
index 0000000..a0f0742
--- /dev/null
@@ -0,0 +1,25 @@
+class CowDict:
+    def __init__(self, orig_dict):
+        self.orig_dict = orig_dict
+        self.copy = None
+
+    @property
+    def dict(self):
+        return self.copy or self.orig_dict
+
+    def __getitem__(self, key):
+        return self.dict[key]
+
+    def _clone(self):
+        if self.copy is None:
+            self.copy = self.orig_dict.copy()
+
+    def __setitem__(self, key, value):
+        self._clone()
+        self.copy[key] = value
+
+    def __getattr__(self, item):
+        mod_methods = ("clear", "pop", "popitem", "setdefault", "update")
+        if self.copy is None and item in mod_methods:
+            self._clone()
+        return getattr(self.dict, item)