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)
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:
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__(
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()
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"),
),
)
- KEY_METHODS = {
- frozenset(): {
- pygame.K_ESCAPE: Modal.deactivate,
- pygame.K_c: Modal.deactivate,
- }
- }
+ key_methods = {frozenset(): {pygame.K_ESCAPE: Modal.deactivate}}
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}}
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}}
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
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
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):
class Child(EventMethodDispatcher):
def __init__(self, parent, enabled=True):
+ super().__init__()
self.parent = parent
parent.children.append(self)
self.enabled = enabled
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()
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()
BACKGROUND_COLOR: pygame.Color
def __init__(self, surf, font=None):
- from .child import Child
-
super().__init__()
self.font = font
self.running = True
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):
self.cursor = None
super().deactivate()
- KEY_METHODS = {
+ key_methods = {
frozenset(): {
pygame.K_LEFT: key_left,
pygame.K_RIGHT: key_right,
--- /dev/null
+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)