diff options
Diffstat (limited to 'scene/gui/text_edit.cpp')
| -rw-r--r-- | scene/gui/text_edit.cpp | 244 |
1 files changed, 140 insertions, 104 deletions
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 3b2013f7ec..86e726d9da 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -39,9 +39,9 @@ #include "core/os/os.h" #include "core/string/string_builder.h" #include "core/string/translation.h" -#include "label.h" - +#include "scene/gui/label.h" #include "scene/main/window.h" +#include "scene/theme/theme_db.h" /////////////////////////////////////////////////////////////////////////////// /// TEXT /// @@ -212,9 +212,6 @@ void TextEdit::Text::invalidate_cache(int p_line, int p_column, bool p_text_chan for (int i = 0; i < spans; i++) { TS->shaped_set_span_update_font(r, i, font->get_rids(), font_size, font->get_opentype_features()); } - for (int i = 0; i < TextServer::SPACING_MAX; i++) { - TS->shaped_text_set_spacing(r, TextServer::SpacingType(i), font->get_spacing(TextServer::SpacingType(i))); - } } // Apply tab align. @@ -1072,12 +1069,7 @@ void TextEdit::_notification(int p_what) { if (rtl) { gutter_rect.position.x = size.width - gutter_rect.position.x - gutter_rect.size.x; } - - Variant args[3] = { line, g, Rect2(gutter_rect) }; - const Variant *argp[] = { &args[0], &args[1], &args[2] }; - Callable::CallError ce; - Variant ret; - gutter.custom_draw_callback.callp(argp, 3, ret, ce); + gutter.custom_draw_callback.call(line, g, Rect2(gutter_rect)); } } break; } @@ -1254,7 +1246,7 @@ void TextEdit::_notification(int p_what) { if ((brace_matching[c].open_match_line == line && brace_matching[c].open_match_column == glyphs[j].start) || (get_caret_column(c) == glyphs[j].start && get_caret_line(c) == line && carets_wrap_index[c] == line_wrap_index && (brace_matching[c].open_matching || brace_matching[c].open_mismatch))) { if (brace_matching[c].open_mismatch) { - gl_color = theme_cache.brace_mismatch_color; + gl_color = _get_brace_mismatch_color(); } Rect2 rect = Rect2(char_pos, ofs_y + theme_cache.font->get_underline_position(theme_cache.font_size), glyphs[j].advance * glyphs[j].repeat, MAX(theme_cache.font->get_underline_thickness(theme_cache.font_size) * theme_cache.base_scale, 1)); draw_rect(rect, gl_color); @@ -1263,7 +1255,7 @@ void TextEdit::_notification(int p_what) { if ((brace_matching[c].close_match_line == line && brace_matching[c].close_match_column == glyphs[j].start) || (get_caret_column(c) == glyphs[j].start + 1 && get_caret_line(c) == line && carets_wrap_index[c] == line_wrap_index && (brace_matching[c].close_matching || brace_matching[c].close_mismatch))) { if (brace_matching[c].close_mismatch) { - gl_color = theme_cache.brace_mismatch_color; + gl_color = _get_brace_mismatch_color(); } Rect2 rect = Rect2(char_pos, ofs_y + theme_cache.font->get_underline_position(theme_cache.font_size), glyphs[j].advance * glyphs[j].repeat, MAX(theme_cache.font->get_underline_thickness(theme_cache.font_size) * theme_cache.base_scale, 1)); draw_rect(rect, gl_color); @@ -1298,7 +1290,8 @@ void TextEdit::_notification(int p_what) { if (had_glyphs_drawn) { if (first_visible_char > glyphs[j].start) { first_visible_char = glyphs[j].start; - } else if (last_visible_char < glyphs[j].end) { + } + if (last_visible_char < glyphs[j].end) { last_visible_char = glyphs[j].end; } } @@ -1313,12 +1306,12 @@ void TextEdit::_notification(int p_what) { // is_line_folded if (line_wrap_index == line_wrap_amount && line < text.size() - 1 && _is_line_hidden(line + 1)) { - int xofs = char_ofs + char_margin + ofs_x + (theme_cache.folded_eol_icon->get_width() / 2); + int xofs = char_ofs + char_margin + ofs_x + (_get_folded_eol_icon()->get_width() / 2); if (xofs >= xmargin_beg && xofs < xmargin_end) { - int yofs = (text_height - theme_cache.folded_eol_icon->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index); - Color eol_color = theme_cache.code_folding_color; + int yofs = (text_height - _get_folded_eol_icon()->get_height()) / 2 - ldata->get_line_ascent(line_wrap_index); + Color eol_color = _get_code_folding_color(); eol_color.a = 1; - theme_cache.folded_eol_icon->draw(ci, Point2(xofs, ofs_y + yofs), eol_color); + _get_folded_eol_icon()->draw(ci, Point2(xofs, ofs_y + yofs), eol_color); } } @@ -1597,7 +1590,7 @@ void TextEdit::_notification(int p_what) { if (is_drag_successful()) { if (selection_drag_attempt) { selection_drag_attempt = false; - if (is_editable() && !Input::get_singleton()->is_key_pressed(Key::CTRL)) { + if (is_editable() && !Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL)) { delete_selection(); } else if (deselect_on_focus_loss_enabled) { deselect(); @@ -1692,10 +1685,10 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { h_scroll->set_value(h_scroll->get_value() - (100 * mb->get_factor())); } else if (mb->is_alt_pressed()) { // Scroll 5 times as fast as normal (like in Visual Studio Code). - _scroll_up(15 * mb->get_factor()); + _scroll_up(15 * mb->get_factor(), true); } else if (v_scroll->is_visible()) { // Scroll 3 lines. - _scroll_up(3 * mb->get_factor()); + _scroll_up(3 * mb->get_factor(), true); } } if (mb->get_button_index() == MouseButton::WHEEL_DOWN && !mb->is_command_or_control_pressed()) { @@ -1703,10 +1696,10 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { h_scroll->set_value(h_scroll->get_value() + (100 * mb->get_factor())); } else if (mb->is_alt_pressed()) { // Scroll 5 times as fast as normal (like in Visual Studio Code). - _scroll_down(15 * mb->get_factor()); + _scroll_down(15 * mb->get_factor(), true); } else if (v_scroll->is_visible()) { // Scroll 3 lines. - _scroll_down(3 * mb->get_factor()); + _scroll_down(3 * mb->get_factor(), true); } } if (mb->get_button_index() == MouseButton::WHEEL_LEFT) { @@ -1752,11 +1745,27 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { const int triple_click_tolerance = 5; bool is_triple_click = (!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); - if (!is_mouse_over_selection() && !mb->is_double_click() && !is_triple_click) { + if (!mb->is_double_click() && !is_triple_click) { if (mb->is_alt_pressed()) { prev_line = row; prev_col = col; + // Remove caret at clicked location. + if (carets.size() > 1) { + for (int i = 0; i < carets.size(); i++) { + // Deselect if clicked on caret or its selection. + if ((get_caret_column(i) == col && get_caret_line(i) == row) || is_mouse_over_selection(true, i)) { + remove_caret(i); + last_dblclk = 0; + return; + } + } + } + + if (is_mouse_over_selection()) { + return; + } + caret = add_caret(row, col); if (caret == -1) { return; @@ -1766,7 +1775,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { carets.write[caret].selection.selecting_column = col; last_dblclk = 0; - } else if (!mb->is_shift_pressed()) { + } else if (!mb->is_shift_pressed() && !is_mouse_over_selection()) { caret = 0; remove_secondary_carets(); } @@ -1924,9 +1933,9 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { if (pan_gesture.is_valid()) { const real_t delta = pan_gesture->get_delta().y; if (delta < 0) { - _scroll_up(-delta); + _scroll_up(-delta, false); } else { - _scroll_down(delta); + _scroll_down(delta, false); } h_scroll->set_value(h_scroll->get_value() + pan_gesture->get_delta().x * 100); if (v_scroll->get_value() != prev_v_scroll || h_scroll->get_value() != prev_h_scroll) { @@ -2032,7 +2041,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { // Allow unicode handling if: // * No modifiers are pressed (except Shift and CapsLock) - bool allow_unicode_handling = !(k->is_command_or_control_pressed() || k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_meta_pressed()); + bool allow_unicode_handling = !(k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_meta_pressed()); // Check and handle all built-in shortcuts. @@ -2374,7 +2383,7 @@ void TextEdit::_move_caret_left(bool p_select, bool p_move_by_word) { if (caret_mid_grapheme_enabled) { set_caret_column(get_caret_column(i) - 1, i == 0, i); } else { - set_caret_column(TS->shaped_text_prev_grapheme_pos(text.get_line_data(get_caret_line(i))->get_rid(), get_caret_column(i)), i == 0, i); + set_caret_column(TS->shaped_text_prev_character_pos(text.get_line_data(get_caret_line(i))->get_rid(), get_caret_column(i)), i == 0, i); } } } @@ -2433,7 +2442,7 @@ void TextEdit::_move_caret_right(bool p_select, bool p_move_by_word) { if (caret_mid_grapheme_enabled) { set_caret_column(get_caret_column(i) + 1, i == 0, i); } else { - set_caret_column(TS->shaped_text_next_grapheme_pos(text.get_line_data(get_caret_line(i))->get_rid(), get_caret_column(i)), i == 0, i); + set_caret_column(TS->shaped_text_next_character_pos(text.get_line_data(get_caret_line(i))->get_rid(), get_caret_column(i)), i == 0, i); } } } @@ -2815,7 +2824,7 @@ void TextEdit::_delete(bool p_word, bool p_all_to_right) { if (caret_mid_grapheme_enabled) { next_column = get_caret_column(caret_idx) < curline_len ? (get_caret_column(caret_idx) + 1) : 0; } else { - next_column = get_caret_column(caret_idx) < curline_len ? TS->shaped_text_next_grapheme_pos(text.get_line_data(get_caret_line(caret_idx))->get_rid(), (get_caret_column(caret_idx))) : 0; + next_column = get_caret_column(caret_idx) < curline_len ? TS->shaped_text_next_character_pos(text.get_line_data(get_caret_line(caret_idx))->get_rid(), (get_caret_column(caret_idx))) : 0; } // Remove overlapping carets. @@ -2939,15 +2948,21 @@ void TextEdit::_update_placeholder() { return; // Not in tree? } + const String placeholder_translated = atr(placeholder_text); + // Placeholder is generally smaller then text documents, and updates less so this should be fast enough for now. placeholder_data_buf->clear(); placeholder_data_buf->set_width(text.get_width()); placeholder_data_buf->set_break_flags(text.get_brk_flags()); - placeholder_data_buf->set_direction((TextServer::Direction)text_direction); + if (text_direction == Control::TEXT_DIRECTION_INHERITED) { + placeholder_data_buf->set_direction(is_layout_rtl() ? TextServer::DIRECTION_RTL : TextServer::DIRECTION_LTR); + } else { + placeholder_data_buf->set_direction((TextServer::Direction)text_direction); + } placeholder_data_buf->set_preserve_control(draw_control_chars); - placeholder_data_buf->add_string(placeholder_text, theme_cache.font, theme_cache.font_size, language); + placeholder_data_buf->add_string(placeholder_translated, theme_cache.font, theme_cache.font_size, language); - placeholder_bidi_override = structured_text_parser(st_parser, st_args, placeholder_text); + placeholder_bidi_override = structured_text_parser(st_parser, st_args, placeholder_translated); if (placeholder_bidi_override.is_empty()) { TS->shaped_text_set_bidi_override(placeholder_data_buf->get_rid(), placeholder_bidi_override); } @@ -2972,7 +2987,7 @@ void TextEdit::_update_placeholder() { placeholder_wraped_rows.clear(); for (int i = 0; i <= wrap_amount; i++) { Vector2i line_range = placeholder_data_buf->get_line_range(i); - placeholder_wraped_rows.push_back(placeholder_text.substr(line_range.x, line_range.y - line_range.x)); + placeholder_wraped_rows.push_back(placeholder_translated.substr(line_range.x, line_range.y - line_range.x)); } } @@ -2980,51 +2995,11 @@ void TextEdit::_update_theme_item_cache() { Control::_update_theme_item_cache(); theme_cache.base_scale = get_theme_default_base_scale(); - - /* Internal API for CodeEdit */ - theme_cache.brace_mismatch_color = get_theme_color(SNAME("brace_mismatch_color"), SNAME("CodeEdit")); - theme_cache.code_folding_color = get_theme_color(SNAME("code_folding_color"), SNAME("CodeEdit")); - theme_cache.folded_eol_icon = get_theme_icon(SNAME("folded_eol_icon"), SNAME("CodeEdit")); - - /* Search */ - theme_cache.search_result_color = get_theme_color(SNAME("search_result_color")); - theme_cache.search_result_border_color = get_theme_color(SNAME("search_result_border_color")); - - /* Caret */ - theme_cache.caret_width = get_theme_constant(SNAME("caret_width")); - theme_cache.caret_color = get_theme_color(SNAME("caret_color")); - theme_cache.caret_background_color = get_theme_color(SNAME("caret_background_color")); - - /* Selection */ - theme_cache.font_selected_color = get_theme_color(SNAME("font_selected_color")); - theme_cache.selection_color = get_theme_color(SNAME("selection_color")); use_selected_font_color = theme_cache.font_selected_color != Color(0, 0, 0, 0); - /* Other visuals */ - theme_cache.style_normal = get_theme_stylebox(SNAME("normal")); - theme_cache.style_focus = get_theme_stylebox(SNAME("focus")); - theme_cache.style_readonly = get_theme_stylebox(SNAME("read_only")); - - theme_cache.tab_icon = get_theme_icon(SNAME("tab")); - theme_cache.space_icon = get_theme_icon(SNAME("space")); - - theme_cache.font = get_theme_font(SNAME("font")); - theme_cache.font_size = get_theme_font_size(SNAME("font_size")); - theme_cache.font_color = get_theme_color(SNAME("font_color")); - theme_cache.font_readonly_color = get_theme_color(SNAME("font_readonly_color")); - theme_cache.font_placeholder_color = get_theme_color(SNAME("font_placeholder_color")); - - theme_cache.outline_size = get_theme_constant(SNAME("outline_size")); - theme_cache.outline_color = get_theme_color(SNAME("font_outline_color")); - - theme_cache.line_spacing = get_theme_constant(SNAME("line_spacing")); if (text.get_line_height() + theme_cache.line_spacing < 1) { WARN_PRINT("Line height is too small, please increase font_size and/or line_spacing"); } - - theme_cache.background_color = get_theme_color(SNAME("background_color")); - theme_cache.current_line_color = get_theme_color(SNAME("current_line_color")); - theme_cache.word_highlighted_color = get_theme_color(SNAME("word_highlighted_color")); } void TextEdit::_update_caches() { @@ -3096,13 +3071,13 @@ void TextEdit::drop_data(const Point2 &p_point, const Variant &p_data) { int caret_column_tmp = pos.x; if (selection_drag_attempt) { selection_drag_attempt = false; - if (!is_mouse_over_selection(!Input::get_singleton()->is_key_pressed(Key::CTRL))) { + if (!is_mouse_over_selection(!Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL))) { // Set caret back at selection for undo / redo. set_caret_line(get_selection_to_line(), false, false); set_caret_column(get_selection_to_column()); begin_complex_operation(); - if (!Input::get_singleton()->is_key_pressed(Key::CTRL)) { + if (!Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL)) { 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()) { @@ -4131,6 +4106,9 @@ Point2i TextEdit::search(const String &p_key, uint32_t p_search_flags, int p_fro int line = p_from_line; int pos = -1; + bool key_start_is_symbol = is_symbol(p_key[0]); + bool key_end_is_symbol = is_symbol(p_key[p_key.length() - 1]); + for (int i = 0; i < text.size() + 1; i++) { if (line < 0) { line = text.size() - 1; @@ -4194,9 +4172,9 @@ Point2i TextEdit::search(const String &p_key, uint32_t p_search_flags, int p_fro if (pos != -1 && (p_search_flags & SEARCH_WHOLE_WORDS)) { // Validate for whole words. - if (pos > 0 && !is_symbol(text_line[pos - 1])) { + if (!key_start_is_symbol && pos > 0 && !is_symbol(text_line[pos - 1])) { is_match = false; - } else if (pos + p_key.length() < text_line.length() && !is_symbol(text_line[pos + p_key.length()])) { + } else if (!key_end_is_symbol && pos + p_key.length() < text_line.length() && !is_symbol(text_line[pos + p_key.length()])) { is_match = false; } } @@ -4331,6 +4309,9 @@ Point2i TextEdit::get_line_column_at_pos(const Point2i &p_pos, bool p_allow_out_ colx = TS->shaped_text_get_size(text_rid).x - colx; } col = TS->shaped_text_hit_test_position(text_rid, colx); + if (!caret_mid_grapheme_enabled) { + col = TS->shaped_text_closest_character_pos(text_rid, col); + } return Point2i(col, row); } @@ -4345,6 +4326,11 @@ Rect2i TextEdit::get_rect_at_line_column(int p_line, int p_column) const { ERR_FAIL_COND_V(p_column < 0, Rect2i(-1, -1, 0, 0)); ERR_FAIL_COND_V(p_column > text[p_line].length(), Rect2i(-1, -1, 0, 0)); + if (text.size() == 1 && text[0].length() == 0) { + // The TextEdit is empty. + return Rect2i(); + } + if (line_drawing_cache.size() == 0 || !line_drawing_cache.has(p_line)) { // Line is not in the cache, which means it's outside of the viewing area. return Rect2i(-1, -1, 0, 0); @@ -5484,7 +5470,7 @@ void TextEdit::set_line_as_last_visible(int p_line, int p_wrap_index) { set_v_scroll(0); return; } - set_v_scroll(get_scroll_pos_for_line(first_line, next_line.y) + _get_visible_lines_offset()); + set_v_scroll(Math::round(get_scroll_pos_for_line(first_line, next_line.y) + _get_visible_lines_offset())); } int TextEdit::get_last_full_visible_line() const { @@ -6029,8 +6015,12 @@ bool TextEdit::is_drawing_spaces() const { return draw_spaces; } +Color TextEdit::get_font_color() const { + return theme_cache.font_color; +} + void TextEdit::_bind_methods() { - /*Internal. */ + /* Internal. */ ClassDB::bind_method(D_METHOD("_text_changed_emit"), &TextEdit::_text_changed_emit); @@ -6440,14 +6430,6 @@ void TextEdit::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "wrap_mode", PROPERTY_HINT_ENUM, "None,Boundary"), "set_line_wrapping_mode", "get_line_wrapping_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Arbitrary:1,Word:2,Word (Smart):3"), "set_autowrap_mode", "get_autowrap_mode"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_all_occurrences"), "set_highlight_all_occurrences", "is_highlight_all_occurrences_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_current_line"), "set_highlight_current_line", "is_highlight_current_line_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_control_chars"), "set_draw_control_chars", "get_draw_control_chars"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_tabs"), "set_draw_tabs", "is_drawing_tabs"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_spaces"), "set_draw_spaces", "is_drawing_spaces"); - - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "syntax_highlighter", PROPERTY_HINT_RESOURCE_TYPE, "SyntaxHighlighter", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ALWAYS_DUPLICATE), "set_syntax_highlighter", "get_syntax_highlighter"); - ADD_GROUP("Scroll", "scroll_"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_smooth"), "set_smooth_scroll_enabled", "is_smooth_scroll_enabled"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_v_scroll_speed", PROPERTY_HINT_NONE, "suffix:px/s"), "set_v_scroll_speed", "get_v_scroll_speed"); @@ -6469,6 +6451,16 @@ void TextEdit::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_mid_grapheme"), "set_caret_mid_grapheme_enabled", "is_caret_mid_grapheme_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret_multiple"), "set_multiple_carets_enabled", "is_multiple_carets_enabled"); + ADD_GROUP("Highlighting", ""); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "syntax_highlighter", PROPERTY_HINT_RESOURCE_TYPE, "SyntaxHighlighter", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_ALWAYS_DUPLICATE), "set_syntax_highlighter", "get_syntax_highlighter"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_all_occurrences"), "set_highlight_all_occurrences", "is_highlight_all_occurrences_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "highlight_current_line"), "set_highlight_current_line", "is_highlight_current_line_enabled"); + + ADD_GROUP("Visual Whitespace", "draw_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_control_chars"), "set_draw_control_chars", "get_draw_control_chars"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_tabs"), "set_draw_tabs", "is_drawing_tabs"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_spaces"), "set_draw_spaces", "is_drawing_spaces"); + ADD_GROUP("BiDi", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "language", PROPERTY_HINT_LOCALE_ID, ""), "set_language", "get_language"); @@ -6489,6 +6481,43 @@ void TextEdit::_bind_methods() { ADD_SIGNAL(MethodInfo("gutter_added")); ADD_SIGNAL(MethodInfo("gutter_removed")); + /* Theme items */ + /* Search */ + BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, search_result_color); + BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, search_result_border_color); + + /* Caret */ + BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TextEdit, caret_width); + BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, caret_color); + BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, caret_background_color); + + /* Selection */ + BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, font_selected_color); + BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, selection_color); + + /* Other visuals */ + BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TextEdit, style_normal, "normal"); + BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TextEdit, style_focus, "focus"); + BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TextEdit, style_readonly, "read_only"); + + BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TextEdit, tab_icon, "tab"); + BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TextEdit, space_icon, "space"); + + BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, TextEdit, font); + BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, TextEdit, font_size); + BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, font_color); + BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, font_readonly_color); + BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, font_placeholder_color); + + BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TextEdit, outline_size); + BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_COLOR, TextEdit, outline_color, "font_outline_color"); + + BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TextEdit, line_spacing); + + BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, background_color); + BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, current_line_color); + BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TextEdit, word_highlighted_color); + /* Settings. */ GLOBAL_DEF(PropertyInfo(Variant::FLOAT, "gui/timers/text_edit_idle_detect_sec", PROPERTY_HINT_RANGE, "0,10,0.01,or_greater"), 3); GLOBAL_DEF(PropertyInfo(Variant::INT, "gui/common/text_edit_undo_stack_max_size", PROPERTY_HINT_RANGE, "0,10000,1,or_greater"), 1024); @@ -6990,6 +7019,9 @@ int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_searc p_from_column = 0; } + bool key_start_is_symbol = is_symbol(p_key[0]); + bool key_end_is_symbol = is_symbol(p_key[p_key.length() - 1]); + while (col == -1 && p_from_column <= p_search.length()) { if (p_search_flags & SEARCH_MATCH_CASE) { col = p_search.find(p_key, p_from_column); @@ -6997,13 +7029,18 @@ int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_searc col = p_search.findn(p_key, p_from_column); } + // If not found, just break early to improve performance. + if (col == -1) { + break; + } + // Whole words only. if (col != -1 && p_search_flags & SEARCH_WHOLE_WORDS) { p_from_column = col; - if (col > 0 && !is_symbol(p_search[col - 1])) { + if (!key_start_is_symbol && col > 0 && !is_symbol(p_search[col - 1])) { col = -1; - } else if ((col + p_key.length()) < p_search.length() && !is_symbol(p_search[col + p_key.length()])) { + } else if (!key_end_is_symbol && (col + p_key.length()) < p_search.length() && !is_symbol(p_search[col + p_key.length()])) { col = -1; } } @@ -7023,7 +7060,11 @@ int TextEdit::_get_char_pos_for_line(int p_px, int p_line, int p_wrap_index) con if (is_layout_rtl()) { p_px = TS->shaped_text_get_size(text_rid).x - p_px; } - return TS->shaped_text_hit_test_position(text_rid, p_px); + int ofs = TS->shaped_text_hit_test_position(text_rid, p_px); + if (!caret_mid_grapheme_enabled) { + ofs = TS->shaped_text_closest_character_pos(text_rid, ofs); + } + return ofs; } /* Caret */ @@ -7301,7 +7342,7 @@ void TextEdit::_update_scrollbars() { } int visible_width = size.width - theme_cache.style_normal->get_minimum_size().width; - int total_width = (draw_placeholder ? placeholder_max_width : text.get_max_width()) + vmin.x + gutters_width + gutter_padding; + int total_width = (draw_placeholder ? placeholder_max_width : text.get_max_width()) + gutters_width + gutter_padding; if (draw_minimap) { total_width += minimap_width; @@ -7318,11 +7359,6 @@ void TextEdit::_update_scrollbars() { v_scroll->show(); v_scroll->set_max(total_rows + _get_visible_lines_offset()); v_scroll->set_page(visible_rows + _get_visible_lines_offset()); - if (smooth_scroll_enabled) { - v_scroll->set_step(0.25); - } else { - v_scroll->set_step(1); - } set_v_scroll(get_v_scroll()); } else { @@ -7416,7 +7452,7 @@ double TextEdit::_get_v_scroll_offset() const { return CLAMP(val, 0, 1); } -void TextEdit::_scroll_up(real_t p_delta) { +void TextEdit::_scroll_up(real_t p_delta, bool p_animate) { if (scrolling && smooth_scroll_enabled && SIGN(target_v_scroll - v_scroll->get_value()) != SIGN(-p_delta)) { scrolling = false; minimap_clicked = false; @@ -7432,7 +7468,7 @@ void TextEdit::_scroll_up(real_t p_delta) { if (target_v_scroll <= 0) { target_v_scroll = 0; } - if (Math::abs(target_v_scroll - v_scroll->get_value()) < 1.0) { + if (!p_animate || Math::abs(target_v_scroll - v_scroll->get_value()) < 1.0) { v_scroll->set_value(target_v_scroll); } else { scrolling = true; @@ -7443,7 +7479,7 @@ void TextEdit::_scroll_up(real_t p_delta) { } } -void TextEdit::_scroll_down(real_t p_delta) { +void TextEdit::_scroll_down(real_t p_delta, bool p_animate) { if (scrolling && smooth_scroll_enabled && SIGN(target_v_scroll - v_scroll->get_value()) != SIGN(p_delta)) { scrolling = false; minimap_clicked = false; @@ -7460,7 +7496,7 @@ void TextEdit::_scroll_down(real_t p_delta) { if (target_v_scroll > max_v_scroll) { target_v_scroll = max_v_scroll; } - if (Math::abs(target_v_scroll - v_scroll->get_value()) < 1.0) { + if (!p_animate || Math::abs(target_v_scroll - v_scroll->get_value()) < 1.0) { v_scroll->set_value(target_v_scroll); } else { scrolling = true; @@ -7566,9 +7602,9 @@ void TextEdit::_update_minimap_click() { int first_line = row - next_line.x + 1; double delta = get_scroll_pos_for_line(first_line, next_line.y) - get_v_scroll(); if (delta < 0) { - _scroll_up(-delta); + _scroll_up(-delta, true); } else { - _scroll_down(delta); + _scroll_down(delta, true); } } |
