Skip to content

Commit b271a88

Browse files
committed
Merge pull request godotengine#96871 from KoBeWi/borrow_container
Add `SCROLL_MODE_RESERVE` to ScrollContainer
2 parents dd7cb05 + b36bebc commit b271a88

File tree

3 files changed

+28
-11
lines changed

3 files changed

+28
-11
lines changed

doc/classes/ScrollContainer.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@
102102
<constant name="SCROLL_MODE_SHOW_NEVER" value="3" enum="ScrollMode">
103103
Scrolling enabled, scrollbar will be hidden.
104104
</constant>
105+
<constant name="SCROLL_MODE_RESERVE" value="4" enum="ScrollMode">
106+
Combines [constant SCROLL_MODE_AUTO] and [constant SCROLL_MODE_SHOW_ALWAYS]. The scrollbar is only visible if necessary, but the content size is adjusted as if it was always visible. It's useful for ensuring that content size stays the same regardless if the scrollbar is visible.
107+
</constant>
105108
</constants>
106109
<theme_items>
107110
<theme_item name="panel" data_type="style" type="StyleBox">

scene/gui/scroll_container.cpp

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,15 @@ Size2 ScrollContainer::get_minimum_size() const {
5858

5959
if (horizontal_scroll_mode == SCROLL_MODE_DISABLED) {
6060
min_size.x = largest_child_min_size.x;
61-
bool v_scroll_show = vertical_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || (vertical_scroll_mode == SCROLL_MODE_AUTO && largest_child_min_size.y > size.y);
61+
bool v_scroll_show = vertical_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || vertical_scroll_mode == SCROLL_MODE_RESERVE || (vertical_scroll_mode == SCROLL_MODE_AUTO && largest_child_min_size.y > size.y);
6262
if (v_scroll_show && v_scroll->get_parent() == this) {
6363
min_size.x += v_scroll->get_minimum_size().x;
6464
}
6565
}
6666

6767
if (vertical_scroll_mode == SCROLL_MODE_DISABLED) {
6868
min_size.y = largest_child_min_size.y;
69-
bool h_scroll_show = horizontal_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || (horizontal_scroll_mode == SCROLL_MODE_AUTO && largest_child_min_size.x > size.x);
69+
bool h_scroll_show = horizontal_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || horizontal_scroll_mode == SCROLL_MODE_RESERVE || (horizontal_scroll_mode == SCROLL_MODE_AUTO && largest_child_min_size.x > size.x);
7070
if (h_scroll_show && h_scroll->get_parent() == this) {
7171
min_size.y += h_scroll->get_minimum_size().y;
7272
}
@@ -92,6 +92,15 @@ void ScrollContainer::_cancel_drag() {
9292
}
9393
}
9494

95+
bool ScrollContainer::_is_h_scroll_visible() const {
96+
// Scrolls may have been moved out for reasons.
97+
return h_scroll->is_visible() && h_scroll->get_parent() == this;
98+
}
99+
100+
bool ScrollContainer::_is_v_scroll_visible() const {
101+
return v_scroll->is_visible() && v_scroll->get_parent() == this;
102+
}
103+
95104
void ScrollContainer::gui_input(const Ref<InputEvent> &p_gui_input) {
96105
ERR_FAIL_COND(p_gui_input.is_null());
97106

@@ -298,11 +307,11 @@ void ScrollContainer::_reposition_children() {
298307
ofs += theme_cache.panel_style->get_offset();
299308
bool rtl = is_layout_rtl();
300309

301-
if (h_scroll->is_visible_in_tree() && h_scroll->get_parent() == this) { //scrolls may have been moved out for reasons
310+
if (_is_h_scroll_visible() || horizontal_scroll_mode == SCROLL_MODE_RESERVE) {
302311
size.y -= h_scroll->get_minimum_size().y;
303312
}
304313

305-
if (v_scroll->is_visible_in_tree() && v_scroll->get_parent() == this) { //scrolls may have been moved out for reasons
314+
if (_is_v_scroll_visible() || vertical_scroll_mode == SCROLL_MODE_RESERVE) {
306315
size.x -= v_scroll->get_minimum_size().x;
307316
}
308317

@@ -324,7 +333,7 @@ void ScrollContainer::_reposition_children() {
324333
r.size.height = MAX(size.height, minsize.height);
325334
}
326335
r.position += ofs;
327-
if (rtl && v_scroll->is_visible_in_tree() && v_scroll->get_parent() == this) {
336+
if (rtl && _is_v_scroll_visible()) {
328337
r.position.x += v_scroll->get_minimum_size().x;
329338
}
330339
r.position = r.position.floor();
@@ -436,14 +445,14 @@ void ScrollContainer::update_scrollbars() {
436445
Size2 hmin = h_scroll->get_combined_minimum_size();
437446
Size2 vmin = v_scroll->get_combined_minimum_size();
438447

439-
h_scroll->set_visible(horizontal_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || (horizontal_scroll_mode == SCROLL_MODE_AUTO && largest_child_min_size.width > size.width));
440-
v_scroll->set_visible(vertical_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || (vertical_scroll_mode == SCROLL_MODE_AUTO && largest_child_min_size.height > size.height));
448+
h_scroll->set_visible(horizontal_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || ((horizontal_scroll_mode == SCROLL_MODE_AUTO || horizontal_scroll_mode == SCROLL_MODE_RESERVE) && largest_child_min_size.width > size.width));
449+
v_scroll->set_visible(vertical_scroll_mode == SCROLL_MODE_SHOW_ALWAYS || ((vertical_scroll_mode == SCROLL_MODE_AUTO || vertical_scroll_mode == SCROLL_MODE_RESERVE) && largest_child_min_size.height > size.height));
441450

442451
h_scroll->set_max(largest_child_min_size.width);
443-
h_scroll->set_page((v_scroll->is_visible() && v_scroll->get_parent() == this) ? size.width - vmin.width : size.width);
452+
h_scroll->set_page(_is_v_scroll_visible() ? size.width - vmin.width : size.width);
444453

445454
v_scroll->set_max(largest_child_min_size.height);
446-
v_scroll->set_page((h_scroll->is_visible() && h_scroll->get_parent() == this) ? size.height - hmin.height : size.height);
455+
v_scroll->set_page(_is_h_scroll_visible() ? size.height - hmin.height : size.height);
447456

448457
// Avoid scrollbar overlapping.
449458
_updating_scrollbars = true;
@@ -603,14 +612,15 @@ void ScrollContainer::_bind_methods() {
603612
ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_vertical", PROPERTY_HINT_NONE, "suffix:px"), "set_v_scroll", "get_v_scroll");
604613
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_horizontal_custom_step", PROPERTY_HINT_RANGE, "-1,4096,suffix:px"), "set_horizontal_custom_step", "get_horizontal_custom_step");
605614
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "scroll_vertical_custom_step", PROPERTY_HINT_RANGE, "-1,4096,suffix:px"), "set_vertical_custom_step", "get_vertical_custom_step");
606-
ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_scroll_mode", PROPERTY_HINT_ENUM, "Disabled,Auto,Always Show,Never Show"), "set_horizontal_scroll_mode", "get_horizontal_scroll_mode");
607-
ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_scroll_mode", PROPERTY_HINT_ENUM, "Disabled,Auto,Always Show,Never Show"), "set_vertical_scroll_mode", "get_vertical_scroll_mode");
615+
ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_scroll_mode", PROPERTY_HINT_ENUM, "Disabled,Auto,Always Show,Never Show,Reserve"), "set_horizontal_scroll_mode", "get_horizontal_scroll_mode");
616+
ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_scroll_mode", PROPERTY_HINT_ENUM, "Disabled,Auto,Always Show,Never Show,Reserve"), "set_vertical_scroll_mode", "get_vertical_scroll_mode");
608617
ADD_PROPERTY(PropertyInfo(Variant::INT, "scroll_deadzone"), "set_deadzone", "get_deadzone");
609618

610619
BIND_ENUM_CONSTANT(SCROLL_MODE_DISABLED);
611620
BIND_ENUM_CONSTANT(SCROLL_MODE_AUTO);
612621
BIND_ENUM_CONSTANT(SCROLL_MODE_SHOW_ALWAYS);
613622
BIND_ENUM_CONSTANT(SCROLL_MODE_SHOW_NEVER);
623+
BIND_ENUM_CONSTANT(SCROLL_MODE_RESERVE);
614624

615625
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ScrollContainer, panel_style, "panel");
616626

scene/gui/scroll_container.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class ScrollContainer : public Container {
4444
SCROLL_MODE_AUTO,
4545
SCROLL_MODE_SHOW_ALWAYS,
4646
SCROLL_MODE_SHOW_NEVER,
47+
SCROLL_MODE_RESERVE,
4748
};
4849

4950
private:
@@ -75,6 +76,9 @@ class ScrollContainer : public Container {
7576

7677
void _cancel_drag();
7778

79+
bool _is_h_scroll_visible() const;
80+
bool _is_v_scroll_visible() const;
81+
7882
protected:
7983
Size2 get_minimum_size() const override;
8084

0 commit comments

Comments
 (0)