summaryrefslogtreecommitdiff
path: root/editor/code_editor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'editor/code_editor.cpp')
-rw-r--r--editor/code_editor.cpp157
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);