diff options
author | Rémi Verschelde <rverschelde@gmail.com> | 2024-01-30 17:47:54 +0100 |
---|---|---|
committer | Rémi Verschelde <rverschelde@gmail.com> | 2024-01-30 17:47:54 +0100 |
commit | f390b86acd22e2722d79e20b9a42454e59c451d0 (patch) | |
tree | 0f43d6d964304d76ff84f9891e8793b671e5b234 /scene/gui/tab_bar.cpp | |
parent | 9572cf5ab2e34bd4a932e3a1c021587f656b85ed (diff) | |
parent | 6e965f6c8337eb9946a5e3da7183d89aa53aac38 (diff) | |
download | redot-engine-f390b86acd22e2722d79e20b9a42454e59c451d0.tar.gz |
Merge pull request #87194 from kitbdev/tab-deselect
Allow no tabs to be selected in TabBar and TabContainer
Diffstat (limited to 'scene/gui/tab_bar.cpp')
-rw-r--r-- | scene/gui/tab_bar.cpp | 110 |
1 files changed, 79 insertions, 31 deletions
diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp index c153f8bd7d..3b5428d72b 100644 --- a/scene/gui/tab_bar.cpp +++ b/scene/gui/tab_bar.cpp @@ -278,7 +278,11 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) { } if (found != -1) { - set_current_tab(found); + if (deselect_enabled && get_current_tab() == found) { + set_current_tab(-1); + } else { + set_current_tab(found); + } if (mb->get_button_index() == MouseButton::RIGHT) { // Right mouse button clicked. @@ -616,8 +620,8 @@ void TabBar::set_tab_count(int p_count) { if (p_count == 0) { offset = 0; max_drawn_tab = 0; - current = 0; - previous = 0; + current = -1; + previous = -1; } else { offset = MIN(offset, p_count - 1); max_drawn_tab = MIN(max_drawn_tab, p_count - 1); @@ -640,7 +644,12 @@ int TabBar::get_tab_count() const { } void TabBar::set_current_tab(int p_current) { - ERR_FAIL_INDEX(p_current, get_tab_count()); + if (p_current == -1) { + // An index of -1 is only valid if deselecting is enabled or there are no valid tabs. + ERR_FAIL_COND_MSG(!_can_deselect(), "Cannot deselect tabs, deselection is not enabled."); + } else { + ERR_FAIL_INDEX(p_current, get_tab_count()); + } previous = current; current = p_current; @@ -1069,8 +1078,13 @@ void TabBar::add_tab(const String &p_str, const Ref<Texture2D> &p_icon) { queue_redraw(); update_minimum_size(); - if (tabs.size() == 1 && is_inside_tree()) { - emit_signal(SNAME("tab_changed"), 0); + if (tabs.size() == 1) { + if (is_inside_tree()) { + set_current_tab(0); + } else { + current = 0; + previous = -1; + } } } @@ -1082,8 +1096,8 @@ void TabBar::clear_tabs() { tabs.clear(); offset = 0; max_drawn_tab = 0; - current = 0; - previous = 0; + current = -1; + previous = -1; queue_redraw(); update_minimum_size(); @@ -1094,34 +1108,43 @@ void TabBar::remove_tab(int p_idx) { ERR_FAIL_INDEX(p_idx, tabs.size()); tabs.remove_at(p_idx); - bool is_tab_changing = current == p_idx && !tabs.is_empty(); + bool is_tab_changing = current == p_idx; if (current >= p_idx && current > 0) { current--; } + if (previous >= p_idx && previous > 0) { + previous--; + } if (tabs.is_empty()) { offset = 0; max_drawn_tab = 0; - previous = 0; + current = -1; + previous = -1; } else { - // Try to change to a valid tab if possible (without firing the `tab_selected` signal). - for (int i = current; i < tabs.size(); i++) { - if (!is_tab_disabled(i) && !is_tab_hidden(i)) { - current = i; - break; - } - } - // If nothing, try backwards. - if (is_tab_disabled(current) || is_tab_hidden(current)) { - for (int i = current - 1; i >= 0; i--) { + if (current != -1) { + // Try to change to a valid tab if possible (without firing the `tab_selected` signal). + for (int i = current; i < tabs.size(); i++) { if (!is_tab_disabled(i) && !is_tab_hidden(i)) { current = i; break; } } + // If nothing, try backwards. + if (is_tab_disabled(current) || is_tab_hidden(current)) { + for (int i = current - 1; i >= 0; i--) { + if (!is_tab_disabled(i) && !is_tab_hidden(i)) { + current = i; + break; + } + } + } + // If still no valid tab, deselect. + if (is_tab_disabled(current) || is_tab_hidden(current)) { + current = -1; + } } - offset = MIN(offset, tabs.size() - 1); max_drawn_tab = MIN(max_drawn_tab, tabs.size() - 1); @@ -1301,17 +1324,9 @@ void TabBar::_move_tab_from(TabBar *p_from_tabbar, int p_from_index, int p_to_in if (!is_tab_disabled(p_to_index)) { set_current_tab(p_to_index); - if (tabs.size() == 1) { - _update_cache(); - queue_redraw(); - emit_signal(SNAME("tab_changed"), 0); - } } else { _update_cache(); queue_redraw(); - if (tabs.size() == 1) { - emit_signal(SNAME("tab_changed"), 0); - } } update_minimum_size(); @@ -1398,9 +1413,9 @@ void TabBar::move_tab(int p_from, int p_to) { if (previous == p_from) { previous = p_to; - } else if (previous > p_from && previous >= p_to) { + } else if (previous > p_from && previous <= p_to) { previous--; - } else if (previous < p_from && previous <= p_to) { + } else if (previous < p_from && previous >= p_to) { previous++; } @@ -1516,10 +1531,26 @@ void TabBar::_ensure_no_over_offset() { } } +bool TabBar::_can_deselect() const { + if (deselect_enabled) { + return true; + } + // All tabs must be disabled or hidden. + for (const Tab &tab : tabs) { + if (!tab.disabled && !tab.hidden) { + return false; + } + } + return true; +} + void TabBar::ensure_tab_visible(int p_idx) { if (!is_inside_tree() || !buttons_visible) { return; } + if (p_idx == -1 && _can_deselect()) { + return; + } ERR_FAIL_INDEX(p_idx, tabs.size()); if (tabs[p_idx].hidden || (p_idx >= offset && p_idx <= max_drawn_tab)) { @@ -1662,6 +1693,20 @@ bool TabBar::get_select_with_rmb() const { return select_with_rmb; } +void TabBar::set_deselect_enabled(bool p_enabled) { + if (deselect_enabled == p_enabled) { + return; + } + deselect_enabled = p_enabled; + if (!deselect_enabled && current == -1 && !tabs.is_empty()) { + select_next_available(); + } +} + +bool TabBar::get_deselect_enabled() const { + return deselect_enabled; +} + bool TabBar::_set(const StringName &p_name, const Variant &p_value) { Vector<String> components = String(p_name).split("/", true, 2); if (components.size() >= 2 && components[0].begins_with("tab_") && components[0].trim_prefix("tab_").is_valid_int()) { @@ -1766,6 +1811,8 @@ void TabBar::_bind_methods() { ClassDB::bind_method(D_METHOD("get_scroll_to_selected"), &TabBar::get_scroll_to_selected); ClassDB::bind_method(D_METHOD("set_select_with_rmb", "enabled"), &TabBar::set_select_with_rmb); ClassDB::bind_method(D_METHOD("get_select_with_rmb"), &TabBar::get_select_with_rmb); + ClassDB::bind_method(D_METHOD("set_deselect_enabled", "enabled"), &TabBar::set_deselect_enabled); + ClassDB::bind_method(D_METHOD("get_deselect_enabled"), &TabBar::get_deselect_enabled); ClassDB::bind_method(D_METHOD("clear_tabs"), &TabBar::clear_tabs); ADD_SIGNAL(MethodInfo("tab_selected", PropertyInfo(Variant::INT, "tab"))); @@ -1790,6 +1837,7 @@ void TabBar::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "tabs_rearrange_group"), "set_tabs_rearrange_group", "get_tabs_rearrange_group"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scroll_to_selected"), "set_scroll_to_selected", "get_scroll_to_selected"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "select_with_rmb"), "set_select_with_rmb", "get_select_with_rmb"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deselect_enabled"), "set_deselect_enabled", "get_deselect_enabled"); BIND_ENUM_CONSTANT(ALIGNMENT_LEFT); BIND_ENUM_CONSTANT(ALIGNMENT_CENTER); |