diff --git a/pg.py b/pg.py index 7b44f88..cdd97d4 100644 --- a/pg.py +++ b/pg.py @@ -14,7 +14,9 @@ buttons = [] # colors +black = (8, 8, 8) gray = (40, 40, 40) +light_gray = (128, 128, 128) white = (250, 250, 250) @@ -217,6 +219,135 @@ class TextButton: # self.delay = delay +class TextInput: + def __init__( + self, + position: Union[tuple, Callable], + surface: pygame.Surface, + width: int=None, + font: pygame.font.Font=default_font, + bg_color: tuple=(255, 255, 255), + text_color: tuple=black, + desc_text_color: tuple=light_gray, + desc_text: str="", + default_text: str="", + padding: tuple=(8, 8), + cursor_blink_interval: int=30, + border_radius: int=-1, + max_length: int=128 + ): + self.surface = surface + self.font = font + self.bg_color = bg_color + self.text_color = text_color + self.desc_text_color = desc_text_color + self.desc_text = desc_text + self.text = default_text + self.padding = padding + self.focused = True + self.cursor_blink_interval = cursor_blink_interval + self.ticks_til_blink = cursor_blink_interval + self.blink = False + self.border_radius = border_radius + self.max_length = max_length + self.cursor_position = len(default_text) + + sx, sy = surface.get_size() + + if width is None: + self.width = round(sx / 4) + + else: + self.width = width + + self.description_text_object = font.render(self.desc_text, True, self.desc_text_color) + self.text_object = font.render(self.text, True, self.text_color) + self.text_blink_object = font.render(self.text + "|", True, self.text_color) + + self.height = self.text_object.get_height() + + if type(position) is tuple: + self.position = position + + else: + self.position = position(size=self.size) + self.callable_position = position + + self.rect = self.generate_rect() + + def generate_rect(self): + x, y = self.position + px, py = self.padding + x -= px + y -= py + + return pygame.Rect((x, y), (self.width + px * 2, self.height + py * 2)) + + def blit(self): + pygame.draw.rect(self.surface, self.bg_color, self.rect, border_radius=self.border_radius) + + if self.focused: + if self.blink: + self.surface.blit(self.text_blink_object, self.position) + + else: + self.surface.blit(self.text_object, self.position) + + def loop(self): + """Call this function every tick to make the cursor blink.""" + + self.ticks_til_blink -= 1 + + if self.ticks_til_blink == -1: + self.ticks_til_blink = self.cursor_blink_interval + self.blink = not self.blink + + def keypress(self, event: pygame.event, pressed_keys, special_keys): + """ + Call this function when a key is pressed to get user input like this: + + for event in pygame.event.get(): + if event.type == pygame.KEYDOWN: + TextInput.keypress(event, pygame.key.get_pressed(), pygame.key.get_mods()) + """ + + if self.max_length is None or len(self.text) <= self.max_length: + key_unicode = event.unicode + key = event.key + + if key < 32 or key > 101106 or special_keys & pygame.KMOD_CTRL or special_keys & pygame.KMOD_RCTRL or key > 126 and key < 161: + if key == pygame.K_BACKSPACE: + if self.cursor_position > 0: + self.text = text.rsap(self.text, "", self.cursor_position - 1) + self.cursor_position -= 1 + + elif key == pygame.K_LEFT: + if self.cursor_position > 0: + self.cursor_position -= 1 + + elif key == pygame.K_RIGHT: + if self.cursor_position < len(self.text): + self.cursor_position += 1 + + else: + self.text = text.asap(self.text, key_unicode, self.cursor_position) + self.cursor_position += 1 + + self.regenerate_objects() + + def regenerate_objects(self): + self.rect = self.generate_rect() + + self.text_object = self.font.render(self.text, True, self.text_color) + self.text_blink_object = self.font.render(text.asap(self.text, "|", self.cursor_position), True, self.text_color) + + t_width, t_height = self.text_blink_object.get_size() + + if t_width > self.width: + self.text_blink_object = crop_surface(self.text_blink_object, (t_width - (t_width - (t_width - self.width)), 0), (t_width - (t_width - self.width), t_height)) + self.text_object = crop_surface(self.text_object, (t_width - (t_width - (t_width - self.width)), 0), (t_width - (t_width - self.width), t_height)) + + def set_rot_point(img, pos): w, h = img.get_size() w, h = w * 2, h * 2