diff options
Diffstat (limited to 'scene/gui')
-rw-r--r-- | scene/gui/code_edit.cpp | 2 | ||||
-rw-r--r-- | scene/gui/control.cpp | 5 | ||||
-rw-r--r-- | scene/gui/control.h | 1 | ||||
-rw-r--r-- | scene/gui/graph_edit.cpp | 8 | ||||
-rw-r--r-- | scene/gui/item_list.cpp | 16 | ||||
-rw-r--r-- | scene/gui/line_edit.cpp | 8 | ||||
-rw-r--r-- | scene/gui/popup_menu.compat.inc | 9 | ||||
-rw-r--r-- | scene/gui/popup_menu.cpp | 18 | ||||
-rw-r--r-- | scene/gui/popup_menu.h | 3 | ||||
-rw-r--r-- | scene/gui/tab_bar.cpp | 91 | ||||
-rw-r--r-- | scene/gui/tab_bar.h | 10 | ||||
-rw-r--r-- | scene/gui/tab_container.cpp | 28 | ||||
-rw-r--r-- | scene/gui/tab_container.h | 9 | ||||
-rw-r--r-- | scene/gui/text_edit.cpp | 12 | ||||
-rw-r--r-- | scene/gui/text_edit.h | 4 | ||||
-rw-r--r-- | scene/gui/tree.cpp | 2 |
16 files changed, 191 insertions, 35 deletions
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index 6ef8eacfd0..d35d35d36d 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -433,7 +433,7 @@ void CodeEdit::gui_input(const Ref<InputEvent> &p_gui_input) { // Allow unicode handling if: // No modifiers are pressed (except Shift and CapsLock) - bool allow_unicode_handling = !(k->is_command_or_control_pressed() || k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_meta_pressed()); + bool allow_unicode_handling = !(k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_meta_pressed()); /* AUTO-COMPLETE */ if (code_completion_enabled && k->is_action("ui_text_completion_query", true)) { diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 4510de32a0..a258c1ffec 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -2307,6 +2307,10 @@ Control *Control::_get_focus_neighbor(Side p_side, int p_count) { return result; } +Control *Control::find_valid_focus_neighbor(Side p_side) const { + return const_cast<Control *>(this)->_get_focus_neighbor(p_side); +} + void Control::_window_find_focus_neighbor(const Vector2 &p_dir, Node *p_at, const Point2 *p_points, real_t p_min, real_t &r_closest_dist, Control **r_closest) { if (Object::cast_to<Viewport>(p_at)) { return; //bye @@ -3366,6 +3370,7 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("release_focus"), &Control::release_focus); ClassDB::bind_method(D_METHOD("find_prev_valid_focus"), &Control::find_prev_valid_focus); ClassDB::bind_method(D_METHOD("find_next_valid_focus"), &Control::find_next_valid_focus); + ClassDB::bind_method(D_METHOD("find_valid_focus_neighbor", "side"), &Control::find_valid_focus_neighbor); ClassDB::bind_method(D_METHOD("set_h_size_flags", "flags"), &Control::set_h_size_flags); ClassDB::bind_method(D_METHOD("get_h_size_flags"), &Control::get_h_size_flags); diff --git a/scene/gui/control.h b/scene/gui/control.h index e5ed076abf..abbdc42fa4 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -527,6 +527,7 @@ public: Control *find_next_valid_focus() const; Control *find_prev_valid_focus() const; + Control *find_valid_focus_neighbor(Side p_size) const; void set_focus_neighbor(Side p_side, const NodePath &p_neighbor); NodePath get_focus_neighbor(Side p_side) const; diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 7269ed516d..6e12e7f196 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -1155,7 +1155,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { // Snapping can be toggled temporarily by holding down Ctrl. // This is done here as to not toggle the grid when holding down Ctrl. - if (snapping_enabled ^ Input::get_singleton()->is_key_pressed(Key::CTRL)) { + if (snapping_enabled ^ Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL)) { pos = pos.snapped(Vector2(snapping_distance, snapping_distance)); } @@ -1214,7 +1214,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { } if (mb->get_button_index() == MouseButton::LEFT && !mb->is_pressed() && dragging) { - if (!just_selected && drag_accum == Vector2() && Input::get_singleton()->is_key_pressed(Key::CTRL)) { + if (!just_selected && drag_accum == Vector2() && Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL)) { // Deselect current node. for (int i = get_child_count() - 1; i >= 0; i--) { GraphElement *graph_element = Object::cast_to<GraphElement>(get_child(i)); @@ -1281,7 +1281,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { dragging = true; drag_accum = Vector2(); just_selected = !graph_element->is_selected(); - if (!graph_element->is_selected() && !Input::get_singleton()->is_key_pressed(Key::CTRL)) { + if (!graph_element->is_selected() && !Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL)) { for (int i = 0; i < get_child_count(); i++) { GraphElement *child_element = Object::cast_to<GraphElement>(get_child(i)); if (!child_element) { @@ -1314,7 +1314,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { // Left-clicked on empty space, start box select. box_selecting = true; box_selecting_from = mb->get_position(); - if (mb->is_ctrl_pressed()) { + if (mb->is_command_or_control_pressed()) { box_selection_mode_additive = true; prev_selected.clear(); for (int i = get_child_count() - 1; i >= 0; i--) { diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index e1fc7d7cd4..343301e9c4 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -1082,14 +1082,16 @@ void ItemList::_notification(int p_what) { first_visible_separator = lo; } - // Draw visible separators. - for (int i = first_visible_separator; i < separators.size(); i++) { - if (separators[i] > clip.position.y + clip.size.y) { - break; // done - } + // If not in thumbnails mode, draw visible separators. + if (icon_mode != ICON_MODE_TOP) { + for (int i = first_visible_separator; i < separators.size(); i++) { + if (separators[i] > clip.position.y + clip.size.y) { + break; // done + } - const int y = base_ofs.y + separators[i]; - draw_line(Vector2(theme_cache.panel_style->get_margin(SIDE_LEFT), y), Vector2(width, y), theme_cache.guide_color); + const int y = base_ofs.y + separators[i]; + draw_line(Vector2(theme_cache.panel_style->get_margin(SIDE_LEFT), y), Vector2(width, y), theme_cache.guide_color); + } } // Do a binary search to find the first item whose rect reaches below clip.position.y. diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 8746d4079a..100e0c4548 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -614,7 +614,7 @@ void LineEdit::gui_input(const Ref<InputEvent> &p_event) { // Allow unicode handling if: // * No Modifiers are pressed (except shift) - bool allow_unicode_handling = !(k->is_command_or_control_pressed() || k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_meta_pressed()); + bool allow_unicode_handling = !(k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_meta_pressed()); if (allow_unicode_handling && editable && k->get_unicode() >= 32) { // Handle Unicode if no modifiers are active. @@ -679,13 +679,13 @@ void LineEdit::drop_data(const Point2 &p_point, const Variant &p_data) { set_caret_at_pixel_pos(p_point.x); int caret_column_tmp = caret_column; bool is_inside_sel = selection.enabled && caret_column >= selection.begin && caret_column <= selection.end; - if (Input::get_singleton()->is_key_pressed(Key::CTRL)) { + if (Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL)) { is_inside_sel = selection.enabled && caret_column > selection.begin && caret_column < selection.end; } if (selection.drag_attempt) { selection.drag_attempt = false; if (!is_inside_sel) { - if (!Input::get_singleton()->is_key_pressed(Key::CTRL)) { + if (!Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL)) { if (caret_column_tmp > selection.end) { caret_column_tmp = caret_column_tmp - (selection.end - selection.begin); } @@ -1139,7 +1139,7 @@ void LineEdit::_notification(int p_what) { if (is_drag_successful()) { if (selection.drag_attempt) { selection.drag_attempt = false; - if (is_editable() && !Input::get_singleton()->is_key_pressed(Key::CTRL)) { + if (is_editable() && !Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL)) { selection_delete(); } else if (deselect_on_focus_loss_enabled) { deselect(); diff --git a/scene/gui/popup_menu.compat.inc b/scene/gui/popup_menu.compat.inc index ef74a17228..012d6a1334 100644 --- a/scene/gui/popup_menu.compat.inc +++ b/scene/gui/popup_menu.compat.inc @@ -31,16 +31,21 @@ #ifndef DISABLE_DEPRECATED void PopupMenu::_add_shortcut_bind_compat_36493(const Ref<Shortcut> &p_shortcut, int p_id, bool p_global) { - return add_shortcut(p_shortcut, p_id, p_global, false); + add_shortcut(p_shortcut, p_id, p_global, false); } void PopupMenu::_add_icon_shortcut_bind_compat_36493(const Ref<Texture2D> &p_icon, const Ref<Shortcut> &p_shortcut, int p_id, bool p_global) { - return add_icon_shortcut(p_icon, p_shortcut, p_id, p_global, false); + add_icon_shortcut(p_icon, p_shortcut, p_id, p_global, false); +} + +void PopupMenu::_clear_bind_compat_79965() { + clear(false); } void PopupMenu::_bind_compatibility_methods() { ClassDB::bind_compatibility_method(D_METHOD("add_shortcut", "shortcut", "id", "global"), &PopupMenu::_add_shortcut_bind_compat_36493, DEFVAL(-1), DEFVAL(false)); ClassDB::bind_compatibility_method(D_METHOD("add_icon_shortcut", "texture", "shortcut", "id", "global"), &PopupMenu::_add_icon_shortcut_bind_compat_36493, DEFVAL(-1), DEFVAL(false)); + ClassDB::bind_compatibility_method(D_METHOD("clear"), &PopupMenu::_clear_bind_compat_79965); } #endif diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index d64136a682..54fd8b8745 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -1908,10 +1908,18 @@ void PopupMenu::add_separator(const String &p_text, int p_id) { _menu_changed(); } -void PopupMenu::clear() { - for (int i = 0; i < items.size(); i++) { - if (items[i].shortcut.is_valid()) { - _unref_shortcut(items[i].shortcut); +void PopupMenu::clear(bool p_free_submenus) { + for (const Item &I : items) { + if (I.shortcut.is_valid()) { + _unref_shortcut(I.shortcut); + } + + if (p_free_submenus && !I.submenu.is_empty()) { + Node *submenu = get_node_or_null(I.submenu); + if (submenu) { + remove_child(submenu); + submenu->queue_free(); + } } } items.clear(); @@ -2236,7 +2244,7 @@ void PopupMenu::_bind_methods() { ClassDB::bind_method(D_METHOD("remove_item", "index"), &PopupMenu::remove_item); ClassDB::bind_method(D_METHOD("add_separator", "label", "id"), &PopupMenu::add_separator, DEFVAL(String()), DEFVAL(-1)); - ClassDB::bind_method(D_METHOD("clear"), &PopupMenu::clear); + ClassDB::bind_method(D_METHOD("clear", "free_submenus"), &PopupMenu::clear, DEFVAL(false)); ClassDB::bind_method(D_METHOD("set_hide_on_item_selection", "enable"), &PopupMenu::set_hide_on_item_selection); ClassDB::bind_method(D_METHOD("is_hide_on_item_selection"), &PopupMenu::is_hide_on_item_selection); diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index 72a579b90a..f123d08400 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -202,6 +202,7 @@ protected: #ifndef DISABLE_DEPRECATED void _add_shortcut_bind_compat_36493(const Ref<Shortcut> &p_shortcut, int p_id = -1, bool p_global = false); void _add_icon_shortcut_bind_compat_36493(const Ref<Texture2D> &p_icon, const Ref<Shortcut> &p_shortcut, int p_id = -1, bool p_global = false); + void _clear_bind_compat_79965(); static void _bind_compatibility_methods(); #endif @@ -296,7 +297,7 @@ public: void add_separator(const String &p_text = String(), int p_id = -1); - void clear(); + void clear(bool p_free_submenus = true); virtual String get_tooltip(const Point2 &p_pos) const; diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp index a9c16a9942..14eed4c7a2 100644 --- a/scene/gui/tab_bar.cpp +++ b/scene/gui/tab_bar.cpp @@ -290,6 +290,34 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) { } } } + + if (p_event->is_pressed()) { + Input *input = Input::get_singleton(); + Ref<InputEventJoypadMotion> joypadmotion_event = p_event; + Ref<InputEventJoypadButton> joypadbutton_event = p_event; + bool is_joypad_event = (joypadmotion_event.is_valid() || joypadbutton_event.is_valid()); + if (p_event->is_action("ui_right", true)) { + if (is_joypad_event) { + if (!input->is_action_just_pressed("ui_right", true)) { + return; + } + set_process_internal(true); + } + if (is_layout_rtl() ? select_previous_available() : select_next_available()) { + accept_event(); + } + } else if (p_event->is_action("ui_left", true)) { + if (is_joypad_event) { + if (!input->is_action_just_pressed("ui_left", true)) { + return; + } + set_process_internal(true); + } + if (is_layout_rtl() ? select_next_available() : select_previous_available()) { + accept_event(); + } + } + } } void TabBar::_shape(int p_tab) { @@ -307,6 +335,28 @@ void TabBar::_shape(int p_tab) { void TabBar::_notification(int p_what) { switch (p_what) { + case NOTIFICATION_INTERNAL_PROCESS: { + Input *input = Input::get_singleton(); + + if (input->is_action_just_released("ui_left") || input->is_action_just_released("ui_right")) { + gamepad_event_delay_ms = DEFAULT_GAMEPAD_EVENT_DELAY_MS; + set_process_internal(false); + return; + } + + gamepad_event_delay_ms -= get_process_delta_time(); + if (gamepad_event_delay_ms <= 0) { + gamepad_event_delay_ms = GAMEPAD_EVENT_REPEAT_RATE_MS + gamepad_event_delay_ms; + if (input->is_action_pressed("ui_right")) { + is_layout_rtl() ? select_previous_available() : select_next_available(); + } + + if (input->is_action_pressed("ui_left")) { + is_layout_rtl() ? select_next_available() : select_previous_available(); + } + } + } break; + case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: { queue_redraw(); } break; @@ -379,7 +429,7 @@ void TabBar::_notification(int p_what) { col = theme_cache.font_unselected_color; } - _draw_tab(sb, col, i, rtl ? size.width - ofs - tabs[i].size_cache : ofs); + _draw_tab(sb, col, i, rtl ? size.width - ofs - tabs[i].size_cache : ofs, false); } ofs += tabs[i].size_cache; @@ -390,7 +440,7 @@ void TabBar::_notification(int p_what) { Ref<StyleBox> sb = tabs[current].disabled ? theme_cache.tab_disabled_style : theme_cache.tab_selected_style; float x = rtl ? size.width - tabs[current].ofs_cache - tabs[current].size_cache : tabs[current].ofs_cache; - _draw_tab(sb, theme_cache.font_selected_color, current, x); + _draw_tab(sb, theme_cache.font_selected_color, current, x, has_focus()); } if (buttons_visible) { @@ -456,12 +506,16 @@ void TabBar::_notification(int p_what) { } } -void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_index, float p_x) { +void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_index, float p_x, bool p_focus) { RID ci = get_canvas_item(); bool rtl = is_layout_rtl(); Rect2 sb_rect = Rect2(p_x, 0, tabs[p_index].size_cache, get_size().height); p_tab_style->draw(ci, sb_rect); + if (p_focus) { + Ref<StyleBox> focus_style = theme_cache.tab_focus_style; + focus_style->draw(ci, sb_rect); + } p_x += rtl ? tabs[p_index].size_cache - p_tab_style->get_margin(SIDE_LEFT) : p_tab_style->get_margin(SIDE_LEFT); @@ -607,6 +661,33 @@ int TabBar::get_hovered_tab() const { return hover; } +bool TabBar::select_previous_available() { + const int offset_end = (get_current_tab() + 1); + for (int i = 1; i < offset_end; i++) { + int target_tab = get_current_tab() - i; + if (target_tab < 0) { + target_tab += get_tab_count(); + } + if (!is_tab_disabled(target_tab)) { + set_current_tab(target_tab); + return true; + } + } + return false; +} + +bool TabBar::select_next_available() { + const int offset_end = (get_tab_count() - get_current_tab()); + for (int i = 1; i < offset_end; i++) { + int target_tab = (get_current_tab() + i) % get_tab_count(); + if (!is_tab_disabled(target_tab)) { + set_current_tab(target_tab); + return true; + } + } + return false; +} + int TabBar::get_tab_offset() const { return offset; } @@ -1589,6 +1670,8 @@ void TabBar::_bind_methods() { ClassDB::bind_method(D_METHOD("set_current_tab", "tab_idx"), &TabBar::set_current_tab); ClassDB::bind_method(D_METHOD("get_current_tab"), &TabBar::get_current_tab); ClassDB::bind_method(D_METHOD("get_previous_tab"), &TabBar::get_previous_tab); + ClassDB::bind_method(D_METHOD("select_previous_available"), &TabBar::select_previous_available); + ClassDB::bind_method(D_METHOD("select_next_available"), &TabBar::select_next_available); ClassDB::bind_method(D_METHOD("set_tab_title", "tab_idx", "title"), &TabBar::set_tab_title); ClassDB::bind_method(D_METHOD("get_tab_title", "tab_idx"), &TabBar::get_tab_title); ClassDB::bind_method(D_METHOD("set_tab_text_direction", "tab_idx", "direction"), &TabBar::set_tab_text_direction); @@ -1674,6 +1757,7 @@ void TabBar::_bind_methods() { BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabBar, tab_hovered_style, "tab_hovered"); BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabBar, tab_selected_style, "tab_selected"); BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabBar, tab_disabled_style, "tab_disabled"); + BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabBar, tab_focus_style, "tab_focus"); BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TabBar, increment_icon, "increment"); BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TabBar, increment_hl_icon, "increment_highlight"); @@ -1699,5 +1783,6 @@ void TabBar::_bind_methods() { TabBar::TabBar() { set_size(Size2(get_size().width, get_minimum_size().height)); + set_focus_mode(FOCUS_ALL); connect("mouse_exited", callable_mp(this, &TabBar::_on_mouse_exited)); } diff --git a/scene/gui/tab_bar.h b/scene/gui/tab_bar.h index d89b1866bf..b79c170a7b 100644 --- a/scene/gui/tab_bar.h +++ b/scene/gui/tab_bar.h @@ -107,6 +107,10 @@ private: bool scroll_to_selected = true; int tabs_rearrange_group = -1; + const float DEFAULT_GAMEPAD_EVENT_DELAY_MS = 0.5; + const float GAMEPAD_EVENT_REPEAT_RATE_MS = 1.0 / 20; + float gamepad_event_delay_ms = DEFAULT_GAMEPAD_EVENT_DELAY_MS; + struct ThemeCache { int h_separation = 0; int icon_max_width = 0; @@ -115,6 +119,7 @@ private: Ref<StyleBox> tab_hovered_style; Ref<StyleBox> tab_selected_style; Ref<StyleBox> tab_disabled_style; + Ref<StyleBox> tab_focus_style; Ref<Texture2D> increment_icon; Ref<Texture2D> increment_hl_icon; @@ -148,7 +153,7 @@ private: void _on_mouse_exited(); void _shape(int p_tab); - void _draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_index, float p_x); + void _draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_index, float p_x, bool p_focus); protected: virtual void gui_input(const Ref<InputEvent> &p_event) override; @@ -214,6 +219,9 @@ public: int get_previous_tab() const; int get_hovered_tab() const; + bool select_previous_available(); + bool select_next_available(); + int get_tab_offset() const; bool get_offset_buttons_visible() const; diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 14bc87ad40..b757b516d1 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -195,6 +195,7 @@ void TabContainer::_on_theme_changed() { tab_bar->add_theme_style_override(SNAME("tab_hovered"), theme_cache.tab_hovered_style); tab_bar->add_theme_style_override(SNAME("tab_selected"), theme_cache.tab_selected_style); tab_bar->add_theme_style_override(SNAME("tab_disabled"), theme_cache.tab_disabled_style); + tab_bar->add_theme_style_override(SNAME("tab_focus"), theme_cache.tab_focus_style); tab_bar->add_theme_icon_override(SNAME("increment"), theme_cache.increment_icon); tab_bar->add_theme_icon_override(SNAME("increment_highlight"), theme_cache.increment_hl_icon); @@ -585,6 +586,10 @@ void TabContainer::remove_child_notify(Node *p_child) { } } +TabBar *TabContainer::get_tab_bar() const { + return tab_bar; +} + int TabContainer::get_tab_count() const { return tab_bar->get_tab_count(); } @@ -601,6 +606,14 @@ int TabContainer::get_previous_tab() const { return tab_bar->get_previous_tab(); } +bool TabContainer::select_previous_available() { + return tab_bar->select_previous_available(); +} + +bool TabContainer::select_next_available() { + return tab_bar->select_next_available(); +} + Control *TabContainer::get_tab_control(int p_idx) const { Vector<Control *> controls = _get_tab_controls(); if (p_idx >= 0 && p_idx < controls.size()) { @@ -645,6 +658,14 @@ TabBar::AlignmentMode TabContainer::get_tab_alignment() const { return tab_bar->get_tab_alignment(); } +void TabContainer::set_tab_focus_mode(Control::FocusMode p_focus_mode) { + tab_bar->set_focus_mode(p_focus_mode); +} + +Control::FocusMode TabContainer::get_tab_focus_mode() const { + return tab_bar->get_focus_mode(); +} + void TabContainer::set_clip_tabs(bool p_clip_tabs) { tab_bar->set_clip_tabs(p_clip_tabs); } @@ -911,7 +932,10 @@ void TabContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_current_tab", "tab_idx"), &TabContainer::set_current_tab); ClassDB::bind_method(D_METHOD("get_current_tab"), &TabContainer::get_current_tab); ClassDB::bind_method(D_METHOD("get_previous_tab"), &TabContainer::get_previous_tab); + ClassDB::bind_method(D_METHOD("select_previous_available"), &TabContainer::select_previous_available); + ClassDB::bind_method(D_METHOD("select_next_available"), &TabContainer::select_next_available); ClassDB::bind_method(D_METHOD("get_current_tab_control"), &TabContainer::get_current_tab_control); + ClassDB::bind_method(D_METHOD("get_tab_bar"), &TabContainer::get_tab_bar); ClassDB::bind_method(D_METHOD("get_tab_control", "tab_idx"), &TabContainer::get_tab_control); ClassDB::bind_method(D_METHOD("set_tab_alignment", "alignment"), &TabContainer::set_tab_alignment); ClassDB::bind_method(D_METHOD("get_tab_alignment"), &TabContainer::get_tab_alignment); @@ -943,6 +967,8 @@ void TabContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_tabs_rearrange_group"), &TabContainer::get_tabs_rearrange_group); ClassDB::bind_method(D_METHOD("set_use_hidden_tabs_for_min_size", "enabled"), &TabContainer::set_use_hidden_tabs_for_min_size); ClassDB::bind_method(D_METHOD("get_use_hidden_tabs_for_min_size"), &TabContainer::get_use_hidden_tabs_for_min_size); + ClassDB::bind_method(D_METHOD("set_tab_focus_mode", "focus_mode"), &TabContainer::set_tab_focus_mode); + ClassDB::bind_method(D_METHOD("get_tab_focus_mode"), &TabContainer::get_tab_focus_mode); ADD_SIGNAL(MethodInfo("active_tab_rearranged", PropertyInfo(Variant::INT, "idx_to"))); ADD_SIGNAL(MethodInfo("tab_changed", PropertyInfo(Variant::INT, "tab"))); @@ -960,6 +986,7 @@ void TabContainer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_to_rearrange_enabled"), "set_drag_to_rearrange_enabled", "get_drag_to_rearrange_enabled"); ADD_PROPERTY(PropertyInfo(Variant::INT, "tabs_rearrange_group"), "set_tabs_rearrange_group", "get_tabs_rearrange_group"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_hidden_tabs_for_min_size"), "set_use_hidden_tabs_for_min_size", "get_use_hidden_tabs_for_min_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_focus_mode", PROPERTY_HINT_ENUM, "None,Click,All"), "set_tab_focus_mode", "get_tab_focus_mode"); BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TabContainer, side_margin); @@ -977,6 +1004,7 @@ void TabContainer::_bind_methods() { BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabContainer, tab_hovered_style, "tab_hovered"); BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabContainer, tab_selected_style, "tab_selected"); BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabContainer, tab_disabled_style, "tab_disabled"); + BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, TabContainer, tab_focus_style, "tab_focus"); BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TabContainer, increment_icon, "increment"); BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_ICON, TabContainer, increment_hl_icon, "increment_highlight"); diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index 2bcc640d05..a831416612 100644 --- a/scene/gui/tab_container.h +++ b/scene/gui/tab_container.h @@ -66,6 +66,7 @@ class TabContainer : public Container { Ref<StyleBox> tab_hovered_style; Ref<StyleBox> tab_selected_style; Ref<StyleBox> tab_disabled_style; + Ref<StyleBox> tab_focus_style; Ref<Texture2D> increment_icon; Ref<Texture2D> increment_hl_icon; @@ -111,12 +112,17 @@ protected: static void _bind_methods(); public: + TabBar *get_tab_bar() const; + int get_tab_idx_at_point(const Point2 &p_point) const; int get_tab_idx_from_control(Control *p_child) const; void set_tab_alignment(TabBar::AlignmentMode p_alignment); TabBar::AlignmentMode get_tab_alignment() const; + void set_tab_focus_mode(FocusMode p_focus_mode); + FocusMode get_tab_focus_mode() const; + void set_clip_tabs(bool p_clip_tabs); bool get_clip_tabs() const; @@ -149,6 +155,9 @@ public: int get_current_tab() const; int get_previous_tab() const; + bool select_previous_available(); + bool select_next_available(); + Control *get_tab_control(int p_idx) const; Control *get_current_tab_control() const; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 98bedd4493..9e159cd303 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1598,7 +1598,7 @@ void TextEdit::_notification(int p_what) { if (is_drag_successful()) { if (selection_drag_attempt) { selection_drag_attempt = false; - if (is_editable() && !Input::get_singleton()->is_key_pressed(Key::CTRL)) { + if (is_editable() && !Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL)) { delete_selection(); } else if (deselect_on_focus_loss_enabled) { deselect(); @@ -2049,7 +2049,7 @@ void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { // Allow unicode handling if: // * No modifiers are pressed (except Shift and CapsLock) - bool allow_unicode_handling = !(k->is_command_or_control_pressed() || k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_meta_pressed()); + bool allow_unicode_handling = !(k->is_ctrl_pressed() || k->is_alt_pressed() || k->is_meta_pressed()); // Check and handle all built-in shortcuts. @@ -3077,13 +3077,13 @@ void TextEdit::drop_data(const Point2 &p_point, const Variant &p_data) { int caret_column_tmp = pos.x; if (selection_drag_attempt) { selection_drag_attempt = false; - if (!is_mouse_over_selection(!Input::get_singleton()->is_key_pressed(Key::CTRL))) { + if (!is_mouse_over_selection(!Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL))) { // Set caret back at selection for undo / redo. set_caret_line(get_selection_to_line(), false, false); set_caret_column(get_selection_to_column()); begin_complex_operation(); - if (!Input::get_singleton()->is_key_pressed(Key::CTRL)) { + if (!Input::get_singleton()->is_key_pressed(Key::CMD_OR_CTRL)) { if (caret_row_tmp > get_selection_to_line()) { caret_row_tmp = caret_row_tmp - (get_selection_to_line() - get_selection_from_line()); } else if (caret_row_tmp == get_selection_to_line() && caret_column_tmp >= get_selection_to_column()) { @@ -6018,6 +6018,10 @@ bool TextEdit::is_drawing_spaces() const { return draw_spaces; } +Color TextEdit::get_font_color() const { + return theme_cache.font_color; +} + void TextEdit::_bind_methods() { /* Internal. */ diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 7be58bd927..56d5b67e0b 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -41,8 +41,6 @@ class TextEdit : public Control { GDCLASS(TextEdit, Control); - friend class CodeHighlighter; - public: /* Edit Actions. */ enum EditAction { @@ -1029,6 +1027,8 @@ public: void set_draw_spaces(bool p_enabled); bool is_drawing_spaces() const; + Color get_font_color() const; + TextEdit(const String &p_placeholder = String()); }; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 4ed52bd465..e2b16cdd66 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -3815,7 +3815,7 @@ void Tree::gui_input(const Ref<InputEvent> &p_event) { } if (mb->get_button_index() == MouseButton::LEFT) { - if (get_item_at_position(mb->get_position()) == nullptr && !mb->is_shift_pressed() && !mb->is_ctrl_pressed() && !mb->is_command_or_control_pressed()) { + if (get_item_at_position(mb->get_position()) == nullptr && !mb->is_shift_pressed() && !mb->is_command_or_control_pressed()) { emit_signal(SNAME("nothing_selected")); } } |