diff options
-rw-r--r-- | doc/classes/TextEdit.xml | 32 | ||||
-rw-r--r-- | scene/gui/code_edit.cpp | 123 | ||||
-rw-r--r-- | scene/gui/code_edit.h | 9 | ||||
-rw-r--r-- | scene/gui/text_edit.cpp | 345 | ||||
-rw-r--r-- | scene/gui/text_edit.h | 29 |
5 files changed, 314 insertions, 224 deletions
diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index 7b34b3c461..855f19852f 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -13,13 +13,35 @@ <method name="_backspace" qualifiers="virtual"> <return type="void" /> <description> - A virtual method that is called whenever backspace is triggered. + Overide this method to define what happens when the user presses the backspace key. + </description> + </method> + <method name="_copy" qualifiers="virtual"> + <return type="void"> + </return> + <description> + Overide this method to define what happens when the user performs a copy. + </description> + </method> + <method name="_cut" qualifiers="virtual"> + <return type="void"> + </return> + <description> + Overide this method to define what happens when the user perfroms a cut. </description> </method> <method name="_handle_unicode_input" qualifiers="virtual"> <return type="void" /> <argument index="0" name="unicode" type="int" /> <description> + Overide this method to define what happens when the types in the provided key [code]unicode[/code]. + </description> + </method> + <method name="_paste" qualifiers="virtual"> + <return type="void"> + </return> + <description> + Overide this method to define what happens when the user perfroms a paste. </description> </method> <method name="add_gutter"> @@ -31,7 +53,7 @@ <method name="backspace"> <return type="void" /> <description> - Causes the [TextEdit] to perform a backspace. + Called when the user presses the backspace key. Can be overriden with [method _backspace]. </description> </method> <method name="center_viewport_to_cursor"> @@ -55,7 +77,7 @@ <method name="copy"> <return type="void" /> <description> - Copy's the current text selection. + Copy's the current text selection. Can be overriden with [method _copy]. </description> </method> <method name="cursor_get_column" qualifiers="const"> @@ -94,7 +116,7 @@ <method name="cut"> <return type="void" /> <description> - Cut's the current selection. + Cut's the current selection. Can be overriden with [method _cut]. </description> </method> <method name="delete_selection"> @@ -351,7 +373,7 @@ <method name="paste"> <return type="void" /> <description> - Paste the current selection. + Paste the current selection. Can be overriden with [method _paste]. </description> </method> <method name="redo"> diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 32922f609d..0790317380 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -544,18 +544,21 @@ Control::CursorShape CodeEdit::get_cursor_shape(const Point2 &p_pos) const { return TextEdit::get_cursor_shape(p_pos); } -void CodeEdit::handle_unicode_input(uint32_t p_unicode) { +/* Text manipulation */ + +// Overridable actions +void CodeEdit::_handle_unicode_input(const uint32_t p_unicode) { bool had_selection = is_selection_active(); if (had_selection) { begin_complex_operation(); delete_selection(); } - // Remove the old character if in insert mode and no selection. + /* Remove the old character if in insert mode and no selection. */ if (is_insert_mode() && !had_selection) { begin_complex_operation(); - // Make sure we don't try and remove empty space. + /* Make sure we don't try and remove empty space. */ if (cursor_get_column() < get_line(cursor_get_line()).length()) { _remove_text(cursor_get_line(), cursor_get_column(), cursor_get_line(), cursor_get_column() + 1); } @@ -596,6 +599,63 @@ void CodeEdit::handle_unicode_input(uint32_t p_unicode) { } } +void CodeEdit::_backspace() { + if (is_readonly()) { + return; + } + + int cc = cursor_get_column(); + int cl = cursor_get_line(); + + if (cc == 0 && cl == 0) { + return; + } + + if (is_selection_active()) { + delete_selection(); + return; + } + + if (cl > 0 && is_line_hidden(cl - 1)) { + unfold_line(cursor_get_line() - 1); + } + + int prev_line = cc ? cl : cl - 1; + int prev_column = cc ? (cc - 1) : (get_line(cl - 1).length()); + + merge_gutters(cl, prev_line); + + if (auto_brace_completion_enabled && cc > 0) { + int idx = _get_auto_brace_pair_open_at_pos(cl, cc); + if (idx != -1) { + prev_column = cc - auto_brace_completion_pairs[idx].open_key.length(); + + if (_get_auto_brace_pair_close_at_pos(cl, cc) == idx) { + _remove_text(prev_line, prev_column, cl, cc + auto_brace_completion_pairs[idx].close_key.length()); + } else { + _remove_text(prev_line, prev_column, cl, cc); + } + cursor_set_line(prev_line, false, true); + cursor_set_column(prev_column); + return; + } + } + + /* For space indentation we need to do a simple unindent if there are no chars to the left, acting in the */ + /* same way as tabs. */ + if (indent_using_spaces && cc != 0) { + if (get_first_non_whitespace_column(cl) > cc) { + prev_column = cc - _calculate_spaces_till_next_left_indent(cc); + prev_line = cl; + } + } + + _remove_text(prev_line, prev_column, cl, cc); + + cursor_set_line(prev_line, false, true); + cursor_set_column(prev_column); +} + /* Indent management */ void CodeEdit::set_indent_size(const int p_size) { ERR_FAIL_COND_MSG(p_size <= 0, "Indend size must be greater than 0."); @@ -955,63 +1015,6 @@ void CodeEdit::_new_line(bool p_split_current_line, bool p_above) { end_complex_operation(); } -void CodeEdit::backspace() { - if (is_readonly()) { - return; - } - - int cc = cursor_get_column(); - int cl = cursor_get_line(); - - if (cc == 0 && cl == 0) { - return; - } - - if (is_selection_active()) { - delete_selection(); - return; - } - - if (cl > 0 && is_line_hidden(cl - 1)) { - unfold_line(cursor_get_line() - 1); - } - - int prev_line = cc ? cl : cl - 1; - int prev_column = cc ? (cc - 1) : (get_line(cl - 1).length()); - - merge_gutters(cl, prev_line); - - if (auto_brace_completion_enabled && cc > 0) { - int idx = _get_auto_brace_pair_open_at_pos(cl, cc); - if (idx != -1) { - prev_column = cc - auto_brace_completion_pairs[idx].open_key.length(); - - if (_get_auto_brace_pair_close_at_pos(cl, cc) == idx) { - _remove_text(prev_line, prev_column, cl, cc + auto_brace_completion_pairs[idx].close_key.length()); - } else { - _remove_text(prev_line, prev_column, cl, cc); - } - cursor_set_line(prev_line, false, true); - cursor_set_column(prev_column); - return; - } - } - - /* For space indentation we need to do a simple unindent if there are no chars to the left, acting in the */ - /* same way as tabs. */ - if (indent_using_spaces && cc != 0) { - if (get_first_non_whitespace_column(cl) > cc) { - prev_column = cc - _calculate_spaces_till_next_left_indent(cc); - prev_line = cl; - } - } - - _remove_text(prev_line, prev_column, cl, cc); - - cursor_set_line(prev_line, false, true); - cursor_set_column(prev_column); -} - /* Auto brace completion */ void CodeEdit::set_auto_brace_completion_enabled(bool p_enabled) { auto_brace_completion_enabled = p_enabled; diff --git a/scene/gui/code_edit.h b/scene/gui/code_edit.h index 72fdc6e787..b875e4009c 100644 --- a/scene/gui/code_edit.h +++ b/scene/gui/code_edit.h @@ -239,10 +239,15 @@ protected: static void _bind_methods(); + /* Text manipulation */ + + // Overridable actions + virtual void _handle_unicode_input(const uint32_t p_unicode) override; + virtual void _backspace() override; + public: /* General overrides */ virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override; - virtual void handle_unicode_input(uint32_t p_unicode) override; /* Indent management */ void set_indent_size(const int p_size); @@ -263,8 +268,6 @@ public: void indent_lines(); void unindent_lines(); - virtual void backspace() override; - /* Auto brace completion */ void set_auto_brace_completion_enabled(bool p_enabled); bool is_auto_brace_completion_enabled() const; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 56b5459558..27046570bb 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1503,40 +1503,6 @@ void TextEdit::_notification(int p_what) { } } -void TextEdit::backspace() { - ScriptInstance *si = get_script_instance(); - if (si && si->has_method("_backspace")) { - si->call("_backspace"); - return; - } - - if (readonly) { - return; - } - - if (cursor.column == 0 && cursor.line == 0) { - return; - } - - if (is_selection_active()) { - delete_selection(); - return; - } - - int prev_line = cursor.column ? cursor.line : cursor.line - 1; - int prev_column = cursor.column ? (cursor.column - 1) : (text[cursor.line - 1].length()); - - merge_gutters(cursor.line, prev_line); - - if (is_line_hidden(cursor.line)) { - set_line_as_hidden(prev_line, true); - } - _remove_text(prev_line, prev_column, cursor.line, cursor.column); - - cursor_set_line(prev_line, false, true); - cursor_set_column(prev_column); -} - void TextEdit::_swap_current_input_direction() { if (input_direction == TEXT_DIRECTION_LTR) { input_direction = TEXT_DIRECTION_RTL; @@ -1955,37 +1921,6 @@ void TextEdit::_move_cursor_document_end(bool p_select) { } } -void TextEdit::handle_unicode_input(uint32_t p_unicode) { - ScriptInstance *si = get_script_instance(); - if (si && si->has_method("_handle_unicode_input")) { - si->call("_handle_unicode_input", p_unicode); - return; - } - - bool had_selection = selection.active; - if (had_selection) { - begin_complex_operation(); - delete_selection(); - } - - // Remove the old character if in insert mode and no selection. - if (insert_mode && !had_selection) { - begin_complex_operation(); - - // Make sure we don't try and remove empty space. - if (cursor.column < get_line(cursor.line).length()) { - _remove_text(cursor.line, cursor.column, cursor.line, cursor.column + 1); - } - } - - const char32_t chr[2] = { (char32_t)p_unicode, 0 }; - insert_text_at_cursor(chr); - - if ((insert_mode && !had_selection) || (had_selection)) { - end_complex_operation(); - } -} - void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) const { float rows = p_mouse.y; rows -= cache.style_normal->get_margin(SIDE_TOP); @@ -3785,6 +3720,54 @@ void TextEdit::_update_caches() { } } +/* Text manipulation */ + +// Overridable actions +void TextEdit::handle_unicode_input(const uint32_t p_unicode) { + ScriptInstance *si = get_script_instance(); + if (si && si->has_method("_handle_unicode_input")) { + si->call("_handle_unicode_input", p_unicode); + return; + } + _handle_unicode_input(p_unicode); +} + +void TextEdit::backspace() { + ScriptInstance *si = get_script_instance(); + if (si && si->has_method("_backspace")) { + si->call("_backspace"); + return; + } + _backspace(); +} + +void TextEdit::cut() { + ScriptInstance *si = get_script_instance(); + if (si && si->has_method("_cut")) { + si->call("_cut"); + return; + } + _cut(); +} + +void TextEdit::copy() { + ScriptInstance *si = get_script_instance(); + if (si && si->has_method("_copy")) { + si->call("_copy"); + return; + } + _copy(); +} + +void TextEdit::paste() { + ScriptInstance *si = get_script_instance(); + if (si && si->has_method("_paste")) { + si->call("_paste"); + return; + } + _paste(); +} + /* Syntax Highlighting. */ Ref<SyntaxHighlighter> TextEdit::get_syntax_highlighter() { return syntax_highlighter; @@ -4028,84 +4011,6 @@ Color TextEdit::get_line_background_color(int p_line) { return text.get_line_background_color(p_line); } -void TextEdit::cut() { - if (readonly) { - return; - } - - if (!selection.active) { - String clipboard = text[cursor.line]; - DisplayServer::get_singleton()->clipboard_set(clipboard); - cursor_set_line(cursor.line); - cursor_set_column(0); - - if (cursor.line == 0 && get_line_count() > 1) { - _remove_text(cursor.line, 0, cursor.line + 1, 0); - } else { - _remove_text(cursor.line, 0, cursor.line, text[cursor.line].length()); - backspace(); - cursor_set_line(cursor.line + 1); - } - - update(); - cut_copy_line = clipboard; - - } else { - String clipboard = _base_get_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column); - DisplayServer::get_singleton()->clipboard_set(clipboard); - - _remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column); - cursor_set_line(selection.from_line, false); // Set afterwards else it causes the view to be offset. - cursor_set_column(selection.from_column); - - selection.active = false; - selection.selecting_mode = SelectionMode::SELECTION_MODE_NONE; - update(); - cut_copy_line = ""; - } -} - -void TextEdit::copy() { - if (!selection.active) { - if (text[cursor.line].length() != 0) { - String clipboard = _base_get_text(cursor.line, 0, cursor.line, text[cursor.line].length()); - DisplayServer::get_singleton()->clipboard_set(clipboard); - cut_copy_line = clipboard; - } - } else { - String clipboard = _base_get_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column); - DisplayServer::get_singleton()->clipboard_set(clipboard); - cut_copy_line = ""; - } -} - -void TextEdit::paste() { - if (readonly) { - return; - } - - String clipboard = DisplayServer::get_singleton()->clipboard_get(); - - begin_complex_operation(); - if (selection.active) { - selection.active = false; - selection.selecting_mode = SelectionMode::SELECTION_MODE_NONE; - _remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column); - cursor_set_line(selection.from_line, false); - cursor_set_column(selection.from_column); - - } else if (!cut_copy_line.is_empty() && cut_copy_line == clipboard) { - cursor_set_column(0); - String ins = "\n"; - clipboard += ins; - } - - insert_text_at_cursor(clipboard); - end_complex_operation(); - - update(); -} - void TextEdit::select_all() { if (!selecting_enabled) { return; @@ -5425,13 +5330,6 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("is_selecting_enabled"), &TextEdit::is_selecting_enabled); ClassDB::bind_method(D_METHOD("delete_selection"), &TextEdit::delete_selection); - ClassDB::bind_method(D_METHOD("backspace"), &TextEdit::backspace); - BIND_VMETHOD(MethodInfo("_backspace")); - BIND_VMETHOD(MethodInfo("_handle_unicode_input", PropertyInfo(Variant::INT, "unicode"))) - - ClassDB::bind_method(D_METHOD("cut"), &TextEdit::cut); - ClassDB::bind_method(D_METHOD("copy"), &TextEdit::copy); - ClassDB::bind_method(D_METHOD("paste"), &TextEdit::paste); ClassDB::bind_method(D_METHOD("select", "from_line", "from_column", "to_line", "to_column"), &TextEdit::select); ClassDB::bind_method(D_METHOD("select_all"), &TextEdit::select_all); @@ -5462,6 +5360,23 @@ void TextEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("set_override_selected_font_color", "override"), &TextEdit::set_override_selected_font_color); ClassDB::bind_method(D_METHOD("is_overriding_selected_font_color"), &TextEdit::is_overriding_selected_font_color); + /* Text manipulation */ + + // Overridable actions + ClassDB::bind_method(D_METHOD("backspace"), &TextEdit::backspace); + + ClassDB::bind_method(D_METHOD("cut"), &TextEdit::cut); + ClassDB::bind_method(D_METHOD("copy"), &TextEdit::copy); + ClassDB::bind_method(D_METHOD("paste"), &TextEdit::paste); + + BIND_VMETHOD(MethodInfo("_handle_unicode_input", PropertyInfo(Variant::INT, "unicode"))) + BIND_VMETHOD(MethodInfo("_backspace")); + + BIND_VMETHOD(MethodInfo("_cut")); + BIND_VMETHOD(MethodInfo("_copy")); + BIND_VMETHOD(MethodInfo("_paste")); + + /* Syntax Highlighting. */ ClassDB::bind_method(D_METHOD("set_syntax_highlighter", "syntax_highlighter"), &TextEdit::set_syntax_highlighter); ClassDB::bind_method(D_METHOD("get_syntax_highlighter"), &TextEdit::get_syntax_highlighter); @@ -5679,6 +5594,136 @@ void TextEdit::_ensure_menu() { menu_dir->set_item_checked(menu_dir->get_item_index(MENU_DIR_RTL), text_direction == TEXT_DIRECTION_RTL); } +/* Text manipulation */ + +// Overridable actions +void TextEdit::_handle_unicode_input(const uint32_t p_unicode) { + if (readonly) { + return; + } + + bool had_selection = is_selection_active(); + if (had_selection) { + begin_complex_operation(); + delete_selection(); + } + + /* Remove the old character if in insert mode and no selection. */ + if (insert_mode && !had_selection) { + begin_complex_operation(); + + /* Make sure we don't try and remove empty space. */ + int cl = cursor_get_line(); + int cc = cursor_get_column(); + if (cc < get_line(cl).length()) { + _remove_text(cl, cc, cl, cc + 1); + } + } + + const char32_t chr[2] = { (char32_t)p_unicode, 0 }; + insert_text_at_cursor(chr); + + if ((insert_mode && !had_selection) || (had_selection)) { + end_complex_operation(); + } +} + +void TextEdit::_backspace() { + if (readonly) { + return; + } + + int cc = cursor_get_column(); + int cl = cursor_get_line(); + + if (cc == 0 && cl == 0) { + return; + } + + if (is_selection_active()) { + delete_selection(); + return; + } + + int prev_line = cc ? cl : cl - 1; + int prev_column = cc ? (cc - 1) : (text[cl - 1].length()); + + merge_gutters(cl, prev_line); + + if (is_line_hidden(cl)) { + set_line_as_hidden(prev_line, true); + } + _remove_text(prev_line, prev_column, cl, cc); + + cursor_set_line(prev_line, false, true); + cursor_set_column(prev_column); +} + +void TextEdit::_cut() { + if (readonly) { + return; + } + + if (is_selection_active()) { + DisplayServer::get_singleton()->clipboard_set(get_selection_text()); + delete_selection(); + cut_copy_line = ""; + return; + } + + int cl = cursor_get_line(); + + String clipboard = text[cl]; + DisplayServer::get_singleton()->clipboard_set(clipboard); + cursor_set_line(cl); + cursor_set_column(0); + + if (cl == 0 && get_line_count() > 1) { + _remove_text(cl, 0, cl + 1, 0); + } else { + _remove_text(cl, 0, cl, text[cl].length()); + backspace(); + cursor_set_line(cursor_get_line() + 1); + } + + cut_copy_line = clipboard; +} + +void TextEdit::_copy() { + if (is_selection_active()) { + DisplayServer::get_singleton()->clipboard_set(get_selection_text()); + cut_copy_line = ""; + return; + } + + int cl = cursor_get_line(); + if (text[cl].length() != 0) { + String clipboard = _base_get_text(cl, 0, cl, text[cl].length()); + DisplayServer::get_singleton()->clipboard_set(clipboard); + cut_copy_line = clipboard; + } +} + +void TextEdit::_paste() { + if (readonly) { + return; + } + + String clipboard = DisplayServer::get_singleton()->clipboard_get(); + + begin_complex_operation(); + if (is_selection_active()) { + delete_selection(); + } else if (!cut_copy_line.is_empty() && cut_copy_line == clipboard) { + cursor_set_column(0); + String ins = "\n"; + clipboard += ins; + } + + insert_text_at_cursor(clipboard); + end_complex_operation(); +} + TextEdit::TextEdit() { clear(); set_focus_mode(FOCUS_ALL); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 978a13317c..eee0f72f18 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -173,6 +173,9 @@ private: const Color get_line_background_color(int p_line) const { return text[p_line].background_color; } }; + /* Text manipulation */ + String cut_copy_line = ""; + struct Cursor { Point2 draw_pos; bool visible = false; @@ -290,7 +293,6 @@ private: bool scroll_past_end_of_file_enabled = false; bool highlight_current_line = false; - String cut_copy_line; bool insert_mode = false; bool select_identifiers_enabled = false; @@ -473,7 +475,27 @@ protected: void _set_symbol_lookup_word(const String &p_symbol); + /* Text manipulation */ + + // Overridable actions + virtual void _handle_unicode_input(const uint32_t p_unicode); + virtual void _backspace(); + + virtual void _cut(); + virtual void _copy(); + virtual void _paste(); + public: + /* Text manipulation */ + + // Overridable actions + void handle_unicode_input(const uint32_t p_unicode); + void backspace(); + + void cut(); + void copy(); + void paste(); + /* Syntax Highlighting. */ Ref<SyntaxHighlighter> get_syntax_highlighter(); void set_syntax_highlighter(Ref<SyntaxHighlighter> p_syntax_highlighter); @@ -667,11 +689,6 @@ public: void delete_selection(); - virtual void handle_unicode_input(uint32_t p_unicode); - virtual void backspace(); - void cut(); - void copy(); - void paste(); void select_all(); void select_word_under_caret(); void select(int p_from_line, int p_from_column, int p_to_line, int p_to_column); |