diff options
Diffstat (limited to 'scene')
-rw-r--r-- | scene/gui/text_edit.cpp | 417 | ||||
-rw-r--r-- | scene/gui/text_edit.h | 48 |
2 files changed, 224 insertions, 241 deletions
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 38302136d6..2339cb36e5 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -921,7 +921,7 @@ void TextEdit::_notification(int p_what) { } const String &str = wrap_rows[line_wrap_index]; - int char_margin = xmargin_beg - caret.x_ofs; + int char_margin = xmargin_beg - first_visible_col; int ofs_x = 0; int ofs_y = 0; @@ -934,7 +934,7 @@ void TextEdit::_notification(int p_what) { } ofs_y += i * row_height + line_spacing / 2; - ofs_y -= caret.wrap_ofs * row_height; + ofs_y -= first_visible_line_wrap_ofs * row_height; ofs_y -= _get_v_scroll_offset() * row_height; bool clipped = false; @@ -969,7 +969,7 @@ void TextEdit::_notification(int p_what) { } // Give visual indication of empty selected line. - if (selection.active && line >= selection.from_line && line <= selection.to_line && char_margin >= xmargin_beg) { + if (has_selection() && line >= get_selection_from_line() && line <= get_selection_to_line() && char_margin >= xmargin_beg) { float char_w = font->get_char_size(' ', font_size).width; if (rtl) { RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(size.width - xmargin_beg - ofs_x - char_w, ofs_y, char_w, row_height), selection_color); @@ -1074,9 +1074,9 @@ void TextEdit::_notification(int p_what) { char_margin = size.width - char_margin - TS->shaped_text_get_size(rid).x; } - if (!clipped && selection.active && line >= selection.from_line && line <= selection.to_line) { // Selection - int sel_from = (line > selection.from_line) ? TS->shaped_text_get_range(rid).x : selection.from_column; - int sel_to = (line < selection.to_line) ? TS->shaped_text_get_range(rid).y : selection.to_column; + if (!clipped && has_selection() && line >= get_selection_from_line() && line <= get_selection_to_line()) { // Selection + int sel_from = (line > get_selection_from_line()) ? TS->shaped_text_get_range(rid).x : get_selection_from_column(); + int sel_to = (line < get_selection_to_line()) ? TS->shaped_text_get_range(rid).y : get_selection_to_column(); Vector<Vector2> sel = TS->shaped_text_get_selection(rid, sel_from, sel_to); for (int j = 0; j < sel.size(); j++) { Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y, sel[j].y - sel[j].x, row_height); @@ -1203,9 +1203,9 @@ void TextEdit::_notification(int p_what) { } Color gl_color = current_color; - if (selection.active && line >= selection.from_line && line <= selection.to_line) { // Selection - int sel_from = (line > selection.from_line) ? TS->shaped_text_get_range(rid).x : selection.from_column; - int sel_to = (line < selection.to_line) ? TS->shaped_text_get_range(rid).y : selection.to_column; + if (has_selection() && line >= get_selection_from_line() && line <= get_selection_to_line()) { // Selection + int sel_from = (line > get_selection_from_line()) ? TS->shaped_text_get_range(rid).x : get_selection_from_column(); + int sel_to = (line < get_selection_to_line()) ? TS->shaped_text_get_range(rid).y : get_selection_to_column(); if (glyphs[j].start >= sel_from && glyphs[j].end <= sel_to && override_selected_font_color) { gl_color = font_selected_color; @@ -1455,12 +1455,12 @@ void TextEdit::_notification(int p_what) { int caret_start = -1; int caret_end = -1; - if (!selection.active) { + if (!has_selection()) { String full_text = _base_get_text(0, 0, caret.line, caret.column); caret_start = full_text.length(); } else { - String pre_text = _base_get_text(0, 0, selection.from_line, selection.from_column); + String pre_text = _base_get_text(0, 0, get_selection_from_line(), get_selection_from_column()); String post_text = get_selected_text(); caret_start = pre_text.length(); @@ -1490,7 +1490,7 @@ void TextEdit::_notification(int p_what) { DisplayServer::get_singleton()->virtual_keyboard_hide(); } - if (deselect_on_focus_loss_enabled && !selection.drag_attempt) { + if (deselect_on_focus_loss_enabled && !selection_drag_attempt) { deselect(); } } break; @@ -1513,7 +1513,7 @@ void TextEdit::_notification(int p_what) { } break; case NOTIFICATION_DRAG_BEGIN: { - selection.selecting_mode = SelectionMode::SELECTION_MODE_NONE; + selecting_mode = SelectionMode::SELECTION_MODE_NONE; drag_action = true; dragging_minimap = false; dragging_selection = false; @@ -1523,8 +1523,8 @@ void TextEdit::_notification(int p_what) { case NOTIFICATION_DRAG_END: { if (is_drag_successful()) { - if (selection.drag_attempt) { - selection.drag_attempt = false; + if (selection_drag_attempt) { + selection_drag_attempt = false; if (is_editable() && !Input::get_singleton()->is_key_pressed(Key::CTRL)) { delete_selection(); } else if (deselect_on_focus_loss_enabled) { @@ -1532,7 +1532,7 @@ void TextEdit::_notification(int p_what) { } } } else { - selection.drag_attempt = false; + selection_drag_attempt = false; } drag_action = false; drag_caret_force_displayed = false; @@ -1677,58 +1677,56 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { set_caret_line(row, false, false); set_caret_column(col); - selection.drag_attempt = false; + selection_drag_attempt = false; if (selecting_enabled && mb->is_shift_pressed() && (caret.column != prev_col || caret.line != prev_line)) { - if (!selection.active) { - selection.active = true; - selection.selecting_mode = SelectionMode::SELECTION_MODE_POINTER; - selection.from_column = prev_col; - selection.from_line = prev_line; - selection.to_column = caret.column; - selection.to_line = caret.line; - - if (selection.from_line > selection.to_line || (selection.from_line == selection.to_line && selection.from_column > selection.to_column)) { - SWAP(selection.from_column, selection.to_column); - SWAP(selection.from_line, selection.to_line); - selection.shiftclick_left = false; + if (!caret.selection.active) { + caret.selection.active = true; + selecting_mode = SelectionMode::SELECTION_MODE_POINTER; + caret.selection.from_column = prev_col; + caret.selection.from_line = prev_line; + caret.selection.to_column = caret.column; + caret.selection.to_line = caret.line; + + if (caret.selection.from_line > caret.selection.to_line || (caret.selection.from_line == caret.selection.to_line && caret.selection.from_column > caret.selection.to_column)) { + SWAP(caret.selection.from_column, caret.selection.to_column); + SWAP(caret.selection.from_line, caret.selection.to_line); + caret.selection.shiftclick_left = false; } else { - selection.shiftclick_left = true; + caret.selection.shiftclick_left = true; } - selection.selecting_line = prev_line; - selection.selecting_column = prev_col; + caret.selection.selecting_line = prev_line; + caret.selection.selecting_column = prev_col; queue_redraw(); } else { - if (caret.line < selection.selecting_line || (caret.line == selection.selecting_line && caret.column < selection.selecting_column)) { - if (selection.shiftclick_left) { - selection.shiftclick_left = !selection.shiftclick_left; + if (caret.line < caret.selection.selecting_line || (caret.line == caret.selection.selecting_line && caret.column < caret.selection.selecting_column)) { + if (caret.selection.shiftclick_left) { + caret.selection.shiftclick_left = !caret.selection.shiftclick_left; } - selection.from_column = caret.column; - selection.from_line = caret.line; - - } else if (caret.line > selection.selecting_line || (caret.line == selection.selecting_line && caret.column > selection.selecting_column)) { - if (!selection.shiftclick_left) { - SWAP(selection.from_column, selection.to_column); - SWAP(selection.from_line, selection.to_line); - selection.shiftclick_left = !selection.shiftclick_left; + caret.selection.from_column = caret.column; + caret.selection.from_line = caret.line; + + } else if (caret.line > caret.selection.selecting_line || (caret.line == caret.selection.selecting_line && caret.column > caret.selection.selecting_column)) { + if (!caret.selection.shiftclick_left) { + SWAP(caret.selection.from_column, caret.selection.to_column); + SWAP(caret.selection.from_line, caret.selection.to_line); + caret.selection.shiftclick_left = !caret.selection.shiftclick_left; } - selection.to_column = caret.column; - selection.to_line = caret.line; + caret.selection.to_column = caret.column; + caret.selection.to_line = caret.line; } else { - selection.active = false; + deselect(); } queue_redraw(); } } else if (drag_and_drop_selection_enabled && is_mouse_over_selection()) { - selection.selecting_mode = SelectionMode::SELECTION_MODE_NONE; - selection.drag_attempt = true; + set_selection_mode(SelectionMode::SELECTION_MODE_NONE); + selection_drag_attempt = true; } else { - selection.active = false; - selection.selecting_mode = SelectionMode::SELECTION_MODE_POINTER; - selection.selecting_line = row; - selection.selecting_column = col; + deselect(); + set_selection_mode(SelectionMode::SELECTION_MODE_POINTER, row, col); } const int triple_click_timeout = 600; @@ -1736,13 +1734,13 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { if (!mb->is_double_click() && (OS::get_singleton()->get_ticks_msec() - last_dblclk) < triple_click_timeout && mb->get_position().distance_to(last_dblclk_pos) < triple_click_tolerance) { // Triple-click select line. - selection.selecting_mode = SelectionMode::SELECTION_MODE_LINE; - selection.drag_attempt = false; + selecting_mode = SelectionMode::SELECTION_MODE_LINE; + selection_drag_attempt = false; _update_selection_mode_line(); last_dblclk = 0; } else if (mb->is_double_click() && text[caret.line].length()) { // Double-click select word. - selection.selecting_mode = SelectionMode::SELECTION_MODE_WORD; + selecting_mode = SelectionMode::SELECTION_MODE_WORD; _update_selection_mode_word(); last_dblclk = OS::get_singleton()->get_ticks_msec(); last_dblclk_pos = mb->get_position(); @@ -1789,15 +1787,15 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } } else { if (mb->get_button_index() == MouseButton::LEFT) { - if (selection.drag_attempt && is_mouse_over_selection()) { - selection.active = false; + if (selection_drag_attempt && is_mouse_over_selection()) { + caret.selection.active = false; } dragging_minimap = false; dragging_selection = false; can_drag_minimap = false; click_select_held->stop(); if (!drag_action) { - selection.drag_attempt = false; + selection_drag_attempt = false; } if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) { DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text()); @@ -1841,7 +1839,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } if (!dragging_minimap) { - switch (selection.selecting_mode) { + switch (selecting_mode) { case SelectionMode::SELECTION_MODE_POINTER: { _update_selection_mode_pointer(); } break; @@ -1923,8 +1921,6 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { // * No Modifiers are pressed (except shift) bool allow_unicode_handling = !(k->is_command_or_control_pressed() || k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_meta_pressed()); - selection.selecting_text = false; - // Check and handle all built in shortcuts. // NEWLINES. @@ -2186,10 +2182,10 @@ void TextEdit::_move_caret_left(bool p_select, bool p_move_by_word) { // Handle selection if (p_select) { _pre_shift_selection(); - } else if (selection.active && !p_move_by_word) { + } else if (has_selection() && !p_move_by_word) { // If a selection is active, move caret to start of selection - set_caret_line(selection.from_line); - set_caret_column(selection.from_column); + set_caret_line(get_selection_from_line()); + set_caret_column(get_selection_from_column()); deselect(); return; } else { @@ -2242,10 +2238,10 @@ void TextEdit::_move_caret_right(bool p_select, bool p_move_by_word) { // Handle selection if (p_select) { _pre_shift_selection(); - } else if (selection.active && !p_move_by_word) { + } else if (has_selection() && !p_move_by_word) { // If a selection is active, move caret to end of selection - set_caret_line(selection.to_line); - set_caret_column(selection.to_column); + set_caret_line(get_selection_to_line()); + set_caret_column(get_selection_to_column()); deselect(); return; } else { @@ -2677,7 +2673,7 @@ bool TextEdit::is_text_field() const { } Variant TextEdit::get_drag_data(const Point2 &p_point) { - if (selection.active && selection.drag_attempt) { + if (has_selection() && selection_drag_attempt) { String t = get_selected_text(); Label *l = memnew(Label); l->set_text(t); @@ -2704,15 +2700,15 @@ void TextEdit::drop_data(const Point2 &p_point, const Variant &p_data) { Point2i pos = get_line_column_at_pos(get_local_mouse_pos()); int caret_row_tmp = pos.y; int caret_column_tmp = pos.x; - if (selection.drag_attempt) { - selection.drag_attempt = false; + if (selection_drag_attempt) { + selection_drag_attempt = false; if (!is_mouse_over_selection(!Input::get_singleton()->is_key_pressed(Key::CTRL))) { begin_complex_operation(); if (!Input::get_singleton()->is_key_pressed(Key::CTRL)) { - if (caret_row_tmp > selection.to_line) { - caret_row_tmp = caret_row_tmp - (selection.to_line - selection.from_line); - } else if (caret_row_tmp == selection.to_line && caret_column_tmp >= selection.to_column) { - caret_column_tmp = caret_column_tmp - (selection.to_column - selection.from_column); + if (caret_row_tmp > get_selection_to_line()) { + caret_row_tmp = caret_row_tmp - (get_selection_to_line() - get_selection_from_line()); + } else if (caret_row_tmp == get_selection_to_line() && caret_column_tmp >= get_selection_to_column()) { + caret_column_tmp = caret_column_tmp - (caret.selection.to_column - caret.selection.from_column); } delete_selection(); } else { @@ -2725,8 +2721,8 @@ void TextEdit::drop_data(const Point2 &p_point, const Variant &p_data) { end_complex_operation(); } } else if (is_mouse_over_selection()) { - caret_row_tmp = selection.from_line; - caret_column_tmp = selection.from_column; + caret_row_tmp = get_selection_from_line(); + caret_column_tmp = get_selection_from_column(); set_caret_line(caret_row_tmp, true, false); set_caret_column(caret_column_tmp); insert_text_at_caret(p_data); @@ -2993,11 +2989,11 @@ void TextEdit::_clear() { text.clear(); set_caret_line(0, false); set_caret_column(0); - caret.x_ofs = 0; - caret.line_ofs = 0; - caret.wrap_ofs = 0; + first_visible_col = 0; + first_visible_line = 0; + first_visible_line_wrap_ofs = 0; caret.last_fit_x = 0; - selection.active = false; + caret.selection.active = false; emit_signal(SNAME("lines_edited_from"), old_text_size, 0); } @@ -3068,8 +3064,8 @@ void TextEdit::set_line(int p_line, const String &p_new_text) { if (caret.line == p_line && caret.column > p_new_text.length()) { set_caret_column(p_new_text.length(), false); } - if (has_selection() && p_line == selection.to_line && selection.to_column > text[p_line].length()) { - selection.to_column = text[p_line].length(); + if (has_selection() && p_line == get_selection_to_line() && get_selection_to_column() > text[p_line].length()) { + caret.selection.to_column = text[p_line].length(); } end_complex_operation(); } @@ -3141,13 +3137,12 @@ void TextEdit::insert_line_at(int p_at, const String &p_text) { set_caret_line(caret.line + 1, false); } if (has_selection()) { - if (selection.from_line >= p_at) { + if (get_selection_from_line() >= p_at) { // offset selection when located after inserted line - ++selection.from_line; - ++selection.to_line; - } else if (selection.to_line >= p_at) { + select(get_selection_from_line() + 1, get_selection_from_column(), get_selection_to_line() + 1, get_selection_to_column()); + } else if (get_selection_to_line() >= p_at) { // extend selection that includes inserted line - ++selection.to_line; + select(get_selection_from_line(), get_selection_from_column(), get_selection_to_line() + 1, get_selection_to_column()); } } queue_redraw(); @@ -3793,7 +3788,7 @@ Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_ int wrap_index = 0; if (get_line_wrapping_mode() != LineWrappingMode::LINE_WRAPPING_NONE || _is_hiding_enabled()) { - Point2i f_ofs = get_next_visible_line_index_offset_from(first_vis_line, caret.wrap_ofs, rows + (1 * SIGN(rows))); + Point2i f_ofs = get_next_visible_line_index_offset_from(first_vis_line, first_visible_line_wrap_ofs, rows + (1 * SIGN(rows))); wrap_index = f_ofs.y; if (rows < 0) { @@ -3821,7 +3816,7 @@ Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_ int col = 0; int colx = p_pos.x - (style_normal->get_margin(SIDE_LEFT) + gutters_width + gutter_padding); - colx += caret.x_ofs; + colx += first_visible_col; col = _get_char_pos_for_line(colx, row, wrap_index); if (get_line_wrapping_mode() != LineWrappingMode::LINE_WRAPPING_NONE && wrap_index < get_line_wrap_count(row)) { // Move back one if we are at the end of the row. @@ -3918,7 +3913,7 @@ int TextEdit::get_minimap_line_at_pos(const Point2i &p_pos) const { int row = minimap_line + Math::floor(rows); if (get_line_wrapping_mode() != LineWrappingMode::LINE_WRAPPING_NONE || _is_hiding_enabled()) { - int f_ofs = get_next_visible_line_index_offset_from(minimap_line, caret.wrap_ofs, rows + (1 * SIGN(rows))).x - 1; + int f_ofs = get_next_visible_line_index_offset_from(minimap_line, first_visible_line_wrap_ofs, rows + (1 * SIGN(rows))).x - 1; if (rows < 0) { row = minimap_line - f_ofs; } else { @@ -3949,11 +3944,11 @@ bool TextEdit::is_mouse_over_selection(bool p_edges) const { int row = pos.y; int col = pos.x; if (p_edges) { - if ((row == selection.from_line && col == selection.from_column) || (row == selection.to_line && col == selection.to_column)) { + if ((row == get_selection_from_line() && col == get_selection_from_column()) || (row == get_selection_to_line() && col == get_selection_to_column())) { return true; } } - return (row >= selection.from_line && row <= selection.to_line && (row > selection.from_line || col > selection.from_column) && (row < selection.to_line || col < selection.to_column)); + return (row >= get_selection_from_line() && row <= get_selection_to_line() && (row > get_selection_from_line() || col > get_selection_from_column()) && (row < get_selection_to_line() || col < get_selection_to_column())); } /* Caret */ @@ -4156,7 +4151,7 @@ void TextEdit::set_deselect_on_focus_loss_enabled(const bool p_enabled) { } deselect_on_focus_loss_enabled = p_enabled; - if (p_enabled && selection.active && !has_focus()) { + if (p_enabled && has_selection() && !has_focus()) { deselect(); } } @@ -4182,21 +4177,21 @@ bool TextEdit::is_overriding_selected_font_color() const { } void TextEdit::set_selection_mode(SelectionMode p_mode, int p_line, int p_column) { - selection.selecting_mode = p_mode; + selecting_mode = p_mode; if (p_line >= 0) { ERR_FAIL_INDEX(p_line, text.size()); - selection.selecting_line = p_line; - selection.selecting_column = CLAMP(selection.selecting_column, 0, text[selection.selecting_line].length()); + caret.selection.selecting_line = p_line; + caret.selection.selecting_column = CLAMP(caret.selection.selecting_column, 0, text[caret.selection.selecting_line].length()); } if (p_column >= 0) { - ERR_FAIL_INDEX(selection.selecting_line, text.size()); - ERR_FAIL_INDEX(p_column, text[selection.selecting_line].length()); - selection.selecting_column = p_column; + ERR_FAIL_INDEX(caret.selection.selecting_line, text.size()); + ERR_FAIL_INDEX(p_column, text[caret.selection.selecting_line].length() + 1); + caret.selection.selecting_column = p_column; } } TextEdit::SelectionMode TextEdit::get_selection_mode() const { - return selection.selecting_mode; + return selecting_mode; } void TextEdit::select_all() { @@ -4207,17 +4202,12 @@ void TextEdit::select_all() { if (text.size() == 1 && text[0].length() == 0) { return; } - selection.active = true; - selection.from_line = 0; - selection.from_column = 0; - selection.selecting_line = 0; - selection.selecting_column = 0; - selection.to_line = text.size() - 1; - selection.to_column = text[selection.to_line].length(); - selection.selecting_mode = SelectionMode::SELECTION_MODE_SHIFT; - selection.shiftclick_left = true; - set_caret_line(selection.to_line, false); - set_caret_column(selection.to_column, false); + + select(0, 0, text.size() - 1, text[text.size() - 1].length()); + set_selection_mode(SelectionMode::SELECTION_MODE_SHIFT, 0, 0); + caret.selection.shiftclick_left = true; + set_caret_line(get_selection_to_line(), false); + set_caret_column(get_selection_to_column(), false); queue_redraw(); } @@ -4230,7 +4220,7 @@ void TextEdit::select_word_under_caret() { return; } - if (selection.active) { + if (has_selection()) { /* Allow toggling selection by pressing the shortcut a second time. */ /* This is also usable as a general-purpose "deselect" shortcut after */ /* selecting anything. */ @@ -4288,78 +4278,78 @@ void TextEdit::select(int p_from_line, int p_from_column, int p_to_line, int p_t p_to_column = 0; } - selection.from_line = p_from_line; - selection.from_column = p_from_column; - selection.to_line = p_to_line; - selection.to_column = p_to_column; + caret.selection.from_line = p_from_line; + caret.selection.from_column = p_from_column; + caret.selection.to_line = p_to_line; + caret.selection.to_column = p_to_column; - selection.active = true; + caret.selection.active = true; - if (selection.from_line == selection.to_line) { - if (selection.from_column == selection.to_column) { - selection.active = false; + if (caret.selection.from_line == caret.selection.to_line) { + if (caret.selection.from_column == caret.selection.to_column) { + caret.selection.active = false; - } else if (selection.from_column > selection.to_column) { - selection.shiftclick_left = false; - SWAP(selection.from_column, selection.to_column); + } else if (caret.selection.from_column > caret.selection.to_column) { + caret.selection.shiftclick_left = false; + SWAP(caret.selection.from_column, caret.selection.to_column); } else { - selection.shiftclick_left = true; + caret.selection.shiftclick_left = true; } - } else if (selection.from_line > selection.to_line) { - selection.shiftclick_left = false; - SWAP(selection.from_line, selection.to_line); - SWAP(selection.from_column, selection.to_column); + } else if (caret.selection.from_line > caret.selection.to_line) { + caret.selection.shiftclick_left = false; + SWAP(caret.selection.from_line, caret.selection.to_line); + SWAP(caret.selection.from_column, caret.selection.to_column); } else { - selection.shiftclick_left = true; + caret.selection.shiftclick_left = true; } queue_redraw(); } bool TextEdit::has_selection() const { - return selection.active; + return caret.selection.active; } String TextEdit::get_selected_text() const { - if (!selection.active) { + if (!has_selection()) { return ""; } - return _base_get_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column); + return _base_get_text(get_selection_from_line(), get_selection_from_column(), get_selection_to_line(), get_selection_to_column()); } int TextEdit::get_selection_line() const { - ERR_FAIL_COND_V(!selection.active, -1); - return selection.selecting_line; + ERR_FAIL_COND_V(!has_selection(), -1); + return caret.selection.selecting_line; } int TextEdit::get_selection_column() const { - ERR_FAIL_COND_V(!selection.active, -1); - return selection.selecting_column; + ERR_FAIL_COND_V(!has_selection(), -1); + return caret.selection.selecting_column; } int TextEdit::get_selection_from_line() const { - ERR_FAIL_COND_V(!selection.active, -1); - return selection.from_line; + ERR_FAIL_COND_V(!has_selection(), -1); + return caret.selection.from_line; } int TextEdit::get_selection_from_column() const { - ERR_FAIL_COND_V(!selection.active, -1); - return selection.from_column; + ERR_FAIL_COND_V(!has_selection(), -1); + return caret.selection.from_column; } int TextEdit::get_selection_to_line() const { - ERR_FAIL_COND_V(!selection.active, -1); - return selection.to_line; + ERR_FAIL_COND_V(!has_selection(), -1); + return caret.selection.to_line; } int TextEdit::get_selection_to_column() const { - ERR_FAIL_COND_V(!selection.active, -1); - return selection.to_column; + ERR_FAIL_COND_V(!has_selection(), -1); + return caret.selection.to_column; } void TextEdit::deselect() { - selection.active = false; + caret.selection.active = false; queue_redraw(); } @@ -4368,11 +4358,11 @@ void TextEdit::delete_selection() { return; } - selection.active = false; - selection.selecting_mode = SelectionMode::SELECTION_MODE_NONE; - _remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column); - set_caret_line(selection.from_line, false, false); - set_caret_column(selection.from_column); + caret.selection.active = false; + selecting_mode = SelectionMode::SELECTION_MODE_NONE; + _remove_text(caret.selection.from_line, caret.selection.from_column, caret.selection.to_line, caret.selection.to_column); + set_caret_line(caret.selection.from_line, false, false); + set_caret_column(caret.selection.from_column); queue_redraw(); } @@ -4543,7 +4533,7 @@ void TextEdit::set_line_as_first_visible(int p_line, int p_wrap_index) { } int TextEdit::get_first_visible_line() const { - return CLAMP(caret.line_ofs, 0, text.size() - 1); + return CLAMP(first_visible_line, 0, text.size() - 1); } void TextEdit::set_line_as_center_visible(int p_line, int p_wrap_index) { @@ -4582,14 +4572,14 @@ void TextEdit::set_line_as_last_visible(int p_line, int p_wrap_index) { int TextEdit::get_last_full_visible_line() const { int first_vis_line = get_first_visible_line(); int last_vis_line = 0; - last_vis_line = first_vis_line + get_next_visible_line_index_offset_from(first_vis_line, caret.wrap_ofs, get_visible_line_count()).x - 1; + last_vis_line = first_vis_line + get_next_visible_line_index_offset_from(first_vis_line, first_visible_line_wrap_ofs, get_visible_line_count()).x - 1; last_vis_line = CLAMP(last_vis_line, 0, text.size() - 1); return last_vis_line; } int TextEdit::get_last_full_visible_line_wrap_index() const { int first_vis_line = get_first_visible_line(); - return get_next_visible_line_index_offset_from(first_vis_line, caret.wrap_ofs, get_visible_line_count()).y; + return get_next_visible_line_index_offset_from(first_vis_line, first_visible_line_wrap_ofs, get_visible_line_count()).y; } int TextEdit::get_visible_line_count() const { @@ -4634,7 +4624,7 @@ void TextEdit::adjust_viewport_to_caret() { int cur_wrap = get_caret_wrap_index(); int first_vis_line = get_first_visible_line(); - int first_vis_wrap = caret.wrap_ofs; + int first_vis_wrap = first_visible_line_wrap_ofs; int last_vis_line = get_last_full_visible_line(); int last_vis_wrap = get_last_full_visible_line_wrap_index(); @@ -4677,17 +4667,17 @@ void TextEdit::adjust_viewport_to_caret() { caret_pos.y = caret_pos.x; } - if (MAX(caret_pos.x, caret_pos.y) > (caret.x_ofs + visible_width)) { - caret.x_ofs = MAX(caret_pos.x, caret_pos.y) - visible_width + 1; + if (MAX(caret_pos.x, caret_pos.y) > (first_visible_col + visible_width)) { + first_visible_col = MAX(caret_pos.x, caret_pos.y) - visible_width + 1; } - if (MIN(caret_pos.x, caret_pos.y) < caret.x_ofs) { - caret.x_ofs = MIN(caret_pos.x, caret_pos.y); + if (MIN(caret_pos.x, caret_pos.y) < first_visible_col) { + first_visible_col = MIN(caret_pos.x, caret_pos.y); } } else { - caret.x_ofs = 0; + first_visible_col = 0; } - h_scroll->set_value(caret.x_ofs); + h_scroll->set_value(first_visible_col); queue_redraw(); } @@ -4730,17 +4720,17 @@ void TextEdit::center_viewport_to_caret() { caret_pos.y = caret_pos.x; } - if (MAX(caret_pos.x, caret_pos.y) > (caret.x_ofs + visible_width)) { - caret.x_ofs = MAX(caret_pos.x, caret_pos.y) - visible_width + 1; + if (MAX(caret_pos.x, caret_pos.y) > (first_visible_col + visible_width)) { + first_visible_col = MAX(caret_pos.x, caret_pos.y) - visible_width + 1; } - if (MIN(caret_pos.x, caret_pos.y) < caret.x_ofs) { - caret.x_ofs = MIN(caret_pos.x, caret_pos.y); + if (MIN(caret_pos.x, caret_pos.y) < first_visible_col) { + first_visible_col = MIN(caret_pos.x, caret_pos.y); } } else { - caret.x_ofs = 0; + first_visible_col = 0; } - h_scroll->set_value(caret.x_ofs); + h_scroll->set_value(first_visible_col); queue_redraw(); } @@ -6029,8 +6019,8 @@ void TextEdit::_click_selection_held() { // Warning: is_mouse_button_pressed(MouseButton::LEFT) returns false for double+ clicks, so this doesn't work for MODE_WORD // and MODE_LINE. However, moving the mouse triggers _gui_input, which calls these functions too, so that's not a huge problem. // I'm unsure if there's an actual fix that doesn't have a ton of side effects. - if (Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT) && selection.selecting_mode != SelectionMode::SELECTION_MODE_NONE) { - switch (selection.selecting_mode) { + if (Input::get_singleton()->is_mouse_button_pressed(MouseButton::LEFT) && get_selection_mode() != SelectionMode::SELECTION_MODE_NONE) { + switch (get_selection_mode()) { case SelectionMode::SELECTION_MODE_POINTER: { _update_selection_mode_pointer(); } break; @@ -6057,7 +6047,7 @@ void TextEdit::_update_selection_mode_pointer() { int line = pos.y; int col = pos.x; - select(selection.selecting_line, selection.selecting_column, line, col); + select(caret.selection.selecting_line, caret.selection.selecting_column, line, col); set_caret_line(line, false); set_caret_column(col); @@ -6087,25 +6077,25 @@ void TextEdit::_update_selection_mode_word() { } /* Initial selection. */ - if (!selection.active) { + if (!has_selection()) { select(line, beg, line, end); - selection.selecting_column = beg; - selection.selected_word_beg = beg; - selection.selected_word_end = end; - selection.selected_word_origin = beg; + caret.selection.selecting_column = beg; + caret.selection.selected_word_beg = beg; + caret.selection.selected_word_end = end; + caret.selection.selected_word_origin = beg; set_caret_line(line, false); set_caret_column(end); } else { - if ((col <= selection.selected_word_origin && line == selection.selecting_line) || line < selection.selecting_line) { - selection.selecting_column = selection.selected_word_end; - select(line, beg, selection.selecting_line, selection.selected_word_end); - set_caret_line(selection.from_line, false); - set_caret_column(selection.from_column); + if ((col <= caret.selection.selected_word_origin && line == get_selection_line()) || line < get_selection_line()) { + caret.selection.selecting_column = caret.selection.selected_word_end; + select(line, beg, get_selection_line(), caret.selection.selected_word_end); + set_caret_line(get_selection_from_line(), false); + set_caret_column(get_selection_from_column()); } else { - selection.selecting_column = selection.selected_word_beg; - select(selection.selecting_line, selection.selected_word_beg, line, end); - set_caret_line(selection.to_line, false); - set_caret_column(selection.to_column); + caret.selection.selecting_column = caret.selection.selected_word_beg; + select(get_selection_line(), caret.selection.selected_word_beg, line, end); + set_caret_line(get_selection_to_line(), false); + set_caret_column(get_selection_to_column()); } } @@ -6127,19 +6117,19 @@ void TextEdit::_update_selection_mode_line() { int col = pos.x; col = 0; - if (line < selection.selecting_line) { + if (line < caret.selection.selecting_line) { /* Caret is above us. */ set_caret_line(line - 1, false); - selection.selecting_column = text[selection.selecting_line].length(); + caret.selection.selecting_column = text[get_selection_line()].length(); } else { /* Caret is below us. */ set_caret_line(line + 1, false); - selection.selecting_column = 0; + caret.selection.selecting_column = 0; col = text[line].length(); } set_caret_column(0); - select(selection.selecting_line, selection.selecting_column, line, col); + select(caret.selection.selecting_line, caret.selection.selecting_column, line, col); if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CLIPBOARD_PRIMARY)) { DisplayServer::get_singleton()->clipboard_set_primary(get_selected_text()); } @@ -6154,13 +6144,12 @@ void TextEdit::_pre_shift_selection() { return; } - if (!selection.active || selection.selecting_mode == SelectionMode::SELECTION_MODE_NONE) { - selection.selecting_line = caret.line; - selection.selecting_column = caret.column; - selection.active = true; + if (!has_selection() || get_selection_mode() == SelectionMode::SELECTION_MODE_NONE) { + caret.selection.active = true; + set_selection_mode(SelectionMode::SELECTION_MODE_SHIFT, caret.line, caret.column); } - selection.selecting_mode = SelectionMode::SELECTION_MODE_SHIFT; + set_selection_mode(SelectionMode::SELECTION_MODE_SHIFT); } void TextEdit::_post_shift_selection() { @@ -6168,12 +6157,9 @@ void TextEdit::_post_shift_selection() { return; } - if (selection.active && selection.selecting_mode == SelectionMode::SELECTION_MODE_SHIFT) { - select(selection.selecting_line, selection.selecting_column, caret.line, caret.column); - queue_redraw(); + if (has_selection() && get_selection_mode() == SelectionMode::SELECTION_MODE_SHIFT) { + select(get_selection_line(), get_selection_column(), caret.line, caret.column); } - - selection.selecting_text = true; } /* Line Wrapping */ @@ -6199,17 +6185,14 @@ void TextEdit::_update_wrap_at_column(bool p_force) { _update_placeholder(); } - _update_caret_wrap_offset(); -} - -void TextEdit::_update_caret_wrap_offset() { + // Update viewport. int first_vis_line = get_first_visible_line(); if (is_line_wrapped(first_vis_line)) { - caret.wrap_ofs = MIN(caret.wrap_ofs, get_line_wrap_count(first_vis_line)); + first_visible_line_wrap_ofs = MIN(first_visible_line_wrap_ofs, get_line_wrap_count(first_vis_line)); } else { - caret.wrap_ofs = 0; + first_visible_line_wrap_ofs = 0; } - set_line_as_first_visible(caret.line_ofs, caret.wrap_ofs); + set_line_as_first_visible(first_visible_line, first_visible_line_wrap_ofs); } /* Viewport. */ @@ -6258,8 +6241,8 @@ void TextEdit::_update_scrollbars() { set_v_scroll(get_v_scroll()); } else { - caret.line_ofs = 0; - caret.wrap_ofs = 0; + first_visible_line = 0; + first_visible_line_wrap_ofs = 0; v_scroll->set_value(0); v_scroll->set_max(0); v_scroll->hide(); @@ -6269,15 +6252,15 @@ void TextEdit::_update_scrollbars() { h_scroll->show(); h_scroll->set_max(total_width); h_scroll->set_page(visible_width); - if (caret.x_ofs > (total_width - visible_width)) { - caret.x_ofs = (total_width - visible_width); + if (first_visible_col > (total_width - visible_width)) { + first_visible_col = (total_width - visible_width); } - if (fabs(h_scroll->get_value() - (double)caret.x_ofs) >= 1) { - h_scroll->set_value(caret.x_ofs); + if (fabs(h_scroll->get_value() - (double)first_visible_col) >= 1) { + h_scroll->set_value(first_visible_col); } } else { - caret.x_ofs = 0; + first_visible_col = 0; h_scroll->set_value(0); h_scroll->set_max(0); h_scroll->hide(); @@ -6306,7 +6289,7 @@ void TextEdit::_scroll_moved(double p_to_val) { } if (h_scroll->is_visible_in_tree()) { - caret.x_ofs = h_scroll->get_value(); + first_visible_col = h_scroll->get_value(); } if (v_scroll->is_visible_in_tree()) { // Set line ofs and wrap ofs. @@ -6329,8 +6312,8 @@ void TextEdit::_scroll_moved(double p_to_val) { int wi = line_wrap_amount - (sc - v_scroll_i - 1); wi = CLAMP(wi, 0, line_wrap_amount); - caret.line_ofs = n_line; - caret.wrap_ofs = wi; + first_visible_line = n_line; + first_visible_line_wrap_ofs = wi; } queue_redraw(); } @@ -6411,7 +6394,7 @@ void TextEdit::_scroll_lines_up() { set_v_scroll(get_v_scroll() - 1); // Adjust the caret to viewport. - if (!selection.active) { + if (!has_selection()) { int cur_line = caret.line; int cur_wrap = get_caret_wrap_index(); int last_vis_line = get_last_full_visible_line(); @@ -6431,11 +6414,11 @@ void TextEdit::_scroll_lines_down() { set_v_scroll(get_v_scroll() + 1); // Adjust the caret to viewport. - if (!selection.active) { + if (!has_selection()) { int cur_line = caret.line; int cur_wrap = get_caret_wrap_index(); int first_vis_line = get_first_visible_line(); - int first_vis_wrap = caret.wrap_ofs; + int first_vis_wrap = first_visible_line_wrap_ofs; if (cur_line < first_vis_line || (cur_line == first_vis_line && cur_wrap < first_vis_wrap)) { set_caret_line(first_vis_line, false, false, first_vis_wrap); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index a8da878ede..5de45fe9cc 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -361,15 +361,30 @@ private: int _get_char_pos_for_line(int p_px, int p_line, int p_wrap_index = 0) const; /* Caret. */ + struct Selection { + bool active = false; + bool shiftclick_left = false; + + int selecting_line = 0; + int selecting_column = 0; + int selected_word_beg = 0; + int selected_word_end = 0; + int selected_word_origin = 0; + + int from_line = 0; + int from_column = 0; + int to_line = 0; + int to_column = 0; + }; + struct Caret { + Selection selection; + Point2 draw_pos; bool visible = false; int last_fit_x = 0; int line = 0; int column = 0; - int x_ofs = 0; - int line_ofs = 0; - int wrap_ofs = 0; } caret; bool setting_caret_line = false; @@ -400,25 +415,7 @@ private: int _get_column_x_offset_for_line(int p_char, int p_line) const; /* Selection. */ - struct Selection { - SelectionMode selecting_mode = SelectionMode::SELECTION_MODE_NONE; - int selecting_line = 0; - int selecting_column = 0; - int selected_word_beg = 0; - int selected_word_end = 0; - int selected_word_origin = 0; - bool selecting_text = false; - - bool active = false; - - int from_line = 0; - int from_column = 0; - int to_line = 0; - int to_column = 0; - - bool shiftclick_left = false; - bool drag_attempt = false; - } selection; + SelectionMode selecting_mode = SelectionMode::SELECTION_MODE_NONE; bool selecting_enabled = true; bool deselect_on_focus_loss_enabled = true; @@ -428,6 +425,7 @@ private: Color selection_color = Color(1, 1, 1); bool override_selected_font_color = false; + bool selection_drag_attempt = false; bool dragging_selection = false; Timer *click_select_held = nullptr; @@ -450,8 +448,6 @@ private: void _update_wrap_at_column(bool p_force = false); - void _update_caret_wrap_offset(); - /* Viewport. */ HScrollBar *h_scroll = nullptr; VScrollBar *v_scroll = nullptr; @@ -466,6 +462,10 @@ private: float v_scroll_speed = 80.0; // Scrolling. + int first_visible_line = 0; + int first_visible_line_wrap_ofs = 0; + int first_visible_col = 0; + bool scrolling = false; bool updating_scrolls = false; |