diff options
Diffstat (limited to 'scene/gui/tab_container.cpp')
-rw-r--r-- | scene/gui/tab_container.cpp | 98 |
1 files changed, 72 insertions, 26 deletions
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index 741b38a35a..d0c3f3d65e 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -30,9 +30,6 @@ #include "tab_container.h" -#include "scene/gui/box_container.h" -#include "scene/gui/label.h" -#include "scene/gui/texture_rect.h" #include "scene/theme/theme_db.h" int TabContainer::_get_tab_height() const { @@ -150,9 +147,7 @@ void TabContainer::_notification(int p_what) { if (get_tab_count() > 0) { _refresh_tab_names(); } - } break; - case NOTIFICATION_POST_ENTER_TREE: { if (setup_current_tab >= -1) { set_current_tab(setup_current_tab); setup_current_tab = -2; @@ -194,6 +189,25 @@ void TabContainer::_notification(int p_what) { } } break; + case NOTIFICATION_VISIBILITY_CHANGED: { + if (!is_visible() || setup_current_tab > -2) { + return; + } + + updating_visibility = true; + + // As the visibility change notification will be triggered for all children soon after, + // beat it to the punch and make sure that the correct node is the only one visible first. + // Otherwise, it can prevent a tab change done right before this container was made visible. + Vector<Control *> controls = _get_tab_controls(); + int current = get_current_tab(); + for (int i = 0; i < controls.size(); i++) { + controls[i]->set_visible(i == current); + } + + updating_visibility = false; + } break; + case NOTIFICATION_TRANSLATION_CHANGED: case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: case NOTIFICATION_THEME_CHANGED: { @@ -403,6 +417,7 @@ void TabContainer::move_tab_from_tab_container(TabContainer *p_from, int p_from_ // Get the tab properties before they get erased by the child removal. String tab_title = p_from->get_tab_title(p_from_index); + String tab_tooltip = p_from->get_tab_tooltip(p_from_index); Ref<Texture2D> tab_icon = p_from->get_tab_icon(p_from_index); Ref<Texture2D> tab_button_icon = p_from->get_tab_button_icon(p_from_index); bool tab_disabled = p_from->is_tab_disabled(p_from_index); @@ -420,6 +435,7 @@ void TabContainer::move_tab_from_tab_container(TabContainer *p_from, int p_from_ move_child(moving_tabc, get_tab_control(p_to_index)->get_index(false)); set_tab_title(p_to_index, tab_title); + set_tab_tooltip(p_to_index, tab_tooltip); set_tab_icon(p_to_index, tab_icon); set_tab_button_icon(p_to_index, tab_button_icon); set_tab_disabled(p_to_index, tab_disabled); @@ -500,6 +516,13 @@ void TabContainer::_on_tab_visibility_changed(Control *p_child) { updating_visibility = false; } +void TabContainer::_refresh_tab_indices() { + Vector<Control *> controls = _get_tab_controls(); + for (int i = 0; i < controls.size(); i++) { + controls[i]->set_meta("_tab_index", i); + } +} + void TabContainer::_refresh_tab_names() { Vector<Control *> controls = _get_tab_controls(); for (int i = 0; i < controls.size(); i++) { @@ -523,6 +546,7 @@ void TabContainer::add_child_notify(Node *p_child) { c->hide(); tab_bar->add_tab(p_child->get_name()); + c->set_meta("_tab_index", tab_bar->get_tab_count() - 1); _update_margins(); if (get_tab_count() == 1) { @@ -530,7 +554,7 @@ void TabContainer::add_child_notify(Node *p_child) { } p_child->connect("renamed", callable_mp(this, &TabContainer::_refresh_tab_names)); - p_child->connect(SNAME("visibility_changed"), callable_mp(this, &TabContainer::_on_tab_visibility_changed).bind(c)); + p_child->connect(SceneStringName(visibility_changed), callable_mp(this, &TabContainer::_on_tab_visibility_changed).bind(c)); // TabBar won't emit the "tab_changed" signal when not inside the tree. if (!is_inside_tree()) { @@ -547,19 +571,10 @@ void TabContainer::move_child_notify(Node *p_child) { Control *c = Object::cast_to<Control>(p_child); if (c && !c->is_set_as_top_level()) { - int old_idx = -1; - String tab_name = String(c->get_meta("_tab_name", c->get_name())); - - // Find the previous tab index of the control. - for (int i = 0; i < get_tab_count(); i++) { - if (get_tab_title(i) == tab_name) { - old_idx = i; - break; - } - } - - tab_bar->move_tab(old_idx, get_tab_idx_from_control(c)); + tab_bar->move_tab(c->get_meta("_tab_index"), get_tab_idx_from_control(c)); } + + _refresh_tab_indices(); } void TabContainer::remove_child_notify(Node *p_child) { @@ -578,7 +593,10 @@ void TabContainer::remove_child_notify(Node *p_child) { // As the child hasn't been removed yet, keep track of it so when the "tab_changed" signal is fired it can be ignored. children_removing.push_back(c); + tab_bar->remove_tab(idx); + _refresh_tab_indices(); + children_removing.erase(c); _update_margins(); @@ -586,9 +604,10 @@ void TabContainer::remove_child_notify(Node *p_child) { queue_redraw(); } + p_child->remove_meta("_tab_index"); p_child->remove_meta("_tab_name"); p_child->disconnect("renamed", callable_mp(this, &TabContainer::_refresh_tab_names)); - p_child->disconnect(SNAME("visibility_changed"), callable_mp(this, &TabContainer::_on_tab_visibility_changed)); + p_child->disconnect(SceneStringName(visibility_changed), callable_mp(this, &TabContainer::_on_tab_visibility_changed)); // TabBar won't emit the "tab_changed" signal when not inside the tree. if (!is_inside_tree()) { @@ -609,6 +628,7 @@ void TabContainer::set_current_tab(int p_current) { setup_current_tab = p_current; return; } + tab_bar->set_current_tab(p_current); } @@ -760,16 +780,22 @@ void TabContainer::set_tab_title(int p_tab, const String &p_title) { child->set_meta("_tab_name", p_title); } - _update_margins(); - if (!get_clip_tabs()) { - update_minimum_size(); - } + _repaint(); + queue_redraw(); } String TabContainer::get_tab_title(int p_tab) const { return tab_bar->get_tab_title(p_tab); } +void TabContainer::set_tab_tooltip(int p_tab, const String &p_tooltip) { + tab_bar->set_tab_tooltip(p_tab, p_tooltip); +} + +String TabContainer::get_tab_tooltip(int p_tab) const { + return tab_bar->get_tab_tooltip(p_tab); +} + void TabContainer::set_tab_icon(int p_tab, const Ref<Texture2D> &p_icon) { if (tab_bar->get_tab_icon(p_tab) == p_icon) { return; @@ -779,12 +805,29 @@ void TabContainer::set_tab_icon(int p_tab, const Ref<Texture2D> &p_icon) { _update_margins(); _repaint(); + queue_redraw(); } Ref<Texture2D> TabContainer::get_tab_icon(int p_tab) const { return tab_bar->get_tab_icon(p_tab); } +void TabContainer::set_tab_icon_max_width(int p_tab, int p_width) { + if (tab_bar->get_tab_icon_max_width(p_tab) == p_width) { + return; + } + + tab_bar->set_tab_icon_max_width(p_tab, p_width); + + _update_margins(); + _repaint(); + queue_redraw(); +} + +int TabContainer::get_tab_icon_max_width(int p_tab) const { + return tab_bar->get_tab_icon_max_width(p_tab); +} + void TabContainer::set_tab_disabled(int p_tab, bool p_disabled) { if (tab_bar->is_tab_disabled(p_tab) == p_disabled) { return; @@ -871,8 +914,7 @@ Size2 TabContainer::get_minimum_size() const { } Size2 cms = c->get_combined_minimum_size(); - largest_child_min_size.x = MAX(largest_child_min_size.x, cms.x); - largest_child_min_size.y = MAX(largest_child_min_size.y, cms.y); + largest_child_min_size = largest_child_min_size.max(cms); } ms.y += largest_child_min_size.y; @@ -978,8 +1020,12 @@ void TabContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("is_all_tabs_in_front"), &TabContainer::is_all_tabs_in_front); ClassDB::bind_method(D_METHOD("set_tab_title", "tab_idx", "title"), &TabContainer::set_tab_title); ClassDB::bind_method(D_METHOD("get_tab_title", "tab_idx"), &TabContainer::get_tab_title); + ClassDB::bind_method(D_METHOD("set_tab_tooltip", "tab_idx", "tooltip"), &TabContainer::set_tab_tooltip); + ClassDB::bind_method(D_METHOD("get_tab_tooltip", "tab_idx"), &TabContainer::get_tab_tooltip); ClassDB::bind_method(D_METHOD("set_tab_icon", "tab_idx", "icon"), &TabContainer::set_tab_icon); ClassDB::bind_method(D_METHOD("get_tab_icon", "tab_idx"), &TabContainer::get_tab_icon); + ClassDB::bind_method(D_METHOD("set_tab_icon_max_width", "tab_idx", "width"), &TabContainer::set_tab_icon_max_width); + ClassDB::bind_method(D_METHOD("get_tab_icon_max_width", "tab_idx"), &TabContainer::get_tab_icon_max_width); ClassDB::bind_method(D_METHOD("set_tab_disabled", "tab_idx", "disabled"), &TabContainer::set_tab_disabled); ClassDB::bind_method(D_METHOD("is_tab_disabled", "tab_idx"), &TabContainer::is_tab_disabled); ClassDB::bind_method(D_METHOD("set_tab_hidden", "tab_idx", "hidden"), &TabContainer::set_tab_hidden); @@ -1075,5 +1121,5 @@ TabContainer::TabContainer() { tab_bar->connect("tab_button_pressed", callable_mp(this, &TabContainer::_on_tab_button_pressed)); tab_bar->connect("active_tab_rearranged", callable_mp(this, &TabContainer::_on_active_tab_rearranged)); - connect("mouse_exited", callable_mp(this, &TabContainer::_on_mouse_exited)); + connect(SceneStringName(mouse_exited), callable_mp(this, &TabContainer::_on_mouse_exited)); } |