summaryrefslogtreecommitdiffstats
path: root/scene/gui/tab_container.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui/tab_container.cpp')
-rw-r--r--scene/gui/tab_container.cpp98
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));
}