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`.
This commit is contained in:
1 parent
6d6e822c68
commit
05737cd449
33 files changed
+454
-72
No files matched your search
@@ -288,7 +288,7 @@ void BoxContainer::_resort() {
|
||||
}
|
||||
}
|
||||
|
||||
Size2 BoxContainer::get_minimum_size() const {
|
||||
Size2 BoxContainer::_get_minimum_size(bool p_use_desired_sizes) const {
|
||||
/* Calculate MINIMUM SIZE */
|
||||
|
||||
Size2i minimum;
|
||||
@@ -301,7 +301,7 @@ Size2 BoxContainer::get_minimum_size() const {
|
||||
continue;
|
||||
}
|
||||
|
||||
Size2i size = c->get_bound_minimum_size();
|
||||
Size2i size = p_use_desired_sizes ? c->get_bound_desired_size() : c->get_bound_minimum_size();
|
||||
|
||||
if (vertical) { /* VERTICAL */
|
||||
|
||||
@@ -326,6 +326,14 @@ Size2 BoxContainer::get_minimum_size() const {
|
||||
return minimum;
|
||||
}
|
||||
|
||||
Size2 BoxContainer::get_minimum_size() const {
|
||||
return _get_minimum_size(false);
|
||||
}
|
||||
|
||||
Size2 BoxContainer::get_desired_size() const {
|
||||
return _get_minimum_size(true);
|
||||
}
|
||||
|
||||
void BoxContainer::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_SORT_CHILDREN: {
|
||||
|
||||
@@ -51,6 +51,7 @@ private:
|
||||
} theme_cache;
|
||||
|
||||
void _resort();
|
||||
Size2 _get_minimum_size(bool p_use_desired_sizes) const;
|
||||
|
||||
protected:
|
||||
bool is_fixed = false;
|
||||
@@ -69,6 +70,7 @@ public:
|
||||
bool is_vertical() const;
|
||||
|
||||
virtual Size2 get_minimum_size() const override;
|
||||
virtual Size2 get_desired_size() const override;
|
||||
|
||||
virtual Vector<int> get_allowed_size_flags_horizontal() const override;
|
||||
virtual Vector<int> get_allowed_size_flags_vertical() const override;
|
||||
|
||||
@@ -49,6 +49,23 @@ Size2 CenterContainer::get_minimum_size() const {
|
||||
return ms;
|
||||
}
|
||||
|
||||
Size2 CenterContainer::get_desired_size() const {
|
||||
if (use_top_left) {
|
||||
return Size2();
|
||||
}
|
||||
Size2 ds;
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
Control *c = as_sortable_control(get_child(i), SortableVisibilityMode::VISIBLE);
|
||||
if (!c) {
|
||||
continue;
|
||||
}
|
||||
Size2 minsize = c->get_bound_desired_size();
|
||||
ds = ds.max(minsize);
|
||||
}
|
||||
|
||||
return ds;
|
||||
}
|
||||
|
||||
void CenterContainer::set_use_top_left(bool p_enable) {
|
||||
if (use_top_left == p_enable) {
|
||||
return;
|
||||
|
||||
@@ -46,6 +46,7 @@ public:
|
||||
bool is_using_top_left() const;
|
||||
|
||||
virtual Size2 get_minimum_size() const override;
|
||||
virtual Size2 get_desired_size() const override;
|
||||
|
||||
virtual Vector<int> get_allowed_size_flags_horizontal() const override;
|
||||
virtual Vector<int> get_allowed_size_flags_vertical() const override;
|
||||
|
||||
@@ -39,6 +39,11 @@ void Container::_child_minsize_changed() {
|
||||
queue_sort();
|
||||
}
|
||||
|
||||
void Container::_child_desired_size_changed() {
|
||||
update_desired_size();
|
||||
queue_sort();
|
||||
}
|
||||
|
||||
void Container::add_child_notify(Node *p_child) {
|
||||
Control::add_child_notify(p_child);
|
||||
|
||||
@@ -50,6 +55,7 @@ void Container::add_child_notify(Node *p_child) {
|
||||
control->connect(SceneStringName(size_flags_changed), callable_mp(this, &Container::queue_sort));
|
||||
control->connect(SceneStringName(minimum_size_changed), callable_mp(this, &Container::_child_minsize_changed));
|
||||
control->connect(SceneStringName(maximum_size_changed), callable_mp(this, &Container::_child_minsize_changed));
|
||||
control->connect("_desired_size_changed", callable_mp(this, &Container::_child_desired_size_changed));
|
||||
control->connect(SceneStringName(visibility_changed), callable_mp(this, &Container::_child_minsize_changed));
|
||||
|
||||
update_minimum_size();
|
||||
@@ -78,6 +84,7 @@ void Container::remove_child_notify(Node *p_child) {
|
||||
control->disconnect(SceneStringName(size_flags_changed), callable_mp(this, &Container::queue_sort));
|
||||
control->disconnect(SceneStringName(minimum_size_changed), callable_mp(this, &Container::_child_minsize_changed));
|
||||
control->disconnect(SceneStringName(maximum_size_changed), callable_mp(this, &Container::_child_minsize_changed));
|
||||
control->disconnect("_desired_size_changed", callable_mp(this, &Container::_child_desired_size_changed));
|
||||
control->disconnect(SceneStringName(visibility_changed), callable_mp(this, &Container::_child_minsize_changed));
|
||||
|
||||
update_minimum_size();
|
||||
@@ -105,6 +112,7 @@ void Container::fit_child_in_rect(RequiredParam<Control> rp_child, const Rect2 &
|
||||
|
||||
bool rtl = is_layout_rtl();
|
||||
Size2 minsize = p_child->get_combined_minimum_size();
|
||||
Size2 desired_size = p_child->get_bound_desired_size();
|
||||
Size2 maxsize = p_child->get_combined_maximum_size();
|
||||
Rect2 r = p_rect;
|
||||
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 &
|
||||
|
||||
if (!h_size_flags.has_flag(SIZE_FILL)) {
|
||||
float final_width = minsize.width;
|
||||
final_width = MAX(MIN(desired_size.width, r.size.width), final_width);
|
||||
if (maxsize.width >= 0) {
|
||||
final_width = MIN(final_width, maxsize.width);
|
||||
}
|
||||
@@ -127,6 +136,7 @@ void Container::fit_child_in_rect(RequiredParam<Control> rp_child, const Rect2 &
|
||||
|
||||
if (!v_size_flags.has_flag(SIZE_FILL)) {
|
||||
float final_height = minsize.y;
|
||||
final_height = MAX(MIN(desired_size.y, r.size.y), final_height);
|
||||
if (maxsize.height >= 0) {
|
||||
final_height = MIN(final_height, maxsize.height);
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ class Container : public Control {
|
||||
bool accessibility_region = false;
|
||||
void _sort_children();
|
||||
void _child_minsize_changed();
|
||||
void _child_desired_size_changed();
|
||||
|
||||
protected:
|
||||
enum class SortableVisibilityMode {
|
||||
|
||||
@@ -1550,6 +1550,8 @@ void Control::set_size(const Size2 &p_size, bool p_keep_offsets) {
|
||||
}
|
||||
#endif // TOOLS_ENABLED
|
||||
|
||||
data.expanded_by_desired_size = false;
|
||||
|
||||
if (p_keep_offsets) {
|
||||
_compute_anchors(Rect2(data.pos_cache, new_size), data.offset, data.anchor);
|
||||
} else {
|
||||
@@ -1761,6 +1763,11 @@ void Control::update_maximum_size() {
|
||||
data.updating_last_minimum_size = true;
|
||||
callable_mp(this, &Control::_update_minimum_size).call_deferred();
|
||||
}
|
||||
// Same with desired size.
|
||||
if (!data.updating_last_desired_size) {
|
||||
data.updating_last_desired_size = true;
|
||||
callable_mp(this, &Control::_update_desired_size).call_deferred();
|
||||
}
|
||||
|
||||
callable_mp(this, &Control::_update_maximum_size).call_deferred();
|
||||
}
|
||||
@@ -1948,6 +1955,107 @@ Size2 Control::get_custom_minimum_size() const {
|
||||
return data.custom_minimum_size;
|
||||
}
|
||||
|
||||
void Control::_update_desired_size_cache() const {
|
||||
Size2 desired_size = get_desired_size();
|
||||
|
||||
data.desired_size_cache = desired_size;
|
||||
data.desired_size_valid = true;
|
||||
}
|
||||
|
||||
void Control::_update_desired_size() {
|
||||
if (!is_inside_tree()) {
|
||||
data.updating_last_desired_size = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Size2 desired_size = get_desired_size();
|
||||
data.updating_last_desired_size = false;
|
||||
|
||||
if (desired_size != data.last_desired_size) {
|
||||
data.last_desired_size = desired_size;
|
||||
grow_to_desired_size();
|
||||
emit_signal("_desired_size_changed");
|
||||
}
|
||||
}
|
||||
|
||||
void Control::update_desired_size() {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Invalidate cache upwards.
|
||||
Control *invalidate = this;
|
||||
while (invalidate && invalidate->data.desired_size_valid) {
|
||||
invalidate->data.desired_size_valid = false;
|
||||
if (invalidate->is_set_as_top_level()) {
|
||||
break; // Do not go further up.
|
||||
}
|
||||
|
||||
Window *parent_window = invalidate->get_parent_window();
|
||||
if (parent_window && parent_window->is_wrapping_controls()) {
|
||||
parent_window->child_controls_changed();
|
||||
break; // Stop on a window as well.
|
||||
}
|
||||
|
||||
invalidate = invalidate->get_parent_control();
|
||||
}
|
||||
|
||||
if (!is_visible_in_tree()) {
|
||||
// Invalidate the last desired size so it will update when made visible.
|
||||
data.last_desired_size = Size2(-1, -1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.updating_last_desired_size) {
|
||||
return;
|
||||
}
|
||||
data.updating_last_desired_size = true;
|
||||
|
||||
callable_mp(this, &Control::_update_desired_size).call_deferred();
|
||||
}
|
||||
|
||||
Size2 Control::get_bound_desired_size() const {
|
||||
ERR_READ_THREAD_GUARD_V(Size2());
|
||||
if (!data.desired_size_valid) {
|
||||
_update_desired_size_cache();
|
||||
}
|
||||
Size2 desired_size = data.desired_size_cache;
|
||||
desired_size = desired_size.max(get_combined_minimum_size());
|
||||
Size2 max_size = get_combined_maximum_size();
|
||||
if (max_size.x >= 0) {
|
||||
desired_size.x = MIN(desired_size.x, max_size.x);
|
||||
}
|
||||
if (max_size.y >= 0) {
|
||||
desired_size.y = MIN(desired_size.y, max_size.y);
|
||||
}
|
||||
return desired_size;
|
||||
}
|
||||
|
||||
Size2 Control::get_desired_size() const {
|
||||
return Size2();
|
||||
}
|
||||
|
||||
void Control::grow_to_desired_size() {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
if (!is_inside_tree()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Size2 desired_size = get_bound_desired_size();
|
||||
if (desired_size <= get_combined_minimum_size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.expanded_by_desired_size) {
|
||||
set_size(desired_size);
|
||||
data.expanded_by_desired_size = true;
|
||||
} else if (desired_size.x > get_size().x || desired_size.y > get_size().y) {
|
||||
set_size(desired_size);
|
||||
data.expanded_by_desired_size = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Control::add_child_notify(Node *p_child) {
|
||||
CanvasItem::add_child_notify(p_child);
|
||||
|
||||
@@ -2021,6 +2129,9 @@ void Control::_update_minimum_size_cache() const {
|
||||
|
||||
data.minimum_size_cache = minsize;
|
||||
data.minimum_size_valid = true;
|
||||
|
||||
// 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.
|
||||
data.desired_size_valid = false;
|
||||
}
|
||||
|
||||
Size2 Control::get_combined_minimum_size() const {
|
||||
@@ -5024,6 +5135,7 @@ void Control::_bind_methods() {
|
||||
ADD_SIGNAL(MethodInfo("size_flags_changed"));
|
||||
ADD_SIGNAL(MethodInfo("maximum_size_changed"));
|
||||
ADD_SIGNAL(MethodInfo("minimum_size_changed"));
|
||||
ADD_SIGNAL(MethodInfo("_desired_size_changed"));
|
||||
ADD_SIGNAL(MethodInfo("theme_changed"));
|
||||
|
||||
GDVIRTUAL_BIND(_has_point, "point");
|
||||
|
||||
@@ -256,6 +256,14 @@ private:
|
||||
bool updating_last_minimum_size = false;
|
||||
bool block_minimum_size_adjust = false;
|
||||
|
||||
mutable Size2 desired_size_cache;
|
||||
mutable bool desired_size_valid = false;
|
||||
|
||||
Size2 last_desired_size;
|
||||
bool updating_last_desired_size = false;
|
||||
|
||||
bool expanded_by_desired_size = false;
|
||||
|
||||
bool layout_pending = false;
|
||||
|
||||
bool size_warning = true;
|
||||
@@ -371,6 +379,9 @@ private:
|
||||
void _update_maximum_size();
|
||||
void _update_minimum_size_cache() const;
|
||||
void _update_minimum_size();
|
||||
void _update_desired_size_cache() const;
|
||||
void _update_desired_size();
|
||||
void _grow_to_desired_size();
|
||||
void _size_changed();
|
||||
|
||||
void _top_level_changed() override {} // Controls don't need to do anything, only other CanvasItems.
|
||||
@@ -603,6 +614,9 @@ public:
|
||||
|
||||
void update_maximum_size();
|
||||
void update_minimum_size();
|
||||
void update_desired_size();
|
||||
|
||||
void grow_to_desired_size();
|
||||
|
||||
void set_block_maximum_size_adjust(bool p_block);
|
||||
void set_block_minimum_size_adjust(bool p_block);
|
||||
@@ -624,6 +638,9 @@ public:
|
||||
|
||||
virtual Size2 get_bound_minimum_size() const;
|
||||
|
||||
Size2 get_bound_desired_size() const;
|
||||
virtual Size2 get_desired_size() const;
|
||||
|
||||
bool is_layout_pending() const;
|
||||
bool is_layout_pending_in_tree() const;
|
||||
void layout_pending_start();
|
||||
|
||||
@@ -347,7 +347,7 @@ void FlowContainer::_resort() {
|
||||
cached_line_max_child_count = lines_data.size() > 0 ? lines_data[0].child_count : 0;
|
||||
}
|
||||
|
||||
Size2 FlowContainer::get_minimum_size() const {
|
||||
Size2 FlowContainer::_get_minimum_size(bool p_use_desired_sizes) const {
|
||||
Size2i minimum;
|
||||
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
@@ -356,7 +356,7 @@ Size2 FlowContainer::get_minimum_size() const {
|
||||
continue;
|
||||
}
|
||||
|
||||
Size2i size = c->get_bound_minimum_size();
|
||||
Size2i size = p_use_desired_sizes ? c->get_bound_desired_size() : c->get_bound_minimum_size();
|
||||
|
||||
if (vertical) { /* VERTICAL */
|
||||
minimum.height = MAX(minimum.height, size.height);
|
||||
@@ -371,6 +371,14 @@ Size2 FlowContainer::get_minimum_size() const {
|
||||
return minimum;
|
||||
}
|
||||
|
||||
Size2 FlowContainer::get_minimum_size() const {
|
||||
return _get_minimum_size(false);
|
||||
}
|
||||
|
||||
Size2 FlowContainer::get_desired_size() const {
|
||||
return _get_minimum_size(true);
|
||||
}
|
||||
|
||||
Vector<int> FlowContainer::get_allowed_size_flags_horizontal() const {
|
||||
Vector<int> flags;
|
||||
flags.append(SIZE_FILL);
|
||||
|
||||
@@ -64,6 +64,7 @@ private:
|
||||
} theme_cache;
|
||||
|
||||
void _resort();
|
||||
Size2 _get_minimum_size(bool p_use_desired_sizes) const;
|
||||
|
||||
protected:
|
||||
bool is_fixed = false;
|
||||
@@ -89,6 +90,7 @@ public:
|
||||
bool is_reverse_fill() const;
|
||||
|
||||
virtual Size2 get_minimum_size() const override;
|
||||
virtual Size2 get_desired_size() const override;
|
||||
|
||||
virtual Vector<int> get_allowed_size_flags_horizontal() const override;
|
||||
virtual Vector<int> get_allowed_size_flags_vertical() const override;
|
||||
|
||||
@@ -54,6 +54,26 @@ Size2 FoldableContainer::get_minimum_size() const {
|
||||
return Size2(MAX(ms.width, title_minimum_size.width), ms.height + title_minimum_size.height);
|
||||
}
|
||||
|
||||
Size2 FoldableContainer::get_desired_size() const {
|
||||
_update_title_min_size();
|
||||
|
||||
if (folded) {
|
||||
return title_minimum_size;
|
||||
}
|
||||
Size2 ds;
|
||||
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
Control *c = as_sortable_control(get_child(i));
|
||||
if (!c) {
|
||||
continue;
|
||||
}
|
||||
ds = ds.max(c->get_bound_desired_size());
|
||||
}
|
||||
ds += theme_cache.panel_style->get_minimum_size();
|
||||
|
||||
return Size2(MAX(ds.width, title_minimum_size.width), ds.height + title_minimum_size.height);
|
||||
}
|
||||
|
||||
Size2 FoldableContainer::get_inner_combined_maximum_size() const {
|
||||
Size2 ms = Container::get_inner_combined_maximum_size();
|
||||
|
||||
|
||||
@@ -138,6 +138,7 @@ public:
|
||||
void remove_title_bar_control(Control *p_control);
|
||||
|
||||
virtual Size2 get_minimum_size() const override;
|
||||
virtual Size2 get_desired_size() const override;
|
||||
virtual Size2 get_inner_combined_maximum_size() const override;
|
||||
|
||||
virtual Vector<int> get_allowed_size_flags_horizontal() const override { return { SIZE_FILL, SIZE_SHRINK_BEGIN, SIZE_SHRINK_CENTER, SIZE_SHRINK_END }; }
|
||||
|
||||
@@ -323,11 +323,11 @@ bool GraphFrame::has_point(const Point2 &p_point) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
Size2 GraphFrame::get_minimum_size() const {
|
||||
Size2 GraphFrame::_get_minimum_size(bool p_use_desired_sizes) const {
|
||||
Ref<StyleBox> sb_panel = theme_cache.panel;
|
||||
Ref<StyleBox> sb_titlebar = theme_cache.titlebar;
|
||||
|
||||
Size2 minsize = titlebar_hbox->get_minimum_size() + sb_titlebar->get_minimum_size();
|
||||
Size2 minsize = (p_use_desired_sizes ? titlebar_hbox->get_bound_desired_size() : titlebar_hbox->get_minimum_size()) + sb_titlebar->get_minimum_size();
|
||||
|
||||
for (int i = 0; i < get_child_count(false); i++) {
|
||||
Control *child = as_sortable_control(get_child(i, false));
|
||||
@@ -335,7 +335,7 @@ Size2 GraphFrame::get_minimum_size() const {
|
||||
continue;
|
||||
}
|
||||
|
||||
Size2i size = child->get_bound_minimum_size();
|
||||
Size2i size = p_use_desired_sizes ? child->get_bound_desired_size() : child->get_bound_minimum_size();
|
||||
size.width += sb_panel->get_minimum_size().width;
|
||||
|
||||
minsize.x = MAX(minsize.x, size.x);
|
||||
@@ -347,6 +347,14 @@ Size2 GraphFrame::get_minimum_size() const {
|
||||
return minsize;
|
||||
}
|
||||
|
||||
Size2 GraphFrame::get_minimum_size() const {
|
||||
return _get_minimum_size(false);
|
||||
}
|
||||
|
||||
Size2 GraphFrame::get_desired_size() const {
|
||||
return _get_minimum_size(true);
|
||||
}
|
||||
|
||||
GraphFrame::GraphFrame() {
|
||||
titlebar_hbox = memnew(HBoxContainer);
|
||||
titlebar_hbox->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
|
||||
@@ -60,6 +60,8 @@ private:
|
||||
bool tint_color_enabled = false;
|
||||
Color tint_color = Color(0.3, 0.3, 0.3, 0.75);
|
||||
|
||||
Size2 _get_minimum_size(bool p_use_desired_sizes) const;
|
||||
|
||||
protected:
|
||||
virtual void gui_input(const Ref<InputEvent> &p_event) override;
|
||||
virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override;
|
||||
@@ -95,6 +97,7 @@ public:
|
||||
|
||||
virtual bool has_point(const Point2 &p_point) const override;
|
||||
virtual Size2 get_minimum_size() const override;
|
||||
virtual Size2 get_desired_size() const override;
|
||||
|
||||
GraphFrame();
|
||||
};
|
||||
@@ -996,13 +996,13 @@ bool GraphNode::is_ignoring_valid_connection_type() const {
|
||||
return ignore_invalid_connection_type;
|
||||
}
|
||||
|
||||
Size2 GraphNode::get_minimum_size() const {
|
||||
Size2 GraphNode::_get_minimum_size(bool p_use_desired_sizes) const {
|
||||
Ref<StyleBox> sb_panel = theme_cache.panel;
|
||||
Ref<StyleBox> sb_titlebar = theme_cache.titlebar;
|
||||
Ref<StyleBox> sb_slot = theme_cache.slot;
|
||||
|
||||
int separation = theme_cache.separation;
|
||||
Size2 minsize = titlebar_hbox->get_minimum_size() + sb_titlebar->get_minimum_size();
|
||||
Size2 minsize = (p_use_desired_sizes ? titlebar_hbox->get_bound_desired_size() : titlebar_hbox->get_minimum_size()) + sb_titlebar->get_minimum_size();
|
||||
|
||||
for (int i = 0; i < get_child_count(false); i++) {
|
||||
Control *child = as_sortable_control(get_child(i, false));
|
||||
@@ -1010,7 +1010,7 @@ Size2 GraphNode::get_minimum_size() const {
|
||||
continue;
|
||||
}
|
||||
|
||||
Size2i size = child->get_bound_minimum_size();
|
||||
Size2i size = p_use_desired_sizes ? child->get_bound_desired_size() : child->get_bound_minimum_size();
|
||||
size.width += sb_panel->get_minimum_size().width;
|
||||
if (slot_table.has(i)) {
|
||||
size += slot_table[i].draw_stylebox ? sb_slot->get_minimum_size() : Size2();
|
||||
@@ -1029,6 +1029,14 @@ Size2 GraphNode::get_minimum_size() const {
|
||||
return minsize;
|
||||
}
|
||||
|
||||
Size2 GraphNode::get_minimum_size() const {
|
||||
return _get_minimum_size(false);
|
||||
}
|
||||
|
||||
Size2 GraphNode::get_desired_size() const {
|
||||
return _get_minimum_size(true);
|
||||
}
|
||||
|
||||
void GraphNode::_port_pos_update() {
|
||||
int edgeofs = theme_cache.port_h_offset;
|
||||
int separation = theme_cache.separation;
|
||||
|
||||
@@ -115,6 +115,8 @@ class GraphNode : public GraphElement {
|
||||
|
||||
void _port_pos_update();
|
||||
|
||||
Size2 _get_minimum_size(bool p_use_desired_sizes) const;
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
static void _bind_methods();
|
||||
@@ -195,6 +197,7 @@ public:
|
||||
Control::FocusMode get_slots_focus_mode() const;
|
||||
|
||||
virtual Size2 get_minimum_size() const override;
|
||||
virtual Size2 get_desired_size() const override;
|
||||
|
||||
virtual CursorShape get_cursor_shape(const Point2 &p_pos = Point2i()) const override;
|
||||
|
||||
|
||||
@@ -378,7 +378,7 @@ void GridContainer::_bind_methods() {
|
||||
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, GridContainer, v_separation);
|
||||
}
|
||||
|
||||
Size2 GridContainer::get_minimum_size() const {
|
||||
Size2 GridContainer::_get_minimum_size(bool p_use_desired_sizes) const {
|
||||
RBMap<int, int> col_minw;
|
||||
RBMap<int, int> row_minh;
|
||||
|
||||
@@ -395,7 +395,7 @@ Size2 GridContainer::get_minimum_size() const {
|
||||
int col = valid_controls_index % columns;
|
||||
valid_controls_index++;
|
||||
|
||||
Size2i ms = c->get_bound_minimum_size();
|
||||
Size2i ms = p_use_desired_sizes ? c->get_bound_desired_size() : c->get_bound_minimum_size();
|
||||
if (col_minw.has(col)) {
|
||||
col_minw[col] = MAX(col_minw[col], ms.width);
|
||||
} else {
|
||||
@@ -426,3 +426,11 @@ Size2 GridContainer::get_minimum_size() const {
|
||||
|
||||
return ms;
|
||||
}
|
||||
|
||||
Size2 GridContainer::get_minimum_size() const {
|
||||
return _get_minimum_size(false);
|
||||
}
|
||||
|
||||
Size2 GridContainer::get_desired_size() const {
|
||||
return _get_minimum_size(true);
|
||||
}
|
||||
@@ -44,6 +44,7 @@ class GridContainer : public Container {
|
||||
|
||||
private:
|
||||
void _resort();
|
||||
Size2 _get_minimum_size(bool p_use_desired_sizes) const;
|
||||
|
||||
protected:
|
||||
void _notification(int p_what);
|
||||
@@ -53,6 +54,7 @@ public:
|
||||
void set_columns(int p_columns);
|
||||
int get_columns() const;
|
||||
virtual Size2 get_minimum_size() const override;
|
||||
virtual Size2 get_desired_size() const override;
|
||||
|
||||
int get_h_separation() const;
|
||||
};
|
||||
+26
-24
@@ -53,6 +53,7 @@ void Label::set_autowrap_mode(TextServer::AutowrapMode p_mode) {
|
||||
if (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
|
||||
update_minimum_size();
|
||||
}
|
||||
update_desired_size();
|
||||
}
|
||||
|
||||
TextServer::AutowrapMode Label::get_autowrap_mode() const {
|
||||
@@ -74,6 +75,7 @@ void Label::set_autowrap_trim_flags(BitField<TextServer::LineBreakFlag> p_flags)
|
||||
if (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
|
||||
update_minimum_size();
|
||||
}
|
||||
update_desired_size();
|
||||
}
|
||||
|
||||
BitField<TextServer::LineBreakFlag> Label::get_autowrap_trim_flags() const {
|
||||
@@ -152,11 +154,7 @@ void Label::_shape() const {
|
||||
if (maximum_width <= 0) {
|
||||
maximum_width = 1;
|
||||
}
|
||||
if (width > 0) {
|
||||
width = MIN(width, maximum_width);
|
||||
} else {
|
||||
width = maximum_width;
|
||||
}
|
||||
width = maximum_width;
|
||||
}
|
||||
|
||||
if (text_dirty) {
|
||||
@@ -914,6 +912,7 @@ void Label::_notification(int p_what) {
|
||||
case NOTIFICATION_THEME_CHANGED: {
|
||||
font_dirty = true;
|
||||
queue_redraw();
|
||||
update_desired_size();
|
||||
update_configuration_warnings();
|
||||
} break;
|
||||
|
||||
@@ -993,9 +992,6 @@ Size2 Label::get_minimum_size() const {
|
||||
_ensure_shaped();
|
||||
|
||||
Size2 min_size = minsize;
|
||||
Size2 combined_maximum_size = get_combined_maximum_size();
|
||||
bool wrap_with_max_width = autowrap_mode != TextServer::AUTOWRAP_OFF && combined_maximum_size.x > 0;
|
||||
bool overrun_with_max_width = autowrap_mode == TextServer::AUTOWRAP_OFF && combined_maximum_size.x > 0 && (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING);
|
||||
|
||||
const Ref<Font> &font = (settings.is_valid() && settings->get_font().is_valid()) ? settings->get_font() : theme_cache.font;
|
||||
int font_size = settings.is_valid() ? settings->get_font_size() : theme_cache.font_size;
|
||||
@@ -1010,28 +1006,29 @@ Size2 Label::get_minimum_size() const {
|
||||
} else if (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
|
||||
min_size.height = 1;
|
||||
}
|
||||
if (wrap_with_max_width) {
|
||||
min_size.width = MAX(1, min_size.width);
|
||||
return min_size + min_style;
|
||||
} else {
|
||||
return Size2(1, min_size.height) + min_style;
|
||||
}
|
||||
return Size2(1, min_size.height) + min_style;
|
||||
} else {
|
||||
if (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
|
||||
if (overrun_with_max_width) {
|
||||
min_size.width = MAX(1, min_size.width);
|
||||
} else {
|
||||
min_size.width = 1;
|
||||
}
|
||||
min_size.width = 1;
|
||||
}
|
||||
Size2 computed_min_size = min_size + min_style;
|
||||
if (overrun_with_max_width) {
|
||||
computed_min_size.width = MIN(computed_min_size.width, combined_maximum_size.x);
|
||||
}
|
||||
return computed_min_size;
|
||||
return min_size + min_style;
|
||||
}
|
||||
}
|
||||
|
||||
Size2 Label::get_desired_size() const {
|
||||
Size2 combined_max = get_combined_maximum_size();
|
||||
if (combined_max.width < 0) {
|
||||
return Size2();
|
||||
}
|
||||
|
||||
_ensure_shaped();
|
||||
Size2 min_style = theme_cache.normal_style->get_minimum_size();
|
||||
Size2 content_size = minsize + min_style;
|
||||
content_size.width = MIN(content_size.width, int(combined_max.width));
|
||||
|
||||
return content_size;
|
||||
}
|
||||
|
||||
#ifndef DISABLE_DEPRECATED
|
||||
bool Label::_set(const StringName &p_name, const Variant &p_value) {
|
||||
if (p_name == SNAME("valign")) {
|
||||
@@ -1144,6 +1141,7 @@ void Label::set_text(const String &p_string) {
|
||||
queue_accessibility_update();
|
||||
queue_redraw();
|
||||
update_minimum_size();
|
||||
update_desired_size();
|
||||
update_configuration_warnings();
|
||||
}
|
||||
|
||||
@@ -1163,6 +1161,7 @@ void Label::_maximum_size_changed() {
|
||||
}
|
||||
queue_redraw();
|
||||
update_minimum_size();
|
||||
update_desired_size();
|
||||
update_configuration_warnings();
|
||||
}
|
||||
|
||||
@@ -1264,6 +1263,7 @@ void Label::set_clip_text(bool p_clip) {
|
||||
clip = p_clip;
|
||||
queue_redraw();
|
||||
update_minimum_size();
|
||||
update_desired_size();
|
||||
}
|
||||
|
||||
bool Label::is_clipping_text() const {
|
||||
@@ -1297,6 +1297,7 @@ void Label::set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior) {
|
||||
if (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
|
||||
update_minimum_size();
|
||||
}
|
||||
update_desired_size();
|
||||
}
|
||||
|
||||
TextServer::OverrunBehavior Label::get_text_overrun_behavior() const {
|
||||
@@ -1320,6 +1321,7 @@ void Label::set_ellipsis_char(const String &p_char) {
|
||||
if (clip || overrun_behavior != TextServer::OVERRUN_NO_TRIMMING) {
|
||||
update_minimum_size();
|
||||
}
|
||||
update_desired_size();
|
||||
}
|
||||
|
||||
String Label::get_ellipsis_char() const {
|
||||
|
||||
@@ -116,6 +116,7 @@ protected:
|
||||
|
||||
public:
|
||||
virtual Size2 get_minimum_size() const override;
|
||||
virtual Size2 get_desired_size() const override;
|
||||
virtual PackedStringArray get_configuration_warnings() const override;
|
||||
|
||||
void set_horizontal_alignment(HorizontalAlignment p_alignment);
|
||||
|
||||
@@ -42,12 +42,7 @@ Size2 MarginContainer::get_minimum_size() const {
|
||||
}
|
||||
|
||||
Size2 s = c->get_bound_minimum_size();
|
||||
if (s.width > max.width) {
|
||||
max.width = s.width;
|
||||
}
|
||||
if (s.height > max.height) {
|
||||
max.height = s.height;
|
||||
}
|
||||
max = max.max(s);
|
||||
}
|
||||
|
||||
max.width += (theme_cache.margin_left + theme_cache.margin_right);
|
||||
@@ -56,6 +51,25 @@ Size2 MarginContainer::get_minimum_size() const {
|
||||
return max;
|
||||
}
|
||||
|
||||
Size2 MarginContainer::get_desired_size() const {
|
||||
Size2 ds;
|
||||
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
Control *c = as_sortable_control(get_child(i), SortableVisibilityMode::VISIBLE);
|
||||
if (!c) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Size2 s = c->get_desired_size();
|
||||
ds = ds.max(s);
|
||||
}
|
||||
|
||||
ds.width += (theme_cache.margin_left + theme_cache.margin_right);
|
||||
ds.height += (theme_cache.margin_top + theme_cache.margin_bottom);
|
||||
|
||||
return ds;
|
||||
}
|
||||
|
||||
Size2 MarginContainer::get_inner_combined_maximum_size() const {
|
||||
Size2 ms = Container::get_inner_combined_maximum_size();
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ protected:
|
||||
|
||||
public:
|
||||
virtual Size2 get_minimum_size() const override;
|
||||
virtual Size2 get_desired_size() const override;
|
||||
virtual Size2 get_inner_combined_maximum_size() const override;
|
||||
|
||||
virtual Vector<int> get_allowed_size_flags_horizontal() const override;
|
||||
|
||||
@@ -50,6 +50,24 @@ Size2 PanelContainer::get_minimum_size() const {
|
||||
return ms;
|
||||
}
|
||||
|
||||
Size2 PanelContainer::get_desired_size() const {
|
||||
Size2 ds;
|
||||
|
||||
for (int i = 0; i < get_child_count(); i++) {
|
||||
Control *c = as_sortable_control(get_child(i), SortableVisibilityMode::VISIBLE);
|
||||
if (!c) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Size2 minsize = c->get_desired_size();
|
||||
ds = ds.max(minsize);
|
||||
}
|
||||
if (theme_cache.panel_style.is_valid()) {
|
||||
ds += theme_cache.panel_style->get_minimum_size();
|
||||
}
|
||||
return ds;
|
||||
}
|
||||
|
||||
Size2 PanelContainer::get_inner_combined_maximum_size() const {
|
||||
Size2 ms = Container::get_inner_combined_maximum_size();
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ protected:
|
||||
|
||||
public:
|
||||
virtual Size2 get_minimum_size() const override;
|
||||
virtual Size2 get_desired_size() const override;
|
||||
virtual Size2 get_inner_combined_maximum_size() const override;
|
||||
|
||||
virtual Vector<int> get_allowed_size_flags_horizontal() const override;
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
#include "servers/display/accessibility_server.h"
|
||||
#include "servers/display/display_server.h"
|
||||
|
||||
Size2 ScrollContainer::get_minimum_size() const {
|
||||
Size2 ScrollContainer::_get_minimum_size(bool p_use_desired_sizes) const {
|
||||
// Calculated in this function, as it needs to traverse all child controls once to calculate;
|
||||
// and needs to be calculated before being used by `_update_scrollbars()`.
|
||||
largest_child_min_size = Size2();
|
||||
@@ -51,7 +51,7 @@ Size2 ScrollContainer::get_minimum_size() const {
|
||||
continue;
|
||||
}
|
||||
|
||||
Size2 child_min_size = c->get_bound_minimum_size();
|
||||
Size2 child_min_size = p_use_desired_sizes ? c->get_bound_desired_size() : c->get_bound_minimum_size();
|
||||
largest_child_min_size = largest_child_min_size.max(child_min_size);
|
||||
}
|
||||
|
||||
@@ -93,6 +93,14 @@ Size2 ScrollContainer::get_minimum_size() const {
|
||||
return min_size;
|
||||
}
|
||||
|
||||
Size2 ScrollContainer::get_minimum_size() const {
|
||||
return _get_minimum_size(false);
|
||||
}
|
||||
|
||||
Size2 ScrollContainer::get_desired_size() const {
|
||||
return _get_minimum_size(true);
|
||||
}
|
||||
|
||||
Size2 ScrollContainer::get_inner_combined_maximum_size() const {
|
||||
Size2 ms = Container::get_inner_combined_maximum_size();
|
||||
|
||||
|
||||
@@ -117,8 +117,11 @@ private:
|
||||
bool focus_border_is_drawn = false;
|
||||
bool child_has_focus();
|
||||
|
||||
Size2 _get_minimum_size(bool p_use_desired_sizes) const;
|
||||
|
||||
protected:
|
||||
Size2 get_minimum_size() const override;
|
||||
Size2 get_desired_size() const override;
|
||||
Size2 get_inner_combined_maximum_size() const override;
|
||||
|
||||
void _gui_focus_changed(Control *p_control);
|
||||
|
||||
@@ -1073,7 +1073,7 @@ void SplitContainer::_update_draggers() {
|
||||
}
|
||||
}
|
||||
|
||||
Size2 SplitContainer::get_minimum_size() const {
|
||||
Size2 SplitContainer::_get_minimum_size(bool p_use_desired_sizes) const {
|
||||
const int sep = _get_separation();
|
||||
const int axis = vertical ? 1 : 0;
|
||||
const int other_axis = vertical ? 0 : 1;
|
||||
@@ -1085,7 +1085,7 @@ Size2 SplitContainer::get_minimum_size() const {
|
||||
}
|
||||
|
||||
for (const Control *child : valid_children) {
|
||||
const Size2 min_size = child->get_bound_minimum_size();
|
||||
const Size2 min_size = p_use_desired_sizes ? child->get_bound_desired_size() : child->get_bound_minimum_size();
|
||||
minimum[axis] += (int)min_size[axis];
|
||||
minimum[other_axis] = (int)MAX(minimum[other_axis], min_size[other_axis]);
|
||||
}
|
||||
@@ -1093,6 +1093,14 @@ Size2 SplitContainer::get_minimum_size() const {
|
||||
return minimum;
|
||||
}
|
||||
|
||||
Size2 SplitContainer::get_minimum_size() const {
|
||||
return _get_minimum_size(false);
|
||||
}
|
||||
|
||||
Size2 SplitContainer::get_desired_size() const {
|
||||
return _get_minimum_size(true);
|
||||
}
|
||||
|
||||
void SplitContainer::_validate_property(PropertyInfo &p_property) const {
|
||||
if (is_fixed && p_property.name == "vertical") {
|
||||
p_property.usage = PROPERTY_USAGE_NONE;
|
||||
|
||||
@@ -169,6 +169,8 @@ private:
|
||||
void _update_nested_ancestors(bool p_remove = false);
|
||||
void _update_all_nested_descendents(Control *p_control, Control *p_first_child = nullptr);
|
||||
|
||||
Size2 _get_minimum_size(bool p_use_desired_sizes) const;
|
||||
|
||||
protected:
|
||||
bool is_fixed = false;
|
||||
|
||||
@@ -207,6 +209,7 @@ public:
|
||||
bool is_dragging_enabled() const;
|
||||
|
||||
virtual Size2 get_minimum_size() const override;
|
||||
virtual Size2 get_desired_size() const override;
|
||||
|
||||
virtual Vector<int> get_allowed_size_flags_horizontal() const override;
|
||||
virtual Vector<int> get_allowed_size_flags_vertical() const override;
|
||||
|
||||
+94
-21
@@ -50,8 +50,6 @@ static inline Color _select_color(const Color &p_override_color, const Color &p_
|
||||
Size2 TabBar::get_minimum_size() const {
|
||||
Size2 ms;
|
||||
Size2 combined_max = get_combined_maximum_size();
|
||||
int computed_max_width = 0;
|
||||
bool stop_adding = combined_max.width < 0;
|
||||
|
||||
int buttons_size = get_tab_count() > 1 ? theme_cache.decrement_icon->get_width() + theme_cache.increment_icon->get_width() : 0;
|
||||
|
||||
@@ -120,31 +118,18 @@ Size2 TabBar::get_minimum_size() const {
|
||||
ms.width += theme_cache.tab_separation;
|
||||
}
|
||||
|
||||
if (!stop_adding) {
|
||||
int buttons_eff_size = clip_tabs ? (i != tabs.size() - 1 ? buttons_size : 0) : 0;
|
||||
if (computed_max_width + ms.width - ofs + buttons_eff_size >= combined_max.width) {
|
||||
stop_adding = true;
|
||||
} else {
|
||||
computed_max_width += ms.width - ofs;
|
||||
}
|
||||
}
|
||||
|
||||
if (ms.width - ofs > max_tab_width) {
|
||||
max_tab_width = ms.width - ofs;
|
||||
}
|
||||
}
|
||||
|
||||
if (clip_tabs) {
|
||||
int clip_min_width = max_tab_width + buttons_size;
|
||||
ms.width = max_tab_width + buttons_size;
|
||||
if (combined_max.width >= 0) {
|
||||
int fitted_width = stop_adding ? (computed_max_width + buttons_size) : computed_max_width;
|
||||
ms.width = MAX(clip_min_width, fitted_width);
|
||||
ms.width = MIN(ms.width, int(combined_max.width));
|
||||
} else {
|
||||
ms.width = clip_min_width;
|
||||
}
|
||||
} else if (combined_max.width >= 0) {
|
||||
ms.width = stop_adding ? combined_max.width : MIN(computed_max_width, combined_max.width);
|
||||
ms.width = MIN(ms.width, int(combined_max.width));
|
||||
}
|
||||
|
||||
return ms;
|
||||
@@ -507,10 +492,21 @@ void TabBar::_notification(int p_what) {
|
||||
|
||||
queue_accessibility_update();
|
||||
queue_redraw();
|
||||
update_minimum_size();
|
||||
|
||||
[[fallthrough]];
|
||||
}
|
||||
int ofs_old = offset;
|
||||
int max_old = max_drawn_tab;
|
||||
|
||||
_update_cache();
|
||||
_ensure_no_over_offset();
|
||||
|
||||
if (scroll_to_selected && (offset != ofs_old || max_drawn_tab != max_old)) {
|
||||
ensure_tab_visible(current);
|
||||
}
|
||||
|
||||
update_desired_size();
|
||||
update_minimum_size();
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_RESIZED: {
|
||||
int ofs_old = offset;
|
||||
int max_old = max_drawn_tab;
|
||||
@@ -813,6 +809,7 @@ void TabBar::set_tab_count(int p_count) {
|
||||
|
||||
queue_accessibility_update();
|
||||
queue_redraw();
|
||||
update_desired_size();
|
||||
update_minimum_size();
|
||||
notify_property_list_changed();
|
||||
}
|
||||
@@ -943,6 +940,7 @@ void TabBar::set_tab_title(int p_tab, const String &p_title) {
|
||||
}
|
||||
queue_accessibility_update();
|
||||
queue_redraw();
|
||||
update_desired_size();
|
||||
update_minimum_size();
|
||||
}
|
||||
|
||||
@@ -994,6 +992,7 @@ void TabBar::set_tab_language(int p_tab, const String &p_language) {
|
||||
}
|
||||
queue_accessibility_update();
|
||||
queue_redraw();
|
||||
update_desired_size();
|
||||
update_minimum_size();
|
||||
}
|
||||
}
|
||||
@@ -1018,6 +1017,7 @@ void TabBar::set_tab_icon(int p_tab, const Ref<Texture2D> &p_icon) {
|
||||
ensure_tab_visible(current);
|
||||
}
|
||||
queue_redraw();
|
||||
update_desired_size();
|
||||
update_minimum_size();
|
||||
}
|
||||
|
||||
@@ -1041,6 +1041,7 @@ void TabBar::set_tab_icon_max_width(int p_tab, int p_width) {
|
||||
ensure_tab_visible(current);
|
||||
}
|
||||
queue_redraw();
|
||||
update_desired_size();
|
||||
update_minimum_size();
|
||||
}
|
||||
|
||||
@@ -1096,6 +1097,7 @@ void TabBar::set_tab_disabled(int p_tab, bool p_disabled) {
|
||||
}
|
||||
queue_accessibility_update();
|
||||
queue_redraw();
|
||||
update_desired_size();
|
||||
update_minimum_size();
|
||||
}
|
||||
|
||||
@@ -1120,6 +1122,7 @@ void TabBar::set_tab_hidden(int p_tab, bool p_hidden) {
|
||||
}
|
||||
queue_accessibility_update();
|
||||
queue_redraw();
|
||||
update_desired_size();
|
||||
update_minimum_size();
|
||||
}
|
||||
|
||||
@@ -1153,6 +1156,7 @@ void TabBar::set_tab_button_icon(int p_tab, const Ref<Texture2D> &p_icon) {
|
||||
ensure_tab_visible(current);
|
||||
}
|
||||
queue_redraw();
|
||||
update_desired_size();
|
||||
update_minimum_size();
|
||||
}
|
||||
|
||||
@@ -1232,7 +1236,7 @@ void TabBar::_update_cache(bool p_update_hover) {
|
||||
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;
|
||||
int effective_max_width = max_width > 0 ? MIN(max_width, combined_max_width) : combined_max_width;
|
||||
|
||||
int limit = combined_max.width > 0 ? combined_max.width : get_size().width;
|
||||
int limit = combined_max.width > 0 ? MIN(combined_max.width, get_size().width) : get_size().width;
|
||||
int limit_minus_buttons = limit - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width();
|
||||
|
||||
int w = 0;
|
||||
@@ -1323,6 +1327,68 @@ void TabBar::_update_cache(bool p_update_hover) {
|
||||
}
|
||||
}
|
||||
|
||||
Size2 TabBar::get_desired_size() const {
|
||||
if (!clip_tabs || tabs.is_empty()) {
|
||||
return Size2();
|
||||
}
|
||||
Size2 combined_max = get_combined_maximum_size();
|
||||
if (combined_max.width < 0) {
|
||||
return Size2();
|
||||
}
|
||||
|
||||
int buttons_size = tabs.size() > 1 ? theme_cache.decrement_icon->get_width() + theme_cache.increment_icon->get_width() : 0;
|
||||
int limit = int(combined_max.width);
|
||||
int limit_minus_buttons = limit - buttons_size;
|
||||
|
||||
int w = 0;
|
||||
bool overflowed = false;
|
||||
|
||||
// First pass: check if all tabs fit without buttons.
|
||||
for (int i = offset; i < tabs.size(); i++) {
|
||||
if (tabs[i].hidden) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int next_w = w + tabs[i].size_cache;
|
||||
if (i > offset) {
|
||||
next_w += theme_cache.tab_separation;
|
||||
}
|
||||
|
||||
if (next_w > limit) {
|
||||
overflowed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
w = next_w;
|
||||
}
|
||||
|
||||
// If buttons are needed, recompute against the reduced limit.
|
||||
if (offset > 0 || overflowed) {
|
||||
w = 0;
|
||||
for (int i = offset; i < tabs.size(); i++) {
|
||||
if (tabs[i].hidden) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int next_w = w + tabs[i].size_cache;
|
||||
if (i > offset) {
|
||||
next_w += theme_cache.tab_separation;
|
||||
}
|
||||
|
||||
if (next_w > limit_minus_buttons) {
|
||||
break;
|
||||
}
|
||||
|
||||
w = next_w;
|
||||
}
|
||||
}
|
||||
|
||||
int desired = (offset > 0 || overflowed) ? w + buttons_size : w;
|
||||
desired = MIN(desired, limit);
|
||||
|
||||
return Size2(desired, 0);
|
||||
}
|
||||
|
||||
void TabBar::_hover_switch_timeout() {
|
||||
set_current_tab(hover);
|
||||
}
|
||||
@@ -1352,6 +1418,7 @@ void TabBar::add_tab(const String &p_str, const Ref<Texture2D> &p_icon) {
|
||||
}
|
||||
queue_accessibility_update();
|
||||
queue_redraw();
|
||||
update_desired_size();
|
||||
update_minimum_size();
|
||||
|
||||
if (!deselect_enabled && tabs.size() == 1) {
|
||||
@@ -1383,6 +1450,7 @@ void TabBar::clear_tabs() {
|
||||
|
||||
queue_accessibility_update();
|
||||
queue_redraw();
|
||||
update_desired_size();
|
||||
update_minimum_size();
|
||||
notify_property_list_changed();
|
||||
}
|
||||
@@ -1445,6 +1513,7 @@ void TabBar::remove_tab(int p_idx) {
|
||||
|
||||
queue_accessibility_update();
|
||||
queue_redraw();
|
||||
update_desired_size();
|
||||
update_minimum_size();
|
||||
notify_property_list_changed();
|
||||
|
||||
@@ -1653,6 +1722,7 @@ void TabBar::_move_tab_from(TabBar *p_from_tabbar, int p_from_index, int p_to_in
|
||||
}
|
||||
|
||||
queue_accessibility_update();
|
||||
update_desired_size();
|
||||
update_minimum_size();
|
||||
}
|
||||
|
||||
@@ -1733,6 +1803,7 @@ void TabBar::set_clip_tabs(bool p_clip_tabs) {
|
||||
ensure_tab_visible(current);
|
||||
}
|
||||
queue_redraw();
|
||||
update_desired_size();
|
||||
update_minimum_size();
|
||||
}
|
||||
|
||||
@@ -1988,6 +2059,7 @@ void TabBar::set_tab_close_display_policy(CloseButtonDisplayPolicy p_policy) {
|
||||
ensure_tab_visible(current);
|
||||
}
|
||||
queue_redraw();
|
||||
update_desired_size();
|
||||
update_minimum_size();
|
||||
}
|
||||
|
||||
@@ -2010,6 +2082,7 @@ void TabBar::set_max_tab_width(int p_width) {
|
||||
ensure_tab_visible(current);
|
||||
}
|
||||
queue_redraw();
|
||||
update_desired_size();
|
||||
update_minimum_size();
|
||||
}
|
||||
|
||||
|
||||
@@ -334,6 +334,7 @@ public:
|
||||
|
||||
Rect2 get_tab_rect(int p_tab) const;
|
||||
Size2 get_minimum_size() const override;
|
||||
Size2 get_desired_size() const override;
|
||||
|
||||
TabBar();
|
||||
};
|
||||
|
||||
@@ -266,6 +266,7 @@ void TabContainer::_on_theme_changed() {
|
||||
_repaint();
|
||||
} else {
|
||||
update_minimum_size();
|
||||
update_desired_size();
|
||||
}
|
||||
queue_redraw();
|
||||
|
||||
@@ -933,6 +934,7 @@ void TabContainer::set_tab_disabled(int p_tab, bool p_disabled) {
|
||||
tab_bar->set_tab_disabled(p_tab, p_disabled);
|
||||
|
||||
_update_margins();
|
||||
update_desired_size();
|
||||
if (!get_clip_tabs()) {
|
||||
update_minimum_size();
|
||||
}
|
||||
@@ -958,6 +960,7 @@ void TabContainer::set_tab_hidden(int p_tab, bool p_hidden) {
|
||||
child->hide();
|
||||
|
||||
_update_margins();
|
||||
update_desired_size();
|
||||
if (!get_clip_tabs()) {
|
||||
update_minimum_size();
|
||||
}
|
||||
@@ -987,16 +990,16 @@ Ref<Texture2D> TabContainer::get_tab_button_icon(int p_tab) const {
|
||||
return tab_bar->get_tab_button_icon(p_tab);
|
||||
}
|
||||
|
||||
Size2 TabContainer::get_minimum_size() const {
|
||||
Size2 TabContainer::_get_minimum_size(bool p_use_desired_sizes) const {
|
||||
Size2 ms;
|
||||
|
||||
if (tabs_visible) {
|
||||
ms = tab_bar->get_minimum_size();
|
||||
ms = p_use_desired_sizes ? tab_bar->get_bound_desired_size() : tab_bar->get_minimum_size();
|
||||
ms.width += theme_cache.tabbar_style->get_margin(SIDE_LEFT) + theme_cache.tabbar_style->get_margin(SIDE_RIGHT);
|
||||
ms.height += theme_cache.tabbar_style->get_margin(SIDE_TOP) + theme_cache.tabbar_style->get_margin(SIDE_BOTTOM);
|
||||
|
||||
if (get_popup()) {
|
||||
ms.width += popup_button->get_minimum_size().x;
|
||||
ms.width += p_use_desired_sizes ? popup_button->get_bound_desired_size().x : popup_button->get_minimum_size().x;
|
||||
}
|
||||
|
||||
if (theme_cache.side_margin > 0 && get_tab_alignment() != TabBar::ALIGNMENT_CENTER &&
|
||||
@@ -1014,7 +1017,7 @@ Size2 TabContainer::get_minimum_size() const {
|
||||
continue;
|
||||
}
|
||||
|
||||
Size2 cms = c->get_bound_minimum_size();
|
||||
Size2 cms = p_use_desired_sizes ? c->get_bound_desired_size() : c->get_bound_minimum_size();
|
||||
largest_child_min_size = largest_child_min_size.max(cms);
|
||||
}
|
||||
ms.height += largest_child_min_size.height;
|
||||
@@ -1027,6 +1030,14 @@ Size2 TabContainer::get_minimum_size() const {
|
||||
return ms;
|
||||
}
|
||||
|
||||
Size2 TabContainer::get_minimum_size() const {
|
||||
return _get_minimum_size(false);
|
||||
}
|
||||
|
||||
Size2 TabContainer::get_desired_size() const {
|
||||
return _get_minimum_size(true);
|
||||
}
|
||||
|
||||
Size2 TabContainer::get_inner_combined_maximum_size() const {
|
||||
Size2 ms = Container::get_inner_combined_maximum_size();
|
||||
|
||||
@@ -1105,6 +1116,7 @@ void TabContainer::set_popup(Node *p_popup) {
|
||||
popup_button->set_visible(popup != nullptr);
|
||||
_update_margins();
|
||||
update_minimum_size();
|
||||
update_desired_size();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1155,6 +1167,7 @@ void TabContainer::set_use_hidden_tabs_for_min_size(bool p_use_hidden_tabs) {
|
||||
|
||||
use_hidden_tabs_for_min_size = p_use_hidden_tabs;
|
||||
update_minimum_size();
|
||||
update_desired_size();
|
||||
}
|
||||
|
||||
bool TabContainer::get_use_hidden_tabs_for_min_size() const {
|
||||
|
||||
@@ -152,6 +152,8 @@ private:
|
||||
void _popup_button_hovered(bool p_hover);
|
||||
void _popup_button_pressed();
|
||||
|
||||
Size2 _get_minimum_size(bool p_use_desired_sizes) const;
|
||||
|
||||
protected:
|
||||
bool _set(const StringName &p_name, const Variant &p_value) { return property_helper.property_set_value(p_name, p_value); }
|
||||
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:
|
||||
|
||||
virtual Size2 get_minimum_size() const override;
|
||||
virtual Size2 get_inner_combined_maximum_size() const override;
|
||||
virtual Size2 get_desired_size() const override;
|
||||
|
||||
void set_popup(Node *p_popup);
|
||||
Popup *get_popup() const;
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
|
||||
TEST_FORCE_LINK(test_label)
|
||||
|
||||
#include "modules/modules_enabled.gen.h" // IWYU pragma: keep. Needed for MODULE_TEXT_SERVER_FB_ENABLED and MODULE_TEXT_SERVER_ADV_ENABLED definitions.
|
||||
|
||||
#if defined(MODULE_TEXT_SERVER_FB_ENABLED) || defined(MODULE_TEXT_SERVER_ADV_ENABLED)
|
||||
|
||||
#include "scene/gui/label.h"
|
||||
@@ -139,7 +141,7 @@ TEST_CASE("[SceneTree][Label] Sizing") {
|
||||
real_t max_width = 50;
|
||||
real_t min_width = 25;
|
||||
|
||||
test_label->set_custom_maximum_size(Size2(max_width, 0));
|
||||
test_label->set_custom_maximum_size(Size2(max_width, -1));
|
||||
test_label->set_custom_minimum_size(Size2(min_width, 0));
|
||||
test_label->set_text("This is a long text that should be wrapped and exceeds minimum size.");
|
||||
SceneTree::get_singleton()->process(0);
|
||||
|
||||
Reference in new issue
Block a user