def test_process_event_text_ctrl_x(self, _init_pygame: None, default_ui_manager: UIManager, _display_surface_return_none: None): text_entry = UITextEntryLine(relative_rect=pygame.Rect( 100, 100, 200, 30), manager=default_ui_manager) text_entry.set_text('dan') text_entry.select() processed_key_event = text_entry.process_event( pygame.event.Event(pygame.KEYDOWN, { 'key': pygame.K_a, 'mod': pygame.KMOD_CTRL, 'unicode': 'a' })) text_entry.process_event( pygame.event.Event(pygame.KEYDOWN, { 'key': pygame.K_x, 'mod': pygame.KMOD_CTRL, 'unicode': 'x' })) text_entry.process_event( pygame.event.Event(pygame.KEYDOWN, { 'key': pygame.K_v, 'mod': pygame.KMOD_CTRL, 'unicode': 'v' })) assert processed_key_event and clipboard_paste() == 'dan'
def _process_paste_event(self, event: pygame.event.Event) -> bool: """ Process a paste shortcut event. (CTRL+ V) :param event: The event to process. :return: True if the event is consumed. """ consumed_event = False if event.key == pygame.K_v and event.mod & pygame.KMOD_CTRL: new_text = clipboard_paste() if self.validate_text_string(new_text): if abs(self.select_range[0] - self.select_range[1]) > 0: low_end = min(self.select_range[0], self.select_range[1]) high_end = max(self.select_range[0], self.select_range[1]) final_text = self.text[:low_end] + new_text + self.text[high_end:] within_length_limit = True if self.length_limit is not None and len(final_text) > self.length_limit: within_length_limit = False if within_length_limit: self.text = final_text if self.drawable_shape is not None: self.drawable_shape.text_box_layout.delete_selected_text() self.drawable_shape.apply_active_text_changes() display_new_text = new_text if self.is_text_hidden: display_new_text = self.hidden_text_char * len(new_text) if self.drawable_shape is not None: self.drawable_shape.insert_text(display_new_text, low_end) self.edit_position = low_end + len(new_text) if self.drawable_shape is not None: self.drawable_shape.text_box_layout.set_cursor_position( self.edit_position) self.drawable_shape.apply_active_text_changes() self.select_range = [0, 0] self.cursor_has_moved_recently = True elif len(new_text) > 0: final_text = (self.text[:self.edit_position] + new_text + self.text[self.edit_position:]) within_length_limit = True if self.length_limit is not None and len(final_text) > self.length_limit: within_length_limit = False if within_length_limit: self.text = final_text display_new_text = new_text if self.is_text_hidden: display_new_text = self.hidden_text_char * len(new_text) if self.drawable_shape is not None: self.drawable_shape.insert_text(display_new_text, self.edit_position) self.edit_position += len(new_text) if self.drawable_shape is not None: self.drawable_shape.text_box_layout.set_cursor_position( self.edit_position) self.drawable_shape.apply_active_text_changes() self.cursor_has_moved_recently = True consumed_event = True return consumed_event
def _process_paste_event(self, event: pygame.event.Event) -> bool: """ Process a paste shortcut event. (CTRL+ V) :param event: The event to process. :return: True if the event is consumed. """ consumed_event = False if event.key == pygame.K_v and event.mod & pygame.KMOD_CTRL: new_text = clipboard_paste() if self.validate_text_string(new_text): if abs(self.select_range[0] - self.select_range[1]) > 0: low_end = min(self.select_range[0], self.select_range[1]) high_end = max(self.select_range[0], self.select_range[1]) final_text = self.text[:low_end] + new_text + self.text[ high_end:] within_length_limit = True if self.length_limit is not None and len( final_text) > self.length_limit: within_length_limit = False if within_length_limit: self.text = final_text self.edit_position = low_end + len(new_text) self.select_range = [0, 0] self.cursor_has_moved_recently = True elif len(new_text) > 0: final_text = (self.text[:self.edit_position] + new_text + self.text[self.edit_position:]) within_length_limit = True if self.length_limit is not None and len( final_text) > self.length_limit: within_length_limit = False if within_length_limit: self.text = final_text self.edit_position += len(new_text) self.cursor_has_moved_recently = True consumed_event = True return consumed_event
def test_process_event_text_ctrl_c(self, _init_pygame: None, _display_surface_return_none: None): manager = UIManager( (800, 600), os.path.join("tests", "data", "themes", "ui_text_entry_line_non_default_2.json")) text_entry = UITextEntryLine(relative_rect=pygame.Rect( 100, 100, 200, 30), manager=manager) text_entry.set_text('dan') text_entry.select() text_entry.select_range = [0, 3] processed_key_event = text_entry.process_event( pygame.event.Event(pygame.KEYDOWN, { 'key': pygame.K_c, 'mod': pygame.KMOD_CTRL, 'unicode': 'c' })) text_entry.cursor_on = True text_entry.redraw_cursor() assert processed_key_event and clipboard_paste() == 'dan'
def process_event(self, event: pygame.event.Event) -> bool: """ Allows the text entry box to react to input events, which is it's primary function. The entry element reacts to various types of mouse clicks (double click selecting words, drag select), keyboard combos (CTRL+C, CTRL+V, CTRL+X, CTRL+A), individual editing keys (Backspace, Delete, Left & Right arrows) and other keys for inputting letters, symbols and numbers. :param event: The current event to consider reacting to. :return bool: Returns True if we've done something with the input event. """ processed_event = False if event.type == pygame.MOUSEBUTTONDOWN: if event.button == 1: mouse_x, mouse_y = event.pos if self.rect.collidepoint(mouse_x, mouse_y): if self.double_click_started and self.double_click_select_time_acc < self.double_click_select_time: self.double_click_started = False pattern = re.compile(r"[\w']+") index = min(self.edit_position, len(self.text) - 1) if index > 0: char = self.text[index] while not pattern.match(char): index -= 1 if index > 0: char = self.text[index] else: break while pattern.match(char): index -= 1 if index > 0: char = self.text[index] else: break if index > 0: start_select_index = index + 1 else: start_select_index = index index += 1 char = self.text[index] while index < len( self.text) and pattern.match(char): index += 1 if index < len(self.text): char = self.text[index] end_select_index = index self.select_range[0] = start_select_index self.select_range[1] = end_select_index self.edit_position = end_select_index self.cursor_has_moved_recently = True else: self.double_click_started = True self.edit_position = self.find_edit_position_from_pixel_pos( self.start_text_offset + mouse_x) self.select_range[0] = self.edit_position self.select_range[1] = self.edit_position self.cursor_has_moved_recently = True self.selection_in_progress = True self.double_click_select_time_acc = 0.0 processed_event = True if event.type == pygame.MOUSEBUTTONUP: if event.button == 1: mouse_x, mouse_y = event.pos if self.rect.collidepoint(mouse_x, mouse_y): processed_event = True new_edit_pos = self.find_edit_position_from_pixel_pos( self.start_text_offset + mouse_x) if new_edit_pos != self.edit_position: self.cursor_has_moved_recently = True self.select_range[1] = self.edit_position self.selection_in_progress = False else: self.selection_in_progress = False if self.selected: if event.type == pygame.KEYDOWN: if event.key == pygame.K_RETURN: entry_finished_event = pygame.event.Event( pygame.USEREVENT, { 'user_type': 'ui_text_entry_finished', 'text': self.text, 'ui_element': self, 'ui_object_id': self.object_ids[-1] }) pygame.event.post(entry_finished_event) elif event.key == pygame.K_a and event.mod & pygame.KMOD_CTRL: self.select_range = [0, len(self.text)] self.edit_position = len(self.text) self.cursor_has_moved_recently = True elif event.key == pygame.K_x and event.mod & pygame.KMOD_CTRL: if abs(self.select_range[0] - self.select_range[1]) > 0: low_end = min(self.select_range[0], self.select_range[1]) high_end = max(self.select_range[0], self.select_range[1]) clipboard_copy(self.text[low_end:high_end]) self.text = self.text[:low_end] + self.text[high_end:] self.edit_position = low_end self.select_range = [0, 0] self.cursor_has_moved_recently = True elif event.key == pygame.K_c and event.mod & pygame.KMOD_CTRL: if abs(self.select_range[0] - self.select_range[1]) > 0: low_end = min(self.select_range[0], self.select_range[1]) high_end = max(self.select_range[0], self.select_range[1]) clipboard_copy(self.text[low_end:high_end]) elif event.key == pygame.K_v and event.mod & pygame.KMOD_CTRL: new_text = clipboard_paste() if self.validate_text_string(new_text): if abs(self.select_range[0] - self.select_range[1]) > 0: low_end = min(self.select_range[0], self.select_range[1]) high_end = max(self.select_range[0], self.select_range[1]) final_text = self.text[: low_end] + new_text + self.text[ high_end:] within_length_limit = True if self.length_limit is not None: if len(final_text) > self.length_limit: within_length_limit = False if within_length_limit: self.text = final_text self.edit_position = low_end + len(new_text) self.select_range = [0, 0] self.cursor_has_moved_recently = True elif len(new_text) > 0: final_text = self.text[:self. edit_position] + new_text + self.text[ self.edit_position:] within_length_limit = True if self.length_limit is not None: if len(final_text) > self.length_limit: within_length_limit = False if within_length_limit: self.text = final_text self.edit_position += len(new_text) self.cursor_has_moved_recently = True processed_event = True elif event.key == pygame.K_BACKSPACE: if abs(self.select_range[0] - self.select_range[1]) > 0: low_end = min(self.select_range[0], self.select_range[1]) high_end = max(self.select_range[0], self.select_range[1]) self.text = self.text[:low_end] + self.text[high_end:] self.edit_position = low_end self.select_range = [0, 0] self.cursor_has_moved_recently = True elif self.edit_position > 0: if self.start_text_offset > 0: self.start_text_offset -= self.font.size( self.text[self.edit_position - 1])[0] self.text = self.text[:self.edit_position - 1] + self.text[self. edit_position:] self.edit_position -= 1 self.cursor_has_moved_recently = True processed_event = True elif event.key == pygame.K_DELETE: if abs(self.select_range[0] - self.select_range[1]) > 0: low_end = min(self.select_range[0], self.select_range[1]) high_end = max(self.select_range[0], self.select_range[1]) self.text = self.text[:low_end] + self.text[high_end:] self.edit_position = low_end self.select_range = [0, 0] self.cursor_has_moved_recently = True elif self.edit_position < len(self.text): self.text = self.text[:self.edit_position] + self.text[ self.edit_position + 1:] self.edit_position = self.edit_position self.cursor_has_moved_recently = True processed_event = True elif event.key == pygame.K_LEFT: if abs(self.select_range[0] - self.select_range[1]) > 0: self.edit_position = min(self.select_range[0], self.select_range[1]) self.select_range = [0, 0] self.cursor_has_moved_recently = True elif self.edit_position > 0: self.edit_position -= 1 self.cursor_has_moved_recently = True processed_event = True elif event.key == pygame.K_RIGHT: if abs(self.select_range[0] - self.select_range[1]) > 0: self.edit_position = max(self.select_range[0], self.select_range[1]) self.select_range = [0, 0] self.cursor_has_moved_recently = True elif self.edit_position < len(self.text): self.edit_position += 1 self.cursor_has_moved_recently = True processed_event = True else: within_length_limit = True if self.length_limit is not None: if len(self.text) >= self.length_limit: within_length_limit = False if within_length_limit: character = event.unicode char_metrics = self.font.metrics(character) if len(char_metrics ) > 0 and char_metrics[0] is not None: valid_character = True if self.allowed_characters is not None: if character not in self.allowed_characters: valid_character = False if self.forbidden_characters is not None: if character in self.forbidden_characters: valid_character = False if valid_character: if abs(self.select_range[0] - self.select_range[1]) > 0: low_end = min(self.select_range[0], self.select_range[1]) high_end = max(self.select_range[0], self.select_range[1]) self.text = self.text[: low_end] + character + self.text[ high_end:] self.edit_position = low_end + 1 self.select_range = [0, 0] else: start_str = self.text[:self.edit_position] end_str = self.text[self.edit_position:] self.text = start_str + character + end_str self.edit_position += 1 self.cursor_has_moved_recently = True processed_event = True return processed_event