OverviewFilesCommitsIssuesDocsReleasesPeers

nvidia-rtx-godot commits / 05737cd

Add "desired size" to `Control`
A `Control` can define `get_desired_size()` which allows it to grow based on its content without increasing its minimum size. This new size will be respected by parent `Container`s. Currently used by `Label` and `TabBar`.
05737cd4498ca2fc69e3f5d54c9eb600948ea77f
by StarryWorm <41305715+StarryWorm@users.noreply.github.com> · 2026-04-11T22:18:18.000Z

Changed files (33) +453 -71

scene/gui/box_container.cpp +10 -2
……@@ -288,7 +288,7 @@ void BoxContainer::_resort() {
288288 }
289289}
290290
291Size2 BoxContainer::get_minimum_size() const {
291Size2 BoxContainer::_get_minimum_size(bool p_use_desired_sizes) const {
292292 /* Calculate MINIMUM SIZE */
293293
294294 Size2i minimum;
……@@ -301,7 +301,7 @@ Size2 BoxContainer::get_minimum_size() const {
301301 continue;
302302 }
303303
304 Size2i size = c->get_bound_minimum_size();
304 Size2i size = p_use_desired_sizes ? c->get_bound_desired_size() : c->get_bound_minimum_size();
305305
306306 if (vertical) { /* VERTICAL */
307307
……@@ -326,6 +326,14 @@ Size2 BoxContainer::get_minimum_size() const {
326326 return minimum;
327327}
328328
329Size2 BoxContainer::get_minimum_size() const {
330 return _get_minimum_size(false);
331}
332
333Size2 BoxContainer::get_desired_size() const {
334 return _get_minimum_size(true);
335}
336
329337void BoxContainer::_notification(int p_what) {
330338 switch (p_what) {
331339 case NOTIFICATION_SORT_CHILDREN: {
scene/gui/box_container.h +2 -0
……@@ -51,6 +51,7 @@ private:
5151 } theme_cache;
5252
5353 void _resort();
54 Size2 _get_minimum_size(bool p_use_desired_sizes) const;
5455
5556protected:
5657 bool is_fixed = false;
……@@ -69,6 +70,7 @@ public:
6970 bool is_vertical() const;
7071
7172 virtual Size2 get_minimum_size() const override;
73 virtual Size2 get_desired_size() const override;
7274
7375 virtual Vector<int> get_allowed_size_flags_horizontal() const override;
7476 virtual Vector<int> get_allowed_size_flags_vertical() const override;
scene/gui/center_container.cpp +17 -0
……@@ -49,6 +49,23 @@ Size2 CenterContainer::get_minimum_size() const {
4949 return ms;
5050}
5151
52Size2 CenterContainer::get_desired_size() const {
53 if (use_top_left) {
54 return Size2();
55 }
56 Size2 ds;
57 for (int i = 0; i < get_child_count(); i++) {
58 Control *c = as_sortable_control(get_child(i), SortableVisibilityMode::VISIBLE);
59 if (!c) {
60 continue;
61 }
62 Size2 minsize = c->get_bound_desired_size();
63 ds = ds.max(minsize);
64 }
65
66 return ds;
67}
68
5269void CenterContainer::set_use_top_left(bool p_enable) {
5370 if (use_top_left == p_enable) {
5471 return;
scene/gui/center_container.h +1 -0
……@@ -46,6 +46,7 @@ public:
4646 bool is_using_top_left() const;
4747
4848 virtual Size2 get_minimum_size() const override;
49 virtual Size2 get_desired_size() const override;
4950
5051 virtual Vector<int> get_allowed_size_flags_horizontal() const override;
5152 virtual Vector<int> get_allowed_size_flags_vertical() const override;
scene/gui/container.cpp +10 -0
……@@ -39,6 +39,11 @@ void Container::_child_minsize_changed() {
3939 queue_sort();
4040}
4141
42void Container::_child_desired_size_changed() {
43 update_desired_size();
44 queue_sort();
45}
46
4247void Container::add_child_notify(Node *p_child) {
4348 Control::add_child_notify(p_child);
4449
……@@ -50,6 +55,7 @@ void Container::add_child_notify(Node *p_child) {
5055 control->connect(SceneStringName(size_flags_changed), callable_mp(this, &Container::queue_sort));
5156 control->connect(SceneStringName(minimum_size_changed), callable_mp(this, &Container::_child_minsize_changed));
5257 control->connect(SceneStringName(maximum_size_changed), callable_mp(this, &Container::_child_minsize_changed));
58 control->connect("_desired_size_changed", callable_mp(this, &Container::_child_desired_size_changed));
5359 control->connect(SceneStringName(visibility_changed), callable_mp(this, &Container::_child_minsize_changed));
5460
5561 update_minimum_size();
……@@ -78,6 +84,7 @@ void Container::remove_child_notify(Node *p_child) {
7884 control->disconnect(SceneStringName(size_flags_changed), callable_mp(this, &Container::queue_sort));
7985 control->disconnect(SceneStringName(minimum_size_changed), callable_mp(this, &Container::_child_minsize_changed));
8086 control->disconnect(SceneStringName(maximum_size_changed), callable_mp(this, &Container::_child_minsize_changed));
87 control->disconnect("_desired_size_changed", callable_mp(this, &Container::_child_desired_size_changed));
8188 control->disconnect(SceneStringName(visibility_changed), callable_mp(this, &Container::_child_minsize_changed));
8289
8390 update_minimum_size();
……@@ -105,6 +112,7 @@ void Container::fit_child_in_rect(RequiredParam<Control> rp_child, const Rect2 &
105112
106113 bool rtl = is_layout_rtl();
107114 Size2 minsize = p_child->get_combined_minimum_size();
115 Size2 desired_size = p_child->get_bound_desired_size();
108116 Size2 maxsize = p_child->get_combined_maximum_size();
109117 Rect2 r = p_rect;
110118 BitField<SizeFlags> h_size_flags = p_child->get_h_size_flags();
……@@ -112,6 +120,7 @@ void Container::fit_child_in_rect(RequiredParam<Control> rp_child, const Rect2 &
112120
113121 if (!h_size_flags.has_flag(SIZE_FILL)) {
114122 float final_width = minsize.width;
123 final_width = MAX(MIN(desired_size.width, r.size.width), final_width);
115124 if (maxsize.width >= 0) {
116125 final_width = MIN(final_width, maxsize.width);
117126 }
……@@ -127,6 +136,7 @@ void Container::fit_child_in_rect(RequiredParam<Control> rp_child, const Rect2 &
127136
128137 if (!v_size_flags.has_flag(SIZE_FILL)) {
129138 float final_height = minsize.y;
139 final_height = MAX(MIN(desired_size.y, r.size.y), final_height);
130140 if (maxsize.height >= 0) {
131141 final_height = MIN(final_height, maxsize.height);
132142 }
scene/gui/container.h +1 -0
……@@ -39,6 +39,7 @@ class Container : public Control {
3939 bool accessibility_region = false;
4040 void _sort_children();
4141 void _child_minsize_changed();
42 void _child_desired_size_changed();
4243
4344protected:
4445 enum class SortableVisibilityMode {
scene/gui/control.cpp +112 -0
……@@ -1550,6 +1550,8 @@ void Control::set_size(const Size2 &p_size, bool p_keep_offsets) {
15501550 }
15511551#endif // TOOLS_ENABLED
15521552
1553 data.expanded_by_desired_size = false;
1554
15531555 if (p_keep_offsets) {
15541556 _compute_anchors(Rect2(data.pos_cache, new_size), data.offset, data.anchor);
15551557 } else {
……@@ -1761,6 +1763,11 @@ void Control::update_maximum_size() {
17611763 data.updating_last_minimum_size = true;
17621764 callable_mp(this, &Control::_update_minimum_size).call_deferred();
17631765 }
1766 // Same with desired size.
1767 if (!data.updating_last_desired_size) {
1768 data.updating_last_desired_size = true;
1769 callable_mp(this, &Control::_update_desired_size).call_deferred();
1770 }
17641771
17651772 callable_mp(this, &Control::_update_maximum_size).call_deferred();
17661773}
……@@ -1948,6 +1955,107 @@ Size2 Control::get_custom_minimum_size() const {
19481955 return data.custom_minimum_size;
19491956}
19501957
1958void Control::_update_desired_size_cache() const {
1959 Size2 desired_size = get_desired_size();
1960
1961 data.desired_size_cache = desired_size;
1962 data.desired_size_valid = true;
1963}
1964
1965void Control::_update_desired_size() {
1966 if (!is_inside_tree()) {
1967 data.updating_last_desired_size = false;
1968 return;
1969 }
1970
1971 Size2 desired_size = get_desired_size();
1972 data.updating_last_desired_size = false;
1973
1974 if (desired_size != data.last_desired_size) {
1975 data.last_desired_size = desired_size;
1976 grow_to_desired_size();
1977 emit_signal("_desired_size_changed");
1978 }
1979}
1980
1981void Control::update_desired_size() {
1982 ERR_MAIN_THREAD_GUARD;
1983 if (!is_inside_tree()) {
1984 return;
1985 }
1986
1987 // Invalidate cache upwards.
1988 Control *invalidate = this;
1989 while (invalidate && invalidate->data.desired_size_valid) {
1990 invalidate->data.desired_size_valid = false;
1991 if (invalidate->is_set_as_top_level()) {
1992 break; // Do not go further up.
1993 }
1994
1995 Window *parent_window = invalidate->get_parent_window();
1996 if (parent_window && parent_window->is_wrapping_controls()) {
1997 parent_window->child_controls_changed();
1998 break; // Stop on a window as well.
1999 }
2000
2001 invalidate = invalidate->get_parent_control();
2002 }
2003
2004 if (!is_visible_in_tree()) {
2005 // Invalidate the last desired size so it will update when made visible.
2006 data.last_desired_size = Size2(-1, -1);
2007 return;
2008 }
2009
2010 if (data.updating_last_desired_size) {
2011 return;
2012 }
2013 data.updating_last_desired_size = true;
2014
2015 callable_mp(this, &Control::_update_desired_size).call_deferred();
2016}
2017
2018Size2 Control::get_bound_desired_size() const {
2019 ERR_READ_THREAD_GUARD_V(Size2());
2020 if (!data.desired_size_valid) {
2021 _update_desired_size_cache();
2022 }
2023 Size2 desired_size = data.desired_size_cache;
2024 desired_size = desired_size.max(get_combined_minimum_size());
2025 Size2 max_size = get_combined_maximum_size();
2026 if (max_size.x >= 0) {
2027 desired_size.x = MIN(desired_size.x, max_size.x);
2028 }
2029 if (max_size.y >= 0) {
2030 desired_size.y = MIN(desired_size.y, max_size.y);
2031 }
2032 return desired_size;
2033}
2034
2035Size2 Control::get_desired_size() const {
2036 return Size2();
2037}
2038
2039void Control::grow_to_desired_size() {
2040 ERR_MAIN_THREAD_GUARD;
2041 if (!is_inside_tree()) {
2042 return;
2043 }
2044
2045 Size2 desired_size = get_bound_desired_size();
2046 if (desired_size <= get_combined_minimum_size()) {
2047 return;
2048 }
2049
2050 if (data.expanded_by_desired_size) {
2051 set_size(desired_size);
2052 data.expanded_by_desired_size = true;
2053 } else if (desired_size.x > get_size().x || desired_size.y > get_size().y) {
2054 set_size(desired_size);
2055 data.expanded_by_desired_size = true;
2056 }
2057}
2058
19512059void Control::add_child_notify(Node *p_child) {
19522060 CanvasItem::add_child_notify(p_child);
19532061
……@@ -2021,6 +2129,9 @@ void Control::_update_minimum_size_cache() const {
20212129
20222130 data.minimum_size_cache = minsize;
20232131 data.minimum_size_valid = true;
2132
2133 // Keep the desired size cache in sync so it will update if needed when the minimum size changes. This is needed for get_bound_desired_size to work correctly.
2134 data.desired_size_valid = false;
20242135}
20252136
20262137Size2 Control::get_combined_minimum_size() const {
……@@ -5024,6 +5135,7 @@ void Control::_bind_methods() {
50245135 ADD_SIGNAL(MethodInfo("size_flags_changed"));
50255136 ADD_SIGNAL(MethodInfo("maximum_size_changed"));
50265137 ADD_SIGNAL(MethodInfo("minimum_size_changed"));
5138 ADD_SIGNAL(MethodInfo("_desired_size_changed"));
50275139 ADD_SIGNAL(MethodInfo("theme_changed"));
50285140
50295141 GDVIRTUAL_BIND(_has_point, "point");
scene/gui/control.h +17 -0
……@@ -256,6 +256,14 @@ private:
256256 bool updating_last_minimum_size = false;
257257 bool block_minimum_size_adjust = false;
258258
259 mutable Size2 desired_size_cache;
260 mutable bool desired_size_valid = false;
261
262 Size2 last_desired_size;
263 bool updating_last_desired_size = false;
264
265 bool expanded_by_desired_size = false;
266
259267 bool layout_pending = false;
260268
261269 bool size_warning = true;
……@@ -371,6 +379,9 @@ private:
371379 void _update_maximum_size();
372380 void _update_minimum_size_cache() const;
373381 void _update_minimum_size();
382 void _update_desired_size_cache() const;
383 void _update_desired_size();
384 void _grow_to_desired_size();
374385 void _size_changed();
375386
376387 void _top_level_changed() override {} // Controls don't need to do anything, only other CanvasItems.
……@@ -603,6 +614,9 @@ public:
603614
604615 void update_maximum_size();
605616 void update_minimum_size();
617 void update_desired_size();
618
619 void grow_to_desired_size();
606620
607621 void set_block_maximum_size_adjust(bool p_block);
608622 void set_block_minimum_size_adjust(bool p_block);
……@@ -624,6 +638,9 @@ public:
624638
625639 virtual Size2 get_bound_minimum_size() const;
626640
641 Size2 get_bound_desired_size() const;
642 virtual Size2 get_desired_size() const;
643
627644 bool is_layout_pending() const;
628645 bool is_layout_pending_in_tree() const;
629646 void layout_pending_start();
scene/gui/flow_container.cpp +10 -2
……@@ -347,7 +347,7 @@ void FlowContainer::_resort() {
347347 cached_line_max_child_count = lines_data.size() > 0 ? lines_data[0].child_count : 0;
348348}
349349
350Size2 FlowContainer::get_minimum_size() const {
350Size2 FlowContainer::_get_minimum_size(bool p_use_desired_sizes) const {
351351 Size2i minimum;
352352
353353 for (int i = 0; i < get_child_count(); i++) {
……@@ -356,7 +356,7 @@ Size2 FlowContainer::get_minimum_size() const {
356356 continue;
357357 }
358358
359 Size2i size = c->get_bound_minimum_size();
359 Size2i size = p_use_desired_sizes ? c->get_bound_desired_size() : c->get_bound_minimum_size();
360360
361361 if (vertical) { /* VERTICAL */
362362 minimum.height = MAX(minimum.height, size.height);
……@@ -371,6 +371,14 @@ Size2 FlowContainer::get_minimum_size() const {
371371 return minimum;
372372}
373373
374Size2 FlowContainer::get_minimum_size() const {
375 return _get_minimum_size(false);
376}
377
378Size2 FlowContainer::get_desired_size() const {
379 return _get_minimum_size(true);
380}
381
374382Vector<int> FlowContainer::get_allowed_size_flags_horizontal() const {
375383 Vector<int> flags;
376384 flags.append(SIZE_FILL);
scene/gui/flow_container.h +2 -0
……@@ -64,6 +64,7 @@ private:
6464 } theme_cache;
6565
6666 void _resort();
67 Size2 _get_minimum_size(bool p_use_desired_sizes) const;
6768
6869protected:
6970 bool is_fixed = false;
……@@ -89,6 +90,7 @@ public:
8990 bool is_reverse_fill() const;
9091
9192 virtual Size2 get_minimum_size() const override;
93 virtual Size2 get_desired_size() const override;
9294
9395 virtual Vector<int> get_allowed_size_flags_horizontal() const override;
9496 virtual Vector<int> get_allowed_size_flags_vertical() const override;
scene/gui/foldable_container.cpp +20 -0
……@@ -54,6 +54,26 @@ Size2 FoldableContainer::get_minimum_size() const {
5454 return Size2(MAX(ms.width, title_minimum_size.width), ms.height + title_minimum_size.height);
5555}
5656
57Size2 FoldableContainer::get_desired_size() const {
58 _update_title_min_size();
59
60 if (folded) {
61 return title_minimum_size;
62 }
63 Size2 ds;
64
65 for (int i = 0; i < get_child_count(); i++) {
66 Control *c = as_sortable_control(get_child(i));
67 if (!c) {
68 continue;
69 }
70 ds = ds.max(c->get_bound_desired_size());
71 }
72 ds += theme_cache.panel_style->get_minimum_size();
73
74 return Size2(MAX(ds.width, title_minimum_size.width), ds.height + title_minimum_size.height);
75}
76
5777Size2 FoldableContainer::get_inner_combined_maximum_size() const {
5878 Size2 ms = Container::get_inner_combined_maximum_size();
5979
scene/gui/foldable_container.h +1 -0
……@@ -138,6 +138,7 @@ public:
138138 void remove_title_bar_control(Control *p_control);
139139
140140 virtual Size2 get_minimum_size() const override;
141 virtual Size2 get_desired_size() const override;
141142 virtual Size2 get_inner_combined_maximum_size() const override;
142143
143144 virtual Vector<int> get_allowed_size_flags_horizontal() const override { return { SIZE_FILL, SIZE_SHRINK_BEGIN, SIZE_SHRINK_CENTER, SIZE_SHRINK_END }; }
scene/gui/graph_frame.cpp +11 -3
……@@ -323,11 +323,11 @@ bool GraphFrame::has_point(const Point2 &p_point) const {
323323 return false;
324324}
325325
326Size2 GraphFrame::get_minimum_size() const {
326Size2 GraphFrame::_get_minimum_size(bool p_use_desired_sizes) const {
327327 Ref<StyleBox> sb_panel = theme_cache.panel;
328328 Ref<StyleBox> sb_titlebar = theme_cache.titlebar;
329329
330 Size2 minsize = titlebar_hbox->get_minimum_size() + sb_titlebar->get_minimum_size();
330 Size2 minsize = (p_use_desired_sizes ? titlebar_hbox->get_bound_desired_size() : titlebar_hbox->get_minimum_size()) + sb_titlebar->get_minimum_size();
331331
332332 for (int i = 0; i < get_child_count(false); i++) {
333333 Control *child = as_sortable_control(get_child(i, false));
……@@ -335,7 +335,7 @@ Size2 GraphFrame::get_minimum_size() const {
335335 continue;
336336 }
337337
338 Size2i size = child->get_bound_minimum_size();
338 Size2i size = p_use_desired_sizes ? child->get_bound_desired_size() : child->get_bound_minimum_size();
339339 size.width += sb_panel->get_minimum_size().width;
340340
341341 minsize.x = MAX(minsize.x, size.x);
……@@ -347,6 +347,14 @@ Size2 GraphFrame::get_minimum_size() const {
347347 return minsize;
348348}
349349
350Size2 GraphFrame::get_minimum_size() const {
351 return _get_minimum_size(false);
352}
353
354Size2 GraphFrame::get_desired_size() const {
355 return _get_minimum_size(true);
356}
357
350358GraphFrame::GraphFrame() {
351359 titlebar_hbox = memnew(HBoxContainer);
352360 titlebar_hbox->set_h_size_flags(SIZE_EXPAND_FILL);
scene/gui/graph_frame.h +3 -0
……@@ -60,6 +60,8 @@ private:
6060 bool tint_color_enabled = false;
6161 Color tint_color = Color(0.3, 0.3, 0.3, 0.75);
6262
63 Size2 _get_minimum_size(bool p_use_desired_sizes) const;
64
6365protected:
6466 virtual void gui_input(const Ref<InputEvent> &p_event) override;
6567 virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override;
……@@ -95,6 +97,7 @@ public:
9597
9698 virtual bool has_point(const Point2 &p_point) const override;
9799 virtual Size2 get_minimum_size() const override;
100 virtual Size2 get_desired_size() const override;
98101
99102 GraphFrame();
100103};
scene/gui/graph_node.cpp +11 -3
……@@ -996,13 +996,13 @@ bool GraphNode::is_ignoring_valid_connection_type() const {
996996 return ignore_invalid_connection_type;
997997}
998998
999Size2 GraphNode::get_minimum_size() const {
999Size2 GraphNode::_get_minimum_size(bool p_use_desired_sizes) const {
10001000 Ref<StyleBox> sb_panel = theme_cache.panel;
10011001 Ref<StyleBox> sb_titlebar = theme_cache.titlebar;
10021002 Ref<StyleBox> sb_slot = theme_cache.slot;
10031003
10041004 int separation = theme_cache.separation;
1005 Size2 minsize = titlebar_hbox->get_minimum_size() + sb_titlebar->get_minimum_size();
1005 Size2 minsize = (p_use_desired_sizes ? titlebar_hbox->get_bound_desired_size() : titlebar_hbox->get_minimum_size()) + sb_titlebar->get_minimum_size();
10061006
10071007 for (int i = 0; i < get_child_count(false); i++) {
10081008 Control *child = as_sortable_control(get_child(i, false));
……@@ -1010,7 +1010,7 @@ Size2 GraphNode::get_minimum_size() const {
10101010 continue;
10111011 }
10121012
1013 Size2i size = child->get_bound_minimum_size();
1013 Size2i size = p_use_desired_sizes ? child->get_bound_desired_size() : child->get_bound_minimum_size();
10141014 size.width += sb_panel->get_minimum_size().width;
10151015 if (slot_table.has(i)) {
10161016 size += slot_table[i].draw_stylebox ? sb_slot->get_minimum_size() : Size2();
……@@ -1029,6 +1029,14 @@ Size2 GraphNode::get_minimum_size() const {
10291029 return minsize;
10301030}
10311031
1032Size2 GraphNode::get_minimum_size() const {
1033 return _get_minimum_size(false);
1034}
1035
1036Size2 GraphNode::get_desired_size() const {
1037 return _get_minimum_size(true);
1038}
1039
10321040void GraphNode::_port_pos_update() {
10331041 int edgeofs = theme_cache.port_h_offset;
10341042 int separation = theme_cache.separation;
scene/gui/graph_node.h +3 -0
……@@ -115,6 +115,8 @@ class GraphNode : public GraphElement {
115115
116116 void _port_pos_update();
117117
118 Size2 _get_minimum_size(bool p_use_desired_sizes) const;
119
118120protected:
119121 void _notification(int p_what);
120122 static void _bind_methods();
……@@ -195,6 +197,7 @@ public:
195197 Control::FocusMode get_slots_focus_mode() const;
196198
197199 virtual Size2 get_minimum_size() const override;
200 virtual Size2 get_desired_size() const override;
198201
199202 virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override;
200203
scene/gui/grid_container.cpp +10 -2
……@@ -378,7 +378,7 @@ void GridContainer::_bind_methods() {
378378 BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, GridContainer, v_separation);
379379}
380380
381Size2 GridContainer::get_minimum_size() const {
381Size2 GridContainer::_get_minimum_size(bool p_use_desired_sizes) const {
382382 RBMap<int, int> col_minw;
383383 RBMap<int, int> row_minh;
384384
……@@ -395,7 +395,7 @@ Size2 GridContainer::get_minimum_size() const {
395395 int col = valid_controls_index % columns;
396396 valid_controls_index++;
397397
398 Size2i ms = c->get_bound_minimum_size();
398 Size2i ms = p_use_desired_sizes ? c->get_bound_desired_size() : c->get_bound_minimum_size();
399399 if (col_minw.has(col)) {
400400 col_minw[col] = MAX(col_minw[col], ms.width);
401401 } else {
……@@ -426,3 +426,11 @@ Size2 GridContainer::get_minimum_size() const {
426426
427427 return ms;
428428}
429
430Size2 GridContainer::get_minimum_size() const {
431 return _get_minimum_size(false);
432}
433
434Size2 GridContainer::get_desired_size() const {
435 return _get_minimum_size(true);
436}
scene/gui/grid_container.h +2 -0
……@@ -44,6 +44,7 @@ class GridContainer : public Container {
4444
4545private:
4646 void _resort();
47 Size2 _get_minimum_size(bool p_use_desired_sizes) const;
4748
4849protected:
4950 void _notification(int p_what);
……@@ -53,6 +54,7 @@ public:
5354 void set_columns(int p_columns);
5455 int get_columns() const;
5556 virtual Size2 get_minimum_size() const override;
57 virtual Size2 get_desired_size() const override;
5658
5759 int get_h_separation() const;
5860};
scene/gui/label.cpp +26 -24
……@@ -53,6 +53,7 @@ void Label::set_autowrap_mode(TextServer::AutowrapMode p_mode) {
5353 if (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
5454 update_minimum_size();
5555 }
56 update_desired_size();
5657}
5758
5859TextServer::AutowrapMode Label::get_autowrap_mode() const {
……@@ -74,6 +75,7 @@ void Label::set_autowrap_trim_flags(BitField<TextServer::LineBreakFlag> p_flags)
7475 if (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
7576 update_minimum_size();
7677 }
78 update_desired_size();
7779}
7880
7981BitField<TextServer::LineBreakFlag> Label::get_autowrap_trim_flags() const {
……@@ -152,11 +154,7 @@ void Label::_shape() const {
152154 if (maximum_width <= 0) {
153155 maximum_width = 1;
154156 }
155 if (width > 0) {
156 width = MIN(width, maximum_width);
157 } else {
158 width = maximum_width;
159 }
157 width = maximum_width;
160158 }
161159
162160 if (text_dirty) {
……@@ -914,6 +912,7 @@ void Label::_notification(int p_what) {
914912 case NOTIFICATION_THEME_CHANGED: {
915913 font_dirty = true;
916914 queue_redraw();
915 update_desired_size();
917916 update_configuration_warnings();
918917 } break;
919918
……@@ -993,9 +992,6 @@ Size2 Label::get_minimum_size() const {
993992 _ensure_shaped();
994993
995994 Size2 min_size = minsize;
996 Size2 combined_maximum_size = get_combined_maximum_size();
997 bool wrap_with_max_width = autowrap_mode != TextServer::AUTOWRAP_OFF && combined_maximum_size.x > 0;
998 bool overrun_with_max_width = autowrap_mode == TextServer::AUTOWRAP_OFF && combined_maximum_size.x > 0 && (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING);
999995
1000996 const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : theme_cache.font;
1001997 int font_size = settings.is_valid() ? settings->get_font_size() : theme_cache.font_size;
……@@ -1010,28 +1006,29 @@ Size2 Label::get_minimum_size() const {
10101006 } else if (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
10111007 min_size.height = 1;
10121008 }
1013 if (wrap_with_max_width) {
1014 min_size.width = MAX(1, min_size.width);
1015 return min_size + min_style;
1016 } else {
1017 return Size2(1, min_size.height) + min_style;
1018 }
1009 return Size2(1, min_size.height) + min_style;
10191010 } else {
10201011 if (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
1021 if (overrun_with_max_width) {
1022 min_size.width = MAX(1, min_size.width);
1023 } else {
1024 min_size.width = 1;
1025 }
1026 }
1027 Size2 computed_min_size = min_size + min_style;
1028 if (overrun_with_max_width) {
1029 computed_min_size.width = MIN(computed_min_size.width, combined_maximum_size.x);
1012 min_size.width = 1;
10301013 }
1031 return computed_min_size;
1014 return min_size + min_style;
10321015 }
10331016}
10341017
1018Size2 Label::get_desired_size() const {
1019 Size2 combined_max = get_combined_maximum_size();
1020 if (combined_max.width < 0) {
1021 return Size2();
1022 }
1023
1024 _ensure_shaped();
1025 Size2 min_style = theme_cache.normal_style->get_minimum_size();
1026 Size2 content_size = minsize + min_style;
1027 content_size.width = MIN(content_size.width, int(combined_max.width));
1028
1029 return content_size;
1030}
1031
10351032#ifndef DISABLE_DEPRECATED
10361033bool Label::_set(const StringName &p_name, const Variant &p_value) {
10371034 if (p_name == SNAME("valign")) {
……@@ -1144,6 +1141,7 @@ void Label::set_text(const String &p_string) {
11441141 queue_accessibility_update();
11451142 queue_redraw();
11461143 update_minimum_size();
1144 update_desired_size();
11471145 update_configuration_warnings();
11481146}
11491147
……@@ -1163,6 +1161,7 @@ void Label::_maximum_size_changed() {
11631161 }
11641162 queue_redraw();
11651163 update_minimum_size();
1164 update_desired_size();
11661165 update_configuration_warnings();
11671166}
11681167
……@@ -1264,6 +1263,7 @@ void Label::set_clip_text(bool p_clip) {
12641263 clip = p_clip;
12651264 queue_redraw();
12661265 update_minimum_size();
1266 update_desired_size();
12671267}
12681268
12691269bool Label::is_clipping_text() const {
……@@ -1297,6 +1297,7 @@ void Label::set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior) {
12971297 if (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
12981298 update_minimum_size();
12991299 }
1300 update_desired_size();
13001301}
13011302
13021303TextServer::OverrunBehavior Label::get_text_overrun_behavior() const {
……@@ -1320,6 +1321,7 @@ void Label::set_ellipsis_char(const String &p_char) {
13201321 if (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
13211322 update_minimum_size();
13221323 }
1324 update_desired_size();
13231325}
13241326
13251327String Label::get_ellipsis_char() const {
scene/gui/label.h +1 -0
……@@ -116,6 +116,7 @@ protected:
116116
117117public:
118118 virtual Size2 get_minimum_size() const override;
119 virtual Size2 get_desired_size() const override;
119120 virtual PackedStringArray get_configuration_warnings() const override;
120121
121122 void set_horizontal_alignment(HorizontalAlignment p_alignment);
scene/gui/margin_container.cpp +20 -6
……@@ -42,12 +42,7 @@ Size2 MarginContainer::get_minimum_size() const {
4242 }
4343
4444 Size2 s = c->get_bound_minimum_size();
45 if (s.width > max.width) {
46 max.width = s.width;
47 }
48 if (s.height > max.height) {
49 max.height = s.height;
50 }
45 max = max.max(s);
5146 }
5247
5348 max.width += (theme_cache.margin_left + theme_cache.margin_right);
……@@ -56,6 +51,25 @@ Size2 MarginContainer::get_minimum_size() const {
5651 return max;
5752}
5853
54Size2 MarginContainer::get_desired_size() const {
55 Size2 ds;
56
57 for (int i = 0; i < get_child_count(); i++) {
58 Control *c = as_sortable_control(get_child(i), SortableVisibilityMode::VISIBLE);
59 if (!c) {
60 continue;
61 }
62
63 Size2 s = c->get_desired_size();
64 ds = ds.max(s);
65 }
66
67 ds.width += (theme_cache.margin_left + theme_cache.margin_right);
68 ds.height += (theme_cache.margin_top + theme_cache.margin_bottom);
69
70 return ds;
71}
72
5973Size2 MarginContainer::get_inner_combined_maximum_size() const {
6074 Size2 ms = Container::get_inner_combined_maximum_size();
6175
scene/gui/margin_container.h +1 -0
……@@ -48,6 +48,7 @@ protected:
4848
4949public:
5050 virtual Size2 get_minimum_size() const override;
51 virtual Size2 get_desired_size() const override;
5152 virtual Size2 get_inner_combined_maximum_size() const override;
5253
5354 virtual Vector<int> get_allowed_size_flags_horizontal() const override;
scene/gui/panel_container.cpp +18 -0
……@@ -50,6 +50,24 @@ Size2 PanelContainer::get_minimum_size() const {
5050 return ms;
5151}
5252
53Size2 PanelContainer::get_desired_size() const {
54 Size2 ds;
55
56 for (int i = 0; i < get_child_count(); i++) {
57 Control *c = as_sortable_control(get_child(i), SortableVisibilityMode::VISIBLE);
58 if (!c) {
59 continue;
60 }
61
62 Size2 minsize = c->get_desired_size();
63 ds = ds.max(minsize);
64 }
65 if (theme_cache.panel_style.is_valid()) {
66 ds += theme_cache.panel_style->get_minimum_size();
67 }
68 return ds;
69}
70
5371Size2 PanelContainer::get_inner_combined_maximum_size() const {
5472 Size2 ms = Container::get_inner_combined_maximum_size();
5573
scene/gui/panel_container.h +1 -0
……@@ -45,6 +45,7 @@ protected:
4545
4646public:
4747 virtual Size2 get_minimum_size() const override;
48 virtual Size2 get_desired_size() const override;
4849 virtual Size2 get_inner_combined_maximum_size() const override;
4950
5051 virtual Vector<int> get_allowed_size_flags_horizontal() const override;
scene/gui/scroll_container.cpp +10 -2
……@@ -40,7 +40,7 @@
4040#include "servers/display/accessibility_server.h"
4141#include "servers/display/display_server.h"
4242
43Size2 ScrollContainer::get_minimum_size() const {
43Size2 ScrollContainer::_get_minimum_size(bool p_use_desired_sizes) const {
4444 // Calculated in this function, as it needs to traverse all child controls once to calculate;
4545 // and needs to be calculated before being used by `_update_scrollbars()`.
4646 largest_child_min_size = Size2();
……@@ -51,7 +51,7 @@ Size2 ScrollContainer::get_minimum_size() const {
5151 continue;
5252 }
5353
54 Size2 child_min_size = c->get_bound_minimum_size();
54 Size2 child_min_size = p_use_desired_sizes ? c->get_bound_desired_size() : c->get_bound_minimum_size();
5555 largest_child_min_size = largest_child_min_size.max(child_min_size);
5656 }
5757
……@@ -93,6 +93,14 @@ Size2 ScrollContainer::get_minimum_size() const {
9393 return min_size;
9494}
9595
96Size2 ScrollContainer::get_minimum_size() const {
97 return _get_minimum_size(false);
98}
99
100Size2 ScrollContainer::get_desired_size() const {
101 return _get_minimum_size(true);
102}
103
96104Size2 ScrollContainer::get_inner_combined_maximum_size() const {
97105 Size2 ms = Container::get_inner_combined_maximum_size();
98106
scene/gui/scroll_container.h +3 -0
……@@ -117,8 +117,11 @@ private:
117117 bool focus_border_is_drawn = false;
118118 bool child_has_focus();
119119
120 Size2 _get_minimum_size(bool p_use_desired_sizes) const;
121
120122protected:
121123 Size2 get_minimum_size() const override;
124 Size2 get_desired_size() const override;
122125 Size2 get_inner_combined_maximum_size() const override;
123126
124127 void _gui_focus_changed(Control *p_control);
scene/gui/split_container.cpp +10 -2
……@@ -1073,7 +1073,7 @@ void SplitContainer::_update_draggers() {
10731073 }
10741074}
10751075
1076Size2 SplitContainer::get_minimum_size() const {
1076Size2 SplitContainer::_get_minimum_size(bool p_use_desired_sizes) const {
10771077 const int sep = _get_separation();
10781078 const int axis = vertical ? 1 : 0;
10791079 const int other_axis = vertical ? 0 : 1;
……@@ -1085,7 +1085,7 @@ Size2 SplitContainer::get_minimum_size() const {
10851085 }
10861086
10871087 for (const Control *child : valid_children) {
1088 const Size2 min_size = child->get_bound_minimum_size();
1088 const Size2 min_size = p_use_desired_sizes ? child->get_bound_desired_size() : child->get_bound_minimum_size();
10891089 minimum[axis] += (int)min_size[axis];
10901090 minimum[other_axis] = (int)MAX(minimum[other_axis], min_size[other_axis]);
10911091 }
……@@ -1093,6 +1093,14 @@ Size2 SplitContainer::get_minimum_size() const {
10931093 return minimum;
10941094}
10951095
1096Size2 SplitContainer::get_minimum_size() const {
1097 return _get_minimum_size(false);
1098}
1099
1100Size2 SplitContainer::get_desired_size() const {
1101 return _get_minimum_size(true);
1102}
1103
10961104void SplitContainer::_validate_property(PropertyInfo &p_property) const {
10971105 if (is_fixed && p_property.name == "vertical") {
10981106 p_property.usage = PROPERTY_USAGE_NONE;
scene/gui/split_container.h +3 -0
……@@ -169,6 +169,8 @@ private:
169169 void _update_nested_ancestors(bool p_remove = false);
170170 void _update_all_nested_descendents(Control *p_control, Control *p_first_child = nullptr);
171171
172 Size2 _get_minimum_size(bool p_use_desired_sizes) const;
173
172174protected:
173175 bool is_fixed = false;
174176
……@@ -207,6 +209,7 @@ public:
207209 bool is_dragging_enabled() const;
208210
209211 virtual Size2 get_minimum_size() const override;
212 virtual Size2 get_desired_size() const override;
210213
211214 virtual Vector<int> get_allowed_size_flags_horizontal() const override;
212215 virtual Vector<int> get_allowed_size_flags_vertical() const override;
scene/gui/tab_bar.cpp +93 -20
……@@ -50,8 +50,6 @@ static inline Color _select_color(const Color &p_override_color, const Color &p_
5050Size2 TabBar::get_minimum_size() const {
5151 Size2 ms;
5252 Size2 combined_max = get_combined_maximum_size();
53 int computed_max_width = 0;
54 bool stop_adding = combined_max.width < 0;
5553
5654 int buttons_size = get_tab_count() > 1 ? theme_cache.decrement_icon->get_width() + theme_cache.increment_icon->get_width() : 0;
5755
……@@ -120,31 +118,18 @@ Size2 TabBar::get_minimum_size() const {
120118 ms.width += theme_cache.tab_separation;
121119 }
122120
123 if (!stop_adding) {
124 int buttons_eff_size = clip_tabs ? (i != tabs.size() - 1 ? buttons_size : 0) : 0;
125 if (computed_max_width + ms.width - ofs + buttons_eff_size >= combined_max.width) {
126 stop_adding = true;
127 } else {
128 computed_max_width += ms.width - ofs;
129 }
130 }
131
132121 if (ms.width - ofs > max_tab_width) {
133122 max_tab_width = ms.width - ofs;
134123 }
135124 }
136125
137126 if (clip_tabs) {
138 int clip_min_width = max_tab_width + buttons_size;
127 ms.width = max_tab_width + buttons_size;
139128 if (combined_max.width >= 0) {
140 int fitted_width = stop_adding ? (computed_max_width + buttons_size) : computed_max_width;
141 ms.width = MAX(clip_min_width, fitted_width);
142129 ms.width = MIN(ms.width, int(combined_max.width));
143 } else {
144 ms.width = clip_min_width;
145130 }
146131 } else if (combined_max.width >= 0) {
147 ms.width = stop_adding ? combined_max.width : MIN(computed_max_width, combined_max.width);
132 ms.width = MIN(ms.width, int(combined_max.width));
148133 }
149134
150135 return ms;
……@@ -507,10 +492,21 @@ void TabBar::_notification(int p_what) {
507492
508493 queue_accessibility_update();
509494 queue_redraw();
495
496 int ofs_old = offset;
497 int max_old = max_drawn_tab;
498
499 _update_cache();
500 _ensure_no_over_offset();
501
502 if (scroll_to_selected && (offset != ofs_old || max_drawn_tab != max_old)) {
503 ensure_tab_visible(current);
504 }
505
506 update_desired_size();
510507 update_minimum_size();
508 } break;
511509
512 [[fallthrough]];
513 }
514510 case NOTIFICATION_RESIZED: {
515511 int ofs_old = offset;
516512 int max_old = max_drawn_tab;
……@@ -813,6 +809,7 @@ void TabBar::set_tab_count(int p_count) {
813809
814810 queue_accessibility_update();
815811 queue_redraw();
812 update_desired_size();
816813 update_minimum_size();
817814 notify_property_list_changed();
818815}
……@@ -943,6 +940,7 @@ void TabBar::set_tab_title(int p_tab, const String &p_title) {
943940 }
944941 queue_accessibility_update();
945942 queue_redraw();
943 update_desired_size();
946944 update_minimum_size();
947945}
948946
……@@ -994,6 +992,7 @@ void TabBar::set_tab_language(int p_tab, const String &p_language) {
994992 }
995993 queue_accessibility_update();
996994 queue_redraw();
995 update_desired_size();
997996 update_minimum_size();
998997 }
999998}
……@@ -1018,6 +1017,7 @@ void TabBar::set_tab_icon(int p_tab, const Ref<Texture2D> &p_icon) {
10181017 ensure_tab_visible(current);
10191018 }
10201019 queue_redraw();
1020 update_desired_size();
10211021 update_minimum_size();
10221022}
10231023
……@@ -1041,6 +1041,7 @@ void TabBar::set_tab_icon_max_width(int p_tab, int p_width) {
10411041 ensure_tab_visible(current);
10421042 }
10431043 queue_redraw();
1044 update_desired_size();
10441045 update_minimum_size();
10451046}
10461047
……@@ -1096,6 +1097,7 @@ void TabBar::set_tab_disabled(int p_tab, bool p_disabled) {
10961097 }
10971098 queue_accessibility_update();
10981099 queue_redraw();
1100 update_desired_size();
10991101 update_minimum_size();
11001102}
11011103
……@@ -1120,6 +1122,7 @@ void TabBar::set_tab_hidden(int p_tab, bool p_hidden) {
11201122 }
11211123 queue_accessibility_update();
11221124 queue_redraw();
1125 update_desired_size();
11231126 update_minimum_size();
11241127}
11251128
……@@ -1153,6 +1156,7 @@ void TabBar::set_tab_button_icon(int p_tab, const Ref<Texture2D> &p_icon) {
11531156 ensure_tab_visible(current);
11541157 }
11551158 queue_redraw();
1159 update_desired_size();
11561160 update_minimum_size();
11571161}
11581162
……@@ -1232,7 +1236,7 @@ void TabBar::_update_cache(bool p_update_hover) {
12321236 int combined_max_width = combined_max.width >= 0 ? int(combined_max.width) - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width() : INT_MAX;
12331237 int effective_max_width = max_width > 0 ? MIN(max_width, combined_max_width) : combined_max_width;
12341238
1235 int limit = combined_max.width > 0 ? combined_max.width : get_size().width;
1239 int limit = combined_max.width > 0 ? MIN(combined_max.width, get_size().width) : get_size().width;
12361240 int limit_minus_buttons = limit - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width();
12371241
12381242 int w = 0;
……@@ -1323,6 +1327,68 @@ void TabBar::_update_cache(bool p_update_hover) {
13231327 }
13241328}
13251329
1330Size2 TabBar::get_desired_size() const {
1331 if (!clip_tabs || tabs.is_empty()) {
1332 return Size2();
1333 }
1334 Size2 combined_max = get_combined_maximum_size();
1335 if (combined_max.width < 0) {
1336 return Size2();
1337 }
1338
1339 int buttons_size = tabs.size() > 1 ? theme_cache.decrement_icon->get_width() + theme_cache.increment_icon->get_width() : 0;
1340 int limit = int(combined_max.width);
1341 int limit_minus_buttons = limit - buttons_size;
1342
1343 int w = 0;
1344 bool overflowed = false;
1345
1346 // First pass: check if all tabs fit without buttons.
1347 for (int i = offset; i < tabs.size(); i++) {
1348 if (tabs[i].hidden) {
1349 continue;
1350 }
1351
1352 int next_w = w + tabs[i].size_cache;
1353 if (i > offset) {
1354 next_w += theme_cache.tab_separation;
1355 }
1356
1357 if (next_w > limit) {
1358 overflowed = true;
1359 break;
1360 }
1361
1362 w = next_w;
1363 }
1364
1365 // If buttons are needed, recompute against the reduced limit.
1366 if (offset > 0 || overflowed) {
1367 w = 0;
1368 for (int i = offset; i < tabs.size(); i++) {
1369 if (tabs[i].hidden) {
1370 continue;
1371 }
1372
1373 int next_w = w + tabs[i].size_cache;
1374 if (i > offset) {
1375 next_w += theme_cache.tab_separation;
1376 }
1377
1378 if (next_w > limit_minus_buttons) {
1379 break;
1380 }
1381
1382 w = next_w;
1383 }
1384 }
1385
1386 int desired = (offset > 0 || overflowed) ? w + buttons_size : w;
1387 desired = MIN(desired, limit);
1388
1389 return Size2(desired, 0);
1390}
1391
13261392void TabBar::_hover_switch_timeout() {
13271393 set_current_tab(hover);
13281394}
……@@ -1352,6 +1418,7 @@ void TabBar::add_tab(const String &p_str, const Ref<Texture2D> &p_icon) {
13521418 }
13531419 queue_accessibility_update();
13541420 queue_redraw();
1421 update_desired_size();
13551422 update_minimum_size();
13561423
13571424 if (!deselect_enabled && tabs.size() == 1) {
……@@ -1383,6 +1450,7 @@ void TabBar::clear_tabs() {
13831450
13841451 queue_accessibility_update();
13851452 queue_redraw();
1453 update_desired_size();
13861454 update_minimum_size();
13871455 notify_property_list_changed();
13881456}
……@@ -1445,6 +1513,7 @@ void TabBar::remove_tab(int p_idx) {
14451513
14461514 queue_accessibility_update();
14471515 queue_redraw();
1516 update_desired_size();
14481517 update_minimum_size();
14491518 notify_property_list_changed();
14501519
……@@ -1653,6 +1722,7 @@ void TabBar::_move_tab_from(TabBar *p_from_tabbar, int p_from_index, int p_to_in
16531722 }
16541723
16551724 queue_accessibility_update();
1725 update_desired_size();
16561726 update_minimum_size();
16571727}
16581728
……@@ -1733,6 +1803,7 @@ void TabBar::set_clip_tabs(bool p_clip_tabs) {
17331803 ensure_tab_visible(current);
17341804 }
17351805 queue_redraw();
1806 update_desired_size();
17361807 update_minimum_size();
17371808}
17381809
……@@ -1988,6 +2059,7 @@ void TabBar::set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy) {
19882059 ensure_tab_visible(current);
19892060 }
19902061 queue_redraw();
2062 update_desired_size();
19912063 update_minimum_size();
19922064}
19932065
……@@ -2010,6 +2082,7 @@ void TabBar::set_max_tab_width(int p_width) {
20102082 ensure_tab_visible(current);
20112083 }
20122084 queue_redraw();
2085 update_desired_size();
20132086 update_minimum_size();
20142087}
20152088
scene/gui/tab_bar.h +1 -0
……@@ -334,6 +334,7 @@ public:
334334
335335 Rect2 get_tab_rect(int p_tab) const;
336336 Size2 get_minimum_size() const override;
337 Size2 get_desired_size() const override;
337338
338339 TabBar();
339340};
scene/gui/tab_container.cpp +17 -4
……@@ -266,6 +266,7 @@ void TabContainer::_on_theme_changed() {
266266 _repaint();
267267 } else {
268268 update_minimum_size();
269 update_desired_size();
269270 }
270271 queue_redraw();
271272
……@@ -933,6 +934,7 @@ void TabContainer::set_tab_disabled(int p_tab, bool p_disabled) {
933934 tab_bar->set_tab_disabled(p_tab, p_disabled);
934935
935936 _update_margins();
937 update_desired_size();
936938 if (!get_clip_tabs()) {
937939 update_minimum_size();
938940 }
……@@ -958,6 +960,7 @@ void TabContainer::set_tab_hidden(int p_tab, bool p_hidden) {
958960 child->hide();
959961
960962 _update_margins();
963 update_desired_size();
961964 if (!get_clip_tabs()) {
962965 update_minimum_size();
963966 }
……@@ -987,16 +990,16 @@ Ref<Texture2D> TabContainer::get_tab_button_icon(int p_tab) const {
987990 return tab_bar->get_tab_button_icon(p_tab);
988991}
989992
990Size2 TabContainer::get_minimum_size() const {
993Size2 TabContainer::_get_minimum_size(bool p_use_desired_sizes) const {
991994 Size2 ms;
992995
993996 if (tabs_visible) {
994 ms = tab_bar->get_minimum_size();
997 ms = p_use_desired_sizes ? tab_bar->get_bound_desired_size() : tab_bar->get_minimum_size();
995998 ms.width += theme_cache.tabbar_style->get_margin(SIDE_LEFT) + theme_cache.tabbar_style->get_margin(SIDE_RIGHT);
996999 ms.height += theme_cache.tabbar_style->get_margin(SIDE_TOP) + theme_cache.tabbar_style->get_margin(SIDE_BOTTOM);
9971000
9981001 if (get_popup()) {
999 ms.width += popup_button->get_minimum_size().x;
1002 ms.width += p_use_desired_sizes ? popup_button->get_bound_desired_size().x : popup_button->get_minimum_size().x;
10001003 }
10011004
10021005 if (theme_cache.side_margin > 0 && get_tab_alignment() != TabBar::ALIGNMENT_CENTER &&
……@@ -1014,7 +1017,7 @@ Size2 TabContainer::get_minimum_size() const {
10141017 continue;
10151018 }
10161019
1017 Size2 cms = c->get_bound_minimum_size();
1020 Size2 cms = p_use_desired_sizes ? c->get_bound_desired_size() : c->get_bound_minimum_size();
10181021 largest_child_min_size = largest_child_min_size.max(cms);
10191022 }
10201023 ms.height += largest_child_min_size.height;
……@@ -1027,6 +1030,14 @@ Size2 TabContainer::get_minimum_size() const {
10271030 return ms;
10281031}
10291032
1033Size2 TabContainer::get_minimum_size() const {
1034 return _get_minimum_size(false);
1035}
1036
1037Size2 TabContainer::get_desired_size() const {
1038 return _get_minimum_size(true);
1039}
1040
10301041Size2 TabContainer::get_inner_combined_maximum_size() const {
10311042 Size2 ms = Container::get_inner_combined_maximum_size();
10321043
……@@ -1105,6 +1116,7 @@ void TabContainer::set_popup(Node *p_popup) {
11051116 popup_button->set_visible(popup != nullptr);
11061117 _update_margins();
11071118 update_minimum_size();
1119 update_desired_size();
11081120 }
11091121}
11101122
……@@ -1155,6 +1167,7 @@ void TabContainer::set_use_hidden_tabs_for_min_size(bool p_use_hidden_tabs) {
11551167
11561168 use_hidden_tabs_for_min_size = p_use_hidden_tabs;
11571169 update_minimum_size();
1170 update_desired_size();
11581171}
11591172
11601173bool TabContainer::get_use_hidden_tabs_for_min_size() const {
scene/gui/tab_container.h +3 -0
……@@ -152,6 +152,8 @@ private:
152152 void _popup_button_hovered(bool p_hover);
153153 void _popup_button_pressed();
154154
155 Size2 _get_minimum_size(bool p_use_desired_sizes) const;
156
155157protected:
156158 bool _set(const StringName &p_name, const Variant &p_value) { return property_helper.property_set_value(p_name, p_value); }
157159 bool _get(const StringName &p_name, Variant &r_ret) const { return property_helper.property_get_value(p_name, r_ret); }
……@@ -236,6 +238,7 @@ public:
236238
237239 virtual Size2 get_minimum_size() const override;
238240 virtual Size2 get_inner_combined_maximum_size() const override;
241 virtual Size2 get_desired_size() const override;
239242
240243 void set_popup(Node *p_popup);
241244 Popup *get_popup() const;
tests/scene/test_label.cpp +3 -1
……@@ -32,6 +32,8 @@
3232
3333TEST_FORCE_LINK(test_label)
3434
35#include "modules/modules_enabled.gen.h" // IWYU pragma: keep. Needed for MODULE_TEXT_SERVER_FB_ENABLED and MODULE_TEXT_SERVER_ADV_ENABLED definitions.
36
3537#if defined(MODULE_TEXT_SERVER_FB_ENABLED) || defined(MODULE_TEXT_SERVER_ADV_ENABLED)
3638
3739#include "scene/gui/label.h"
……@@ -139,7 +141,7 @@ TEST_CASE("[SceneTree][Label] Sizing") {
139141 real_t max_width = 50;
140142 real_t min_width = 25;
141143
142 test_label->set_custom_maximum_size(Size2(max_width, 0));
144 test_label->set_custom_maximum_size(Size2(max_width, -1));
143145 test_label->set_custom_minimum_size(Size2(min_width, 0));
144146 test_label->set_text("This is a long text that should be wrapped and exceeds minimum size.");
145147 SceneTree::get_singleton()->process(0);