From 32858dc93c62e219a990e5566975fd70fe085c59 Mon Sep 17 00:00:00 2001 From: Dan Lawrence Date: Thu, 2 May 2024 19:11:58 +0100 Subject: [PATCH] add options to disable copy & paste --- pygame_gui/core/utility.py | 23 +++- pygame_gui/elements/ui_text_box.py | 6 +- pygame_gui/elements/ui_text_entry_box.py | 72 ++++++------ pygame_gui/elements/ui_text_entry_line.py | 128 +++++++++++----------- pygame_gui/ui_manager.py | 3 + 5 files changed, 131 insertions(+), 101 deletions(-) diff --git a/pygame_gui/core/utility.py b/pygame_gui/core/utility.py index d0eec022..9a6c856c 100644 --- a/pygame_gui/core/utility.py +++ b/pygame_gui/core/utility.py @@ -173,7 +173,7 @@ def __linux_paste(): stdout, _ = process.communicate() return stdout.decode('utf-8') -else: +elif PLATFORM == 'DARWIN': def __mac_copy(data: str): with subprocess.Popen('pbcopy', env={'LANG': 'en_US.UTF-8'}, @@ -185,10 +185,19 @@ def __mac_paste(): return subprocess.check_output( 'pbpaste', env={'LANG': 'en_US.UTF-8'}).decode('utf-8') +else: + def __unknown_copy(data: str): + # copy not supported on this platform + pass + + def __unknown_paste(): + # paste not supported on this platform + return "" + def clipboard_copy(data: str): """ - Hopefully cross platform, copy to a clipboard. + Hopefully cross-platform, copy to a clipboard. :return: A platform specific copy function. @@ -201,13 +210,15 @@ def clipboard_copy(data: str): __windows_copy(data) elif current_platform == 'LINUX': __linux_copy(data) - else: + elif current_platform == 'DARWIN': __mac_copy(data) + else: + __unknown_copy(data) def clipboard_paste(): """ - Hopefully cross platform, paste from a clipboard. + Hopefully cross-platform, paste from a clipboard. :return: A platform specific paste function. @@ -220,8 +231,10 @@ def clipboard_paste(): return __windows_paste() elif current_platform == 'LINUX': return __linux_paste() - else: + elif current_platform == 'DARWIN': return __mac_paste() + else: + return __unknown_paste() def create_resource_path(relative_path: Union[str, Path]): diff --git a/pygame_gui/elements/ui_text_box.py b/pygame_gui/elements/ui_text_box.py index 38005fd6..4a653608 100644 --- a/pygame_gui/elements/ui_text_box.py +++ b/pygame_gui/elements/ui_text_box.py @@ -199,6 +199,9 @@ def __init__(self, self.vertical_cursor_movement = False self.last_horiz_cursor_index = 0 + self.copy_text_enabled = True + self.paste_text_enabled = False + self.rebuild_from_changed_theme_data() @property @@ -922,7 +925,8 @@ def _do_copy(self): if self.text_box_layout is not None and 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_box_layout.plain_text[low_end:high_end]) + if self.ui_manager.copy_text_enabled and self.copy_text_enabled: + clipboard_copy(self.text_box_layout.plain_text[low_end:high_end]) def _calculate_double_click_word_selection(self): """ diff --git a/pygame_gui/elements/ui_text_entry_box.py b/pygame_gui/elements/ui_text_entry_box.py index 6500e66c..04262db4 100644 --- a/pygame_gui/elements/ui_text_entry_box.py +++ b/pygame_gui/elements/ui_text_entry_box.py @@ -71,6 +71,7 @@ def __init__(self, self.cursor_blink_delay_after_moving = 1.0 self.blink_cursor_time_acc = 0.0 self.blink_cursor_time = 0.4 + self.paste_text_enabled = True self.cursor_on = False @@ -333,17 +334,19 @@ def _process_cut_event(self, event: Event) -> bool: return consumed_event def _do_cut(self): - 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.html_text[low_end:high_end]) - self.text_box_layout.delete_selected_text() - self.edit_position = low_end - self.html_text = self.html_text[:low_end] + self.html_text[high_end:] - self.text_box_layout.set_cursor_position(self.edit_position) - self.select_range = [0, 0] - self.redraw_from_text_block() - self.cursor_has_moved_recently = True + if self.ui_manager.copy_text_enabled and self.copy_text_enabled: + 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.html_text[low_end:high_end]) + self.text_box_layout.delete_selected_text() + self.edit_position = low_end + self.html_text = self.html_text[:low_end] + self.html_text[high_end:] + self.text_box_layout.set_cursor_position(self.edit_position) + self.select_range = [0, 0] + self.redraw_from_text_block() + self.cursor_has_moved_recently = True def _process_paste_event(self, event: Event) -> bool: """ @@ -362,30 +365,31 @@ def _process_paste_event(self, event: Event) -> bool: return consumed_event def _do_paste(self): - paste = clipboard_paste() - if paste is not None: - new_text = self.convert_all_line_endings_to_unix(clipboard_paste()) + if self.ui_manager.paste_text_enabled and self.paste_text_enabled: + paste = clipboard_paste() + if paste is not None: + new_text = self.convert_all_line_endings_to_unix(clipboard_paste()) - 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.html_text = self.html_text[:low_end] + new_text + self.html_text[high_end:] - self.set_text(self.html_text) - self.edit_position = low_end + len(new_text) - self.text_box_layout.set_cursor_position(self.edit_position) - self.redraw_from_text_block() - self.select_range = [0, 0] - self.cursor_has_moved_recently = True - elif len(new_text) > 0: - self.html_text = (self.html_text[:self.edit_position] + - new_text + - self.html_text[self.edit_position:]) - original_edit_pos = self.edit_position - self.set_text(self.html_text) - self.edit_position = original_edit_pos + len(new_text) - self.text_box_layout.set_cursor_position(self.edit_position) - self.redraw_from_text_block() - self.cursor_has_moved_recently = True + 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.html_text = self.html_text[:low_end] + new_text + self.html_text[high_end:] + self.set_text(self.html_text) + self.edit_position = low_end + len(new_text) + self.text_box_layout.set_cursor_position(self.edit_position) + self.redraw_from_text_block() + self.select_range = [0, 0] + self.cursor_has_moved_recently = True + elif len(new_text) > 0: + self.html_text = (self.html_text[:self.edit_position] + + new_text + + self.html_text[self.edit_position:]) + original_edit_pos = self.edit_position + self.set_text(self.html_text) + self.edit_position = original_edit_pos + len(new_text) + self.text_box_layout.set_cursor_position(self.edit_position) + self.redraw_from_text_block() + self.cursor_has_moved_recently = True def redraw_from_text_block(self): self.text_box_layout.fit_layout_rect_height_to_rows() diff --git a/pygame_gui/elements/ui_text_entry_line.py b/pygame_gui/elements/ui_text_entry_line.py index eb5f6b51..0458d384 100644 --- a/pygame_gui/elements/ui_text_entry_line.py +++ b/pygame_gui/elements/ui_text_entry_line.py @@ -147,6 +147,9 @@ def __init__(self, self.forbidden_characters: Optional[List[str]] = None self.length_limit: Optional[int] = None + self.copy_text_enabled = True + self.paste_text_enabled = True + self.rebuild_from_changed_theme_data() @property @@ -780,20 +783,21 @@ def _process_cut_event(self, event: Event) -> bool: return consumed_event def _do_cut(self): - 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]) - if self.drawable_shape is not None: - self.drawable_shape.text_box_layout.delete_selected_text() - self.drawable_shape.apply_active_text_changes() - self.edit_position = low_end - self.text = self.text[:low_end] + self.text[high_end:] - 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 + if self.ui_manager.copy_text_enabled and self.copy_text_enabled: + 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]) + if self.drawable_shape is not None: + self.drawable_shape.text_box_layout.delete_selected_text() + self.drawable_shape.apply_active_text_changes() + self.edit_position = low_end + self.text = self.text[:low_end] + self.text[high_end:] + 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 def _process_copy_event(self, event: Event) -> bool: """ @@ -817,7 +821,8 @@ def _do_copy(self): 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]) + if self.ui_manager.copy_text_enabled and self.copy_text_enabled: + clipboard_copy(self.text[low_end:high_end]) def _process_paste_event(self, event: pygame.event.Event) -> bool: """ @@ -837,52 +842,53 @@ def _process_paste_event(self, event: pygame.event.Event) -> bool: return consumed_event def _do_paste(self): - 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 + if self.ui_manager.paste_text_enabled and self.paste_text_enabled: + 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 def _process_mouse_button_event(self, event: pygame.event.Event) -> bool: """ diff --git a/pygame_gui/ui_manager.py b/pygame_gui/ui_manager.py index e53a42fc..08802af9 100644 --- a/pygame_gui/ui_manager.py +++ b/pygame_gui/ui_manager.py @@ -101,6 +101,9 @@ def __init__(self, self.text_hovered = False self.hovering_any_ui_element = False + self.copy_text_enabled = True + self.paste_text_enabled = True + if auto_load: self.resource_loader.start() # If we are using a blocking loader this will only return when loading is complete