class TextInput(SelectableText): def __init__(self, screen, **kwargs): super().__init__(screen, **kwargs) self.rect = Rect(0, 0, kwargs.get("height", 0), kwargs.get("width", 0)) self.multiline = kwargs.get("multiline", True) self.cursor = Cursor(height=self.textheight) self.focused = False self.highlighted = False def update(self, event=None): super().update(event) if not None in [self.x2, self.y2]: self.cursor.x_index = self.x2 self.cursor.y_index = self.y2 significant_event = False mouse_pos = pygame.mouse.get_pos() if event.type == MOUSEBUTTONDOWN and event.button == 1 and self.rect.collidepoint(mouse_pos): self.focused = True self.cursor.start() elif event.type == MOUSEBUTTONDOWN and event.button == 1 and not self.rect.collidepoint(mouse_pos): self.focused = False self.cursor.stop() elif event.type == MOUSEMOTION: if self.pressed: significant_event = True if self.rect.collidepoint(mouse_pos): self.highlighted = True else: self.highlighted = False elif event.type == KEYDOWN and self.focused: significant_event = True if event.key == K_BACKSPACE: new_indeces = self.delete_selection() if not new_indeces: self.cursor.x_index -= 1 if self.cursor.x_index < 0: if self.cursor.y_index > 0: self.cursor.y_index -= 1 self.cursor.x_index = len(self.final_lines[self.cursor.y_index].text) self.join_lines(self.cursor.y_index, self.cursor.y_index + 1) else: self.cursor.x_index = 0 else: self.delete((self.cursor.x_index, self.cursor.y_index)) else: self.cursor.x_index, self.cursor.y_index = new_indeces elif event.key == K_DELETE: new_indeces = self.delete_selection() if not new_indeces: if self.cursor.x_index < len(self.final_lines[self.cursor.y_index].text): self.delete((self.cursor.x_index, self.cursor.y_index)) else: if self.cursor.y_index < len(self.final_lines) - 1: self.join_lines(self.cursor.x_index, self.cursor.y_index + 1) else: self.cursor.x_index, self.cursor.y_index = new_indeces elif event.key == K_RETURN: if self.multiline: new_indeces = self.delete_selection() if new_indeces: self.cursor.x_index, self.cursor.y_index = new_indeces self.split_line((self.cursor.x_index, self.cursor.y_index)) self.cursor.x_index = 0 self.cursor.y_index += 1 elif event.key == K_UP: pos = self.get_index_pos((self.cursor.x_index, self.cursor.y_index)) self.cursor.x_index, self.cursor.y_index = self.get_nearest_index((pos[0], pos[1] - self.textheight)) elif event.key == K_DOWN: pos = self.get_index_pos((self.cursor.x_index, self.cursor.y_index)) self.cursor.x_index, self.cursor.y_index = self.get_nearest_index((pos[0], pos[1] + self.lineheight)) elif event.key == K_LEFT: if self.cursor.x_index > 0: self.cursor.x_index -= 1 elif self.cursor.y_index > 0: self.cursor.y_index -= 1 self.cursor.x_index = len(self.final_lines[self.cursor.y_index].text) elif event.key == K_RIGHT: if self.cursor.x_index < len(self.final_lines[self.cursor.y_index].text): self.cursor.x_index += 1 elif self.cursor.y_index < len(self.final_lines) - 1: self.cursor.y_index += 1 self.cursor.x_index = 0 else: new_indeces = self.delete_selection() if new_indeces: self.cursor.x_index, self.cursor.y_index = new_indeces character = event.unicode if len(character) > 0: self.select_none() self.insert((self.cursor.x_index, self.cursor.y_index), character) self.cursor.x_index += 1 if significant_event: self.cursor.event() self.change_color() def change_color(self): if self.highlighted: self.color = (0, 0, 200) elif self.focused: self.color = (0, 0, 150) else: self.color = (0, 0, 100) def draw(self): self.cursor.update() pygame.draw.rect(self.screen, self.color, self.rect, 2) super().draw() self.cursor.draw(self.screen, self.get_index_pos((self.cursor.x_index, self.cursor.y_index)))
class TextInput(): def __init__(self, screen, pos, size, font, **kwargs): self.screen = screen self.pos = pos self.size = size self.rect = Rect(self.pos, self.size) self.font = font self.font_height = self.font.get_height() self.command = kwargs.get("command", None) self.maxlines = kwargs.get("maxlines", -1) self.maxlinelength = kwargs.get("maxlinelength", -1) self.focused = False self.highlighted = False self.cursor = Cursor("|", 700, 500, self.pos) self.text = SelectableText(self.screen, "", self.font, self.pos, textwrap=kwargs.get("textwrap", False), maxlinelength=kwargs.get("maxlinelength", -1)) self.update_text("") pygame.key.set_repeat(500, 20) def update_text(self, text): self.text.change_text(text) def get_text(self): return self.text.text.get_text() def update(self, event): significant_event = False mouse_pos = pygame.mouse.get_pos() if event.type == MOUSEBUTTONDOWN and event.button == 1 and self.rect.collidepoint(mouse_pos): self.focused = True self.cursor.start() elif event.type == MOUSEBUTTONDOWN and event.button == 1 and not self.rect.collidepoint(mouse_pos): self.focused = False self.cursor.stop() elif event.type == MOUSEMOTION: if self.rect.collidepoint(mouse_pos): self.highlighted = True else: self.highlighted = False elif event.type == KEYDOWN and self.focused: mod = event.mod mods = pygame.key.get_mods() significant_event = True if event.key == K_BACKSPACE: if self.text.get_selected_text() != None: points = self.text.get_ordered_points() self.cursor.x, self.cursor.y = points[0] self.text.removeslice(points) else: if self.cursor.x > 0: self.text.remove([self.cursor.x - 1, self.cursor.y]) self.cursor.x -= 1 else: if self.cursor.y > 0: self.cursor.x = len(self.text.lines[self.cursor.y - 1]) self.text.remove([-1, self.cursor.y]) self.cursor.y -= 1 elif event.key == K_DELETE: if self.text.get_selected_text() != None: points = self.text.get_ordered_points() self.cursor.x, self.cursor.y = points[0] self.text.removeslice(points) else: self.text.remove((self.cursor.x, self.cursor.y)) elif event.key == K_RETURN: self.text.insertline((self.cursor.x, self.cursor.y)) self.cursor.y += 1 self.cursor.x = 0 #if self.command != None: # self.command() elif event.key == K_LEFT: if self.cursor.x > 0: self.cursor.x -= 1 else: if self.cursor.y > 0: self.cursor.y -= 1 self.cursor.x = len(self.text.lines[self.cursor.y]) elif event.key == K_RIGHT: if self.cursor.x < len(self.text.lines[self.cursor.y]): self.cursor.x += 1 else: if self.cursor.y < len(self.text.lines) - 1: self.cursor.y += 1 self.cursor.x = 0 elif event.key == K_UP: self.cursor.move_up(self.text.size_list) if self.cursor.x > len(self.text.lines[self.cursor.y]): self.cursor.x = len(self.text.lines[self.cursor.y]) - 1 elif event.key == K_DOWN: self.cursor.move_down(self.text.size_list) if self.cursor.x > len(self.text.lines[self.cursor.y]): self.cursor.x = len(self.text.lines[self.cursor.y]) -1 else: if event.unicode != "" and mods in [0, 1, 2, 4096, 8192, 4097, 4098, 8193, 8194]: if self.text.get_selected_text() != None: self.text.replaceslice(self.text.get_ordered_points(), event.unicode) self.cursor.x = self.text.get_ordered_points()[0][0] + 1 self.cursor.y = self.text.get_ordered_points()[0][1] else: self.text.insert((self.cursor.x, self.cursor.y), event.unicode) self.cursor.x += 1 if mods == 0: self.text.selectnone() if significant_event: self.cursor.event() self.change_color() self.text.update(event) def change_color(self): if self.highlighted: self.color = (0, 0, 200) elif self.focused: self.color = (0, 0, 150) else: self.color = (0, 0, 100) def draw(self): self.cursor.x, self.cursor.y = self.text.wrap([self.cursor.x, self.cursor.y]) self.cursor.update() if self.cursor.visible: if self.text.get_selected_text() != None: self.cursor.x = self.text.x2 self.cursor.y = self.text.y2 self.cursor.calc_pixel_pos(self.text.size_list, self.font.get_height()) self.screen.blit(self.font.render(self.cursor.string, 1, (255, 255, 255)), (self.cursor.pixelx, self.cursor.pixely)) pygame.draw.rect(self.screen, self.color, self.rect, 2) self.text.draw()