summaryrefslogtreecommitdiffstats
path: root/scene/gui
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui')
-rw-r--r--scene/gui/code_edit.cpp2
-rw-r--r--scene/gui/control.cpp5
-rw-r--r--scene/gui/control.h1
-rw-r--r--scene/gui/graph_edit.cpp8
-rw-r--r--scene/gui/item_list.cpp16
-rw-r--r--scene/gui/line_edit.cpp8
-rw-r--r--scene/gui/popup_menu.compat.inc9
-rw-r--r--scene/gui/popup_menu.cpp18
-rw-r--r--scene/gui/popup_menu.h3
-rw-r--r--scene/gui/tab_bar.cpp91
-rw-r--r--scene/gui/tab_bar.h10
-rw-r--r--scene/gui/tab_container.cpp28
-rw-r--r--scene/gui/tab_container.h9
-rw-r--r--scene/gui/text_edit.cpp12
-rw-r--r--scene/gui/text_edit.h4
-rw-r--r--scene/gui/tree.cpp2
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"));
}
}