diff options
Diffstat (limited to 'editor/code_editor.cpp')
-rw-r--r-- | editor/code_editor.cpp | 157 |
1 files changed, 146 insertions, 11 deletions
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 33adb33c8c..4862d4bb5b 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -161,11 +161,14 @@ bool FindReplaceBar::_search(uint32_t p_flags, int p_from_line, int p_from_col) result_line = line; result_col = col; - set_error(""); + _update_results_count(); + set_error(vformat(TTR("Found %d match(es)."), results_count)); } else { result_line = -1; result_col = -1; text_edit->set_search_text(""); + text_edit->set_search_flags(p_flags); + text_edit->set_current_search_result(line, col); set_error(text.empty() ? "" : TTR("No Matches")); } @@ -182,6 +185,8 @@ void FindReplaceBar::_replace() { text_edit->insert_text_at_cursor(get_replace_text()); text_edit->end_complex_operation(); + + results_count = -1; } search_current(); @@ -269,6 +274,7 @@ void FindReplaceBar::_replace_all() { set_error(vformat(TTR("Replaced %d occurrence(s)."), rc)); text_edit->call_deferred("connect", "text_changed", this, "_editor_text_changed"); + results_count = -1; } void FindReplaceBar::_get_search_from(int &r_line, int &r_col) { @@ -295,6 +301,36 @@ void FindReplaceBar::_get_search_from(int &r_line, int &r_col) { } } +void FindReplaceBar::_update_results_count() { + if (results_count != -1) + return; + + results_count = 0; + + String searched = get_search_text(); + if (searched.empty()) return; + + String full_text = text_edit->get_text(); + + int from_pos = 0; + + while (true) { + int pos = is_case_sensitive() ? full_text.find(searched, from_pos) : full_text.findn(searched, from_pos); + if (pos == -1) break; + + if (is_whole_words()) { + from_pos++; // Making sure we won't hit the same match next time, if we get out via a continue. + if (pos > 0 && !is_symbol(full_text[pos - 1])) + continue; + if (pos + searched.length() < full_text.length() && !is_symbol(full_text[pos + searched.length()])) + continue; + } + + results_count++; + from_pos = pos + searched.length(); + } +} + bool FindReplaceBar::search_current() { uint32_t flags = 0; @@ -339,7 +375,11 @@ bool FindReplaceBar::search_prev() { bool FindReplaceBar::search_next() { uint32_t flags = 0; - String text = get_search_text(); + String text; + if (replace_all_mode) + text = get_replace_text(); + else + text = get_search_text(); if (is_whole_words()) flags |= TextEdit::SEARCH_WHOLE_WORDS; @@ -414,11 +454,13 @@ void FindReplaceBar::popup_replace() { void FindReplaceBar::_search_options_changed(bool p_pressed) { + results_count = -1; search_current(); } void FindReplaceBar::_editor_text_changed() { + results_count = -1; if (is_visible_in_tree()) { preserve_cursor = true; search_current(); @@ -428,6 +470,7 @@ void FindReplaceBar::_editor_text_changed() { void FindReplaceBar::_search_text_changed(const String &p_text) { + results_count = -1; search_current(); } @@ -480,6 +523,7 @@ void FindReplaceBar::set_error(const String &p_label) { void FindReplaceBar::set_text_edit(TextEdit *p_text_edit) { + results_count = -1; text_edit = p_text_edit; text_edit->connect("text_changed", this, "_editor_text_changed"); } @@ -506,6 +550,7 @@ void FindReplaceBar::_bind_methods() { FindReplaceBar::FindReplaceBar() { + results_count = -1; replace_all_mode = false; preserve_cursor = false; @@ -587,6 +632,26 @@ FindReplaceBar::FindReplaceBar() { /*** CODE EDITOR ****/ +// This function should be used to handle shortcuts that could otherwise +// be handled too late if they weren't handled here. +void CodeTextEditor::_input(const Ref<InputEvent> &event) { + + const Ref<InputEventKey> key_event = event; + if (!key_event.is_valid() || !key_event->is_pressed()) + return; + + if (ED_IS_SHORTCUT("script_text_editor/move_up", key_event)) { + move_lines_up(); + accept_event(); + return; + } + if (ED_IS_SHORTCUT("script_text_editor/move_down", key_event)) { + move_lines_down(); + accept_event(); + return; + } +} + void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; @@ -702,7 +767,7 @@ void CodeTextEditor::_code_complete_timer_timeout() { void CodeTextEditor::_complete_request() { - List<String> entries; + List<ScriptCodeCompletionOption> entries; String ctext = text_editor->get_text_for_completion(); _code_complete_script(ctext, &entries); bool forced = false; @@ -711,15 +776,55 @@ void CodeTextEditor::_complete_request() { } if (entries.size() == 0) return; - Vector<String> strs; - strs.resize(entries.size()); - int i = 0; - for (List<String>::Element *E = entries.front(); E; E = E->next()) { - strs.write[i++] = E->get(); + for (List<ScriptCodeCompletionOption>::Element *E = entries.front(); E; E = E->next()) { + E->get().icon = _get_completion_icon(E->get()); } + text_editor->code_complete(entries, forced); +} - text_editor->code_complete(strs, forced); +Ref<Texture> CodeTextEditor::_get_completion_icon(const ScriptCodeCompletionOption &p_option) { + Ref<Texture> tex; + switch (p_option.kind) { + case ScriptCodeCompletionOption::KIND_CLASS: { + if (has_icon(p_option.display, "EditorIcons")) { + tex = get_icon(p_option.display, "EditorIcons"); + } else { + tex = get_icon("Object", "EditorIcons"); + } + } break; + case ScriptCodeCompletionOption::KIND_ENUM: + tex = get_icon("Enum", "EditorIcons"); + break; + case ScriptCodeCompletionOption::KIND_FILE_PATH: + tex = get_icon("File", "EditorIcons"); + break; + case ScriptCodeCompletionOption::KIND_NODE_PATH: + tex = get_icon("NodePath", "EditorIcons"); + break; + case ScriptCodeCompletionOption::KIND_VARIABLE: + tex = get_icon("Variant", "EditorIcons"); + break; + case ScriptCodeCompletionOption::KIND_CONSTANT: + tex = get_icon("MemberConstant", "EditorIcons"); + break; + case ScriptCodeCompletionOption::KIND_MEMBER: + tex = get_icon("MemberProperty", "EditorIcons"); + break; + case ScriptCodeCompletionOption::KIND_SIGNAL: + tex = get_icon("MemberSignal", "EditorIcons"); + break; + case ScriptCodeCompletionOption::KIND_FUNCTION: + tex = get_icon("MemberMethod", "EditorIcons"); + break; + case ScriptCodeCompletionOption::KIND_PLAIN_TEXT: + tex = get_icon("CubeMesh", "EditorIcons"); + break; + default: + tex = get_icon("String", "EditorIcons"); + break; + } + return tex; } void CodeTextEditor::_font_resize_timeout() { @@ -804,6 +909,24 @@ void CodeTextEditor::trim_trailing_whitespace() { } } +void CodeTextEditor::insert_final_newline() { + int final_line = text_editor->get_line_count() - 1; + + String line = text_editor->get_line(final_line); + + //length 0 means it's already an empty line, + //no need to add a newline + if (line.length() > 0 && !line.ends_with("\n")) { + text_editor->begin_complex_operation(); + + line += "\n"; + text_editor->set_line(final_line, line); + + text_editor->end_complex_operation(); + text_editor->update(); + } +} + void CodeTextEditor::convert_indent_to_spaces() { int indent_size = EditorSettings::get_singleton()->get("text_editor/indent/size"); String indent = ""; @@ -912,7 +1035,7 @@ void CodeTextEditor::convert_case(CaseStyle p_case) { for (int i = begin; i <= end; i++) { int len = text_editor->get_line(i).length(); if (i == end) - len -= len - end_col; + len = end_col; if (i == begin) len -= begin_col; String new_line = text_editor->get_line(i).substr(i == begin ? begin_col : 0, len); @@ -1179,6 +1302,11 @@ void CodeTextEditor::goto_line_selection(int p_line, int p_begin, int p_end) { text_editor->select(p_line, p_begin, p_line, p_end); } +void CodeTextEditor::goto_line_centered(int p_line) { + goto_line(p_line); + text_editor->call_deferred("center_viewport_to_cursor"); +} + void CodeTextEditor::set_executing_line(int p_line) { text_editor->set_executing_line(p_line); } @@ -1312,11 +1440,14 @@ void CodeTextEditor::_on_settings_change() { } void CodeTextEditor::_text_changed_idle_timeout() { - _validate_script(); emit_signal("validate_script"); } +void CodeTextEditor::validate_script() { + idle->start(); +} + void CodeTextEditor::_warning_label_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { @@ -1354,6 +1485,9 @@ void CodeTextEditor::_notification(int p_what) { warning_button->set_icon(get_icon("NodeWarning", "EditorIcons")); add_constant_override("separation", 4 * EDSCALE); } break; + case NOTIFICATION_VISIBILITY_CHANGED: { + set_process_input(is_visible_in_tree()); + } break; default: break; } @@ -1433,6 +1567,7 @@ void CodeTextEditor::remove_all_bookmarks() { void CodeTextEditor::_bind_methods() { + ClassDB::bind_method(D_METHOD("_input"), &CodeTextEditor::_input); ClassDB::bind_method("_text_editor_gui_input", &CodeTextEditor::_text_editor_gui_input); ClassDB::bind_method("_line_col_changed", &CodeTextEditor::_line_col_changed); ClassDB::bind_method("_text_changed", &CodeTextEditor::_text_changed); |