|
|
|
@ -42,6 +42,13 @@ Rect2 TabContainer::_get_tab_rect() const {
|
|
|
|
return rect;
|
|
|
|
return rect;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TabContainer::CachedTab &TabContainer::get_pending_tab(int p_idx) const {
|
|
|
|
|
|
|
|
if (p_idx >= pending_tabs.size()) {
|
|
|
|
|
|
|
|
pending_tabs.resize(p_idx + 1);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return pending_tabs.write[p_idx];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int TabContainer::_get_tab_height() const {
|
|
|
|
int TabContainer::_get_tab_height() const {
|
|
|
|
int height = 0;
|
|
|
|
int height = 0;
|
|
|
|
if (tabs_visible && get_tab_count() > 0) {
|
|
|
|
if (tabs_visible && get_tab_count() > 0) {
|
|
|
|
@ -133,6 +140,37 @@ void TabContainer::gui_input(const Ref<InputEvent> &p_event) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void TabContainer::_get_property_list(List<PropertyInfo> *p_list) const {
|
|
|
|
|
|
|
|
List<PropertyInfo> properties;
|
|
|
|
|
|
|
|
property_helper.get_property_list(&properties);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (PropertyInfo &info : properties) {
|
|
|
|
|
|
|
|
int index;
|
|
|
|
|
|
|
|
if (info.name.ends_with("title") && property_helper.is_property_valid(info.name, &index)) {
|
|
|
|
|
|
|
|
Control *tab_control = get_tab_control(index);
|
|
|
|
|
|
|
|
ERR_FAIL_NULL(tab_control);
|
|
|
|
|
|
|
|
if (get_tab_title(index) == tab_control->get_name()) {
|
|
|
|
|
|
|
|
// Don't store default title.
|
|
|
|
|
|
|
|
info.usage &= ~PROPERTY_USAGE_STORAGE;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
p_list->push_back(info);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool TabContainer::_property_get_revert(const StringName &p_name, Variant &r_property) const {
|
|
|
|
|
|
|
|
const String sname = p_name;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int index;
|
|
|
|
|
|
|
|
if (sname.ends_with("title") && property_helper.is_property_valid(sname, &index)) {
|
|
|
|
|
|
|
|
Control *tab_control = get_tab_control(index);
|
|
|
|
|
|
|
|
ERR_FAIL_NULL_V(tab_control, false);
|
|
|
|
|
|
|
|
r_property = String(tab_control->get_name());
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return property_helper.property_get_revert(p_name, r_property);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TabContainer::_notification(int p_what) {
|
|
|
|
void TabContainer::_notification(int p_what) {
|
|
|
|
switch (p_what) {
|
|
|
|
switch (p_what) {
|
|
|
|
case NOTIFICATION_ACCESSIBILITY_INVALIDATE: {
|
|
|
|
case NOTIFICATION_ACCESSIBILITY_INVALIDATE: {
|
|
|
|
@ -186,7 +224,21 @@ void TabContainer::_notification(int p_what) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
|
|
case NOTIFICATION_READY:
|
|
|
|
case NOTIFICATION_READY: {
|
|
|
|
|
|
|
|
for (int i = 0; i < pending_tabs.size(); i++) {
|
|
|
|
|
|
|
|
const CachedTab &tab = pending_tabs[i];
|
|
|
|
|
|
|
|
if (tab.has_title) {
|
|
|
|
|
|
|
|
set_tab_title(i, tab.title);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
set_tab_icon(i, tab.icon);
|
|
|
|
|
|
|
|
set_tab_disabled(i, tab.disabled);
|
|
|
|
|
|
|
|
set_tab_hidden(i, tab.hidden);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
pending_tabs.clear();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[fallthrough]];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
case NOTIFICATION_RESIZED: {
|
|
|
|
case NOTIFICATION_RESIZED: {
|
|
|
|
_update_margins();
|
|
|
|
_update_margins();
|
|
|
|
} break;
|
|
|
|
} break;
|
|
|
|
@ -580,9 +632,7 @@ void TabContainer::_refresh_tab_indices() {
|
|
|
|
void TabContainer::_refresh_tab_names() {
|
|
|
|
void TabContainer::_refresh_tab_names() {
|
|
|
|
Vector<Control *> controls = _get_tab_controls();
|
|
|
|
Vector<Control *> controls = _get_tab_controls();
|
|
|
|
for (int i = 0; i < controls.size(); i++) {
|
|
|
|
for (int i = 0; i < controls.size(); i++) {
|
|
|
|
if (!controls[i]->has_meta("_tab_name") && String(controls[i]->get_name()) != get_tab_title(i)) {
|
|
|
|
tab_bar->set_tab_title(i, controls[i]->get_meta("_tab_name", controls[i]->get_name()));
|
|
|
|
tab_bar->set_tab_title(i, controls[i]->get_name());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -599,7 +649,7 @@ void TabContainer::add_child_notify(Node *p_child) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
c->hide();
|
|
|
|
c->hide();
|
|
|
|
|
|
|
|
|
|
|
|
tab_bar->add_tab(p_child->get_name());
|
|
|
|
tab_bar->add_tab(p_child->get_meta("_tab_name", p_child->get_name()));
|
|
|
|
c->set_meta("_tab_index", tab_bar->get_tab_count() - 1);
|
|
|
|
c->set_meta("_tab_index", tab_bar->get_tab_count() - 1);
|
|
|
|
|
|
|
|
|
|
|
|
_update_margins();
|
|
|
|
_update_margins();
|
|
|
|
@ -615,6 +665,7 @@ void TabContainer::add_child_notify(Node *p_child) {
|
|
|
|
if (!is_inside_tree()) {
|
|
|
|
if (!is_inside_tree()) {
|
|
|
|
callable_mp(this, &TabContainer::_repaint).call_deferred();
|
|
|
|
callable_mp(this, &TabContainer::_repaint).call_deferred();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
notify_property_list_changed();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TabContainer::move_child_notify(Node *p_child) {
|
|
|
|
void TabContainer::move_child_notify(Node *p_child) {
|
|
|
|
@ -631,6 +682,7 @@ void TabContainer::move_child_notify(Node *p_child) {
|
|
|
|
|
|
|
|
|
|
|
|
_refresh_tab_indices();
|
|
|
|
_refresh_tab_indices();
|
|
|
|
queue_accessibility_update();
|
|
|
|
queue_accessibility_update();
|
|
|
|
|
|
|
|
notify_property_list_changed();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TabContainer::remove_child_notify(Node *p_child) {
|
|
|
|
void TabContainer::remove_child_notify(Node *p_child) {
|
|
|
|
@ -675,6 +727,7 @@ void TabContainer::remove_child_notify(Node *p_child) {
|
|
|
|
if (!is_inside_tree()) {
|
|
|
|
if (!is_inside_tree()) {
|
|
|
|
callable_mp(this, &TabContainer::_repaint).call_deferred();
|
|
|
|
callable_mp(this, &TabContainer::_repaint).call_deferred();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
notify_property_list_changed();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TabBar *TabContainer::get_tab_bar() const {
|
|
|
|
TabBar *TabContainer::get_tab_bar() const {
|
|
|
|
@ -828,6 +881,12 @@ bool TabContainer::is_all_tabs_in_front() const {
|
|
|
|
|
|
|
|
|
|
|
|
void TabContainer::set_tab_title(int p_tab, const String &p_title) {
|
|
|
|
void TabContainer::set_tab_title(int p_tab, const String &p_title) {
|
|
|
|
Control *child = get_tab_control(p_tab);
|
|
|
|
Control *child = get_tab_control(p_tab);
|
|
|
|
|
|
|
|
if (!child && !is_ready()) {
|
|
|
|
|
|
|
|
CachedTab &tab = get_pending_tab(p_tab);
|
|
|
|
|
|
|
|
tab.title = p_title;
|
|
|
|
|
|
|
|
tab.has_title = true;
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
ERR_FAIL_NULL(child);
|
|
|
|
ERR_FAIL_NULL(child);
|
|
|
|
|
|
|
|
|
|
|
|
if (tab_bar->get_tab_title(p_tab) == p_title) {
|
|
|
|
if (tab_bar->get_tab_title(p_tab) == p_title) {
|
|
|
|
@ -859,6 +918,12 @@ String TabContainer::get_tab_tooltip(int p_tab) const {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TabContainer::set_tab_icon(int p_tab, const Ref<Texture2D> &p_icon) {
|
|
|
|
void TabContainer::set_tab_icon(int p_tab, const Ref<Texture2D> &p_icon) {
|
|
|
|
|
|
|
|
Control *child = get_tab_control(p_tab);
|
|
|
|
|
|
|
|
if (!child && !is_ready()) {
|
|
|
|
|
|
|
|
get_pending_tab(p_tab).icon = p_icon;
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (tab_bar->get_tab_icon(p_tab) == p_icon) {
|
|
|
|
if (tab_bar->get_tab_icon(p_tab) == p_icon) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -891,6 +956,12 @@ int TabContainer::get_tab_icon_max_width(int p_tab) const {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TabContainer::set_tab_disabled(int p_tab, bool p_disabled) {
|
|
|
|
void TabContainer::set_tab_disabled(int p_tab, bool p_disabled) {
|
|
|
|
|
|
|
|
Control *child = get_tab_control(p_tab);
|
|
|
|
|
|
|
|
if (!child && !is_ready()) {
|
|
|
|
|
|
|
|
get_pending_tab(p_tab).disabled = p_disabled;
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (tab_bar->is_tab_disabled(p_tab) == p_disabled) {
|
|
|
|
if (tab_bar->is_tab_disabled(p_tab) == p_disabled) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -909,6 +980,10 @@ bool TabContainer::is_tab_disabled(int p_tab) const {
|
|
|
|
|
|
|
|
|
|
|
|
void TabContainer::set_tab_hidden(int p_tab, bool p_hidden) {
|
|
|
|
void TabContainer::set_tab_hidden(int p_tab, bool p_hidden) {
|
|
|
|
Control *child = get_tab_control(p_tab);
|
|
|
|
Control *child = get_tab_control(p_tab);
|
|
|
|
|
|
|
|
if (!child && !is_ready()) {
|
|
|
|
|
|
|
|
get_pending_tab(p_tab).hidden = p_hidden;
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
ERR_FAIL_NULL(child);
|
|
|
|
ERR_FAIL_NULL(child);
|
|
|
|
|
|
|
|
|
|
|
|
if (tab_bar->is_tab_hidden(p_tab) == p_hidden) {
|
|
|
|
if (tab_bar->is_tab_hidden(p_tab) == p_hidden) {
|
|
|
|
@ -1090,6 +1165,7 @@ void TabContainer::_bind_methods() {
|
|
|
|
ClassDB::bind_method(D_METHOD("are_tabs_visible"), &TabContainer::are_tabs_visible);
|
|
|
|
ClassDB::bind_method(D_METHOD("are_tabs_visible"), &TabContainer::are_tabs_visible);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_all_tabs_in_front", "is_front"), &TabContainer::set_all_tabs_in_front);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_all_tabs_in_front", "is_front"), &TabContainer::set_all_tabs_in_front);
|
|
|
|
ClassDB::bind_method(D_METHOD("is_all_tabs_in_front"), &TabContainer::is_all_tabs_in_front);
|
|
|
|
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("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("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("set_tab_tooltip", "tab_idx", "tooltip"), &TabContainer::set_tab_tooltip);
|
|
|
|
@ -1106,6 +1182,7 @@ void TabContainer::_bind_methods() {
|
|
|
|
ClassDB::bind_method(D_METHOD("get_tab_metadata", "tab_idx"), &TabContainer::get_tab_metadata);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_tab_metadata", "tab_idx"), &TabContainer::get_tab_metadata);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_tab_button_icon", "tab_idx", "icon"), &TabContainer::set_tab_button_icon);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_tab_button_icon", "tab_idx", "icon"), &TabContainer::set_tab_button_icon);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_tab_button_icon", "tab_idx"), &TabContainer::get_tab_button_icon);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_tab_button_icon", "tab_idx"), &TabContainer::get_tab_button_icon);
|
|
|
|
|
|
|
|
|
|
|
|
ClassDB::bind_method(D_METHOD("get_tab_idx_at_point", "point"), &TabContainer::get_tab_idx_at_point);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_tab_idx_at_point", "point"), &TabContainer::get_tab_idx_at_point);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_tab_idx_from_control", "control"), &TabContainer::get_tab_idx_from_control);
|
|
|
|
ClassDB::bind_method(D_METHOD("get_tab_idx_from_control", "control"), &TabContainer::get_tab_idx_from_control);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_popup", "popup"), &TabContainer::set_popup);
|
|
|
|
ClassDB::bind_method(D_METHOD("set_popup", "popup"), &TabContainer::set_popup);
|
|
|
|
@ -1190,6 +1267,16 @@ void TabContainer::_bind_methods() {
|
|
|
|
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_FONT, TabContainer, tab_font, "font");
|
|
|
|
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_FONT, TabContainer, tab_font, "font");
|
|
|
|
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_FONT_SIZE, TabContainer, tab_font_size, "font_size");
|
|
|
|
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_FONT_SIZE, TabContainer, tab_font_size, "font_size");
|
|
|
|
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TabContainer, outline_size);
|
|
|
|
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TabContainer, outline_size);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CachedTab defaults;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
base_property_helper.set_prefix("tab_");
|
|
|
|
|
|
|
|
base_property_helper.set_array_length_getter(&TabContainer::get_tab_count);
|
|
|
|
|
|
|
|
base_property_helper.register_property(PropertyInfo(Variant::STRING, "title"), defaults.title, &TabContainer::set_tab_title, &TabContainer::get_tab_title);
|
|
|
|
|
|
|
|
base_property_helper.register_property(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), defaults.icon, &TabContainer::set_tab_icon, &TabContainer::get_tab_icon);
|
|
|
|
|
|
|
|
base_property_helper.register_property(PropertyInfo(Variant::BOOL, "disabled"), defaults.disabled, &TabContainer::set_tab_disabled, &TabContainer::is_tab_disabled);
|
|
|
|
|
|
|
|
base_property_helper.register_property(PropertyInfo(Variant::BOOL, "hidden"), defaults.hidden, &TabContainer::set_tab_hidden, &TabContainer::is_tab_hidden);
|
|
|
|
|
|
|
|
PropertyListHelper::register_base_helper(&base_property_helper);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TabContainer::TabContainer() {
|
|
|
|
TabContainer::TabContainer() {
|
|
|
|
@ -1204,6 +1291,8 @@ TabContainer::TabContainer() {
|
|
|
|
tab_bar->connect("tab_selected", callable_mp(this, &TabContainer::_on_tab_selected));
|
|
|
|
tab_bar->connect("tab_selected", callable_mp(this, &TabContainer::_on_tab_selected));
|
|
|
|
tab_bar->connect("tab_button_pressed", callable_mp(this, &TabContainer::_on_tab_button_pressed));
|
|
|
|
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));
|
|
|
|
tab_bar->connect("active_tab_rearranged", callable_mp(this, &TabContainer::_on_active_tab_rearranged));
|
|
|
|
|
|
|
|
|
|
|
|
connect(SceneStringName(mouse_exited), callable_mp(this, &TabContainer::_on_mouse_exited));
|
|
|
|
connect(SceneStringName(mouse_exited), callable_mp(this, &TabContainer::_on_mouse_exited));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
property_helper.setup_for_instance(base_property_helper, this);
|
|
|
|
|
|
|
|
property_helper.enable_out_of_bounds_assign();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|