Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion doc/classes/TextEdit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1370,6 +1370,9 @@
The syntax highlighter to use.
[b]Note:[/b] A [SyntaxHighlighter] instance should not be used across multiple [TextEdit] nodes.
</member>
<member name="tab_moves_focus_enabled" type="bool" setter="set_tab_moves_focus_enabled" getter="is_tab_moves_focus_enabled" default="false">
If [code]true[/code], Tab key will move focus out of this [TextEdit]. Otherwise, pressing Tab will insert the "tab" character.
</member>
<member name="text" type="String" setter="set_text" getter="get_text" default="&quot;&quot;">
String value of the [TextEdit].
</member>
Expand Down Expand Up @@ -1525,7 +1528,10 @@
<constant name="MENU_EMOJI_AND_SYMBOL" value="30" enum="MenuItems">
Opens system emoji and symbol picker.
</constant>
<constant name="MENU_MAX" value="31" enum="MenuItems">
<constant name="MENU_TAB_MOVES_FOCUS" value="31" enum="MenuItems">
Toggles tab key behavior.
</constant>
<constant name="MENU_MAX" value="32" enum="MenuItems">
Represents the size of the [enum MenuItems] enum.
</constant>
<constant name="ACTION_NONE" value="0" enum="EditAction">
Expand Down
42 changes: 42 additions & 0 deletions editor/code_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -961,6 +961,11 @@ void CodeTextEditor::_text_editor_gui_input(const Ref<InputEvent> &p_event) {
accept_event();
return;
}
if (ED_IS_SHORTCUT("script_editor/toggle_tab_key_moves_focus", p_event)) {
set_tab_key_moving_focus(!is_tab_key_moving_focus());
accept_event();
return;
}
}
}
}
Expand Down Expand Up @@ -1561,6 +1566,7 @@ void CodeTextEditor::_update_text_editor_theme() {
error->add_theme_color_override(SceneStringName(font_color), error_color);
error_button->add_theme_color_override(SceneStringName(font_color), error_color);
warning_button->add_theme_color_override(SceneStringName(font_color), warning_color);
tab_moves_focus_button->add_theme_color_override(SceneStringName(font_color), warning_color);

_update_font_ligatures();
}
Expand Down Expand Up @@ -1617,6 +1623,11 @@ void CodeTextEditor::_warning_button_pressed() {
_set_show_errors_panel(false);
}

void CodeTextEditor::_tab_moves_focus_button_pressed() {
set_tab_key_moving_focus(false);
text_editor->grab_focus();
}

void CodeTextEditor::_zoom_popup_id_pressed(int p_idx) {
_zoom_to(zoom_button->get_popup()->get_item_metadata(p_idx));
}
Expand Down Expand Up @@ -1649,6 +1660,7 @@ void CodeTextEditor::_notification(int p_what) {
case NOTIFICATION_READY: {
set_error_count(0);
set_warning_count(0);
set_tab_key_moving_focus(EditorSettings::get_singleton()->get_project_metadata("code_text_edtior", "tab_key_moves_focus", false));
} break;

case NOTIFICATION_THEME_CHANGED: {
Expand Down Expand Up @@ -1802,6 +1814,23 @@ float CodeTextEditor::get_zoom_factor() {
return zoom_factor;
}

void CodeTextEditor::set_tab_key_moving_focus(bool p_enabled) {
if (is_tab_moving_focus == p_enabled) {
return;
}

is_tab_moving_focus = p_enabled;
tab_moves_focus_button->set_visible(p_enabled);
get_text_editor()->set_tab_moves_focus_enabled(p_enabled);

EditorSettings::get_singleton()->set_project_metadata("code_text_edtior", "tab_key_moves_focus", p_enabled);
EditorNode::get_singleton()->emit_signal(SNAME("script_tab_moves_focus"), p_enabled);
}

bool CodeTextEditor::is_tab_key_moving_focus() {
return is_tab_moving_focus;
}

void CodeTextEditor::_bind_methods() {
ADD_SIGNAL(MethodInfo("validate_script"));
ADD_SIGNAL(MethodInfo("load_theme_settings"));
Expand Down Expand Up @@ -1833,11 +1862,14 @@ void CodeTextEditor::update_toggle_scripts_button() {

CodeTextEditor::CodeTextEditor() {
code_complete_func = nullptr;
ED_SHORTCUT("script_editor/toggle_tab_key_moves_focus", TTRC("Toggle Tab Key Moves Focus"), KeyModifierMask::CMD_OR_CTRL | Key::M);
ED_SHORTCUT("script_editor/zoom_in", TTRC("Zoom In"), KeyModifierMask::CMD_OR_CTRL | Key::EQUAL);
ED_SHORTCUT("script_editor/zoom_out", TTRC("Zoom Out"), KeyModifierMask::CMD_OR_CTRL | Key::MINUS);
ED_SHORTCUT_ARRAY("script_editor/reset_zoom", TTRC("Reset Zoom"),
{ int32_t(KeyModifierMask::CMD_OR_CTRL | Key::KEY_0), int32_t(KeyModifierMask::CMD_OR_CTRL | Key::KP_0) });

EditorNode::get_singleton()->connect("script_tab_moves_focus", callable_mp(this, &CodeTextEditor::set_tab_key_moving_focus));

text_editor = memnew(CodeEdit);
add_child(text_editor);
text_editor->set_v_size_flags(SIZE_EXPAND_FILL);
Expand Down Expand Up @@ -1903,6 +1935,16 @@ CodeTextEditor::CodeTextEditor() {
warning_button->connect(SceneStringName(pressed), callable_mp(this, &CodeTextEditor::_warning_button_pressed));
warning_button->set_tooltip_text(TTR("Warnings"));

// Tab moves focus display
tab_moves_focus_button = memnew(Button);
tab_moves_focus_button->set_theme_type_variation("FlatButton");
status_bar->add_child(tab_moves_focus_button);
tab_moves_focus_button->set_v_size_flags(SIZE_EXPAND | SIZE_SHRINK_CENTER);
tab_moves_focus_button->set_default_cursor_shape(CURSOR_POINTING_HAND);
tab_moves_focus_button->set_text(TTR("Tab Moves Focus"));
tab_moves_focus_button->set_tooltip_text(vformat(TTR("Toggle Tab Key Moves Focus (%s)"), ED_GET_SHORTCUT("script_editor/toggle_tab_key_moves_focus")->get_as_text()));
tab_moves_focus_button->connect(SceneStringName(pressed), callable_mp(this, &CodeTextEditor::_tab_moves_focus_button_pressed));

status_bar->add_child(memnew(VSeparator));

// Zoom
Expand Down
6 changes: 6 additions & 0 deletions editor/code_editor.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ class CodeTextEditor : public VBoxContainer {
Control *toggle_scripts_list = nullptr;
Button *error_button = nullptr;
Button *warning_button = nullptr;
Button *tab_moves_focus_button = nullptr;
bool is_tab_moving_focus = false;

MenuButton *zoom_button = nullptr;
Label *line_and_col_txt = nullptr;
Expand Down Expand Up @@ -215,6 +217,7 @@ class CodeTextEditor : public VBoxContainer {

void _error_button_pressed();
void _warning_button_pressed();
void _tab_moves_focus_button_pressed();
void _set_show_errors_panel(bool p_show);
void _set_show_warnings_panel(bool p_show);
void _error_pressed(const Ref<InputEvent> &p_event);
Expand Down Expand Up @@ -271,6 +274,9 @@ class CodeTextEditor : public VBoxContainer {
bool is_previewing_navigation_change() const;
void set_preview_navigation_change(bool p_preview);

void set_tab_key_moving_focus(bool p_enabled);
bool is_tab_key_moving_focus();

void set_error_count(int p_error_count);
void set_warning_count(int p_warning_count);

Expand Down
1 change: 1 addition & 0 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6736,6 +6736,7 @@ void EditorNode::_bind_methods() {

ADD_SIGNAL(MethodInfo("request_help_search"));
ADD_SIGNAL(MethodInfo("script_add_function_request", PropertyInfo(Variant::OBJECT, "obj"), PropertyInfo(Variant::STRING, "function"), PropertyInfo(Variant::PACKED_STRING_ARRAY, "args")));
ADD_SIGNAL(MethodInfo("script_tab_moves_focus", PropertyInfo(Variant::BOOL, "toggled_on")));
ADD_SIGNAL(MethodInfo("resource_saved", PropertyInfo(Variant::OBJECT, "obj")));
ADD_SIGNAL(MethodInfo("scene_saved", PropertyInfo(Variant::STRING, "path")));
ADD_SIGNAL(MethodInfo("scene_changed"));
Expand Down
10 changes: 10 additions & 0 deletions editor/editor_properties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,13 @@ void EditorPropertyMultilineText::_big_text_changed() {
emit_changed(get_edited_property(), big_text->get_text(), "", true);
}

void EditorPropertyMultilineText::_big_text_dialog_visibility_changed() {
if (big_text_dialog->is_visible()) {
return;
}
text->set_tab_moves_focus_enabled(big_text->is_tab_moves_focus_enabled());
}

void EditorPropertyMultilineText::_text_changed() {
text->set_tooltip_text(get_tooltip_string(text->get_text()));
emit_changed(get_edited_property(), text->get_text(), "", true);
Expand All @@ -175,13 +182,15 @@ void EditorPropertyMultilineText::_open_big_text() {
big_text->connect(SceneStringName(text_changed), callable_mp(this, &EditorPropertyMultilineText::_big_text_changed));
big_text->set_line_wrapping_mode(TextEdit::LineWrappingMode::LINE_WRAPPING_BOUNDARY);
big_text_dialog = memnew(AcceptDialog);
big_text_dialog->connect(SceneStringName(visibility_changed), callable_mp(this, &EditorPropertyMultilineText::_big_text_dialog_visibility_changed));
big_text_dialog->add_child(big_text);
big_text_dialog->set_title(TTR("Edit Text:"));
add_child(big_text_dialog);
}

big_text_dialog->popup_centered_clamped(Size2(1000, 900) * EDSCALE, 0.8);
big_text->set_text(text->get_text());
big_text->set_tab_moves_focus_enabled(text->is_tab_moves_focus_enabled());
big_text->grab_focus();
}

Expand Down Expand Up @@ -232,6 +241,7 @@ EditorPropertyMultilineText::EditorPropertyMultilineText(bool p_expression) {
text = memnew(TextEdit);
text->connect(SceneStringName(text_changed), callable_mp(this, &EditorPropertyMultilineText::_text_changed));
text->set_line_wrapping_mode(TextEdit::LineWrappingMode::LINE_WRAPPING_BOUNDARY);
text->set_tab_moves_focus_enabled(true);
add_focusable(text);
hb->add_child(text);
text->set_h_size_flags(SIZE_EXPAND_FILL);
Expand Down
1 change: 1 addition & 0 deletions editor/editor_properties.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class EditorPropertyMultilineText : public EditorProperty {
void _big_text_changed();
void _text_changed();
void _open_big_text();
void _big_text_dialog_visibility_changed();
bool expression = false;

protected:
Expand Down
13 changes: 13 additions & 0 deletions scene/gui/code_edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,19 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
}

/* MISC */
if (is_tab_moves_focus_enabled()) {
if (k->is_action("ui_focus_next", true)) {
find_next_valid_focus()->grab_focus();
accept_event();
return;
}
if (k->is_action("ui_focus_prev", true)) {
find_prev_valid_focus()->grab_focus();
accept_event();
return;
}
}

if (!code_hint.is_empty() && k->is_action("ui_cancel", true)) {
set_code_hint("");
accept_event();
Expand Down
36 changes: 36 additions & 0 deletions scene/gui/text_edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2126,6 +2126,19 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {

// Check and handle all built-in shortcuts.

if (is_tab_moves_focus_enabled()) {
if (k->is_action("ui_focus_next", true)) {
find_next_valid_focus()->grab_focus();
accept_event();
return;
}
if (k->is_action("ui_focus_prev", true)) {
find_prev_valid_focus()->grab_focus();
accept_event();
return;
}
}

// NEWLINES.
if (k->is_action("ui_text_newline_above", true)) {
_new_line(false, true);
Expand Down Expand Up @@ -3378,6 +3391,18 @@ bool TextEdit::is_empty_selection_clipboard_enabled() const {
return empty_selection_clipboard_enabled;
}

void TextEdit::set_tab_moves_focus_enabled(bool p_enabled) {
tab_moves_focus_enabled = p_enabled;

if (menu) {
menu->set_item_checked(menu->get_item_index(MENU_TAB_MOVES_FOCUS), p_enabled);
}
}

bool TextEdit::is_tab_moves_focus_enabled() const {
return tab_moves_focus_enabled;
}

// Text manipulation
void TextEdit::clear() {
setting_text = true;
Expand Down Expand Up @@ -4024,6 +4049,9 @@ void TextEdit::menu_option(int p_option) {
case MENU_EMOJI_AND_SYMBOL: {
show_emoji_and_symbol_picker();
} break;
case MENU_TAB_MOVES_FOCUS: {
set_tab_moves_focus_enabled(!is_tab_moves_focus_enabled());
} break;
}
}

Expand Down Expand Up @@ -6519,6 +6547,9 @@ void TextEdit::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_empty_selection_clipboard_enabled", "enabled"), &TextEdit::set_empty_selection_clipboard_enabled);
ClassDB::bind_method(D_METHOD("is_empty_selection_clipboard_enabled"), &TextEdit::is_empty_selection_clipboard_enabled);

ClassDB::bind_method(D_METHOD("set_tab_moves_focus_enabled", "enabled"), &TextEdit::set_tab_moves_focus_enabled);
ClassDB::bind_method(D_METHOD("is_tab_moves_focus_enabled"), &TextEdit::is_tab_moves_focus_enabled);

// Text manipulation
ClassDB::bind_method(D_METHOD("clear"), &TextEdit::clear);

Expand Down Expand Up @@ -6599,6 +6630,7 @@ void TextEdit::_bind_methods() {
BIND_ENUM_CONSTANT(MENU_INSERT_WJ);
BIND_ENUM_CONSTANT(MENU_INSERT_SHY);
BIND_ENUM_CONSTANT(MENU_EMOJI_AND_SYMBOL);
BIND_ENUM_CONSTANT(MENU_TAB_MOVES_FOCUS);
BIND_ENUM_CONSTANT(MENU_MAX);

/* Versioning */
Expand Down Expand Up @@ -6915,6 +6947,7 @@ void TextEdit::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "virtual_keyboard_enabled"), "set_virtual_keyboard_enabled", "is_virtual_keyboard_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "middle_mouse_paste_enabled"), "set_middle_mouse_paste_enabled", "is_middle_mouse_paste_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "empty_selection_clipboard_enabled"), "set_empty_selection_clipboard_enabled", "is_empty_selection_clipboard_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tab_moves_focus_enabled"), "set_tab_moves_focus_enabled", "is_tab_moves_focus_enabled");
ADD_PROPERTY(PropertyInfo(Variant::INT, "wrap_mode", PROPERTY_HINT_ENUM, "None,Boundary"), "set_line_wrapping_mode", "get_line_wrapping_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Arbitrary:1,Word:2,Word (Smart):3"), "set_autowrap_mode", "get_autowrap_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "indent_wrapped_lines"), "set_indent_wrapped_lines", "is_indent_wrapped_lines");
Expand Down Expand Up @@ -7378,6 +7411,8 @@ void TextEdit::_generate_context_menu() {
menu->add_separator();
menu->add_check_item(ETR("Display Control Characters"), MENU_DISPLAY_UCC);
menu->add_submenu_node_item(ETR("Insert Control Character"), menu_ctl, MENU_SUBMENU_INSERT_UCC);
menu->add_separator();
menu->add_check_item(ETR("Tab Key Moves Focus"), MENU_TAB_MOVES_FOCUS);

menu->connect(SceneStringName(id_pressed), callable_mp(this, &TextEdit::menu_option));
menu_dir->connect(SceneStringName(id_pressed), callable_mp(this, &TextEdit::menu_option));
Expand Down Expand Up @@ -7431,6 +7466,7 @@ void TextEdit::_update_context_menu() {
MENU_ITEM_CHECKED(menu_dir, MENU_DIR_LTR, text_direction == TEXT_DIRECTION_LTR)
MENU_ITEM_CHECKED(menu_dir, MENU_DIR_RTL, text_direction == TEXT_DIRECTION_RTL)
MENU_ITEM_CHECKED(menu, MENU_DISPLAY_UCC, draw_control_chars)
MENU_ITEM_CHECKED(menu, MENU_TAB_MOVES_FOCUS, tab_moves_focus_enabled)
MENU_ITEM_DISABLED(menu, MENU_SUBMENU_INSERT_UCC, !editable)

#undef MENU_ITEM_ACTION_DISABLED
Expand Down
5 changes: 5 additions & 0 deletions scene/gui/text_edit.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class TextEdit : public Control {
MENU_INSERT_WJ,
MENU_INSERT_SHY,
MENU_EMOJI_AND_SYMBOL,
MENU_TAB_MOVES_FOCUS,
MENU_MAX

};
Expand Down Expand Up @@ -318,6 +319,7 @@ class TextEdit : public Control {
bool virtual_keyboard_enabled = true;
bool middle_mouse_paste_enabled = true;
bool empty_selection_clipboard_enabled = true;
bool tab_moves_focus_enabled = false;

// Overridable actions.
String cut_copy_line = "";
Expand Down Expand Up @@ -780,6 +782,9 @@ class TextEdit : public Control {
void set_empty_selection_clipboard_enabled(bool p_enabled);
bool is_empty_selection_clipboard_enabled() const;

void set_tab_moves_focus_enabled(bool p_enabled);
bool is_tab_moves_focus_enabled() const;

// Text manipulation
void clear();

Expand Down