Răsfoiți Sursa

move keyboard classes into keyboard.py; add more properties for special keys; type annotations

Falko Schindler 3 ani în urmă
părinte
comite
6a4d573fc9
3 a modificat fișierele cu 200 adăugiri și 109 ștergeri
  1. 6 6
      main.py
  2. 194 6
      nicegui/elements/keyboard.py
  3. 0 97
      nicegui/utils.py

+ 6 - 6
main.py

@@ -393,19 +393,19 @@ with example(get_decorator):
 
 with example(ui.keyboard):
     def handle_keys(e):
-        if e.key == 'f' and not e.key.repeat:
+        if e.key == 'f' and not e.action.repeat:
             if e.action.keyup:
                 ui.notify('f was just released')
             elif e.action.keydown:
                 ui.notify('f was just pressed')
-        if e.modifiers.shiftkey and e.action.keydown:
-            if e.key.left:
+        if e.modifiers.shift and e.action.keydown:
+            if e.key.arrow_left:
                 ui.notify('going left')
-            elif e.key.right:
+            elif e.key.arrow_right:
                 ui.notify('going right')
-            elif e.key.up:
+            elif e.key.arrow_up:
                 ui.notify('going up')
-            elif e.key.down:
+            elif e.key.arrow_down:
                 ui.notify('going down')
 
     keyboard = ui.keyboard(handle_keys)

+ 194 - 6
nicegui/elements/keyboard.py

@@ -1,9 +1,8 @@
-from typing import Callable
-
+from pydantic import BaseModel
+from typing import Callable, Optional
+from ..utils import handle_exceptions, provide_arguments
 from .custom_view import CustomView
 from .element import Element
-from ..utils import handle_exceptions, provide_arguments
-
 
 class KeyboardView(CustomView):
 
@@ -14,8 +13,29 @@ class KeyboardView(CustomView):
         self.active = active
 
         def execute_when_active(*args):
-            if self.active:
-                handle_exceptions(provide_arguments(handle_keys, 'key_data', 'event_type'))(*args)
+            if not self.active:
+                return
+
+            event_args = args[1]
+            event_args.action = KeyboardAction(
+                keypress=event_args.key_data['action'] == 'keypress',
+                keydown=event_args.key_data['action'] == 'keydown',
+                keyup=event_args.key_data['action'] == 'keyup',
+                repeat=event_args.key_data['repeat'],
+            )
+            event_args.modifiers = KeyboardModifiers(
+                alt=event_args.key_data['altKey'],
+                ctrl=event_args.key_data['ctrlKey'],
+                meta=event_args.key_data['metaKey'],
+                shift=event_args.key_data['shiftKey'],
+            )
+            event_args.key = KeyboardKey(
+                name=event_args.key_data['key'],
+                code=event_args.key_data['code'],
+                location=event_args.key_data['location'],
+            )
+
+            handle_exceptions(provide_arguments(handle_keys, 'key_data', 'action', 'modifiers', 'key'))(*args)
 
         self.initialize(temp=False, on_keyboardEvent=execute_when_active)
 
@@ -32,3 +52,171 @@ class Keyboard(Element):
         :param active: boolean flag indicating whether the callback should be executed or not
         """
         super().__init__(KeyboardView(handle_keys=handle_keys, active=active))
+
+class KeyboardAction(BaseModel):
+    keypress: bool
+    keydown: bool
+    keyup: bool
+    repeat: bool
+
+class KeyboardModifiers(BaseModel):
+    alt: bool
+    ctrl: bool
+    meta: bool
+    shift: bool
+
+class KeyboardKey(BaseModel):
+    name: str
+    code: str
+    location: int
+
+    def __eq__(self, other: str) -> bool:
+        return self.name == other or self.code == other
+
+    def __repr__(self):
+        return str(self.name)
+
+    @property
+    def is_cursorkey(self):
+        return self.code.startswith('Arrow')
+
+    @property
+    def number(self) -> Optional[int]:
+        """Integer value of a number key."""
+        return int(self.name) if self.code.startswith('Digit') else None
+
+    @property
+    def backspace(self) -> bool:
+        return self.name == 'Backspace'
+
+    @property
+    def tab(self) -> bool:
+        return self.name == 'Tab'
+
+    @property
+    def enter(self) -> bool:
+        return self.name == 'enter'
+
+    @property
+    def shift(self) -> bool:
+        return self.name == 'Shift'
+
+    @property
+    def control(self) -> bool:
+        return self.name == 'Control'
+
+    @property
+    def alt(self) -> bool:
+        return self.name == 'Alt'
+
+    @property
+    def pause(self) -> bool:
+        return self.name == 'Pause'
+
+    @property
+    def caps_lock(self) -> bool:
+        return self.name == 'CapsLock'
+
+    @property
+    def escape(self) -> bool:
+        return self.name == 'Escape'
+
+    @property
+    def space(self) -> bool:
+        return self.name == 'Space'
+
+    @property
+    def page_up(self) -> bool:
+        return self.name == 'PageUp'
+
+    @property
+    def page_down(self) -> bool:
+        return self.name == 'PageDown'
+
+    @property
+    def end(self) -> bool:
+        return self.name == 'End'
+
+    @property
+    def home(self) -> bool:
+        return self.name == 'Home'
+
+    @property
+    def arrow_left(self) -> bool:
+        return self.name == 'ArrowLeft'
+
+    @property
+    def arrow_up(self) -> bool:
+        return self.name == 'ArrowUp'
+
+    @property
+    def arrow_right(self) -> bool:
+        return self.name == 'ArrowRight'
+
+    @property
+    def arrow_down(self) -> bool:
+        return self.name == 'ArrowDown'
+
+    @property
+    def print_screen(self) -> bool:
+        return self.name == 'PrintScreen'
+
+    @property
+    def insert(self) -> bool:
+        return self.name == 'Insert'
+
+    @property
+    def delete(self) -> bool:
+        return self.name == 'Delete'
+
+    @property
+    def meta(self) -> bool:
+        return self.name == 'Meta'
+
+    @property
+    def f1(self) -> bool:
+        return self.name == 'F1'
+
+    @property
+    def f2(self) -> bool:
+        return self.name == 'F2'
+
+    @property
+    def f3(self) -> bool:
+        return self.name == 'F3'
+
+    @property
+    def f4(self) -> bool:
+        return self.name == 'F4'
+
+    @property
+    def f5(self) -> bool:
+        return self.name == 'F5'
+
+    @property
+    def f6(self) -> bool:
+        return self.name == 'F6'
+
+    @property
+    def f7(self) -> bool:
+        return self.name == 'F7'
+
+    @property
+    def f8(self) -> bool:
+        return self.name == 'F8'
+
+    @property
+    def f9(self) -> bool:
+        return self.name == 'F9'
+
+    @property
+    def f10(self) -> bool:
+        return self.name == 'F10'
+
+    @property
+    def f11(self) -> bool:
+        return self.name == 'F11'
+
+    @property
+    def f12(self) -> bool:
+        return self.name == 'F12'

+ 0 - 97
nicegui/utils.py

@@ -3,108 +3,11 @@ import traceback
 
 
 class EventArguments:
-
     def __init__(self, sender, **kwargs):
         self.sender = sender
         for key, value in kwargs.items():
             setattr(self, key, value)
 
-        if hasattr(self, 'key_data'):
-            self.action = KeyboardAction(self.key_data)
-            self.key = KeyboardKey(self.key_data)
-            self.modifiers = KeyboardModifiers(self.key_data)
-
-
-class KeyboardAction:
-
-    def __init__(self, key_data):
-        self.action = getattr(key_data, 'action', False)
-
-    @property
-    def keydown(self):
-        return self.action and self.action == 'keydown'
-
-    @property
-    def keyup(self):
-        return self.action and self.action == 'keyup'
-
-    @property
-    def keypress(self):
-        return self.action and self.action == 'keypress'
-
-
-class KeyboardKey:
-    def __init__(self, key_data):
-        self.key = getattr(key_data, 'key', False)
-        self.keycode = getattr(key_data, 'code', '')
-        self.repeat = getattr(key_data, 'repeat', False)
-
-    def __eq__(self, other):
-        return self.key == other
-
-    def __repr__(self):
-        return str(self.key)
-
-    def __int__(self):
-        return int(self.key)
-
-    @property
-    def code(self):
-        return self.keycode
-
-    @property
-    def left(self):
-        return self.key and self.key == 'ArrowLeft'
-
-    @property
-    def right(self):
-        return self.key and self.key == 'ArrowRight'
-
-    @property
-    def up(self):
-        return self.key and self.key == 'ArrowUp'
-
-    @property
-    def down(self):
-        return self.key and self.key == 'ArrowDown'
-
-    @property
-    def shift(self):
-        return self.key and self.key == 'Shift'
-
-    @property
-    def is_cursorkey(self):
-        return self.key and (self.left or self.right or self.up or self.down)
-
-    # Number key codes
-    number_key_codes = {f'Digit{number}': number for number in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}
-
-    @property
-    def numberkey(self):
-        """Returns number of a key as a string based on the key code, meaning ignoring modifiers."""
-        return self.number_key_codes.get(self.keycode)
-
-
-class KeyboardModifiers:
-    def __init__(self, key_data):
-        self.key_data = key_data
-
-    @property
-    def altkey(self):
-        return getattr(self.key_data, 'shiftKey', False)
-
-    @property
-    def ctrlkey(self):
-        return getattr(self.key_data, 'ctrlKey', False)
-
-    @property
-    def shiftkey(self):
-        return getattr(self.key_data, 'shiftKey', False)
-
-    @property
-    def metakey(self):
-        return getattr(self.key_data, 'metaKey', False)
-
 
 def provide_arguments(func, *keys):
     def inner_function(sender, event):