Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Tabs node minimum size #47491

Merged
merged 1 commit into from
Mar 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions doc/classes/Tabs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,9 @@
</method>
</methods>
<members>
<member name="clip_tabs" type="bool" setter="set_clip_tabs" getter="get_clip_tabs" default="true">
If [code]true[/code], tabs overflowing this node's width will be hidden, displaying two navigation buttons instead. Otherwise, this node's minimum size is updated so that all tabs are visible.
</member>
<member name="current_tab" type="int" setter="set_current_tab" getter="get_current_tab" default="0">
Select tab at index [code]tab_idx[/code].
</member>
Expand Down
59 changes: 42 additions & 17 deletions scene/gui/tabs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ Size2 Tabs::get_minimum_size() const {
}
}

ms.width = 0; //TODO: should make this optional
if (clip_tabs) {
ms.width = 0;
}

return ms;
}

Expand All @@ -105,10 +108,10 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) {
highlight_arrow = 0;
}
} else {
int limit = get_size().width - incr->get_width() - decr->get_width();
if (pos.x > limit + decr->get_width()) {
int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width();
if (pos.x > limit_minus_buttons + decr->get_width()) {
highlight_arrow = 1;
} else if (pos.x > limit) {
} else if (pos.x > limit_minus_buttons) {
highlight_arrow = 0;
}
}
Expand Down Expand Up @@ -305,7 +308,8 @@ void Tabs::_notification(int p_what) {
Ref<Texture2D> incr_hl = get_theme_icon("increment_highlight");
Ref<Texture2D> decr_hl = get_theme_icon("decrement_highlight");

int limit = get_size().width - incr->get_size().width - decr->get_size().width;
int limit = get_size().width;
int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width();

missing_right = false;

Expand All @@ -328,7 +332,8 @@ void Tabs::_notification(int p_what) {
col = font_unselected_color;
}

if (w + lsize > limit) {
int new_width = w + lsize;
if (new_width > limit || (i < tabs.size() - 1 && new_width > limit_minus_buttons)) { // For the last tab, we accept if the tab covers the buttons.
max_drawn_tab = i - 1;
missing_right = true;
break;
Expand Down Expand Up @@ -459,15 +464,15 @@ void Tabs::_notification(int p_what) {
}
} else {
if (offset > 0) {
draw_texture(highlight_arrow == 0 ? decr_hl : decr, Point2(limit, vofs));
draw_texture(highlight_arrow == 0 ? decr_hl : decr, Point2(limit_minus_buttons, vofs));
} else {
draw_texture(decr, Point2(limit, vofs), Color(1, 1, 1, 0.5));
draw_texture(decr, Point2(limit_minus_buttons, vofs), Color(1, 1, 1, 0.5));
}

if (missing_right) {
draw_texture(highlight_arrow == 1 ? incr_hl : incr, Point2(limit + decr->get_size().width, vofs));
draw_texture(highlight_arrow == 1 ? incr_hl : incr, Point2(limit_minus_buttons + decr->get_size().width, vofs));
} else {
draw_texture(incr, Point2(limit + decr->get_size().width, vofs), Color(1, 1, 1, 0.5));
draw_texture(incr, Point2(limit_minus_buttons + decr->get_size().width, vofs), Color(1, 1, 1, 0.5));
}
}

Expand Down Expand Up @@ -666,7 +671,7 @@ void Tabs::_update_cache() {
Ref<StyleBox> tab_selected = get_theme_stylebox("tab_selected");
Ref<Texture2D> incr = get_theme_icon("increment");
Ref<Texture2D> decr = get_theme_icon("decrement");
int limit = get_size().width - incr->get_width() - decr->get_width();
int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width();

int w = 0;
int mw = 0;
Expand All @@ -686,7 +691,7 @@ void Tabs::_update_cache() {
}
int m_width = min_width;
if (count_resize > 0) {
m_width = MAX((limit - size_fixed) / count_resize, min_width);
m_width = MAX((limit_minus_buttons - size_fixed) / count_resize, min_width);
}
for (int i = offset; i < tabs.size(); i++) {
Ref<StyleBox> sb;
Expand All @@ -699,7 +704,7 @@ void Tabs::_update_cache() {
}
int lsize = tabs[i].size_cache;
int slen = tabs[i].size_text;
if (min_width > 0 && mw > limit && i != current) {
if (min_width > 0 && mw > limit_minus_buttons && i != current) {
if (lsize > m_width) {
slen = m_width - (sb->get_margin(SIDE_LEFT) + sb->get_margin(SIDE_RIGHT));
if (tabs[i].icon.is_valid()) {
Expand Down Expand Up @@ -909,6 +914,19 @@ Tabs::TabAlign Tabs::get_tab_align() const {
return tab_align;
}

void Tabs::set_clip_tabs(bool p_clip_tabs) {
if (clip_tabs == p_clip_tabs) {
return;
}
clip_tabs = p_clip_tabs;
update();
minimum_size_changed();
}

bool Tabs::get_clip_tabs() const {
return clip_tabs;
}

void Tabs::move_tab(int from, int to) {
if (from == to) {
return;
Expand Down Expand Up @@ -975,15 +993,16 @@ void Tabs::_ensure_no_over_offset() {
Ref<Texture2D> incr = get_theme_icon("increment");
Ref<Texture2D> decr = get_theme_icon("decrement");

int limit = get_size().width - incr->get_width() - decr->get_width();
int limit = get_size().width;
int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width();

while (offset > 0) {
int total_w = 0;
for (int i = offset - 1; i < tabs.size(); i++) {
total_w += tabs[i].size_cache;
}

if (total_w < limit) {
if ((buttons_visible && total_w < limit_minus_buttons) || total_w < limit) { // For the last tab, we accept if the tab covers the buttons.
offset--;
update();
} else {
Expand Down Expand Up @@ -1014,9 +1033,12 @@ void Tabs::ensure_tab_visible(int p_idx) {
int prev_offset = offset;
Ref<Texture2D> incr = get_theme_icon("increment");
Ref<Texture2D> decr = get_theme_icon("decrement");
int limit = get_size().width - incr->get_width() - decr->get_width();
int limit = get_size().width;
int limit_minus_buttons = get_size().width - incr->get_width() - decr->get_width();

for (int i = offset; i <= p_idx; i++) {
if (tabs[i].ofs_cache + tabs[i].size_cache > limit) {
int total_w = tabs[i].ofs_cache + tabs[i].size_cache;
if (total_w > limit || (buttons_visible && total_w > limit_minus_buttons)) {
offset++;
}
}
Expand Down Expand Up @@ -1105,6 +1127,8 @@ void Tabs::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_tab", "title", "icon"), &Tabs::add_tab, DEFVAL(""), DEFVAL(Ref<Texture2D>()));
ClassDB::bind_method(D_METHOD("set_tab_align", "align"), &Tabs::set_tab_align);
ClassDB::bind_method(D_METHOD("get_tab_align"), &Tabs::get_tab_align);
ClassDB::bind_method(D_METHOD("set_clip_tabs", "clip_tabs"), &Tabs::set_clip_tabs);
ClassDB::bind_method(D_METHOD("get_clip_tabs"), &Tabs::get_clip_tabs);
ClassDB::bind_method(D_METHOD("get_tab_offset"), &Tabs::get_tab_offset);
ClassDB::bind_method(D_METHOD("get_offset_buttons_visible"), &Tabs::get_offset_buttons_visible);
ClassDB::bind_method(D_METHOD("ensure_tab_visible", "idx"), &Tabs::ensure_tab_visible);
Expand All @@ -1131,6 +1155,7 @@ void Tabs::_bind_methods() {

ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1", PROPERTY_USAGE_EDITOR), "set_current_tab", "get_current_tab");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_align", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_tab_align", "get_tab_align");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_tabs"), "set_clip_tabs", "get_clip_tabs");
ADD_PROPERTY(PropertyInfo(Variant::INT, "tab_close_display_policy", PROPERTY_HINT_ENUM, "Show Never,Show Active Only,Show Always"), "set_tab_close_display_policy", "get_tab_close_display_policy");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "scrolling_enabled"), "set_scrolling_enabled", "get_scrolling_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_to_rearrange_enabled"), "set_drag_to_rearrange_enabled", "get_drag_to_rearrange_enabled");
Expand Down
4 changes: 4 additions & 0 deletions scene/gui/tabs.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class Tabs : public Control {
int previous = 0;
int _get_top_margin() const;
TabAlign tab_align = ALIGN_CENTER;
bool clip_tabs = true;
int rb_hover = -1;
bool rb_pressing = false;

Expand Down Expand Up @@ -148,6 +149,9 @@ class Tabs : public Control {
void set_tab_align(TabAlign p_align);
TabAlign get_tab_align() const;

void set_clip_tabs(bool p_clip_tabs);
bool get_clip_tabs() const;

void move_tab(int from, int to);

void set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy);
Expand Down