diff options
Diffstat (limited to 'scene/gui/code_edit.cpp')
-rw-r--r-- | scene/gui/code_edit.cpp | 158 |
1 files changed, 109 insertions, 49 deletions
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 7fba94da4c..398b909195 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -5,8 +5,8 @@ /* GODOT ENGINE */ /* https://godotengine.org */ /*************************************************************************/ -/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ @@ -143,7 +143,6 @@ void CodeEdit::_notification(int p_what) { code_completion_line_ofs = CLAMP(code_completion_current_selected - lines / 2, 0, code_completion_options_count - lines); RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(code_completion_rect.position.x, code_completion_rect.position.y + (code_completion_current_selected - code_completion_line_ofs) * row_height), Size2(code_completion_rect.size.width, row_height)), code_completion_selected_color); - draw_rect(Rect2(code_completion_rect.position + Vector2(icon_area_size.x + icon_hsep, 0), Size2(MIN(code_completion_base_width, code_completion_rect.size.width - (icon_area_size.x + icon_hsep)), code_completion_rect.size.height)), code_completion_existing_color); for (int i = 0; i < lines; i++) { int l = code_completion_line_ofs + i; @@ -170,13 +169,24 @@ void CodeEdit::_notification(int p_what) { if (code_completion_options[l].default_value.get_type() == Variant::COLOR) { draw_rect(Rect2(Point2(code_completion_rect.position.x, icon_area.position.y), icon_area_size), (Color)code_completion_options[l].default_value); } - tl->set_align(HALIGN_RIGHT); + tl->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_RIGHT); } else { if (code_completion_options[l].default_value.get_type() == Variant::COLOR) { draw_rect(Rect2(Point2(code_completion_rect.position.x + code_completion_rect.size.width - icon_area_size.x, icon_area.position.y), icon_area_size), (Color)code_completion_options[l].default_value); } - tl->set_align(HALIGN_LEFT); + tl->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_LEFT); } + + Point2 match_pos = Point2(code_completion_rect.position.x + icon_area_size.x + icon_hsep, code_completion_rect.position.y + i * row_height); + + for (int j = 0; j < code_completion_options[l].matches.size(); j++) { + Pair<int, int> match = code_completion_options[l].matches[j]; + int match_offset = font->get_string_size(code_completion_options[l].display.substr(0, match.first), font_size).width; + int match_len = font->get_string_size(code_completion_options[l].display.substr(match.first, match.second), font_size).width; + + draw_rect(Rect2(match_pos + Point2(match_offset, 0), Size2(match_len, row_height)), code_completion_existing_color); + } + tl->draw(ci, title_pos, code_completion_options[l].font_color); } @@ -189,7 +199,7 @@ void CodeEdit::_notification(int p_what) { } /* Code hint */ - if (caret_visible && code_hint != "" && (!code_completion_active || (code_completion_below != code_hint_draw_below))) { + if (caret_visible && !code_hint.is_empty() && (!code_completion_active || (code_completion_below != code_hint_draw_below))) { const int font_height = font->get_height(font_size); Ref<StyleBox> sb = get_theme_stylebox(SNAME("panel"), SNAME("TooltipPanel")); Color font_color = get_theme_color(SNAME("font_color"), SNAME("TooltipLabel")); @@ -229,7 +239,7 @@ void CodeEdit::_notification(int p_what) { Point2 round_ofs = hint_ofs + sb->get_offset() + Vector2(0, font->get_ascent(font_size) + font_height * i + yofs); round_ofs = round_ofs.round(); - draw_string(font, round_ofs, line.replace(String::chr(0xFFFF), ""), HALIGN_LEFT, -1, font_size, font_color); + draw_string(font, round_ofs, line.replace(String::chr(0xFFFF), ""), HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, font_color); if (end > 0) { // Draw an underline for the currently edited function parameter. const Vector2 b = hint_ofs + sb->get_offset() + Vector2(begin, font_height + font_height * i + yofs); @@ -315,7 +325,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) { } } else { if (mb->get_button_index() == MouseButton::LEFT) { - if (mb->is_command_pressed() && symbol_lookup_word != String()) { + if (mb->is_command_pressed() && !symbol_lookup_word.is_empty()) { Vector2i mpos = mb->get_position(); if (is_layout_rtl()) { mpos.x = get_size().x - mpos.x; @@ -530,7 +540,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) { /* General overrides */ Control::CursorShape CodeEdit::get_cursor_shape(const Point2 &p_pos) const { - if (symbol_lookup_word != String()) { + if (!symbol_lookup_word.is_empty()) { return CURSOR_POINTING_HAND; } @@ -1419,40 +1429,23 @@ void CodeEdit::fold_line(int p_line) { /* End line is the same therefore we have a block of single line delimiters. */ if (end_line == p_line) { for (int i = p_line + 1; i <= line_count; i++) { - if (i == line_count) { - end_line = line_count; - break; - } - if ((in_string != -1 && is_in_string(i) == -1) || (in_comment != -1 && is_in_comment(i) == -1)) { - end_line = i - 1; break; } + end_line = i; } } } else { int start_indent = get_indent_level(p_line); for (int i = p_line + 1; i <= line_count; i++) { - if (get_line(p_line).strip_edges().size() == 0 || is_in_string(i) != -1 || is_in_comment(i) != -1) { - end_line = i; + if (get_line(i).strip_edges().size() == 0) { continue; } - - if (i == line_count) { - /* Do not fold empty last line of script if any */ + if (get_indent_level(i) > start_indent) { end_line = i; - if (get_line(i).strip_edges().size() == 0) { - end_line--; - } - break; + continue; } - - if ((get_indent_level(i) <= start_indent && get_line(i).strip_edges().size() != 0)) { - /* Keep an empty line unfolded if any */ - end_line = i - 1; - if (get_line(i - 1).strip_edges().size() == 0 && i - 2 > p_line) { - end_line = i - 2; - } + if (is_in_string(i) == -1 && is_in_comment(i) == -1) { break; } } @@ -2395,7 +2388,7 @@ void CodeEdit::_update_delimiter_cache(int p_from_line, int p_to_line) { if (start_line != end_line) { if (p_to_line < p_from_line) { for (int i = end_line; i > start_line; i--) { - delimiter_cache.remove(i); + delimiter_cache.remove_at(i); } } else { for (int i = start_line; i < end_line; i++) { @@ -2614,7 +2607,7 @@ void CodeEdit::_add_delimiter(const String &p_start_key, const String &p_end_key delimiter.type = p_type; delimiter.start_key = p_start_key; delimiter.end_key = p_end_key; - delimiter.line_only = p_line_only || p_end_key == ""; + delimiter.line_only = p_line_only || p_end_key.is_empty(); delimiters.insert(at, delimiter); if (!setting_delimiters) { delimiter_cache.clear(); @@ -2632,7 +2625,7 @@ void CodeEdit::_remove_delimiter(const String &p_start_key, DelimiterType p_type break; } - delimiters.remove(i); + delimiters.remove_at(i); if (!setting_delimiters) { delimiter_cache.clear(); _update_delimiter_cache(); @@ -2664,7 +2657,7 @@ void CodeEdit::_set_delimiters(const TypedArray<String> &p_delimiters, Delimiter const String start_key = key.get_slice(" ", 0); const String end_key = key.get_slice_count(" ") > 1 ? key.get_slice(" ", 1) : String(); - _add_delimiter(start_key, end_key, end_key == "", p_type); + _add_delimiter(start_key, end_key, end_key.is_empty(), p_type); } setting_delimiters = false; _update_delimiter_cache(); @@ -2673,7 +2666,7 @@ void CodeEdit::_set_delimiters(const TypedArray<String> &p_delimiters, Delimiter void CodeEdit::_clear_delimiters(DelimiterType p_type) { for (int i = delimiters.size() - 1; i >= 0; i--) { if (delimiters[i].type == p_type) { - delimiters.remove(i); + delimiters.remove_at(i); } } delimiter_cache.clear(); @@ -2825,6 +2818,8 @@ void CodeEdit::_filter_code_completion_candidates_impl() { code_completion_base = string_to_complete; Vector<ScriptCodeCompletionOption> completion_options_casei; + Vector<ScriptCodeCompletionOption> completion_options_substr; + Vector<ScriptCodeCompletionOption> completion_options_substr_casei; Vector<ScriptCodeCompletionOption> completion_options_subseq; Vector<ScriptCodeCompletionOption> completion_options_subseq_casei; @@ -2879,35 +2874,100 @@ void CodeEdit::_filter_code_completion_candidates_impl() { const char32_t *tgt = &option.display[0]; const char32_t *tgt_lower = &display_lower[0]; - const char32_t *ssq_last_tgt = nullptr; - const char32_t *ssq_lower_last_tgt = nullptr; + const char32_t *sst = &string_to_complete[0]; + const char32_t *sst_lower = &display_lower[0]; - for (; *tgt; tgt++, tgt_lower++) { + Vector<Pair<int, int>> ssq_matches; + int ssq_match_start = 0; + int ssq_match_len = 0; + + Vector<Pair<int, int>> ssq_lower_matches; + int ssq_lower_match_start = 0; + int ssq_lower_match_len = 0; + + int sst_start = -1; + int sst_lower_start = -1; + + for (int i = 0; *tgt; tgt++, tgt_lower++, i++) { + // Check substring. + if (*sst == *tgt) { + sst++; + if (sst_start == -1) { + sst_start = i; + } + } else if (sst_start != -1 && *sst) { + sst = &string_to_complete[0]; + sst_start = -1; + } + + // Check subsequence. if (*ssq == *tgt) { ssq++; - ssq_last_tgt = tgt; + if (ssq_match_len == 0) { + ssq_match_start = i; + } + ssq_match_len++; + } else if (ssq_match_len > 0) { + ssq_matches.push_back(Pair<int, int>(ssq_match_start, ssq_match_len)); + ssq_match_len = 0; + } + + // Check lower substring. + if (*sst_lower == *tgt) { + sst_lower++; + if (sst_lower_start == -1) { + sst_lower_start = i; + } + } else if (sst_lower_start != -1 && *sst_lower) { + sst_lower = &string_to_complete[0]; + sst_lower_start = -1; } + + // Check lower subsequence. if (*ssq_lower == *tgt_lower) { ssq_lower++; - ssq_lower_last_tgt = tgt; + if (ssq_lower_match_len == 0) { + ssq_lower_match_start = i; + } + ssq_lower_match_len++; + } else if (ssq_lower_match_len > 0) { + ssq_lower_matches.push_back(Pair<int, int>(ssq_lower_match_start, ssq_lower_match_len)); + ssq_lower_match_len = 0; } } /* Matched the whole subsequence in s. */ - if (!*ssq) { - /* Finished matching in the first s.length() characters. */ - if (ssq_last_tgt == &option.display[string_to_complete.length() - 1]) { + if (!*ssq) { // Matched the whole subsequence in s. + option.matches.clear(); + + if (sst_start == 0) { // Matched substring in beginning of s. + option.matches.push_back(Pair<int, int>(sst_start, string_to_complete.length())); code_completion_options.push_back(option); + } else if (sst_start > 0) { // Matched substring in s. + option.matches.push_back(Pair<int, int>(sst_start, string_to_complete.length())); + completion_options_substr.push_back(option); } else { + if (ssq_match_len > 0) { + ssq_matches.push_back(Pair<int, int>(ssq_match_start, ssq_match_len)); + } + option.matches.append_array(ssq_matches); completion_options_subseq.push_back(option); } max_width = MAX(max_width, font->get_string_size(option.display, font_size).width + offset); - /* Matched the whole subsequence in s_lower. */ - } else if (!*ssq_lower) { - /* Finished matching in the first s.length() characters. */ - if (ssq_lower_last_tgt == &option.display[string_to_complete.length() - 1]) { + } else if (!*ssq_lower) { // Matched the whole subsequence in s_lower. + option.matches.clear(); + + if (sst_lower_start == 0) { // Matched substring in beginning of s_lower. + option.matches.push_back(Pair<int, int>(sst_lower_start, string_to_complete.length())); completion_options_casei.push_back(option); + } else if (sst_lower_start > 0) { // Matched substring in s_lower. + option.matches.push_back(Pair<int, int>(sst_lower_start, string_to_complete.length())); + completion_options_substr_casei.push_back(option); } else { + if (ssq_lower_match_len > 0) { + ssq_lower_matches.push_back(Pair<int, int>(ssq_lower_match_start, ssq_lower_match_len)); + } + option.matches.append_array(ssq_lower_matches); completion_options_subseq_casei.push_back(option); } max_width = MAX(max_width, font->get_string_size(option.display, font_size).width + offset); @@ -3007,7 +3067,7 @@ CodeEdit::CodeEdit() { add_auto_brace_completion_pair("\"", "\""); add_auto_brace_completion_pair("\'", "\'"); - /* Delimiter traking */ + /* Delimiter tracking */ add_string_delimiter("\"", "\"", false); add_string_delimiter("\'", "\'", false); |