summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRémi Verschelde <remi@verschelde.fr>2016-05-29 18:32:06 +0200
committerRémi Verschelde <remi@verschelde.fr>2016-05-29 18:32:06 +0200
commit6a7530c71882967b90946ef91a2f546dd4a380df (patch)
treeba2e3da330b6535a731aefdf7b5939673b16d299
parent7d262947af09303394a440700d13590a275271fd (diff)
parent51be9beec9c38a8cd5a0f9a42a8258484aece9fb (diff)
Merge pull request #4812 from neikeq/pr-search-bar
ScriptEditor/ShaderEditor: Replace find/replace dialog with a bar
-rw-r--r--scene/gui/text_edit.cpp94
-rw-r--r--scene/gui/text_edit.h13
-rw-r--r--tools/editor/code_editor.cpp471
-rw-r--r--tools/editor/code_editor.h71
-rw-r--r--tools/editor/editor_settings.cpp4
-rw-r--r--tools/editor/plugins/script_editor_plugin.cpp19
-rw-r--r--tools/editor/plugins/script_editor_plugin.h2
-rw-r--r--tools/editor/plugins/shader_editor_plugin.cpp19
-rw-r--r--tools/editor/plugins/shader_editor_plugin.h2
9 files changed, 640 insertions, 55 deletions
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index d021c7b40e..827b420d3e 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -682,9 +682,13 @@ void TextEdit::_notification(int p_what) {
// check if line contains highlighted word
int highlighted_text_col = -1;
- if (highlighted_text.length() != 0) {
- highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, 0);
- }
+ int search_text_col = -1;
+
+ if (!search_text.empty())
+ search_text_col = _get_column_pos_of_word(search_text, str, search_flags, 0);
+
+ if (highlighted_text.length() != 0 && highlighted_text != search_text)
+ highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, SEARCH_MATCH_CASE|SEARCH_WHOLE_WORDS, 0);
if (cache.line_number_w) {
String fc = String::num(line+1);
@@ -879,20 +883,45 @@ void TextEdit::_notification(int p_what) {
break;
}
- bool in_selection = (selection.active && line>=selection.from_line && line<=selection.to_line && (line>selection.from_line || j>=selection.from_column) && (line<selection.to_line || j<selection.to_column));
+ bool in_search_result=false;
+
+ if (search_text_col != -1) {
+ // if we are at the end check for new search result on same line
+ if (j >= search_text_col+search_text.length())
+ search_text_col = _get_column_pos_of_word(search_text, str, search_flags, j);
+ in_search_result = j >= search_text_col && j < search_text_col+search_text.length();
+
+ if (in_search_result) {
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y ), Size2i(char_w, get_row_height())),cache.search_result_color);
+ }
+ }
+
+ bool in_selection = (selection.active && line>=selection.from_line && line<=selection.to_line && (line>selection.from_line || j>=selection.from_column) && (line<selection.to_line || j<selection.to_column));
if (in_selection) {
//inside selection!
VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y ), Size2i(char_w,get_row_height())),cache.selection_color);
}
+ if (in_search_result) {
+ Color border_color=(line==search_result_line && j>=search_result_col && j<search_result_col+search_text.length())?cache.font_color:cache.search_result_border_color;
+
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y ), Size2i(char_w,1)),border_color);
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y+get_row_height()-1 ), Size2i(char_w,1)),border_color);
+
+ if (j==search_text_col)
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y ), Size2i(1,get_row_height())),border_color);
+ if (j==search_text_col+search_text.length()-1)
+ VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin+char_w-1, ofs_y ), Size2i(1,get_row_height())),border_color);
+ }
+
if (highlight_all_occurrences) {
if (highlighted_text_col != -1) {
// if we are at the end check for new word on same line
if (j > highlighted_text_col+highlighted_text.length()) {
- highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, j);
+ highlighted_text_col = _get_column_pos_of_word(highlighted_text, str, SEARCH_MATCH_CASE|SEARCH_WHOLE_WORDS, j);
}
bool in_highlighted_word = (j >= highlighted_text_col && j < highlighted_text_col+highlighted_text.length());
@@ -1892,7 +1921,8 @@ void TextEdit::_input_event(const InputEvent& p_input_event) {
if (completion_hint!="") {
completion_hint="";
update();
-
+ } else {
+ scancode_handled=false;
}
} break;
case KEY_TAB: {
@@ -3220,6 +3250,8 @@ void TextEdit::_update_caches() {
cache.breakpoint_color=get_color("breakpoint_color");
cache.brace_mismatch_color=get_color("brace_mismatch_color");
cache.word_highlighted_color=get_color("word_highlighted_color");
+ cache.search_result_color=get_color("search_result_color");
+ cache.search_result_border_color=get_color("search_result_border_color");
cache.line_spacing=get_constant("line_spacing");
cache.row_height = cache.font->get_height() + cache.line_spacing;
cache.tab_icon=get_icon("tab");
@@ -3481,12 +3513,25 @@ String TextEdit::get_word_under_cursor() const {
return text[cursor.line].substr(prev_cc, next_cc-prev_cc);
}
+void TextEdit::set_search_text(const String &p_search_text) {
+ search_text = p_search_text;
+}
+
+void TextEdit::set_search_flags(uint32_t p_flags) {
+ search_flags = p_flags;
+}
+
+void TextEdit::set_current_search_result(int line, int col) {
+ search_result_line = line;
+ search_result_col = col;
+}
+
void TextEdit::set_highlight_all_occurrences(const bool p_enabled) {
highlight_all_occurrences = p_enabled;
update();
}
-int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_search, int p_from_column) {
+int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_search, uint32_t p_search_flags, int p_from_column) {
int col = -1;
if (p_key.length() > 0 && p_search.length() > 0) {
@@ -3494,12 +3539,15 @@ int TextEdit::_get_column_pos_of_word(const String &p_key, const String &p_searc
p_from_column = 0;
}
- while (col == -1 && p_from_column <= p_search.length()) {
- // match case
- col = p_search.findn(p_key, p_from_column);
+ 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);
+ } else {
+ col = p_search.findn(p_key,p_from_column);
+ }
// whole words only
- if (col != -1) {
+ if (col != -1 && p_search_flags&SEARCH_WHOLE_WORDS) {
p_from_column=col;
if (col > 0 && _is_text_char(p_search[col-1])) {
@@ -3565,10 +3613,8 @@ bool TextEdit::search(const String &p_key,uint32_t p_search_flags, int p_from_li
//wrapped
if (p_search_flags&SEARCH_BACKWARDS) {
- text_line=text_line.substr(from_column,text_line.length());
from_column=text_line.length();
} else {
- text_line=text_line.substr(0,from_column);
from_column=0;
}
@@ -3579,7 +3625,6 @@ bool TextEdit::search(const String &p_key,uint32_t p_search_flags, int p_from_li
} else {
- //text_line=text_line.substr(0,p_from_column); //wrap around for missing begining.
if (p_search_flags&SEARCH_BACKWARDS)
from_column=text_line.length()-1;
else
@@ -3588,12 +3633,25 @@ bool TextEdit::search(const String &p_key,uint32_t p_search_flags, int p_from_li
pos=-1;
- if (!(p_search_flags&SEARCH_BACKWARDS)) {
+ int pos_from=0;
+ int last_pos=-1;
+ while ((last_pos=(p_search_flags&SEARCH_MATCH_CASE)?text_line.find(p_key,pos_from):text_line.findn(p_key,pos_from))!=-1) {
- pos = (p_search_flags&SEARCH_MATCH_CASE)?text_line.find(p_key,from_column):text_line.findn(p_key,from_column);
- } else {
+ if (p_search_flags&SEARCH_BACKWARDS) {
+
+ if (last_pos>from_column)
+ break;
+ pos=last_pos;
+
+ } else {
+
+ if (last_pos>=from_column) {
+ pos=last_pos;
+ break;
+ }
+ }
- pos = (p_search_flags&SEARCH_MATCH_CASE)?text_line.rfind(p_key,from_column):text_line.rfindn(p_key,from_column);
+ pos_from=last_pos+p_key.length();
}
if (pos!=-1 && (p_search_flags&SEARCH_WHOLE_WORDS)) {
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index dbe6293240..f39b898c66 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -88,6 +88,8 @@ class TextEdit : public Control {
Color current_line_color;
Color brace_mismatch_color;
Color word_highlighted_color;
+ Color search_result_color;
+ Color search_result_border_color;
int row_height;
int line_spacing;
@@ -249,6 +251,11 @@ class TextEdit : public Control {
bool callhint_below;
Vector2 callhint_offset;
+ String search_text;
+ uint32_t search_flags;
+ int search_result_line;
+ int search_result_col;
+
int get_visible_rows() const;
int get_char_count();
@@ -287,7 +294,7 @@ class TextEdit : public Control {
String _base_get_text(int p_from_line, int p_from_column,int p_to_line,int p_to_column) const;
void _base_remove_text(int p_from_line, int p_from_column,int p_to_line,int p_to_column);
- int _get_column_pos_of_word(const String &p_key, const String &p_search, int p_from_column);
+ int _get_column_pos_of_word(const String &p_key, const String &p_search, uint32_t p_search_flags, int p_from_column);
DVector<int> _search_bind(const String &p_key,uint32_t p_search_flags, int p_from_line,int p_from_column) const;
@@ -408,6 +415,10 @@ public:
void select(int p_from_line,int p_from_column,int p_to_line,int p_to_column);
void deselect();
+ void set_search_text(const String& p_search_text);
+ void set_search_flags(uint32_t p_flags);
+ void set_current_search_result(int line, int col);
+
void set_highlight_all_occurrences(const bool p_enabled);
bool is_selection_active() const;
int get_selection_from_line() const;
diff --git a/tools/editor/code_editor.cpp b/tools/editor/code_editor.cpp
index d605a41600..a9e31a6561 100644
--- a/tools/editor/code_editor.cpp
+++ b/tools/editor/code_editor.cpp
@@ -30,6 +30,7 @@
#include "editor_settings.h"
#include "scene/gui/margin_container.h"
#include "scene/gui/separator.h"
+#include "os/keyboard.h"
void GotoLineDialog::popup_find_line(TextEdit *p_edit) {
@@ -76,6 +77,436 @@ GotoLineDialog::GotoLineDialog() {
}
+void FindReplaceBar::_notification(int p_what) {
+
+ if (p_what == NOTIFICATION_READY) {
+
+ find_prev->set_icon(get_icon("MoveUp", "EditorIcons"));
+ find_next->set_icon(get_icon("MoveDown", "EditorIcons"));
+ hide_button->set_normal_texture(get_icon("Close","EditorIcons"));
+ hide_button->set_hover_texture(get_icon("CloseHover","EditorIcons"));
+ hide_button->set_pressed_texture(get_icon("Close","EditorIcons"));
+
+ } else if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
+
+ set_process_unhandled_input(is_visible());
+ }
+}
+
+void FindReplaceBar::_unhandled_input(const InputEvent &p_event) {
+
+ if (p_event.type == InputEvent::KEY) {
+
+ const InputEventKey& k = p_event.key;
+
+ if (k.pressed && (text_edit->has_focus() || text_vbc->is_a_parent_of(get_focus_owner()))) {
+
+ bool accepted = true;
+
+ switch (k.scancode) {
+
+ case KEY_ESCAPE: {
+
+ _hide_bar();
+ } break;
+ default: {
+
+ accepted = false;
+ } break;
+ }
+
+ if (accepted) {
+ accept_event();
+ }
+ }
+ }
+}
+
+bool FindReplaceBar::_search(bool p_include_current, bool p_backwards) {
+
+ String text=get_search_text();
+ uint32_t flags=0;
+
+ if (is_whole_words())
+ flags|=TextEdit::SEARCH_WHOLE_WORDS;
+ if (is_case_sensitive())
+ flags|=TextEdit::SEARCH_MATCH_CASE;
+ if (p_backwards)
+ flags|=TextEdit::SEARCH_BACKWARDS;
+
+ int line=text_edit->cursor_get_line();
+ int col=text_edit->cursor_get_column();
+
+ if (text_edit->is_selection_active() && !replace_all_mode) {
+ line = text_edit->get_selection_from_line();
+ col = text_edit->get_selection_from_column();
+ }
+
+ bool cursor_at_result=false;
+
+ if (line==current_result_line && col>=current_result_col && col<=current_result_col+text.length()) {
+ col=current_result_col;
+ cursor_at_result=true;
+ }
+
+ if (!p_include_current) {
+ if (p_backwards) {
+ col-=text.length();
+ if (col<0) {
+ line-=1;
+ if (line<0)
+ line=text_edit->get_line_count()-1;
+ col=text_edit->get_line(line).length();
+ }
+ } else if (cursor_at_result) {
+ col+=text.length();
+ if (col>text_edit->get_line(line).length()) {
+ line+=1;
+ if (line>=text_edit->get_line_count())
+ line=0;
+ col=0;
+ }
+ }
+ }
+
+ bool found = text_edit->search(text,flags,line,col,line,col);
+
+ if (!found) {
+ if (p_backwards) {
+ line = text_edit->get_line_count()-1;
+ col = text_edit->get_line(line).length()-1;
+ } else {
+ line = 0;
+ col = 0;
+ }
+
+ found = text_edit->search(text,flags,line,col,line,col);
+ }
+
+ if (found) {
+ text_edit->cursor_set_line(line);
+ text_edit->cursor_set_column(p_backwards?col:col+text.length());
+ text_edit->select(line,col,line,col+text.length());
+ text_edit->set_search_text(text);
+ text_edit->set_search_flags(flags);
+ text_edit->set_current_search_result(line,col);
+
+ current_result_line = line;
+ current_result_col = col;
+
+ set_error("");
+ } else {
+ current_result_line = -1;
+ current_result_col = -1;
+ text_edit->set_search_text("");
+ set_error(text.empty()?"":TTR("No Matches"));
+ }
+
+ return found;
+}
+
+void FindReplaceBar::_replace() {
+
+ if (text_edit->get_selection_text()==get_search_text()) {
+ text_edit->insert_text_at_cursor(get_replace_text());
+ }
+
+ search_current();
+}
+
+void FindReplaceBar::_replace_all() {
+
+ // line as x so it gets priority in comparison, column as y
+ Point2i orig_cursor(text_edit->cursor_get_line(),text_edit->cursor_get_column());
+ Point2i prev_match=Point2(-1,-1);
+
+ bool selection_enabled = text_edit->is_selection_active();
+ Point2i selection_begin,selection_end;
+ if (selection_enabled) {
+ selection_begin=Point2i(text_edit->get_selection_from_line(),text_edit->get_selection_from_column());
+ selection_end=Point2i(text_edit->get_selection_to_line(),text_edit->get_selection_to_column());
+ }
+
+ int vsval = text_edit->get_v_scroll();
+
+ text_edit->cursor_set_line(0);
+ text_edit->cursor_set_column(0);
+
+ int rc=0;
+
+ replace_all_mode = true;
+
+ text_edit->begin_complex_operation();
+
+ while(_search(false)) {
+
+ if (!text_edit->is_selection_active()) {
+ // search selects
+ break;
+ }
+
+ // replace area
+ Point2i match_from(text_edit->get_selection_from_line(),text_edit->get_selection_from_column());
+ Point2i match_to(text_edit->get_selection_to_line(),text_edit->get_selection_to_column());
+
+ if (match_from < prev_match)
+ break; // done
+
+ prev_match=match_to;
+
+ if (selection_enabled && is_selection_only()) {
+
+ if (match_from<selection_begin || match_to>selection_end)
+ continue;
+
+ // replace but adjust selection bounds
+ text_edit->insert_text_at_cursor(get_replace_text());
+ if (match_to.x==selection_end.x)
+ selection_end.y+=get_replace_text().length() - get_search_text().length();
+ } else {
+ //just replace
+ text_edit->insert_text_at_cursor(get_replace_text());
+ }
+
+ rc++;
+ }
+
+ text_edit->end_complex_operation();
+
+ replace_all_mode = false;
+
+ // restore editor state (selection, cursor, scroll)
+ text_edit->cursor_set_line(orig_cursor.x);
+ text_edit->cursor_set_column(orig_cursor.y);
+
+ if (selection_enabled && is_selection_only()) {
+ // reselect
+ text_edit->select(selection_begin.x,selection_begin.y,selection_end.x,selection_end.y);
+ } else {
+ text_edit->deselect();
+ }
+
+ text_edit->set_v_scroll(vsval);
+ set_error(vformat(TTR("Replaced %d Ocurrence(s)."), rc));
+}
+
+void FindReplaceBar::search_current() {
+
+ _search(true);
+}
+
+void FindReplaceBar::search_prev() {
+
+ _search(false, true);
+}
+
+void FindReplaceBar::search_next() {
+
+ _search();
+}
+
+void FindReplaceBar::_hide_bar() {
+
+ text_edit->set_search_text("");
+ current_result_line = -1;
+ current_result_col = -1;
+ replace_hbc->hide();
+ replace_options_hbc->hide();
+ hide();
+}
+
+void FindReplaceBar::_show_search() {
+
+ show();
+ search_text->grab_focus();
+
+ if (text_edit->is_selection_active()) {
+ search_text->set_text(text_edit->get_selection_text());
+ }
+
+ if (!get_search_text().empty()) {
+ search_text->select_all();
+ search_text->set_cursor_pos(search_text->get_text().length());
+ search_current();
+ }
+}
+
+void FindReplaceBar::popup_search() {
+
+ replace_hbc->hide();
+ replace_options_hbc->hide();
+ _show_search();
+}
+
+void FindReplaceBar::popup_replace() {
+
+ if (!replace_hbc->is_visible() || !replace_options_hbc->is_visible()) {
+ replace_text->clear();
+ replace_hbc->show();
+ replace_options_hbc->show();
+ }
+
+ _show_search();
+}
+
+void FindReplaceBar::_search_options_changed(bool p_pressed) {
+
+ search_current();
+}
+
+void FindReplaceBar::_search_text_changed(const String& p_text) {
+
+ search_current();
+}
+
+void FindReplaceBar::_search_text_entered(const String& p_text) {
+
+ search_next();
+}
+
+String FindReplaceBar::get_search_text() const {
+
+ return search_text->get_text();
+}
+
+String FindReplaceBar::get_replace_text() const {
+
+ return replace_text->get_text();
+}
+
+bool FindReplaceBar::is_case_sensitive() const {
+
+ return case_sensitive->is_pressed();
+}
+
+bool FindReplaceBar::is_whole_words() const {
+
+ return whole_words->is_pressed();
+}
+
+bool FindReplaceBar::is_selection_only() const {
+
+ return selection_only->is_pressed();
+}
+
+void FindReplaceBar::set_error(const String &p_label) {
+
+ error_label->set_text(p_label);
+}
+
+void FindReplaceBar::set_text_edit(TextEdit *p_text_edit) {
+
+ text_edit = p_text_edit;
+ text_edit->connect("_text_changed",this,"_search_text_changed",varray(String()));
+}
+
+void FindReplaceBar::_bind_methods() {
+
+ ObjectTypeDB::bind_method("_unhandled_input",&FindReplaceBar::_unhandled_input);
+
+ ObjectTypeDB::bind_method("_search_text_changed",&FindReplaceBar::_search_text_changed);
+ ObjectTypeDB::bind_method("_search_text_entered",&FindReplaceBar::_search_text_entered);
+ ObjectTypeDB::bind_method("_search_current",&FindReplaceBar::search_current);
+ ObjectTypeDB::bind_method("_search_next",&FindReplaceBar::search_next);
+ ObjectTypeDB::bind_method("_search_prev",&FindReplaceBar::search_prev);
+ ObjectTypeDB::bind_method("_replace_pressed",&FindReplaceBar::_replace);
+ ObjectTypeDB::bind_method("_replace_all_pressed",&FindReplaceBar::_replace_all);
+ ObjectTypeDB::bind_method("_search_options_changed",&FindReplaceBar::_search_options_changed);
+ ObjectTypeDB::bind_method("_hide_pressed",&FindReplaceBar::_hide_bar);
+
+ ADD_SIGNAL(MethodInfo("search"));
+}
+
+FindReplaceBar::FindReplaceBar() {
+
+ text_vbc = memnew(VBoxContainer);
+ add_child(text_vbc);
+
+ HBoxContainer *search_hbc = memnew(HBoxContainer);
+ text_vbc->add_child(search_hbc);
+
+ search_text = memnew(LineEdit);
+ search_hbc->add_child(search_text);
+ search_text->set_custom_minimum_size(Size2(200, 0));
+ search_text->connect("text_changed",this,"_search_text_changed");
+ search_text->connect("text_entered",this,"_search_text_entered");
+
+ find_prev = memnew(ToolButton);
+ search_hbc->add_child(find_prev);
+ find_prev->set_focus_mode(FOCUS_NONE);
+ find_prev->connect("pressed",this,"_search_prev");
+
+ find_next = memnew(ToolButton);
+ search_hbc->add_child(find_next);
+ find_next->set_focus_mode(FOCUS_NONE);
+ find_next->connect("pressed",this,"_search_next");
+
+ replace_hbc = memnew(HBoxContainer);
+ text_vbc->add_child(replace_hbc);
+ replace_hbc->hide();
+
+ replace_text = memnew(LineEdit);
+ replace_hbc->add_child(replace_text);
+ replace_text->set_custom_minimum_size(Size2(200, 0));
+ replace_text->connect("text_entered",this,"_search_text_entered");
+
+ replace = memnew(ToolButton);
+ replace_hbc->add_child(replace);
+ replace->set_text(TTR("Replace"));
+ replace->set_focus_mode(FOCUS_NONE);
+ replace->connect("pressed",this,"_replace_pressed");
+
+ replace_all = memnew(ToolButton);
+ replace_hbc->add_child(replace_all);
+ replace_all->set_text(TTR("Replace All"));
+ replace_all->set_focus_mode(FOCUS_NONE);
+ replace_all->connect("pressed",this,"_replace_all_pressed");
+
+ Control *spacer_split = memnew( Control );
+ spacer_split->set_custom_minimum_size(Size2(0, 1));
+ text_vbc->add_child(spacer_split);
+
+ VBoxContainer *options_vbc = memnew(VBoxContainer);
+ add_child(options_vbc);
+ options_vbc->set_h_size_flags(SIZE_EXPAND_FILL);
+
+ HBoxContainer *search_options = memnew(HBoxContainer);
+ options_vbc->add_child(search_options);
+
+ case_sensitive = memnew(CheckBox);
+ search_options->add_child(case_sensitive);
+ case_sensitive->set_text(TTR("Match Case"));
+ case_sensitive->set_focus_mode(FOCUS_NONE);
+ case_sensitive->connect("toggled",this,"_search_options_changed");
+
+ whole_words = memnew(CheckBox);
+ search_options->add_child(whole_words);
+ whole_words->set_text(TTR("Whole Words"));
+ whole_words->set_focus_mode(FOCUS_NONE);
+ whole_words->connect("toggled",this,"_search_options_changed");
+
+ error_label = memnew(Label);
+ search_options->add_child(error_label);
+
+ search_options->add_spacer();
+
+ hide_button = memnew(TextureButton);
+ search_options->add_child(hide_button);
+ hide_button->set_focus_mode(FOCUS_NONE);
+ hide_button->connect("pressed",this,"_hide_pressed");
+
+ replace_options_hbc = memnew(HBoxContainer);
+ options_vbc->add_child(replace_options_hbc);
+ replace_options_hbc->hide();
+
+ selection_only = memnew(CheckBox);
+ replace_options_hbc->add_child(selection_only);
+ selection_only->set_text(TTR("Selection Only"));
+ selection_only->set_focus_mode(FOCUS_NONE);
+ selection_only->connect("toggled",this,"_search_options_changed");
+}
+
+
void FindReplaceDialog::popup_search() {
set_title(TTR("Search"));
@@ -610,22 +1041,32 @@ void CodeTextEditor::_bind_methods() {
CodeTextEditor::CodeTextEditor() {
+ find_replace_bar = memnew( FindReplaceBar );
+ add_child(find_replace_bar);
+ find_replace_bar->set_h_size_flags(SIZE_EXPAND_FILL);
+ find_replace_bar->hide();
+
text_editor = memnew( TextEdit );
add_child(text_editor);
- text_editor->set_area_as_parent_rect();
- text_editor->set_margin(MARGIN_BOTTOM,20);
+ text_editor->set_v_size_flags(SIZE_EXPAND_FILL);
+
+ find_replace_bar->set_text_edit(text_editor);
text_editor->set_show_line_numbers(true);
text_editor->set_brace_matching(true);
text_editor->set_auto_indent(true);
- line_col = memnew( Label );
- add_child(line_col);
- line_col->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,135);
- line_col->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,15);
- line_col->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,1);
- line_col->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,5);
- //line_col->set_align(Label::ALIGN_RIGHT);
+ MarginContainer *status_mc = memnew( MarginContainer );
+ add_child(status_mc);
+ status_mc->set("custom_constants/margin_left", 2);
+ status_mc->set("custom_constants/margin_top", 5);
+ status_mc->set("custom_constants/margin_right", 2);
+ status_mc->set("custom_constants/margin_bottom", 1);
+
+ HBoxContainer *status_bar = memnew( HBoxContainer );
+ status_mc->add_child(status_bar);
+ status_bar->set_h_size_flags(SIZE_EXPAND_FILL);
+
idle = memnew( Timer );
add_child(idle);
idle->set_one_shot(true);
@@ -639,14 +1080,16 @@ CodeTextEditor::CodeTextEditor() {
code_complete_timer->set_wait_time(EDITOR_DEF("text_editor/code_complete_delay",.3f));
error = memnew( Label );
- add_child(error);
- error->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,5);
- error->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,15);
- error->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,1);
- error->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,130);
+ status_bar->add_child(error);
error->hide();
+ error->set_valign(Label::VALIGN_CENTER);
error->add_color_override("font_color",Color(1,0.7,0.6,0.9));
+ status_bar->add_spacer();
+
+ line_col = memnew( Label );
+ status_bar->add_child(line_col);
+ line_col->set_valign(Label::VALIGN_CENTER);
text_editor->connect("cursor_changed", this,"_line_col_changed");
diff --git a/tools/editor/code_editor.h b/tools/editor/code_editor.h
index f1a1a7072f..52a36c979d 100644
--- a/tools/editor/code_editor.h
+++ b/tools/editor/code_editor.h
@@ -33,7 +33,9 @@
#include "scene/gui/text_edit.h"
#include "scene/gui/dialogs.h"
#include "scene/main/timer.h"
+#include "scene/gui/tool_button.h"
#include "scene/gui/check_button.h"
+#include "scene/gui/check_box.h"
#include "scene/gui/line_edit.h"
@@ -58,8 +60,71 @@ public:
GotoLineDialog();
};
+class FindReplaceBar : public HBoxContainer {
+ OBJ_TYPE(FindReplaceBar,HBoxContainer);
+ LineEdit *search_text;
+ ToolButton *find_prev;
+ ToolButton *find_next;
+ CheckBox *case_sensitive;
+ CheckBox *whole_words;
+ Label *error_label;
+ TextureButton *hide_button;
+
+ LineEdit *replace_text;
+ ToolButton *replace;
+ ToolButton *replace_all;
+ CheckBox *selection_only;
+
+ VBoxContainer *text_vbc;
+ HBoxContainer *replace_hbc;
+ HBoxContainer *replace_options_hbc;
+
+ TextEdit *text_edit;
+
+ int current_result_line;
+ int current_result_col;
+
+ bool replace_all_mode;
+
+ void _show_search();
+ void _hide_bar();
+ void _search_options_changed(bool p_pressed);
+ void _search_text_changed(const String& p_text);
+ void _search_text_entered(const String& p_text);
+
+protected:
+ void _notification(int p_what);
+ void _unhandled_input(const InputEvent &p_event);
+
+ bool _search(bool p_include_current=false, bool p_backwards=false);
+
+ void _replace();
+ void _replace_all();
+
+ static void _bind_methods();
+
+public:
+ String get_search_text() const;
+ String get_replace_text() const;
+
+ bool is_case_sensitive() const;
+ bool is_whole_words() const;
+ bool is_selection_only() const;
+ void set_error(const String& p_label);
+
+ void set_text_edit(TextEdit *p_text_edit);
+
+ void popup_search();
+ void popup_replace();
+
+ void search_current();
+ void search_prev();
+ void search_next();
+
+ FindReplaceBar();
+};
class FindReplaceDialog : public ConfirmationDialog {
@@ -119,11 +184,12 @@ public:
};
-class CodeTextEditor : public Control {
+class CodeTextEditor : public VBoxContainer {
- OBJ_TYPE(CodeTextEditor,Control);
+ OBJ_TYPE(CodeTextEditor,VBoxContainer);
TextEdit *text_editor;
+ FindReplaceBar *find_replace_bar;
Label *line_col;
Label *info;
@@ -158,6 +224,7 @@ protected:
public:
TextEdit *get_text_edit() { return text_editor; }
+ FindReplaceBar *get_find_replace_bar() { return find_replace_bar; }
virtual void apply_code() {}
CodeTextEditor();
diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp
index 96ced0d5e3..c589cb05be 100644
--- a/tools/editor/editor_settings.cpp
+++ b/tools/editor/editor_settings.cpp
@@ -620,6 +620,8 @@ void EditorSettings::_load_default_text_editor_theme() {
set("text_editor/mark_color", Color(1.0,0.4,0.4,0.4));
set("text_editor/breakpoint_color", Color(0.8,0.8,0.4,0.2));
set("text_editor/word_highlighted_color",Color(0.8,0.9,0.9,0.15));
+ set("text_editor/search_result_color",Color(0.05,0.25,0.05,1));
+ set("text_editor/search_result_border_color",Color(0.1,0.45,0.1,1));
}
void EditorSettings::notify_changes() {
@@ -851,6 +853,8 @@ bool EditorSettings::_save_text_editor_theme(String p_file) {
cf->set_value(theme_section, "mark_color", ((Color)get("text_editor/mark_color")).to_html());
cf->set_value(theme_section, "breakpoint_color", ((Color)get("text_editor/breakpoint_color")).to_html());
cf->set_value(theme_section, "word_highlighted_color", ((Color)get("text_editor/word_highlighted_color")).to_html());
+ cf->set_value(theme_section, "search_result_color", ((Color)get("text_editor/search_result_color")).to_html());
+ cf->set_value(theme_section, "search_result_border_color", ((Color)get("text_editor/search_result_border_color")).to_html());
Error err = cf->save(p_file);
if (err == OK) {
diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp
index e3c339f1d6..34f7c7b5e8 100644
--- a/tools/editor/plugins/script_editor_plugin.cpp
+++ b/tools/editor/plugins/script_editor_plugin.cpp
@@ -300,6 +300,8 @@ void ScriptTextEditor::_load_theme_settings() {
get_text_edit()->add_color_override("member_variable_color",EDITOR_DEF("text_editor/member_variable_color",Color(0.9,0.3,0.3)));
get_text_edit()->add_color_override("mark_color", EDITOR_DEF("text_editor/mark_color", Color(1.0,0.4,0.4,0.4)));
get_text_edit()->add_color_override("breakpoint_color", EDITOR_DEF("text_editor/breakpoint_color", Color(0.8,0.8,0.4,0.2)));
+ get_text_edit()->add_color_override("search_result_color",EDITOR_DEF("text_editor/search_result_color",Color(0.05,0.25,0.05,1)));
+ get_text_edit()->add_color_override("search_result_border_color",EDITOR_DEF("text_editor/search_result_border_color",Color(0.1,0.45,0.1,1)));
Color keyword_color= EDITOR_DEF("text_editor/keyword_color",Color(0.5,0.0,0.2));
@@ -1405,18 +1407,19 @@ void ScriptEditor::_menu_option(int p_option) {
} break;
case SEARCH_FIND: {
- find_replace_dialog->set_text_edit(current->get_text_edit());
- find_replace_dialog->popup_search();
+ current->get_find_replace_bar()->popup_search();
} break;
case SEARCH_FIND_NEXT: {
- find_replace_dialog->set_text_edit(current->get_text_edit());
- find_replace_dialog->search_next();
+ current->get_find_replace_bar()->search_next();
+ } break;
+ case SEARCH_FIND_PREV: {
+
+ current->get_find_replace_bar()->search_prev();
} break;
case SEARCH_REPLACE: {
- find_replace_dialog->set_text_edit(current->get_text_edit());
- find_replace_dialog->popup_replace();
+ current->get_find_replace_bar()->popup_replace();
} break;
case SEARCH_LOCATE_FUNCTION: {
@@ -2531,6 +2534,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
search_menu->set_text(TTR("Search"));
search_menu->get_popup()->add_item(TTR("Find.."),SEARCH_FIND,KEY_MASK_CMD|KEY_F);
search_menu->get_popup()->add_item(TTR("Find Next"),SEARCH_FIND_NEXT,KEY_F3);
+ search_menu->get_popup()->add_item(TTR("Find Previous"),SEARCH_FIND_PREV,KEY_MASK_SHIFT|KEY_F3);
search_menu->get_popup()->add_item(TTR("Replace.."),SEARCH_REPLACE,KEY_MASK_CMD|KEY_R);
search_menu->get_popup()->add_separator();
search_menu->get_popup()->add_item(TTR("Goto Function.."),SEARCH_LOCATE_FUNCTION,KEY_MASK_SHIFT|KEY_MASK_CMD|KEY_F);
@@ -2635,9 +2639,6 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) {
tab_container->connect("tab_changed", this,"_tab_changed");
- find_replace_dialog = memnew(FindReplaceDialog);
- add_child(find_replace_dialog);
-
erase_tab_confirm = memnew( ConfirmationDialog );
add_child(erase_tab_confirm);
erase_tab_confirm->connect("confirmed", this,"_close_current_tab");
diff --git a/tools/editor/plugins/script_editor_plugin.h b/tools/editor/plugins/script_editor_plugin.h
index 20e0b621c4..c6610a0209 100644
--- a/tools/editor/plugins/script_editor_plugin.h
+++ b/tools/editor/plugins/script_editor_plugin.h
@@ -144,6 +144,7 @@ class ScriptEditor : public VBoxContainer {
EDIT_CLONE_DOWN,
SEARCH_FIND,
SEARCH_FIND_NEXT,
+ SEARCH_FIND_PREV,
SEARCH_REPLACE,
SEARCH_LOCATE_FUNCTION,
SEARCH_GOTO_LINE,
@@ -184,7 +185,6 @@ class ScriptEditor : public VBoxContainer {
HSplitContainer *script_split;
TabContainer *tab_container;
EditorFileDialog *file_dialog;
- FindReplaceDialog *find_replace_dialog;
GotoLineDialog *goto_line_dialog;
ConfirmationDialog *erase_tab_confirm;
ScriptCreateDialog *script_create_dialog;
diff --git a/tools/editor/plugins/shader_editor_plugin.cpp b/tools/editor/plugins/shader_editor_plugin.cpp
index cc121d6c6f..0ca6a069bc 100644
--- a/tools/editor/plugins/shader_editor_plugin.cpp
+++ b/tools/editor/plugins/shader_editor_plugin.cpp
@@ -90,6 +90,8 @@ void ShaderTextEditor::_load_theme_settings() {
get_text_edit()->add_color_override("member_variable_color",EDITOR_DEF("text_editor/member_variable_color",Color(0.9,0.3,0.3)));
get_text_edit()->add_color_override("mark_color", EDITOR_DEF("text_editor/mark_color", Color(1.0,0.4,0.4,0.4)));
get_text_edit()->add_color_override("breakpoint_color", EDITOR_DEF("text_editor/breakpoint_color", Color(0.8,0.8,0.4,0.2)));
+ get_text_edit()->add_color_override("search_result_color",EDITOR_DEF("text_editor/search_result_color",Color(0.05,0.25,0.05,1)));
+ get_text_edit()->add_color_override("search_result_border_color",EDITOR_DEF("text_editor/search_result_border_color",Color(0.1,0.45,0.1,1)));
Color keyword_color= EDITOR_DEF("text_editor/keyword_color",Color(0.5,0.0,0.2));
@@ -212,18 +214,19 @@ void ShaderEditor::_menu_option(int p_option) {
} break;
case SEARCH_FIND: {
- find_replace_dialog->set_text_edit(current->get_text_edit());
- find_replace_dialog->popup_search();
+ current->get_find_replace_bar()->popup_search();
} break;
case SEARCH_FIND_NEXT: {
- find_replace_dialog->set_text_edit(current->get_text_edit());
- find_replace_dialog->search_next();
+ current->get_find_replace_bar()->search_next();
+ } break;
+ case SEARCH_FIND_PREV: {
+
+ current->get_find_replace_bar()->search_prev();
} break;
case SEARCH_REPLACE: {
- find_replace_dialog->set_text_edit(current->get_text_edit());
- find_replace_dialog->popup_replace();
+ current->get_find_replace_bar()->popup_replace();
} break;
// case SEARCH_LOCATE_SYMBOL: {
@@ -507,6 +510,7 @@ ShaderEditor::ShaderEditor() {
search_menu->set_text(TTR("Search"));
search_menu->get_popup()->add_item(TTR("Find.."),SEARCH_FIND,KEY_MASK_CMD|KEY_F);
search_menu->get_popup()->add_item(TTR("Find Next"),SEARCH_FIND_NEXT,KEY_F3);
+ search_menu->get_popup()->add_item(TTR("Find Previous"),SEARCH_FIND_PREV,KEY_MASK_SHIFT|KEY_F3);
search_menu->get_popup()->add_item(TTR("Replace.."),SEARCH_REPLACE,KEY_MASK_CMD|KEY_R);
search_menu->get_popup()->add_separator();
// search_menu->get_popup()->add_item("Locate Symbol..",SEARCH_LOCATE_SYMBOL,KEY_MASK_CMD|KEY_K);
@@ -516,9 +520,6 @@ ShaderEditor::ShaderEditor() {
tab_container->connect("tab_changed", this,"_tab_changed");
- find_replace_dialog = memnew(FindReplaceDialog);
- add_child(find_replace_dialog);
-
erase_tab_confirm = memnew( ConfirmationDialog );
add_child(erase_tab_confirm);
erase_tab_confirm->connect("confirmed", this,"_close_current_tab");
diff --git a/tools/editor/plugins/shader_editor_plugin.h b/tools/editor/plugins/shader_editor_plugin.h
index e10c10a446..9219a1fbc2 100644
--- a/tools/editor/plugins/shader_editor_plugin.h
+++ b/tools/editor/plugins/shader_editor_plugin.h
@@ -76,6 +76,7 @@ class ShaderEditor : public Control {
EDIT_SELECT_ALL,
SEARCH_FIND,
SEARCH_FIND_NEXT,
+ SEARCH_FIND_PREV,
SEARCH_REPLACE,
//SEARCH_LOCATE_SYMBOL,
SEARCH_GOTO_LINE,
@@ -88,7 +89,6 @@ class ShaderEditor : public Control {
uint64_t idle;
TabContainer *tab_container;
- FindReplaceDialog *find_replace_dialog;
GotoLineDialog *goto_line_dialog;
ConfirmationDialog *erase_tab_confirm;