Merge pull request #112441 from YeldhamDev/scrollbar_padding

Allow to add padding to `ScrollBar`s
This commit is contained in:
Thaddeus Crews 2025-11-13 20:52:26 -06:00
commit 2cd268fea4
No known key found for this signature in database
GPG key ID: 8C6E5FEB5FC03CCC
4 changed files with 61 additions and 10 deletions

View file

@ -8,4 +8,14 @@
</description> </description>
<tutorials> <tutorials>
</tutorials> </tutorials>
<theme_items>
<theme_item name="padding_bottom" data_type="constant" type="int" default="0">
Padding between the bottom of the [theme_item ScrollBar.scroll] element and the [theme_item ScrollBar.grabber].
[b]Note:[/b] To apply horizontal padding, modify the left/right content margins of [theme_item ScrollBar.scroll] instead.
</theme_item>
<theme_item name="padding_top" data_type="constant" type="int" default="0">
Padding between the top of the [theme_item ScrollBar.scroll] element and the [theme_item ScrollBar.grabber].
[b]Note:[/b] To apply horizontal padding, modify the left/right content margins of [theme_item ScrollBar.scroll] instead.
</theme_item>
</theme_items>
</class> </class>

View file

@ -12,4 +12,14 @@
<member name="size_flags_horizontal" type="int" setter="set_h_size_flags" getter="get_h_size_flags" overrides="Control" enum="Control.SizeFlags" is_bitfield="true" default="0" /> <member name="size_flags_horizontal" type="int" setter="set_h_size_flags" getter="get_h_size_flags" overrides="Control" enum="Control.SizeFlags" is_bitfield="true" default="0" />
<member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" enum="Control.SizeFlags" is_bitfield="true" default="1" /> <member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" enum="Control.SizeFlags" is_bitfield="true" default="1" />
</members> </members>
<theme_items>
<theme_item name="padding_left" data_type="constant" type="int" default="0">
Padding between the left of the [theme_item ScrollBar.scroll] element and the [theme_item ScrollBar.grabber].
[b]Note:[/b] To apply vertical padding, modify the top/bottom content margins of [theme_item ScrollBar.scroll] instead.
</theme_item>
<theme_item name="padding_right" data_type="constant" type="int" default="0">
Padding between the right of the [theme_item ScrollBar.scroll] element and the [theme_item ScrollBar.grabber].
[b]Note:[/b] To apply vertical padding, modify the top/bottom content margins of [theme_item ScrollBar.scroll] instead.
</theme_item>
</theme_items>
</class> </class>

View file

@ -295,15 +295,19 @@ void ScrollBar::_notification(int p_what) {
Rect2 grabber_rect; Rect2 grabber_rect;
if (orientation == HORIZONTAL) { if (orientation == HORIZONTAL) {
int padding_top = MAX(theme_cache.padding_top, 0);
int padding_bottom = MAX(theme_cache.padding_bottom, 0);
grabber_rect.size.width = get_grabber_size(); grabber_rect.size.width = get_grabber_size();
grabber_rect.size.height = get_size().height; grabber_rect.size.height = get_size().height - padding_top - padding_bottom;
grabber_rect.position.y = 0; grabber_rect.position.y = padding_top;
grabber_rect.position.x = get_grabber_offset() + decr->get_width() + theme_cache.scroll_style->get_margin(SIDE_LEFT); grabber_rect.position.x = get_grabber_offset() + decr->get_width() + theme_cache.scroll_style->get_margin(SIDE_LEFT);
} else { } else {
grabber_rect.size.width = get_size().width; int padding_left = MAX(theme_cache.padding_left, 0);
int padding_right = MAX(theme_cache.padding_right, 0);
grabber_rect.size.width = get_size().width - padding_left - padding_right;
grabber_rect.size.height = get_grabber_size(); grabber_rect.size.height = get_grabber_size();
grabber_rect.position.y = get_grabber_offset() + decr->get_height() + theme_cache.scroll_style->get_margin(SIDE_TOP); grabber_rect.position.y = get_grabber_offset() + decr->get_height() + theme_cache.scroll_style->get_margin(SIDE_TOP);
grabber_rect.position.x = 0; grabber_rect.position.x = padding_left;
} }
grabber->draw(ci, grabber_rect); grabber->draw(ci, grabber_rect);
@ -488,7 +492,10 @@ Size2 ScrollBar::get_minimum_size() const {
Size2 minsize; Size2 minsize;
if (orientation == VERTICAL) { if (orientation == VERTICAL) {
int padding_left = MAX(theme_cache.padding_left, 0);
int padding_right = MAX(theme_cache.padding_right, 0);
minsize.width = MAX(incr->get_size().width, bg->get_minimum_size().width); minsize.width = MAX(incr->get_size().width, bg->get_minimum_size().width);
minsize.width += padding_left + padding_right;
minsize.height += incr->get_size().height; minsize.height += incr->get_size().height;
minsize.height += decr->get_size().height; minsize.height += decr->get_size().height;
minsize.height += bg->get_minimum_size().height; minsize.height += bg->get_minimum_size().height;
@ -496,7 +503,10 @@ Size2 ScrollBar::get_minimum_size() const {
} }
if (orientation == HORIZONTAL) { if (orientation == HORIZONTAL) {
int padding_top = MAX(theme_cache.padding_top, 0);
int padding_bottom = MAX(theme_cache.padding_bottom, 0);
minsize.height = MAX(incr->get_size().height, bg->get_minimum_size().height); minsize.height = MAX(incr->get_size().height, bg->get_minimum_size().height);
minsize.height += padding_top + padding_bottom;
minsize.width += incr->get_size().width; minsize.width += incr->get_size().width;
minsize.width += decr->get_size().width; minsize.width += decr->get_size().width;
minsize.width += bg->get_minimum_size().width; minsize.width += bg->get_minimum_size().width;
@ -669,3 +679,13 @@ ScrollBar::ScrollBar(Orientation p_orientation) {
ScrollBar::~ScrollBar() { ScrollBar::~ScrollBar() {
} }
void VScrollBar::_bind_methods() {
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, VScrollBar, padding_left);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, VScrollBar, padding_right);
}
void HScrollBar::_bind_methods() {
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, HScrollBar, padding_top);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, HScrollBar, padding_bottom);
}

View file

@ -84,6 +84,12 @@ class ScrollBar : public Range {
double target_scroll = 0.0; double target_scroll = 0.0;
bool smooth_scroll_enabled = false; bool smooth_scroll_enabled = false;
void _drag_node_exit();
void _drag_node_input(const Ref<InputEvent> &p_input);
virtual void gui_input(const Ref<InputEvent> &p_event) override;
protected:
struct ThemeCache { struct ThemeCache {
Ref<StyleBox> scroll_style; Ref<StyleBox> scroll_style;
Ref<StyleBox> scroll_focus_style; Ref<StyleBox> scroll_focus_style;
@ -98,14 +104,13 @@ class ScrollBar : public Range {
Ref<Texture2D> decrement_icon; Ref<Texture2D> decrement_icon;
Ref<Texture2D> decrement_hl_icon; Ref<Texture2D> decrement_hl_icon;
Ref<Texture2D> decrement_pressed_icon; Ref<Texture2D> decrement_pressed_icon;
int padding_left = 0;
int padding_top = 0;
int padding_right = 0;
int padding_bottom = 0;
} theme_cache; } theme_cache;
void _drag_node_exit();
void _drag_node_input(const Ref<InputEvent> &p_input);
virtual void gui_input(const Ref<InputEvent> &p_event) override;
protected:
void _notification(int p_what); void _notification(int p_what);
static void _bind_methods(); static void _bind_methods();
@ -133,6 +138,9 @@ public:
class HScrollBar : public ScrollBar { class HScrollBar : public ScrollBar {
GDCLASS(HScrollBar, ScrollBar); GDCLASS(HScrollBar, ScrollBar);
protected:
static void _bind_methods();
public: public:
HScrollBar() : HScrollBar() :
ScrollBar(HORIZONTAL) { set_v_size_flags(0); } ScrollBar(HORIZONTAL) { set_v_size_flags(0); }
@ -141,6 +149,9 @@ public:
class VScrollBar : public ScrollBar { class VScrollBar : public ScrollBar {
GDCLASS(VScrollBar, ScrollBar); GDCLASS(VScrollBar, ScrollBar);
protected:
static void _bind_methods();
public: public:
VScrollBar() : VScrollBar() :
ScrollBar(VERTICAL) { set_h_size_flags(0); } ScrollBar(VERTICAL) { set_h_size_flags(0); }