summaryrefslogtreecommitdiff
path: root/scene/gui
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui')
-rw-r--r--scene/gui/base_button.cpp4
-rw-r--r--scene/gui/code_edit.cpp490
-rw-r--r--scene/gui/code_edit.h55
-rw-r--r--scene/gui/gradient_edit.cpp28
-rw-r--r--scene/gui/gradient_edit.h2
-rw-r--r--scene/gui/item_list.cpp2
-rw-r--r--scene/gui/popup_menu.cpp6
-rw-r--r--scene/gui/rich_text_label.cpp74
-rw-r--r--scene/gui/rich_text_label.h8
-rw-r--r--scene/gui/shortcut.cpp33
-rw-r--r--scene/gui/shortcut.h12
-rw-r--r--scene/gui/tab_container.cpp4
-rw-r--r--scene/gui/text_edit.cpp376
-rw-r--r--scene/gui/text_edit.h37
-rw-r--r--scene/gui/tree.h4
15 files changed, 626 insertions, 509 deletions
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 75a4464a40..82f4a216b8 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -345,7 +345,7 @@ void BaseButton::_unhandled_key_input(Ref<InputEvent> p_event) {
return;
}
- if (!is_disabled() && is_visible_in_tree() && !p_event->is_echo() && shortcut.is_valid() && shortcut->is_shortcut(p_event)) {
+ if (!is_disabled() && is_visible_in_tree() && !p_event->is_echo() && shortcut.is_valid() && shortcut->matches_event(p_event)) {
on_action_event(p_event);
accept_event();
}
@@ -353,7 +353,7 @@ void BaseButton::_unhandled_key_input(Ref<InputEvent> p_event) {
String BaseButton::get_tooltip(const Point2 &p_pos) const {
String tooltip = Control::get_tooltip(p_pos);
- if (shortcut_in_tooltip && shortcut.is_valid() && shortcut->is_valid()) {
+ if (shortcut_in_tooltip && shortcut.is_valid() && shortcut->has_valid_event()) {
String text = shortcut->get_name() + " (" + shortcut->get_as_text() + ")";
if (tooltip != String() && shortcut->get_name().nocasecmp_to(tooltip) != 0) {
text += "\n" + tooltip;
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index be5e0bf4e5..32922f609d 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -72,13 +72,34 @@ void CodeEdit::_notification(int p_what) {
code_completion_background_color = get_theme_color(SNAME("completion_background_color"));
code_completion_selected_color = get_theme_color(SNAME("completion_selected_color"));
code_completion_existing_color = get_theme_color(SNAME("completion_existing_color"));
+
+ line_length_guideline_color = get_theme_color(SNAME("line_length_guideline_color"));
} break;
case NOTIFICATION_DRAW: {
RID ci = get_canvas_item();
+ const Size2 size = get_size();
const bool caret_visible = is_caret_visible();
const bool rtl = is_layout_rtl();
const int row_height = get_row_height();
+ if (line_length_guideline_columns.size() > 0) {
+ const int xmargin_beg = cache.style_normal->get_margin(SIDE_LEFT) + get_total_gutter_width();
+ const int xmargin_end = size.width - cache.style_normal->get_margin(SIDE_RIGHT) - (is_drawing_minimap() ? get_minimap_width() : 0);
+ const int char_size = (int)cache.font->get_char_size('0', 0, cache.font_size).width;
+
+ for (int i = 0; i < line_length_guideline_columns.size(); i++) {
+ const int xoffset = xmargin_beg + char_size * (int)line_length_guideline_columns[i] - get_h_scroll();
+ if (xoffset > xmargin_beg && xoffset < xmargin_end) {
+ Color guideline_color = (i == 0) ? line_length_guideline_color : line_length_guideline_color * Color(1, 1, 1, 0.5);
+ if (rtl) {
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(size.width - xoffset, 0), Point2(size.width - xoffset, size.height), guideline_color);
+ continue;
+ }
+ RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(xoffset, 0), Point2(xoffset, size.height), guideline_color);
+ }
+ }
+ }
+
bool code_completion_below = false;
if (caret_visible && code_completion_active && code_completion_options.size() > 0) {
Ref<StyleBox> csb = get_theme_stylebox(SNAME("completion"));
@@ -204,8 +225,15 @@ void CodeEdit::_notification(int p_what) {
round_ofs = round_ofs.round();
draw_string(font, round_ofs, line.replace(String::chr(0xFFFF), ""), HALIGN_LEFT, -1, cache.font_size, font_color);
if (end > 0) {
- Vector2 b = hint_ofs + sb->get_offset() + Vector2(begin, font_height + font_height * i + line_spacing - 1);
- draw_line(b, b + Vector2(end - begin, 0), font_color);
+ // Draw an underline for the currently edited function parameter.
+ const Vector2 b = hint_ofs + sb->get_offset() + Vector2(begin, font_height + font_height * i + line_spacing);
+ draw_line(b, b + Vector2(end - begin, 0), font_color, 2);
+
+ // Draw a translucent text highlight as well.
+ const Rect2 highlight_rect = Rect2(
+ hint_ofs + sb->get_offset() + Vector2(begin, 0),
+ Vector2(end - begin, font_height));
+ draw_rect(highlight_rect, font_color * Color(1, 1, 1, 0.2));
}
line_spacing += cache.line_spacing;
}
@@ -278,6 +306,39 @@ void CodeEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
}
+ } else {
+ if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
+ if (mb->is_command_pressed() && symbol_lookup_word != String()) {
+ Vector2i mpos = mb->get_position();
+ if (is_layout_rtl()) {
+ mpos.x = get_size().x - mpos.x;
+ }
+ int line, col;
+ _get_mouse_pos(Point2i(mpos.x, mpos.y), line, col);
+
+ emit_signal(SNAME("symbol_lookup"), symbol_lookup_word, line, col);
+ return;
+ }
+ }
+ }
+ }
+
+ Ref<InputEventMouseMotion> mm = p_gui_input;
+ if (mm.is_valid()) {
+ Vector2i mpos = mm->get_position();
+ if (is_layout_rtl()) {
+ mpos.x = get_size().x - mpos.x;
+ }
+
+ if (symbol_lookup_on_click_enabled) {
+ if (mm->is_command_pressed() && mm->get_button_mask() == 0 && !is_dragging_cursor()) {
+ symbol_lookup_new_word = get_word_at_pos(mpos);
+ if (symbol_lookup_new_word != symbol_lookup_word) {
+ emit_signal(SNAME("symbol_validate"), symbol_lookup_new_word);
+ }
+ } else {
+ set_symbol_lookup_word_as_valid(false);
+ }
}
}
@@ -288,6 +349,25 @@ void CodeEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
return;
}
+ /* Ctrl + Hover symbols */
+#ifdef OSX_ENABLED
+ if (k->get_keycode() == KEY_META) {
+#else
+ if (k->get_keycode() == KEY_CTRL) {
+#endif
+ if (symbol_lookup_on_click_enabled) {
+ if (k->is_pressed() && !is_dragging_cursor()) {
+ symbol_lookup_new_word = get_word_at_pos(_get_local_mouse_pos());
+ if (symbol_lookup_new_word != symbol_lookup_word) {
+ emit_signal(SNAME("symbol_validate"), symbol_lookup_new_word);
+ }
+ } else {
+ set_symbol_lookup_word_as_valid(false);
+ }
+ }
+ return;
+ }
+
/* If a modifier has been pressed, and nothing else, return. */
if (!k->is_pressed() || k->get_keycode() == KEY_CTRL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT || k->get_keycode() == KEY_META) {
return;
@@ -437,7 +517,12 @@ 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()) {
+ return CURSOR_POINTING_HAND;
+ }
+
if ((code_completion_active && code_completion_rect.has_point(p_pos)) || (is_readonly() && (!is_selecting_enabled() || get_line_count() == 0))) {
return CURSOR_ARROW;
}
@@ -459,6 +544,58 @@ Control::CursorShape CodeEdit::get_cursor_shape(const Point2 &p_pos) const {
return TextEdit::get_cursor_shape(p_pos);
}
+void CodeEdit::handle_unicode_input(uint32_t p_unicode) {
+ bool had_selection = is_selection_active();
+ if (had_selection) {
+ begin_complex_operation();
+ delete_selection();
+ }
+
+ // Remove the old character if in insert mode and no selection.
+ if (is_insert_mode() && !had_selection) {
+ begin_complex_operation();
+
+ // Make sure we don't try and remove empty space.
+ if (cursor_get_column() < get_line(cursor_get_line()).length()) {
+ _remove_text(cursor_get_line(), cursor_get_column(), cursor_get_line(), cursor_get_column() + 1);
+ }
+ }
+
+ const char32_t chr[2] = { (char32_t)p_unicode, 0 };
+
+ if (auto_brace_completion_enabled) {
+ int cl = cursor_get_line();
+ int cc = cursor_get_column();
+ int caret_move_offset = 1;
+
+ int post_brace_pair = cc < get_line(cl).length() ? _get_auto_brace_pair_close_at_pos(cl, cc) : -1;
+
+ if (has_string_delimiter(chr) && cc > 0 && _is_char(get_line(cl)[cc - 1]) && post_brace_pair == -1) {
+ insert_text_at_cursor(chr);
+ } else if (cc < get_line(cl).length() && _is_char(get_line(cl)[cc])) {
+ insert_text_at_cursor(chr);
+ } else if (post_brace_pair != -1 && auto_brace_completion_pairs[post_brace_pair].close_key[0] == chr[0]) {
+ caret_move_offset = auto_brace_completion_pairs[post_brace_pair].close_key.length();
+ } else if (is_in_comment(cl, cc) != -1 || (is_in_string(cl, cc) != -1 && has_string_delimiter(chr))) {
+ insert_text_at_cursor(chr);
+ } else {
+ insert_text_at_cursor(chr);
+
+ int pre_brace_pair = _get_auto_brace_pair_open_at_pos(cl, cc + 1);
+ if (pre_brace_pair != -1) {
+ insert_text_at_cursor(auto_brace_completion_pairs[pre_brace_pair].close_key);
+ }
+ }
+ cursor_set_column(cc + caret_move_offset);
+ } else {
+ insert_text_at_cursor(chr);
+ }
+
+ if ((is_insert_mode() && !had_selection) || (had_selection)) {
+ end_complex_operation();
+ }
+}
+
/* Indent management */
void CodeEdit::set_indent_size(const int p_size) {
ERR_FAIL_COND_MSG(p_size <= 0, "Indend size must be greater than 0.");
@@ -527,13 +664,13 @@ void CodeEdit::do_indent() {
}
if (!indent_using_spaces) {
- _insert_text_at_cursor("\t");
+ insert_text_at_cursor("\t");
return;
}
int spaces_to_add = _calculate_spaces_till_next_right_indent(cursor_get_column());
if (spaces_to_add > 0) {
- _insert_text_at_cursor(String(" ").repeat(spaces_to_add));
+ insert_text_at_cursor(String(" ").repeat(spaces_to_add));
}
}
@@ -713,34 +850,6 @@ int CodeEdit::_calculate_spaces_till_next_right_indent(int p_column) const {
return indent_size - p_column % indent_size;
}
-/* TODO: remove once brace completion is refactored. */
-static char32_t _get_right_pair_symbol(char32_t c) {
- if (c == '"') {
- return '"';
- }
- if (c == '\'') {
- return '\'';
- }
- if (c == '(') {
- return ')';
- }
- if (c == '[') {
- return ']';
- }
- if (c == '{') {
- return '}';
- }
- return 0;
-}
-
-static bool _is_pair_left_symbol(char32_t c) {
- return c == '"' ||
- c == '\'' ||
- c == '(' ||
- c == '[' ||
- c == '{';
-}
-
void CodeEdit::_new_line(bool p_split_current_line, bool p_above) {
if (is_readonly()) {
return;
@@ -803,9 +912,8 @@ void CodeEdit::_new_line(bool p_split_current_line, bool p_above) {
if (should_indent) {
ins += indent_text;
- /* TODO: Change when brace completion is refactored. */
- char32_t closing_char = _get_right_pair_symbol(indent_char);
- if (closing_char != 0 && closing_char == line[cc]) {
+ String closing_pair = get_auto_brace_completion_close_key(String::chr(indent_char));
+ if (!closing_pair.is_empty() && line.find(closing_pair, cc) == cc) {
/* No need to move the brace below if we are not taking the text with us. */
if (p_split_current_line) {
brace_indent = true;
@@ -873,12 +981,20 @@ void CodeEdit::backspace() {
merge_gutters(cl, prev_line);
- /* TODO: Change when brace completion is refactored. */
- if (auto_brace_completion_enabled && cc > 0 && _is_pair_left_symbol(get_line(cl)[cc - 1])) {
- _consume_backspace_for_pair_symbol(prev_line, prev_column);
- cursor_set_line(prev_line, false, true);
- cursor_set_column(prev_column);
- return;
+ if (auto_brace_completion_enabled && cc > 0) {
+ int idx = _get_auto_brace_pair_open_at_pos(cl, cc);
+ if (idx != -1) {
+ prev_column = cc - auto_brace_completion_pairs[idx].open_key.length();
+
+ if (_get_auto_brace_pair_close_at_pos(cl, cc) == idx) {
+ _remove_text(prev_line, prev_column, cl, cc + auto_brace_completion_pairs[idx].close_key.length());
+ } else {
+ _remove_text(prev_line, prev_column, cl, cc);
+ }
+ cursor_set_line(prev_line, false, true);
+ cursor_set_column(prev_column);
+ return;
+ }
}
/* For space indentation we need to do a simple unindent if there are no chars to the left, acting in the */
@@ -896,6 +1012,93 @@ void CodeEdit::backspace() {
cursor_set_column(prev_column);
}
+/* Auto brace completion */
+void CodeEdit::set_auto_brace_completion_enabled(bool p_enabled) {
+ auto_brace_completion_enabled = p_enabled;
+}
+
+bool CodeEdit::is_auto_brace_completion_enabled() const {
+ return auto_brace_completion_enabled;
+}
+
+void CodeEdit::set_highlight_matching_braces_enabled(bool p_enabled) {
+ highlight_matching_braces_enabled = p_enabled;
+ update();
+}
+
+bool CodeEdit::is_highlight_matching_braces_enabled() const {
+ return highlight_matching_braces_enabled;
+}
+
+void CodeEdit::add_auto_brace_completion_pair(const String &p_open_key, const String &p_close_key) {
+ ERR_FAIL_COND_MSG(p_open_key.is_empty(), "auto brace completion open key cannot be empty");
+ ERR_FAIL_COND_MSG(p_close_key.is_empty(), "auto brace completion close key cannot be empty");
+
+ for (int i = 0; i < p_open_key.length(); i++) {
+ ERR_FAIL_COND_MSG(!is_symbol(p_open_key[i]), "auto brace completion open key must be a symbol");
+ }
+ for (int i = 0; i < p_close_key.length(); i++) {
+ ERR_FAIL_COND_MSG(!is_symbol(p_close_key[i]), "auto brace completion close key must be a symbol");
+ }
+
+ int at = 0;
+ for (int i = 0; i < auto_brace_completion_pairs.size(); i++) {
+ ERR_FAIL_COND_MSG(auto_brace_completion_pairs[i].open_key == p_open_key, "auto brace completion open key '" + p_open_key + "' already exists.");
+ if (p_open_key.length() < auto_brace_completion_pairs[i].open_key.length()) {
+ at++;
+ }
+ }
+
+ BracePair brace_pair;
+ brace_pair.open_key = p_open_key;
+ brace_pair.close_key = p_close_key;
+ auto_brace_completion_pairs.insert(at, brace_pair);
+}
+
+void CodeEdit::set_auto_brace_completion_pairs(const Dictionary &p_auto_brace_completion_pairs) {
+ auto_brace_completion_pairs.clear();
+
+ Array keys = p_auto_brace_completion_pairs.keys();
+ for (int i = 0; i < keys.size(); i++) {
+ add_auto_brace_completion_pair(keys[i], p_auto_brace_completion_pairs[keys[i]]);
+ }
+}
+
+Dictionary CodeEdit::get_auto_brace_completion_pairs() const {
+ Dictionary brace_pairs;
+ for (int i = 0; i < auto_brace_completion_pairs.size(); i++) {
+ brace_pairs[auto_brace_completion_pairs[i].open_key] = auto_brace_completion_pairs[i].close_key;
+ }
+ return brace_pairs;
+}
+
+bool CodeEdit::has_auto_brace_completion_open_key(const String &p_open_key) const {
+ for (int i = 0; i < auto_brace_completion_pairs.size(); i++) {
+ if (auto_brace_completion_pairs[i].open_key == p_open_key) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool CodeEdit::has_auto_brace_completion_close_key(const String &p_close_key) const {
+ for (int i = 0; i < auto_brace_completion_pairs.size(); i++) {
+ if (auto_brace_completion_pairs[i].close_key == p_close_key) {
+ return true;
+ }
+ }
+ return false;
+}
+
+String CodeEdit::get_auto_brace_completion_close_key(const String &p_open_key) const {
+ for (int i = 0; i < auto_brace_completion_pairs.size(); i++) {
+ if (auto_brace_completion_pairs[i].open_key == p_open_key) {
+ return auto_brace_completion_pairs[i].close_key;
+ }
+ }
+ return String();
+}
+
/* Main Gutter */
void CodeEdit::_update_draw_main_gutter() {
set_gutter_draw(main_gutter, draw_breakpoints || draw_bookmarks || draw_executing_lines);
@@ -1700,35 +1903,40 @@ void CodeEdit::confirm_code_completion(bool p_replace) {
insert_text_at_cursor(insert_text.substr(matching_chars));
}
- /* TODO: merge with autobrace completion, when in CodeEdit. */
/* Handle merging of symbols eg strings, brackets. */
const String line = get_line(caret_line);
char32_t next_char = line[cursor_get_column()];
char32_t last_completion_char = insert_text[insert_text.length() - 1];
char32_t last_completion_char_display = display_text[display_text.length() - 1];
- if ((last_completion_char == '"' || last_completion_char == '\'') && (last_completion_char == next_char || last_completion_char_display == next_char)) {
+ int pre_brace_pair = cursor_get_column() > 0 ? _get_auto_brace_pair_open_at_pos(caret_line, cursor_get_column()) : -1;
+ int post_brace_pair = cursor_get_column() < get_line(caret_line).length() ? _get_auto_brace_pair_close_at_pos(caret_line, cursor_get_column()) : -1;
+
+ if (post_brace_pair != -1 && (last_completion_char == next_char || last_completion_char_display == next_char)) {
_remove_text(caret_line, cursor_get_column(), caret_line, cursor_get_column() + 1);
}
- if (last_completion_char == '(') {
- if (next_char == last_completion_char) {
- _remove_text(caret_line, cursor_get_column() - 1, caret_line, cursor_get_column());
- } else if (auto_brace_completion_enabled) {
- insert_text_at_cursor(")");
- cursor_set_column(cursor_get_column() - 1);
- }
- } else if (last_completion_char == ')' && next_char == '(') {
- _remove_text(caret_line, cursor_get_column() - 2, caret_line, cursor_get_column());
- if (line[cursor_get_column() + 1] != ')') {
- cursor_set_column(cursor_get_column() - 1);
+ if (pre_brace_pair != -1 && pre_brace_pair != post_brace_pair && (last_completion_char == next_char || last_completion_char_display == next_char)) {
+ _remove_text(caret_line, cursor_get_column(), caret_line, cursor_get_column() + 1);
+ } else if (auto_brace_completion_enabled && pre_brace_pair != -1 && post_brace_pair == -1) {
+ insert_text_at_cursor(auto_brace_completion_pairs[pre_brace_pair].close_key);
+ cursor_set_column(cursor_get_column() - auto_brace_completion_pairs[pre_brace_pair].close_key.length());
+ }
+
+ if (pre_brace_pair == -1 && post_brace_pair == -1 && cursor_get_column() > 0 && cursor_get_column() < get_line(caret_line).length()) {
+ pre_brace_pair = _get_auto_brace_pair_open_at_pos(caret_line, cursor_get_column() + 1);
+ if (pre_brace_pair == _get_auto_brace_pair_close_at_pos(caret_line, cursor_get_column() - 1)) {
+ _remove_text(caret_line, cursor_get_column() - 2, caret_line, cursor_get_column());
+ if (_get_auto_brace_pair_close_at_pos(caret_line, cursor_get_column() - 1) != pre_brace_pair) {
+ cursor_set_column(cursor_get_column() - 1);
+ }
}
}
end_complex_operation();
cancel_code_completion();
- if (last_completion_char == '(') {
+ if (code_completion_prefixes.has(String::chr(last_completion_char))) {
request_code_completion();
}
}
@@ -1742,6 +1950,58 @@ void CodeEdit::cancel_code_completion() {
update();
}
+/* Line length guidelines */
+void CodeEdit::set_line_length_guidelines(TypedArray<int> p_guideline_columns) {
+ line_length_guideline_columns = p_guideline_columns;
+ update();
+}
+
+TypedArray<int> CodeEdit::get_line_length_guidelines() const {
+ return line_length_guideline_columns;
+}
+
+/* Symbol lookup */
+void CodeEdit::set_symbol_lookup_on_click_enabled(bool p_enabled) {
+ symbol_lookup_on_click_enabled = p_enabled;
+ set_symbol_lookup_word_as_valid(false);
+}
+
+bool CodeEdit::is_symbol_lookup_on_click_enabled() const {
+ return symbol_lookup_on_click_enabled;
+}
+
+String CodeEdit::get_text_for_symbol_lookup() {
+ int line, col;
+ Point2i mp = _get_local_mouse_pos();
+ _get_mouse_pos(mp, line, col);
+
+ StringBuilder lookup_text;
+ const int text_size = get_line_count();
+ for (int i = 0; i < text_size; i++) {
+ String text = get_line(i);
+
+ if (i == line) {
+ lookup_text += text.substr(0, col);
+ /* Not unicode, represents the cursor. */
+ lookup_text += String::chr(0xFFFF);
+ lookup_text += text.substr(col, text.size());
+ } else {
+ lookup_text += text;
+ }
+
+ if (i != text_size - 1) {
+ lookup_text += "\n";
+ }
+ }
+ return lookup_text.as_string();
+}
+
+void CodeEdit::set_symbol_lookup_word_as_valid(bool p_valid) {
+ symbol_lookup_word = p_valid ? symbol_lookup_new_word : "";
+ symbol_lookup_new_word = "";
+ _set_symbol_lookup_word(symbol_lookup_word);
+}
+
void CodeEdit::_bind_methods() {
/* Indent management */
ClassDB::bind_method(D_METHOD("set_indent_size", "size"), &CodeEdit::set_indent_size);
@@ -1762,6 +2022,22 @@ void CodeEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("indent_lines"), &CodeEdit::indent_lines);
ClassDB::bind_method(D_METHOD("unindent_lines"), &CodeEdit::unindent_lines);
+ /* Auto brace completion */
+ ClassDB::bind_method(D_METHOD("set_auto_brace_completion_enabled", "enable"), &CodeEdit::set_auto_brace_completion_enabled);
+ ClassDB::bind_method(D_METHOD("is_auto_brace_completion_enabled"), &CodeEdit::is_auto_brace_completion_enabled);
+
+ ClassDB::bind_method(D_METHOD("set_highlight_matching_braces_enabled", "enable"), &CodeEdit::set_highlight_matching_braces_enabled);
+ ClassDB::bind_method(D_METHOD("is_highlight_matching_braces_enabled"), &CodeEdit::is_highlight_matching_braces_enabled);
+
+ ClassDB::bind_method(D_METHOD("add_auto_brace_completion_pair", "start_key", "end_key"), &CodeEdit::add_auto_brace_completion_pair);
+ ClassDB::bind_method(D_METHOD("set_auto_brace_completion_pairs", "pairs"), &CodeEdit::set_auto_brace_completion_pairs);
+ ClassDB::bind_method(D_METHOD("get_auto_brace_completion_pairs"), &CodeEdit::get_auto_brace_completion_pairs);
+
+ ClassDB::bind_method(D_METHOD("has_auto_brace_completion_open_key", "open_key"), &CodeEdit::has_auto_brace_completion_open_key);
+ ClassDB::bind_method(D_METHOD("has_auto_brace_completion_close_key", "close_key"), &CodeEdit::has_auto_brace_completion_close_key);
+
+ ClassDB::bind_method(D_METHOD("get_auto_brace_completion_close_key", "open_key"), &CodeEdit::get_auto_brace_completion_close_key);
+
/* Main Gutter */
ClassDB::bind_method(D_METHOD("_main_gutter_draw_callback"), &CodeEdit::_main_gutter_draw_callback);
@@ -1890,19 +2166,35 @@ void CodeEdit::_bind_methods() {
BIND_VMETHOD(MethodInfo("_request_code_completion", PropertyInfo(Variant::BOOL, "force")));
BIND_VMETHOD(MethodInfo(Variant::ARRAY, "_filter_code_completion_candidates", PropertyInfo(Variant::ARRAY, "candidates")));
+ /* Line length guidelines */
+ ClassDB::bind_method(D_METHOD("set_line_length_guidelines", "guideline_columns"), &CodeEdit::set_line_length_guidelines);
+ ClassDB::bind_method(D_METHOD("get_line_length_guidelines"), &CodeEdit::get_line_length_guidelines);
+
+ /* Symbol lookup */
+ ClassDB::bind_method(D_METHOD("set_symbol_lookup_on_click_enabled", "enable"), &CodeEdit::set_symbol_lookup_on_click_enabled);
+ ClassDB::bind_method(D_METHOD("is_symbol_lookup_on_click_enabled"), &CodeEdit::is_symbol_lookup_on_click_enabled);
+
+ ClassDB::bind_method(D_METHOD("get_text_for_symbol_lookup"), &CodeEdit::get_text_for_symbol_lookup);
+
+ ClassDB::bind_method(D_METHOD("set_symbol_lookup_word_as_valid", "valid"), &CodeEdit::set_symbol_lookup_word_as_valid);
+
/* Inspector */
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_breakpoints_gutter"), "set_draw_breakpoints_gutter", "is_drawing_breakpoints_gutter");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "symbol_lookup_on_click"), "set_symbol_lookup_on_click_enabled", "is_symbol_lookup_on_click_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "line_folding"), "set_line_folding_enabled", "is_line_folding_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_bookmarks"), "set_draw_bookmarks_gutter", "is_drawing_bookmarks_gutter");
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_INT32_ARRAY, "line_length_guidelines"), "set_line_length_guidelines", "get_line_length_guidelines");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_executing_lines"), "set_draw_executing_lines_gutter", "is_drawing_executing_lines_gutter");
+ ADD_GROUP("Gutters", "gutters_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gutters_draw_breakpoints_gutter"), "set_draw_breakpoints_gutter", "is_drawing_breakpoints_gutter");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_line_numbers"), "set_draw_line_numbers", "is_draw_line_numbers_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "zero_pad_line_numbers"), "set_line_numbers_zero_padded", "is_line_numbers_zero_padded");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gutters_draw_bookmarks"), "set_draw_bookmarks_gutter", "is_drawing_bookmarks_gutter");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draw_fold_gutter"), "set_draw_fold_gutter", "is_drawing_fold_gutter");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gutters_draw_executing_lines"), "set_draw_executing_lines_gutter", "is_drawing_executing_lines_gutter");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "line_folding"), "set_line_folding_enabled", "is_line_folding_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gutters_draw_line_numbers"), "set_draw_line_numbers", "is_draw_line_numbers_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gutters_zero_pad_line_numbers"), "set_line_numbers_zero_padded", "is_line_numbers_zero_padded");
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gutters_draw_fold_gutter"), "set_draw_fold_gutter", "is_drawing_fold_gutter");
ADD_GROUP("Delimiters", "delimiter_");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "delimiter_strings"), "set_string_delimiters", "get_string_delimiters");
@@ -1918,11 +2210,74 @@ void CodeEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "indent_automatic"), "set_auto_indent_enabled", "is_auto_indent_enabled");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "indent_automatic_prefixes"), "set_auto_indent_prefixes", "get_auto_indent_prefixes");
+ ADD_GROUP("Auto brace completion", "auto_brace_completion_");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_brace_completion_enabled"), "set_auto_brace_completion_enabled", "is_auto_brace_completion_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_brace_completion_highlight_matching"), "set_highlight_matching_braces_enabled", "is_highlight_matching_braces_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "auto_brace_completion_pairs"), "set_auto_brace_completion_pairs", "get_auto_brace_completion_pairs");
+
/* Signals */
+ /* Gutters */
ADD_SIGNAL(MethodInfo("breakpoint_toggled", PropertyInfo(Variant::INT, "line")));
+
+ /* Code Completion */
ADD_SIGNAL(MethodInfo("request_code_completion"));
+
+ /* Symbol lookup */
+ ADD_SIGNAL(MethodInfo("symbol_lookup", PropertyInfo(Variant::STRING, "symbol"), PropertyInfo(Variant::INT, "line"), PropertyInfo(Variant::INT, "column")));
+ ADD_SIGNAL(MethodInfo("symbol_validate", PropertyInfo(Variant::STRING, "symbol")));
}
+/* Auto brace completion */
+int CodeEdit::_get_auto_brace_pair_open_at_pos(int p_line, int p_col) {
+ const String &line = get_line(p_line);
+
+ /* Should be fast enough, expecting low amount of pairs... */
+ for (int i = 0; i < auto_brace_completion_pairs.size(); i++) {
+ const String &open_key = auto_brace_completion_pairs[i].open_key;
+ if (p_col - open_key.length() < 0) {
+ continue;
+ }
+
+ bool is_match = true;
+ for (int j = 0; j < open_key.length(); j++) {
+ if (line[(p_col - 1) - j] != open_key[(open_key.length() - 1) - j]) {
+ is_match = false;
+ break;
+ }
+ }
+
+ if (is_match) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+int CodeEdit::_get_auto_brace_pair_close_at_pos(int p_line, int p_col) {
+ const String &line = get_line(p_line);
+
+ /* Should be fast enough, expecting low amount of pairs... */
+ for (int i = 0; i < auto_brace_completion_pairs.size(); i++) {
+ if (p_col + auto_brace_completion_pairs[i].close_key.length() > line.length()) {
+ continue;
+ }
+
+ bool is_match = true;
+ for (int j = 0; j < auto_brace_completion_pairs[i].close_key.length(); j++) {
+ if (line[p_col + j] != auto_brace_completion_pairs[i].close_key[j]) {
+ is_match = false;
+ break;
+ }
+ }
+
+ if (is_match) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+/* Gutters */
void CodeEdit::_gutter_clicked(int p_line, int p_gutter) {
if (p_gutter == main_gutter) {
if (draw_breakpoints) {
@@ -2547,6 +2902,17 @@ CodeEdit::CodeEdit() {
auto_indent_prefixes.insert('[');
auto_indent_prefixes.insert('(');
+ /* Auto brace completion */
+ add_auto_brace_completion_pair("(", ")");
+ add_auto_brace_completion_pair("{", "}");
+ add_auto_brace_completion_pair("[", "]");
+ add_auto_brace_completion_pair("\"", "\"");
+ add_auto_brace_completion_pair("\'", "\'");
+
+ /* Delimiter traking */
+ add_string_delimiter("\"", "\"", false);
+ add_string_delimiter("\'", "\'", false);
+
/* Text Direction */
set_layout_direction(LAYOUT_DIRECTION_LTR);
set_text_direction(TEXT_DIRECTION_LTR);
diff --git a/scene/gui/code_edit.h b/scene/gui/code_edit.h
index 25b518402b..72fdc6e787 100644
--- a/scene/gui/code_edit.h
+++ b/scene/gui/code_edit.h
@@ -66,6 +66,19 @@ private:
void _new_line(bool p_split_current_line = true, bool p_above = false);
+ /* Auto brace completion */
+ bool auto_brace_completion_enabled = false;
+
+ /* BracePair open_key must be uniquie and ordered by length. */
+ struct BracePair {
+ String open_key = "";
+ String close_key = "";
+ };
+ Vector<BracePair> auto_brace_completion_pairs;
+
+ int _get_auto_brace_pair_open_at_pos(int p_line, int p_col);
+ int _get_auto_brace_pair_close_at_pos(int p_line, int p_col);
+
/* Main Gutter */
enum MainGutterType {
MAIN_GUTTER_BREAKPOINT = 0x01,
@@ -112,7 +125,7 @@ private:
void _update_gutter_indexes();
/* Line Folding */
- bool line_folding_enabled = true;
+ bool line_folding_enabled = false;
/* Delimiters */
enum DelimiterType {
@@ -210,6 +223,16 @@ private:
void _lines_edited_from(int p_from_line, int p_to_line);
+ /* Line length guidelines */
+ TypedArray<int> line_length_guideline_columns;
+ Color line_length_guideline_color;
+
+ /* Symbol lookup */
+ bool symbol_lookup_on_click_enabled = false;
+
+ String symbol_lookup_new_word = "";
+ String symbol_lookup_word = "";
+
protected:
void _gui_input(const Ref<InputEvent> &p_gui_input) override;
void _notification(int p_what);
@@ -217,7 +240,9 @@ protected:
static void _bind_methods();
public:
+ /* General overrides */
virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override;
+ virtual void handle_unicode_input(uint32_t p_unicode) override;
/* Indent management */
void set_indent_size(const int p_size);
@@ -240,6 +265,22 @@ public:
virtual void backspace() override;
+ /* Auto brace completion */
+ void set_auto_brace_completion_enabled(bool p_enabled);
+ bool is_auto_brace_completion_enabled() const;
+
+ void set_highlight_matching_braces_enabled(bool p_enabled);
+ bool is_highlight_matching_braces_enabled() const;
+
+ void add_auto_brace_completion_pair(const String &p_open_key, const String &p_close_key);
+ void set_auto_brace_completion_pairs(const Dictionary &p_auto_brace_completion_pairs);
+ Dictionary get_auto_brace_completion_pairs() const;
+
+ bool has_auto_brace_completion_open_key(const String &p_open_key) const;
+ bool has_auto_brace_completion_close_key(const String &p_close_key) const;
+
+ String get_auto_brace_completion_close_key(const String &p_open_key) const;
+
/* Main Gutter */
void set_draw_breakpoints_gutter(bool p_draw);
bool is_drawing_breakpoints_gutter() const;
@@ -347,6 +388,18 @@ public:
void confirm_code_completion(bool p_replace = false);
void cancel_code_completion();
+ /* Line length guidelines */
+ void set_line_length_guidelines(TypedArray<int> p_guideline_columns);
+ TypedArray<int> get_line_length_guidelines() const;
+
+ /* Symbol lookup */
+ void set_symbol_lookup_on_click_enabled(bool p_enabled);
+ bool is_symbol_lookup_on_click_enabled() const;
+
+ String get_text_for_symbol_lookup();
+
+ void set_symbol_lookup_word_as_valid(bool p_valid);
+
CodeEdit();
~CodeEdit();
};
diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp
index 83ecf1d534..706d3b48c2 100644
--- a/scene/gui/gradient_edit.cpp
+++ b/scene/gui/gradient_edit.cpp
@@ -49,9 +49,6 @@ GradientEdit::GradientEdit() {
popup->add_child(picker);
add_child(popup);
-
- checker = Ref<ImageTexture>(memnew(ImageTexture));
- Ref<Image> img = memnew(Image(checker_bg_png));
}
int GradientEdit::_get_point_from_pos(int x) {
@@ -311,7 +308,7 @@ void GradientEdit::_notification(int p_what) {
int total_w = get_size().width - get_size().height - SPACING;
//Draw checker pattern for ramp
- _draw_checker(0, 0, total_w, h);
+ draw_texture_rect(get_theme_icon("GuiMiniCheckerboard", "EditorIcons"), Rect2(0, 0, total_w, h), true);
//Draw color ramp
Gradient::Point prev;
@@ -378,7 +375,7 @@ void GradientEdit::_notification(int p_what) {
}
//Draw "button" for color selector
- _draw_checker(total_w + SPACING, 0, h, h);
+ draw_texture_rect(get_theme_icon("GuiMiniCheckerboard", "EditorIcons"), Rect2(total_w + SPACING, 0, h, h), true);
if (grabbed != -1) {
//Draw with selection color
draw_rect(Rect2(total_w + SPACING, 0, h, h), points[grabbed].color);
@@ -405,27 +402,6 @@ void GradientEdit::_notification(int p_what) {
}
}
-void GradientEdit::_draw_checker(int x, int y, int w, int h) {
- //Draw it with polygon to insert UVs for scale
- Vector<Vector2> backPoints;
- backPoints.push_back(Vector2(x, y));
- backPoints.push_back(Vector2(x, y + h));
- backPoints.push_back(Vector2(x + w, y + h));
- backPoints.push_back(Vector2(x + w, y));
- Vector<Color> colorPoints;
- colorPoints.push_back(Color(1, 1, 1, 1));
- colorPoints.push_back(Color(1, 1, 1, 1));
- colorPoints.push_back(Color(1, 1, 1, 1));
- colorPoints.push_back(Color(1, 1, 1, 1));
- Vector<Vector2> uvPoints;
- //Draw checker pattern pixel-perfect and scale it by 2.
- uvPoints.push_back(Vector2(x, y));
- uvPoints.push_back(Vector2(x, y + h * .5f / checker->get_height()));
- uvPoints.push_back(Vector2(x + w * .5f / checker->get_width(), y + h * .5f / checker->get_height()));
- uvPoints.push_back(Vector2(x + w * .5f / checker->get_width(), y));
- draw_polygon(backPoints, colorPoints, uvPoints, checker);
-}
-
Size2 GradientEdit::get_minimum_size() const {
return Vector2(0, 16);
}
diff --git a/scene/gui/gradient_edit.h b/scene/gui/gradient_edit.h
index eb7367d598..3d83a02429 100644
--- a/scene/gui/gradient_edit.h
+++ b/scene/gui/gradient_edit.h
@@ -42,8 +42,6 @@ class GradientEdit : public Control {
PopupPanel *popup;
ColorPicker *picker;
- Ref<ImageTexture> checker;
-
bool grabbing = false;
int grabbed = -1;
Vector<Gradient::Point> points;
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index fdf6181f1d..258d65112a 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -245,6 +245,7 @@ void ItemList::set_item_custom_bg_color(int p_idx, const Color &p_custom_bg_colo
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].custom_bg = p_custom_bg_color;
+ update();
}
Color ItemList::get_item_custom_bg_color(int p_idx) const {
@@ -257,6 +258,7 @@ void ItemList::set_item_custom_fg_color(int p_idx, const Color &p_custom_fg_colo
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].custom_fg = p_custom_fg_color;
+ update();
}
Color ItemList::get_item_custom_fg_color(int p_idx) const {
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 490548fce0..44f7200cd7 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -74,7 +74,7 @@ Size2 PopupMenu::_get_contents_minimum_size() const {
size.width += items[i].text_buf->get_size().x;
size.height += vseparation;
- if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->is_valid())) {
+ if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->has_valid_event())) {
int accel_w = hseparation * 2;
accel_w += items[i].accel_text_buf->get_size().x;
accel_max_w = MAX(accel_w, accel_max_w);
@@ -635,7 +635,7 @@ void PopupMenu::_draw_items() {
}
// Accelerator / Shortcut
- if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->is_valid())) {
+ if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->has_valid_event())) {
if (rtl) {
item_ofs.x = scroll_width + style->get_margin(SIDE_LEFT) + item_end_padding;
} else {
@@ -1301,7 +1301,7 @@ bool PopupMenu::activate_item_by_event(const Ref<InputEvent> &p_event, bool p_fo
continue;
}
- if (items[i].shortcut.is_valid() && items[i].shortcut->is_shortcut(p_event) && (items[i].shortcut_is_global || !p_for_global_only)) {
+ if (items[i].shortcut.is_valid() && items[i].shortcut->matches_event(p_event) && (items[i].shortcut_is_global || !p_for_global_only)) {
activate_item(i);
return true;
}
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 3925e0c38e..3cb1f7d2bc 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -2289,7 +2289,7 @@ void RichTextLabel::_remove_item(Item *p_item, const int p_line, const int p_sub
}
}
-void RichTextLabel::add_image(const Ref<Texture2D> &p_image, const int p_width, const int p_height, const Color &p_color, VAlign p_align) {
+void RichTextLabel::add_image(const Ref<Texture2D> &p_image, const int p_width, const int p_height, const Color &p_color, InlineAlign p_align) {
if (current->type == ITEM_TABLE) {
return;
}
@@ -2534,7 +2534,7 @@ void RichTextLabel::push_meta(const Variant &p_meta) {
_add_item(item, true);
}
-void RichTextLabel::push_table(int p_columns, VAlign p_align) {
+void RichTextLabel::push_table(int p_columns, InlineAlign p_align) {
ERR_FAIL_COND(p_columns < 1);
ItemTable *item = memnew(ItemTable);
@@ -2897,18 +2897,35 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
columns = 1;
}
- VAlign align = VALIGN_TOP;
- if (subtag.size() > 1) {
+ int align = INLINE_ALIGN_TOP;
+ if (subtag.size() > 2) {
if (subtag[1] == "top" || subtag[1] == "t") {
- align = VALIGN_TOP;
+ align = INLINE_ALIGN_TOP_TO;
} else if (subtag[1] == "center" || subtag[1] == "c") {
- align = VALIGN_CENTER;
+ align = INLINE_ALIGN_CENTER_TO;
} else if (subtag[1] == "bottom" || subtag[1] == "b") {
- align = VALIGN_BOTTOM;
+ align = INLINE_ALIGN_BOTTOM_TO;
+ }
+ if (subtag[2] == "top" || subtag[2] == "t") {
+ align |= INLINE_ALIGN_TO_TOP;
+ } else if (subtag[2] == "center" || subtag[2] == "c") {
+ align |= INLINE_ALIGN_TO_CENTER;
+ } else if (subtag[2] == "baseline" || subtag[2] == "l") {
+ align |= INLINE_ALIGN_TO_BASELINE;
+ } else if (subtag[2] == "bottom" || subtag[2] == "b") {
+ align |= INLINE_ALIGN_TO_BOTTOM;
+ }
+ } else if (subtag.size() > 1) {
+ if (subtag[1] == "top" || subtag[1] == "t") {
+ align = INLINE_ALIGN_TOP;
+ } else if (subtag[1] == "center" || subtag[1] == "c") {
+ align = INLINE_ALIGN_CENTER;
+ } else if (subtag[1] == "bottom" || subtag[1] == "b") {
+ align = INLINE_ALIGN_BOTTOM;
}
}
- push_table(columns, align);
+ push_table(columns, (InlineAlign)align);
pos = brk_end + 1;
tag_stack.push_front("table");
} else if (tag == "cell") {
@@ -3187,15 +3204,34 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
pos = end;
tag_stack.push_front(bbcode_name);
} else if (tag.begins_with("img")) {
- VAlign align = VALIGN_TOP;
+ int align = INLINE_ALIGN_CENTER;
if (tag.begins_with("img=")) {
- String al = tag.substr(4, tag.length());
- if (al == "top" || al == "t") {
- align = VALIGN_TOP;
- } else if (al == "center" || al == "c") {
- align = VALIGN_CENTER;
- } else if (al == "bottom" || al == "b") {
- align = VALIGN_BOTTOM;
+ Vector<String> subtag = tag.substr(4, tag.length()).split(",");
+ if (subtag.size() > 1) {
+ if (subtag[0] == "top" || subtag[0] == "t") {
+ align = INLINE_ALIGN_TOP_TO;
+ } else if (subtag[0] == "center" || subtag[0] == "c") {
+ align = INLINE_ALIGN_CENTER_TO;
+ } else if (subtag[0] == "bottom" || subtag[0] == "b") {
+ align = INLINE_ALIGN_BOTTOM_TO;
+ }
+ if (subtag[1] == "top" || subtag[1] == "t") {
+ align |= INLINE_ALIGN_TO_TOP;
+ } else if (subtag[1] == "center" || subtag[1] == "c") {
+ align |= INLINE_ALIGN_TO_CENTER;
+ } else if (subtag[1] == "baseline" || subtag[1] == "l") {
+ align |= INLINE_ALIGN_TO_BASELINE;
+ } else if (subtag[1] == "bottom" || subtag[1] == "b") {
+ align |= INLINE_ALIGN_TO_BOTTOM;
+ }
+ } else if (subtag.size() > 0) {
+ if (subtag[0] == "top" || subtag[0] == "t") {
+ align = INLINE_ALIGN_TOP;
+ } else if (subtag[0] == "center" || subtag[0] == "c") {
+ align = INLINE_ALIGN_CENTER;
+ } else if (subtag[0] == "bottom" || subtag[0] == "b") {
+ align = INLINE_ALIGN_BOTTOM;
+ }
}
}
@@ -3236,7 +3272,7 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
}
}
- add_image(texture, width, height, color, align);
+ add_image(texture, width, height, color, (InlineAlign)align);
}
pos = end;
@@ -3961,7 +3997,7 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_text"), &RichTextLabel::get_text);
ClassDB::bind_method(D_METHOD("add_text", "text"), &RichTextLabel::add_text);
ClassDB::bind_method(D_METHOD("set_text", "text"), &RichTextLabel::set_text);
- ClassDB::bind_method(D_METHOD("add_image", "image", "width", "height", "color", "inline_align"), &RichTextLabel::add_image, DEFVAL(0), DEFVAL(0), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(VALIGN_TOP));
+ ClassDB::bind_method(D_METHOD("add_image", "image", "width", "height", "color", "inline_align"), &RichTextLabel::add_image, DEFVAL(0), DEFVAL(0), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(INLINE_ALIGN_CENTER));
ClassDB::bind_method(D_METHOD("newline"), &RichTextLabel::add_newline);
ClassDB::bind_method(D_METHOD("remove_line", "line"), &RichTextLabel::remove_line);
ClassDB::bind_method(D_METHOD("push_font", "font"), &RichTextLabel::push_font);
@@ -3981,7 +4017,7 @@ void RichTextLabel::_bind_methods() {
ClassDB::bind_method(D_METHOD("push_meta", "data"), &RichTextLabel::push_meta);
ClassDB::bind_method(D_METHOD("push_underline"), &RichTextLabel::push_underline);
ClassDB::bind_method(D_METHOD("push_strikethrough"), &RichTextLabel::push_strikethrough);
- ClassDB::bind_method(D_METHOD("push_table", "columns", "inline_align"), &RichTextLabel::push_table, DEFVAL(VALIGN_TOP));
+ ClassDB::bind_method(D_METHOD("push_table", "columns", "inline_align"), &RichTextLabel::push_table, DEFVAL(INLINE_ALIGN_TOP));
ClassDB::bind_method(D_METHOD("push_dropcap", "string", "font", "size", "dropcap_margins", "color", "outline_size", "outline_color"), &RichTextLabel::push_dropcap, DEFVAL(Rect2()), DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(Color(0, 0, 0, 0)));
ClassDB::bind_method(D_METHOD("set_table_column_expand", "column", "expand", "ratio"), &RichTextLabel::set_table_column_expand);
ClassDB::bind_method(D_METHOD("set_cell_row_background_color", "odd_row_bg", "even_row_bg"), &RichTextLabel::set_cell_row_background_color);
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 999d8b05fd..a73176ba7e 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -161,7 +161,7 @@ private:
struct ItemImage : public Item {
Ref<Texture2D> image;
- VAlign inline_align = VALIGN_TOP;
+ InlineAlign inline_align = INLINE_ALIGN_CENTER;
Size2 size;
Color color;
ItemImage() { type = ITEM_IMAGE; }
@@ -248,7 +248,7 @@ private:
int total_width = 0;
int total_height = 0;
- VAlign inline_align = VALIGN_TOP;
+ InlineAlign inline_align = INLINE_ALIGN_TOP;
ItemTable() { type = ITEM_TABLE; }
};
@@ -463,7 +463,7 @@ private:
public:
String get_text();
void add_text(const String &p_text);
- void add_image(const Ref<Texture2D> &p_image, const int p_width = 0, const int p_height = 0, const Color &p_color = Color(1.0, 1.0, 1.0), VAlign p_align = VALIGN_TOP);
+ void add_image(const Ref<Texture2D> &p_image, const int p_width = 0, const int p_height = 0, const Color &p_color = Color(1.0, 1.0, 1.0), InlineAlign p_align = INLINE_ALIGN_CENTER);
void add_newline();
bool remove_line(const int p_line);
void push_dropcap(const String &p_string, const Ref<Font> &p_font, int p_size, const Rect2 &p_dropcap_margins = Rect2(), const Color &p_color = Color(1, 1, 1), int p_ol_size = 0, const Color &p_ol_color = Color(0, 0, 0, 0));
@@ -484,7 +484,7 @@ public:
void push_indent(int p_level);
void push_list(int p_level, ListType p_list, bool p_capitalize);
void push_meta(const Variant &p_meta);
- void push_table(int p_columns, VAlign p_align = VALIGN_TOP);
+ void push_table(int p_columns, InlineAlign p_align = INLINE_ALIGN_TOP);
void push_fade(int p_start_index, int p_length);
void push_shake(int p_strength, float p_rate);
void push_wave(float p_frequency, float p_amplitude);
diff --git a/scene/gui/shortcut.cpp b/scene/gui/shortcut.cpp
index 962c6dcc60..885a51e058 100644
--- a/scene/gui/shortcut.cpp
+++ b/scene/gui/shortcut.cpp
@@ -32,42 +32,39 @@
#include "core/os/keyboard.h"
-void Shortcut::set_shortcut(const Ref<InputEvent> &p_shortcut) {
- shortcut = p_shortcut;
+void Shortcut::set_event(const Ref<InputEvent> &p_event) {
+ event = p_event;
emit_changed();
}
-Ref<InputEvent> Shortcut::get_shortcut() const {
- return shortcut;
+Ref<InputEvent> Shortcut::get_event() const {
+ return event;
}
-bool Shortcut::is_shortcut(const Ref<InputEvent> &p_event) const {
- return shortcut.is_valid() && shortcut->is_match(p_event, true);
+bool Shortcut::matches_event(const Ref<InputEvent> &p_event) const {
+ return event.is_valid() && event->is_match(p_event, true);
}
String Shortcut::get_as_text() const {
- if (shortcut.is_valid()) {
- return shortcut->as_text();
+ if (event.is_valid()) {
+ return event->as_text();
} else {
return "None";
}
}
-bool Shortcut::is_valid() const {
- return shortcut.is_valid();
+bool Shortcut::has_valid_event() const {
+ return event.is_valid();
}
void Shortcut::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_shortcut", "event"), &Shortcut::set_shortcut);
- ClassDB::bind_method(D_METHOD("get_shortcut"), &Shortcut::get_shortcut);
+ ClassDB::bind_method(D_METHOD("set_event", "event"), &Shortcut::set_event);
+ ClassDB::bind_method(D_METHOD("get_event"), &Shortcut::get_event);
- ClassDB::bind_method(D_METHOD("is_valid"), &Shortcut::is_valid);
+ ClassDB::bind_method(D_METHOD("has_valid_event"), &Shortcut::has_valid_event);
- ClassDB::bind_method(D_METHOD("is_shortcut", "event"), &Shortcut::is_shortcut);
+ ClassDB::bind_method(D_METHOD("matches_event", "event"), &Shortcut::matches_event);
ClassDB::bind_method(D_METHOD("get_as_text"), &Shortcut::get_as_text);
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shortcut", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), "set_shortcut", "get_shortcut");
-}
-
-Shortcut::Shortcut() {
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"), "set_event", "get_event");
}
diff --git a/scene/gui/shortcut.h b/scene/gui/shortcut.h
index ea91f29b5d..249dd1971f 100644
--- a/scene/gui/shortcut.h
+++ b/scene/gui/shortcut.h
@@ -37,20 +37,18 @@
class Shortcut : public Resource {
GDCLASS(Shortcut, Resource);
- Ref<InputEvent> shortcut;
+ Ref<InputEvent> event;
protected:
static void _bind_methods();
public:
- void set_shortcut(const Ref<InputEvent> &p_shortcut);
- Ref<InputEvent> get_shortcut() const;
- bool is_shortcut(const Ref<InputEvent> &p_event) const;
- bool is_valid() const;
+ void set_event(const Ref<InputEvent> &p_shortcut);
+ Ref<InputEvent> get_event() const;
+ bool matches_event(const Ref<InputEvent> &p_event) const;
+ bool has_valid_event() const;
String get_as_text() const;
-
- Shortcut();
};
#endif // SHORTCUT_H
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 4b8c4b3e16..cc41d961f6 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -899,7 +899,7 @@ void TabContainer::drop_data(const Point2 &p_point, const Variant &p_data) {
if (hover_now < 0) {
hover_now = get_tab_count() - 1;
}
- move_child(get_tab_control(tab_from_id), hover_now);
+ move_child(get_tab_control(tab_from_id), get_tab_control(hover_now)->get_index());
set_current_tab(hover_now);
} else if (get_tabs_rearrange_group() != -1) {
// drag and drop between TabContainers
@@ -912,7 +912,7 @@ void TabContainer::drop_data(const Point2 &p_point, const Variant &p_data) {
if (hover_now < 0) {
hover_now = get_tab_count() - 1;
}
- move_child(moving_tabc, hover_now);
+ move_child(moving_tabc, get_tab_control(hover_now)->get_index());
set_current_tab(hover_now);
emit_signal(SNAME("tab_changed"), hover_now);
}
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index be3edccc99..1b3935dd25 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -63,45 +63,6 @@ static bool _is_char(char32_t c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
}
-static bool _is_pair_right_symbol(char32_t c) {
- return c == '"' ||
- c == '\'' ||
- c == ')' ||
- c == ']' ||
- c == '}';
-}
-
-static bool _is_pair_left_symbol(char32_t c) {
- return c == '"' ||
- c == '\'' ||
- c == '(' ||
- c == '[' ||
- c == '{';
-}
-
-static bool _is_pair_symbol(char32_t c) {
- return _is_pair_left_symbol(c) || _is_pair_right_symbol(c);
-}
-
-static char32_t _get_right_pair_symbol(char32_t c) {
- if (c == '"') {
- return '"';
- }
- if (c == '\'') {
- return '\'';
- }
- if (c == '(') {
- return ')';
- }
- if (c == '[') {
- return ']';
- }
- if (c == '{') {
- return '}';
- }
- return 0;
-}
-
///////////////////////////////////////////////////////////////////////////////
void TextEdit::Text::set_font(const Ref<Font> &p_font) {
@@ -633,29 +594,6 @@ void TextEdit::_notification(int p_what) {
RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(), get_size()), cache.background_color);
}
- if (line_length_guidelines) {
- const int hard_x = xmargin_beg + (int)cache.font->get_char_size('0', 0, cache.font_size).width * line_length_guideline_hard_col - cursor.x_ofs;
- if (hard_x > xmargin_beg && hard_x < xmargin_end) {
- if (rtl) {
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(size.width - hard_x, 0), Point2(size.width - hard_x, size.height), cache.line_length_guideline_color);
- } else {
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(hard_x, 0), Point2(hard_x, size.height), cache.line_length_guideline_color);
- }
- }
-
- // Draw a "Soft" line length guideline, less visible than the hard line length guideline.
- // It's usually set to a lower column compared to the hard line length guideline.
- // Only drawn if its column differs from the hard line length guideline.
- const int soft_x = xmargin_beg + (int)cache.font->get_char_size('0', 0, cache.font_size).width * line_length_guideline_soft_col - cursor.x_ofs;
- if (hard_x != soft_x && soft_x > xmargin_beg && soft_x < xmargin_end) {
- if (rtl) {
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(size.width - soft_x, 0), Point2(size.width - soft_x, size.height), cache.line_length_guideline_color * Color(1, 1, 1, 0.5));
- } else {
- RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(soft_x, 0), Point2(soft_x, size.height), cache.line_length_guideline_color * Color(1, 1, 1, 0.5));
- }
- }
- }
-
int brace_open_match_line = -1;
int brace_open_match_column = -1;
bool brace_open_matching = false;
@@ -665,7 +603,7 @@ void TextEdit::_notification(int p_what) {
bool brace_close_matching = false;
bool brace_close_mismatch = false;
- if (brace_matching_enabled && cursor.line >= 0 && cursor.line < text.size() && cursor.column >= 0) {
+ if (highlight_matching_braces_enabled && cursor.line >= 0 && cursor.line < text.size() && cursor.column >= 0) {
if (cursor.column < text[cursor.line].length()) {
// Check for open.
char32_t c = text[cursor.line][cursor.column];
@@ -1239,11 +1177,11 @@ void TextEdit::_notification(int p_what) {
}
}
- if (!clipped && select_identifiers_enabled && highlighted_word.length() != 0) { // Highlight word
- if (_is_char(highlighted_word[0]) || highlighted_word[0] == '.') {
- int highlighted_word_col = _get_column_pos_of_word(highlighted_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, 0);
+ if (!clipped && lookup_symbol_word.length() != 0) { // Highlight word
+ if (_is_char(lookup_symbol_word[0]) || lookup_symbol_word[0] == '.') {
+ int highlighted_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, 0);
while (highlighted_word_col != -1) {
- Vector<Vector2> sel = TS->shaped_text_get_selection(rid, highlighted_word_col + start, highlighted_word_col + highlighted_word.length() + start);
+ Vector<Vector2> sel = TS->shaped_text_get_selection(rid, highlighted_word_col + start, highlighted_word_col + lookup_symbol_word.length() + start);
for (int j = 0; j < sel.size(); j++) {
Rect2 rect = Rect2(sel[j].x + char_margin + ofs_x, ofs_y, sel[j].y - sel[j].x, row_height);
if (rect.position.x + rect.size.x <= xmargin_beg || rect.position.x > xmargin_end) {
@@ -1260,7 +1198,7 @@ void TextEdit::_notification(int p_what) {
draw_rect(rect, cache.font_selected_color);
}
- highlighted_word_col = _get_column_pos_of_word(highlighted_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, highlighted_word_col + 1);
+ highlighted_word_col = _get_column_pos_of_word(lookup_symbol_word, str, SEARCH_MATCH_CASE | SEARCH_WHOLE_WORDS, highlighted_word_col + 1);
}
}
}
@@ -1308,7 +1246,7 @@ void TextEdit::_notification(int p_what) {
int char_pos = char_ofs + char_margin + ofs_x;
if (char_pos >= xmargin_beg) {
- if (brace_matching_enabled) {
+ if (highlight_matching_braces_enabled) {
if ((brace_open_match_line == line && brace_open_match_column == glyphs[j].start) ||
(cursor.column == glyphs[j].start && cursor.line == line && cursor_wrap_index == line_wrap_index && (brace_open_matching || brace_open_mismatch))) {
if (brace_open_mismatch) {
@@ -1567,130 +1505,6 @@ void TextEdit::_notification(int p_what) {
}
}
-void TextEdit::_consume_pair_symbol(char32_t ch) {
- int cursor_position_to_move = cursor_get_column() + 1;
-
- char32_t ch_single[2] = { ch, 0 };
- char32_t ch_single_pair[2] = { _get_right_pair_symbol(ch), 0 };
- char32_t ch_pair[3] = { ch, _get_right_pair_symbol(ch), 0 };
-
- if (is_selection_active()) {
- int new_column, new_line;
-
- begin_complex_operation();
- _insert_text(get_selection_from_line(), get_selection_from_column(),
- ch_single,
- &new_line, &new_column);
-
- int to_col_offset = 0;
- if (get_selection_from_line() == get_selection_to_line()) {
- to_col_offset = 1;
- }
-
- _insert_text(get_selection_to_line(),
- get_selection_to_column() + to_col_offset,
- ch_single_pair,
- &new_line, &new_column);
- end_complex_operation();
-
- cursor_set_line(get_selection_to_line());
- cursor_set_column(get_selection_to_column() + to_col_offset);
-
- deselect();
- update();
- return;
- }
-
- if ((ch == '\'' || ch == '"') &&
- cursor_get_column() > 0 && _is_text_char(text[cursor.line][cursor_get_column() - 1]) && !_is_pair_right_symbol(text[cursor.line][cursor_get_column()])) {
- insert_text_at_cursor(ch_single);
- cursor_set_column(cursor_position_to_move);
- return;
- }
-
- if (cursor_get_column() < text[cursor.line].length()) {
- if (_is_text_char(text[cursor.line][cursor_get_column()])) {
- insert_text_at_cursor(ch_single);
- cursor_set_column(cursor_position_to_move);
- return;
- }
- if (_is_pair_right_symbol(ch) &&
- text[cursor.line][cursor_get_column()] == ch) {
- cursor_set_column(cursor_position_to_move);
- return;
- }
- }
-
- String line = text[cursor.line];
-
- bool in_single_quote = false;
- bool in_double_quote = false;
- bool found_comment = false;
-
- int c = 0;
- while (c < line.length()) {
- if (line[c] == '\\') {
- c++; // Skip quoted anything.
-
- if (cursor.column == c) {
- break;
- }
- } else if (!in_single_quote && !in_double_quote && line[c] == '#') {
- found_comment = true;
- break;
- } else {
- if (line[c] == '\'' && !in_double_quote) {
- in_single_quote = !in_single_quote;
- } else if (line[c] == '"' && !in_single_quote) {
- in_double_quote = !in_double_quote;
- }
- }
-
- c++;
-
- if (cursor.column == c) {
- break;
- }
- }
-
- // Do not need to duplicate quotes while in comments
- if (found_comment) {
- insert_text_at_cursor(ch_single);
- cursor_set_column(cursor_position_to_move);
-
- return;
- }
-
- // Disallow inserting duplicated quotes while already in string
- if ((in_single_quote || in_double_quote) && (ch == '"' || ch == '\'')) {
- insert_text_at_cursor(ch_single);
- cursor_set_column(cursor_position_to_move);
-
- return;
- }
-
- insert_text_at_cursor(ch_pair);
- cursor_set_column(cursor_position_to_move);
-}
-
-void TextEdit::_consume_backspace_for_pair_symbol(int prev_line, int prev_column) {
- bool remove_right_symbol = false;
-
- if (cursor.column < text[cursor.line].length() && cursor.column > 0) {
- char32_t left_char = text[cursor.line][cursor.column - 1];
- char32_t right_char = text[cursor.line][cursor.column];
-
- if (right_char == _get_right_pair_symbol(left_char)) {
- remove_right_symbol = true;
- }
- }
- if (remove_right_symbol) {
- _remove_text(prev_line, prev_column, cursor.line, cursor.column + 1);
- } else {
- _remove_text(prev_line, prev_column, cursor.line, cursor.column);
- }
-}
-
void TextEdit::backspace() {
ScriptInstance *si = get_script_instance();
if (si && si->has_method("_backspace")) {
@@ -1719,14 +1533,7 @@ void TextEdit::backspace() {
if (is_line_hidden(cursor.line)) {
set_line_as_hidden(prev_line, true);
}
-
- if (auto_brace_completion_enabled &&
- cursor.column > 0 &&
- _is_pair_left_symbol(text[cursor.line][cursor.column - 1])) {
- _consume_backspace_for_pair_symbol(prev_line, prev_column);
- } else {
- _remove_text(prev_line, prev_column, cursor.line, cursor.column);
- }
+ _remove_text(prev_line, prev_column, cursor.line, cursor.column);
cursor_set_line(prev_line, false, true);
cursor_set_column(prev_column);
@@ -2101,6 +1908,7 @@ void TextEdit::delete_selection() {
}
selection.active = false;
+ selection.selecting_mode = SelectionMode::SELECTION_MODE_NONE;
_remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column);
cursor_set_line(selection.from_line, false, false);
cursor_set_column(selection.from_column);
@@ -2137,13 +1945,21 @@ void TextEdit::_move_cursor_document_end(bool p_select) {
}
}
-void TextEdit::_handle_unicode_character(uint32_t unicode, bool p_had_selection) {
- if (p_had_selection) {
+void TextEdit::handle_unicode_input(uint32_t p_unicode) {
+ ScriptInstance *si = get_script_instance();
+ if (si && si->has_method("_handle_unicode_input")) {
+ si->call("_handle_unicode_input", p_unicode);
+ return;
+ }
+
+ bool had_selection = selection.active;
+ if (had_selection) {
+ begin_complex_operation();
delete_selection();
}
// Remove the old character if in insert mode and no selection.
- if (insert_mode && !p_had_selection) {
+ if (insert_mode && !had_selection) {
begin_complex_operation();
// Make sure we don't try and remove empty space.
@@ -2152,15 +1968,10 @@ void TextEdit::_handle_unicode_character(uint32_t unicode, bool p_had_selection)
}
}
- const char32_t chr[2] = { (char32_t)unicode, 0 };
+ const char32_t chr[2] = { (char32_t)p_unicode, 0 };
+ insert_text_at_cursor(chr);
- if (auto_brace_completion_enabled && _is_pair_symbol(chr[0])) {
- _consume_pair_symbol(chr[0]);
- } else {
- _insert_text_at_cursor(chr);
- }
-
- if ((insert_mode && !p_had_selection) || (selection.active != p_had_selection)) {
+ if ((insert_mode && !had_selection) || (had_selection)) {
end_complex_operation();
}
}
@@ -2301,6 +2112,10 @@ void TextEdit::_get_minimap_mouse_row(const Point2i &p_mouse, int &r_row) const
r_row = row;
}
+bool TextEdit::is_dragging_cursor() const {
+ return dragging_selection || dragging_minimap;
+}
+
void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
ERR_FAIL_COND(p_gui_input.is_null());
@@ -2478,14 +2293,6 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
} else {
if (mb->get_button_index() == MOUSE_BUTTON_LEFT) {
- if (mb->is_command_pressed() && highlighted_word != String()) {
- int row, col;
- _get_mouse_pos(Point2i(mpos.x, mpos.y), row, col);
-
- emit_signal(SNAME("symbol_lookup"), highlighted_word, row, col);
- return;
- }
-
dragging_minimap = false;
dragging_selection = false;
can_drag_minimap = false;
@@ -2520,18 +2327,6 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (is_layout_rtl()) {
mpos.x = get_size().x - mpos.x;
}
- if (select_identifiers_enabled) {
- if (!dragging_minimap && !dragging_selection && mm->is_command_pressed() && mm->get_button_mask() == 0) {
- String new_word = get_word_at_pos(mpos);
- if (new_word != highlighted_word) {
- emit_signal(SNAME("symbol_validate"), new_word);
- }
- } else {
- if (highlighted_word != String()) {
- set_highlighted_word(String());
- }
- }
- }
if (mm->get_button_mask() & MOUSE_BUTTON_MASK_LEFT && get_viewport()->gui_get_drag_data() == Variant()) { // Ignore if dragging.
_reset_caret_blink_timer();
@@ -2566,23 +2361,6 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
Ref<InputEventKey> k = p_gui_input;
if (k.is_valid()) {
- // Ctrl + Hover symbols
-#ifdef OSX_ENABLED
- if (k->get_keycode() == KEY_META) {
-#else
- if (k->get_keycode() == KEY_CTRL) {
-#endif
- if (select_identifiers_enabled) {
- if (k->is_pressed() && !dragging_minimap && !dragging_selection) {
- Point2 mp = _get_local_mouse_pos();
- emit_signal(SNAME("symbol_validate"), get_word_at_pos(mp));
- } else {
- set_highlighted_word(String());
- }
- }
- return;
- }
-
if (!k->is_pressed()) {
return;
}
@@ -2598,9 +2376,6 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
// * No Modifiers are pressed (except shift)
bool allow_unicode_handling = !(k->is_command_pressed() || k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_meta_pressed());
- // Save here for insert mode, just in case it is cleared in the following section.
- bool had_selection = selection.active;
-
selection.selecting_text = false;
// Check and handle all built in shortcuts.
@@ -2806,9 +2581,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
return;
}
+ // Handle Unicode (if no modifiers active).
if (allow_unicode_handling && !readonly && k->get_unicode() >= 32) {
- // Handle Unicode (if no modifiers active).
- _handle_unicode_character(k->get_unicode(), had_selection);
+ handle_unicode_input(k->get_unicode());
accept_event();
return;
}
@@ -3151,16 +2926,6 @@ void TextEdit::_remove_text(int p_from_line, int p_from_column, int p_to_line, i
current_op = op;
}
-void TextEdit::_insert_text_at_cursor(const String &p_text) {
- int new_column, new_line;
- _insert_text(cursor.line, cursor.column, p_text, &new_line, &new_column);
- _update_scrollbars();
- cursor_set_line(new_line, false);
- cursor_set_column(new_column);
-
- update();
-}
-
int TextEdit::get_char_count() {
int totalsize = 0;
@@ -3704,23 +3469,19 @@ int TextEdit::get_column_x_offset_for_line(int p_char, int p_line) const {
void TextEdit::insert_text_at_cursor(const String &p_text) {
if (selection.active) {
- cursor_set_line(selection.from_line, false);
- cursor_set_column(selection.from_column);
-
- _remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column);
- selection.active = false;
- selection.selecting_mode = SelectionMode::SELECTION_MODE_NONE;
+ delete_selection();
}
- _insert_text_at_cursor(p_text);
+ int new_column, new_line;
+ _insert_text(cursor.line, cursor.column, p_text, &new_line, &new_column);
+ _update_scrollbars();
+
+ cursor_set_line(new_line, false);
+ cursor_set_column(new_column);
update();
}
Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const {
- if (highlighted_word != String()) {
- return CURSOR_POINTING_HAND;
- }
-
int row, col;
_get_mouse_pos(p_pos, row, col);
@@ -3753,7 +3514,7 @@ void TextEdit::set_text(String p_text) {
setting_text = true;
if (!undo_enabled) {
_clear();
- _insert_text_at_cursor(p_text);
+ insert_text_at_cursor(p_text);
}
if (undo_enabled) {
@@ -3762,7 +3523,7 @@ void TextEdit::set_text(String p_text) {
begin_complex_operation();
_remove_text(0, 0, MAX(0, get_line_count() - 1), MAX(get_line(MAX(get_line_count() - 1, 0)).size() - 1, 0));
- _insert_text_at_cursor(p_text);
+ insert_text_at_cursor(p_text);
end_complex_operation();
selection.active = false;
}
@@ -3903,30 +3664,6 @@ bool TextEdit::get_draw_control_chars() const {
return draw_control_chars;
}
-String TextEdit::get_text_for_lookup_completion() {
- int row, col;
- Point2i mp = _get_local_mouse_pos();
- _get_mouse_pos(mp, row, col);
-
- String longthing;
- int len = text.size();
- for (int i = 0; i < len; i++) {
- if (i == row) {
- longthing += text[i].substr(0, col);
- longthing += String::chr(0xFFFF); // Not unicode, represents the cursor.
- longthing += text[i].substr(col, text[i].size());
- } else {
- longthing += text[i];
- }
-
- if (i != len - 1) {
- longthing += "\n";
- }
- }
-
- return longthing;
-}
-
String TextEdit::get_line(int line) const {
if (line < 0 || line >= text.size()) {
return "";
@@ -4015,9 +3752,8 @@ void TextEdit::_update_caches() {
cache.font_readonly_color = get_theme_color(SNAME("font_readonly_color"));
cache.selection_color = get_theme_color(SNAME("selection_color"));
cache.current_line_color = get_theme_color(SNAME("current_line_color"));
- cache.line_length_guideline_color = get_theme_color(SNAME("line_length_guideline_color"));
cache.code_folding_color = get_theme_color(SNAME("code_folding_color"), SNAME("CodeEdit"));
- cache.brace_mismatch_color = get_theme_color(SNAME("brace_mismatch_color"));
+ cache.brace_mismatch_color = get_theme_color(SNAME("brace_mismatch_color"), SNAME("CodeEdit"));
cache.word_highlighted_color = get_theme_color(SNAME("word_highlighted_color"));
cache.search_result_color = get_theme_color(SNAME("search_result_color"));
cache.search_result_border_color = get_theme_color(SNAME("search_result_border_color"));
@@ -4364,7 +4100,7 @@ void TextEdit::paste() {
clipboard += ins;
}
- _insert_text_at_cursor(clipboard);
+ insert_text_at_cursor(clipboard);
end_complex_operation();
update();
@@ -5324,21 +5060,6 @@ void TextEdit::insert_at(const String &p_text, int at) {
}
}
-void TextEdit::set_show_line_length_guidelines(bool p_show) {
- line_length_guidelines = p_show;
- update();
-}
-
-void TextEdit::set_line_length_guideline_soft_column(int p_column) {
- line_length_guideline_soft_col = p_column;
- update();
-}
-
-void TextEdit::set_line_length_guideline_hard_column(int p_column) {
- line_length_guideline_hard_col = p_column;
- update();
-}
-
void TextEdit::set_draw_minimap(bool p_draw) {
if (draw_minimap != p_draw) {
draw_minimap = p_draw;
@@ -5515,19 +5236,11 @@ void TextEdit::menu_option(int p_option) {
}
}
-void TextEdit::set_highlighted_word(const String &new_word) {
- highlighted_word = new_word;
+void TextEdit::_set_symbol_lookup_word(const String &p_symbol) {
+ lookup_symbol_word = p_symbol;
update();
}
-void TextEdit::set_select_identifiers_on_hover(bool p_enable) {
- select_identifiers_enabled = p_enable;
-}
-
-bool TextEdit::is_selecting_identifiers_on_hover_enabled() const {
- return select_identifiers_enabled;
-}
-
void TextEdit::set_context_menu_enabled(bool p_enable) {
context_menu_enabled = p_enable;
}
@@ -5719,6 +5432,7 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("delete_selection"), &TextEdit::delete_selection);
ClassDB::bind_method(D_METHOD("backspace"), &TextEdit::backspace);
BIND_VMETHOD(MethodInfo("_backspace"));
+ BIND_VMETHOD(MethodInfo("_handle_unicode_input", PropertyInfo(Variant::INT, "unicode")))
ClassDB::bind_method(D_METHOD("cut"), &TextEdit::cut);
ClassDB::bind_method(D_METHOD("copy"), &TextEdit::copy);
@@ -5727,6 +5441,7 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("select", "from_line", "from_column", "to_line", "to_column"), &TextEdit::select);
ClassDB::bind_method(D_METHOD("select_all"), &TextEdit::select_all);
ClassDB::bind_method(D_METHOD("deselect"), &TextEdit::deselect);
+ ClassDB::bind_method(D_METHOD("is_dragging_cursor"), &TextEdit::is_dragging_cursor);
ClassDB::bind_method(D_METHOD("is_selection_active"), &TextEdit::is_selection_active);
ClassDB::bind_method(D_METHOD("get_selection_from_line"), &TextEdit::get_selection_from_line);
@@ -5777,6 +5492,7 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_gutter_overwritable", "gutter"), &TextEdit::is_gutter_overwritable);
ClassDB::bind_method(D_METHOD("merge_gutters", "from_line", "to_line"), &TextEdit::merge_gutters);
ClassDB::bind_method(D_METHOD("set_gutter_custom_draw", "column", "object", "callback"), &TextEdit::set_gutter_custom_draw);
+ ClassDB::bind_method(D_METHOD("get_total_gutter_width"), &TextEdit::get_total_gutter_width);
// Line gutters.
ClassDB::bind_method(D_METHOD("set_line_gutter_metadata", "line", "gutter", "metadata"), &TextEdit::set_line_gutter_metadata);
@@ -5858,8 +5574,6 @@ void TextEdit::_bind_methods() {
ADD_SIGNAL(MethodInfo("gutter_clicked", PropertyInfo(Variant::INT, "line"), PropertyInfo(Variant::INT, "gutter")));
ADD_SIGNAL(MethodInfo("gutter_added"));
ADD_SIGNAL(MethodInfo("gutter_removed"));
- ADD_SIGNAL(MethodInfo("symbol_lookup", PropertyInfo(Variant::STRING, "symbol"), PropertyInfo(Variant::INT, "row"), PropertyInfo(Variant::INT, "column")));
- ADD_SIGNAL(MethodInfo("symbol_validate", PropertyInfo(Variant::STRING, "symbol")));
BIND_ENUM_CONSTANT(MENU_CUT);
BIND_ENUM_CONSTANT(MENU_COPY);
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 62d576b48a..9e6dedb267 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -280,9 +280,6 @@ private:
bool cursor_changed_dirty = false;
bool text_changed_dirty = false;
bool undo_enabled = true;
- bool line_length_guidelines = false;
- int line_length_guideline_soft_col = 80;
- int line_length_guideline_hard_col = 100;
bool hiding_enabled = false;
bool draw_minimap = false;
int minimap_width = 80;
@@ -291,7 +288,6 @@ private:
bool highlight_all_occurrences = false;
bool scroll_past_end_of_file_enabled = false;
- bool brace_matching_enabled = false;
bool highlight_current_line = false;
String cut_copy_line;
@@ -309,7 +305,7 @@ private:
float target_v_scroll = 0.0;
float v_scroll_speed = 80.0;
- String highlighted_word;
+ String lookup_symbol_word;
uint64_t last_dblclk = 0;
@@ -386,7 +382,6 @@ private:
Size2 get_minimum_size() const override;
int _get_control_height() const;
- Point2 _get_local_mouse_pos() const;
int _get_menu_action_accelerator(const String &p_action);
void _reset_caret_blink_timer();
@@ -431,10 +426,9 @@ private:
void _delete(bool p_word = false, bool p_all_to_right = false);
void _move_cursor_document_start(bool p_select);
void _move_cursor_document_end(bool p_select);
- void _handle_unicode_character(uint32_t unicode, bool p_had_selection);
protected:
- bool auto_brace_completion_enabled = false;
+ bool highlight_matching_braces_enabled = false;
struct Cache {
Ref<Texture2D> tab_icon;
@@ -455,7 +449,6 @@ protected:
Color selection_color;
Color code_folding_color;
Color current_line_color;
- Color line_length_guideline_color;
Color brace_mismatch_color;
Color word_highlighted_color;
Color search_result_color;
@@ -470,19 +463,17 @@ protected:
void _insert_text(int p_line, int p_char, const String &p_text, int *r_end_line = nullptr, int *r_end_char = nullptr);
void _remove_text(int p_from_line, int p_from_column, int p_to_line, int p_to_column);
- void _insert_text_at_cursor(const String &p_text);
virtual void _gui_input(const Ref<InputEvent> &p_gui_input);
void _notification(int p_what);
- void _consume_pair_symbol(char32_t ch);
- void _consume_backspace_for_pair_symbol(int prev_line, int prev_column);
-
static void _bind_methods();
bool _set(const StringName &p_name, const Variant &p_value);
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
+ void _set_symbol_lookup_word(const String &p_symbol);
+
public:
/* Syntax Highlighting. */
Ref<SyntaxHighlighter> get_syntax_highlighter();
@@ -577,8 +568,10 @@ public:
virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override;
+ Point2 _get_local_mouse_pos() const;
void _get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) const;
void _get_minimap_mouse_row(const Point2i &p_mouse, int &r_row) const;
+ bool is_dragging_cursor() const;
//void delete_char();
//void delete_line();
@@ -607,7 +600,6 @@ public:
void set_structured_text_bidi_override_options(Array p_args);
Array get_structured_text_bidi_override_options() const;
- void set_highlighted_word(const String &new_word);
void set_text(String p_text);
void insert_text_at_cursor(const String &p_text);
void insert_at(const String &p_text, int at);
@@ -635,13 +627,6 @@ public:
scroll_past_end_of_file_enabled = p_enabled;
update();
}
- inline void set_auto_brace_completion(bool p_enabled) {
- auto_brace_completion_enabled = p_enabled;
- }
- inline void set_brace_matching(bool p_enabled) {
- brace_matching_enabled = p_enabled;
- update();
- }
void center_viewport_to_cursor();
@@ -686,6 +671,7 @@ public:
void delete_selection();
+ virtual void handle_unicode_input(uint32_t p_unicode);
virtual void backspace();
void cut();
void copy();
@@ -751,10 +737,6 @@ public:
void set_highlight_current_line(bool p_enabled);
bool is_highlight_current_line_enabled() const;
- void set_show_line_length_guidelines(bool p_show);
- void set_line_length_guideline_soft_column(int p_column);
- void set_line_length_guideline_hard_column(int p_column);
-
void set_draw_minimap(bool p_draw);
bool is_drawing_minimap() const;
@@ -766,9 +748,6 @@ public:
void set_tooltip_request_func(Object *p_obj, const StringName &p_function, const Variant &p_udata);
- void set_select_identifiers_on_hover(bool p_enable);
- bool is_selecting_identifiers_on_hover_enabled() const;
-
void set_context_menu_enabled(bool p_enable);
bool is_context_menu_enabled();
@@ -784,8 +763,6 @@ public:
bool is_menu_visible() const;
PopupMenu *get_menu() const;
- String get_text_for_lookup_completion();
-
virtual bool is_text_field() const override;
TextEdit();
~TextEdit();
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index 10e6642303..be711b4c4f 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -462,8 +462,6 @@ private:
void _gui_input(Ref<InputEvent> p_event);
void _notification(int p_what);
- Size2 get_minimum_size() const override;
-
void item_edited(int p_column, TreeItem *p_item, bool p_lmb = true);
void item_changed(int p_column, TreeItem *p_item);
void item_selected(int p_column, TreeItem *p_item);
@@ -721,6 +719,8 @@ public:
void set_allow_reselect(bool p_allow);
bool get_allow_reselect() const;
+ Size2 get_minimum_size() const override;
+
Tree();
~Tree();
};