1 | """Handle the whole user interface of the sublinput package.""" |
||
2 | |||
3 | from __future__ import annotations |
||
4 | |||
5 | import os |
||
6 | from typing import Union, Tuple, Optional, Any |
||
7 | |||
8 | # Hides the pygame support message |
||
9 | os.environ['PYGAME_HIDE_SUPPORT_PROMPT']: str = "hide" |
||
10 | |||
11 | import pygame |
||
12 | |||
13 | Color = Union[Tuple[int, int, int], Tuple[int, int, int, int]] |
||
14 | |||
15 | pygame.init() |
||
0 ignored issues
–
show
|
|||
16 | pygame.display.init() |
||
17 | |||
18 | HEIGHT: int = 24 |
||
19 | WIDTH: int = 480 |
||
20 | |||
21 | WHITE: Color = (255,) * 3 |
||
22 | BLACK: Color = (0,) * 3 |
||
23 | ALPHA: Color = (0,) * 4 |
||
24 | |||
25 | SCREEN_TEXT_OFFSET: int = 5 |
||
26 | |||
27 | ICON: pygame.Surface = pygame.Surface((64, 64), pygame.SRCALPHA) |
||
0 ignored issues
–
show
|
|||
28 | ICON.fill(ALPHA) |
||
29 | |||
30 | FONT: pygame.font.SysFont = pygame.font.SysFont('Consolas', 16) |
||
31 | |||
32 | |||
33 | class InputBoxScreen: |
||
0 ignored issues
–
show
|
|||
34 | |||
35 | def __init__(self) -> None: |
||
36 | """Initialize the input box screen.""" |
||
37 | self.screen: Optional[pygame.display] = None |
||
38 | self.is_running: bool = True |
||
39 | self.result_value: str = '' |
||
40 | |||
41 | def __enter__(self) -> InputBoxScreen: |
||
42 | """Initialize pygame display.""" |
||
43 | pygame.display.init() |
||
44 | return self |
||
45 | |||
46 | def __call__(self, __prompt: str) -> str: |
||
47 | """Create a screen and get a value from the user.""" |
||
48 | self.screen: pygame.display = pygame.display.set_mode((WIDTH, HEIGHT)) |
||
49 | pygame.display.set_caption(__prompt) |
||
50 | pygame.display.set_icon(ICON) |
||
51 | |||
52 | while self.is_running: |
||
53 | self.handle_event(pygame.event.wait()) |
||
54 | self.draw() |
||
55 | |||
56 | print(f"{__prompt}{self.result_value}") |
||
57 | return self.result_value |
||
58 | |||
59 | def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None: |
||
60 | """QUit pygame display and raise possible exception.""" |
||
61 | pygame.display.quit() |
||
62 | |||
63 | if exc_type: |
||
64 | raise |
||
65 | |||
66 | def handle_event(self, event: pygame.Event) -> None: |
||
0 ignored issues
–
show
|
|||
67 | """Handle event from the user.""" |
||
68 | if event.type == pygame.QUIT: |
||
0 ignored issues
–
show
|
|||
69 | self.is_running: bool = False |
||
70 | return |
||
71 | |||
72 | if event.type == pygame.TEXTINPUT: |
||
0 ignored issues
–
show
|
|||
73 | self.result_value += event.text |
||
74 | return |
||
75 | |||
76 | if event.type != pygame.KEYDOWN: |
||
0 ignored issues
–
show
|
|||
77 | return |
||
78 | |||
79 | if event.key == pygame.K_BACKSPACE: |
||
0 ignored issues
–
show
|
|||
80 | self.result_value: str = self.result_value[:-1] |
||
81 | return |
||
82 | |||
83 | if event.key == pygame.K_RETURN: |
||
0 ignored issues
–
show
|
|||
84 | self.is_running: bool = False |
||
85 | return |
||
86 | |||
87 | def draw(self) -> None: |
||
88 | """Render the user text on the screen.""" |
||
89 | self.screen.fill(BLACK) |
||
90 | text: pygame.Surface = FONT.render(self.result_value, True, WHITE) |
||
91 | text_rect: pygame.Rect = text.get_rect() |
||
92 | |||
93 | text_rect.top = SCREEN_TEXT_OFFSET |
||
94 | |||
95 | # Scroll when value length is higher then screen size |
||
96 | if text_rect.width < (WIDTH - SCREEN_TEXT_OFFSET): |
||
97 | text_rect.left = SCREEN_TEXT_OFFSET |
||
98 | else: |
||
99 | text_rect.right = WIDTH - SCREEN_TEXT_OFFSET |
||
100 | |||
101 | self.screen.blit(text, text_rect) |
||
102 | pygame.display.update() |
||
103 | |||
104 | |||
105 | def main() -> None: |
||
106 | """A Demo of the InputBoxScreen class.""" |
||
107 | with InputBoxScreen() as input_box_demo: |
||
108 | input_box_demo("Demo: ") |
||
109 | |||
110 | |||
111 | if __name__ == '__main__': |
||
112 | main() |
||
113 |
This check looks for calls to members that are non-existent. These calls will fail.
The member could have been renamed or removed.