From 66d1ce27861881971a6fdaac4b87dad568875551 Mon Sep 17 00:00:00 2001
From: sydist <81040138+sydist@users.noreply.github.com>
Date: Mon, 22 Dec 2025 23:19:17 +0200
Subject: [PATCH] Add font color and StyleBox customization for disabled items
in ItemList
---
doc/classes/ItemList.xml | 12 +++++
scene/gui/item_list.cpp | 82 +++++++++++++++++++++--------------
scene/gui/item_list.h | 4 ++
scene/theme/default_theme.cpp | 6 ++-
4 files changed, 71 insertions(+), 33 deletions(-)
diff --git a/doc/classes/ItemList.xml b/doc/classes/ItemList.xml
index 99e682a1b3..efef6fc98d 100644
--- a/doc/classes/ItemList.xml
+++ b/doc/classes/ItemList.xml
@@ -535,6 +535,12 @@
Default text [Color] of the item.
+
+ Text [Color] used when the item is disabled.
+
+
+ Text [Color] used when the item is disabled and hovered.
+
Text [Color] used when the item is hovered and not selected yet.
@@ -584,6 +590,12 @@
[StyleBox] used for the cursor, when the [ItemList] is not being focused.
+
+ [StyleBox] for items that are disabled.
+
+
+ [StyleBox] for items that are disabled, hovered, but not selected.
+
The focused style for the [ItemList], drawn on top of everything.
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index ff72170ce5..59f09acbfc 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -1535,35 +1535,45 @@ void ItemList::_notification(int p_what) {
rcache.size.width = width - rcache.position.x;
}
- bool should_draw_selected_bg = items[i].selected && hovered != i;
- bool should_draw_hovered_selected_bg = items[i].selected && hovered == i;
- bool should_draw_hovered_bg = hovered == i && !items[i].selected;
- bool should_draw_custom_bg = items[i].custom_bg.a > 0.001;
+ Rect2 r = rcache;
+ r.position += base_ofs;
- if (should_draw_selected_bg || should_draw_hovered_selected_bg || should_draw_hovered_bg || should_draw_custom_bg) {
- Rect2 r = rcache;
- r.position += base_ofs;
+ if (rtl) {
+ r.position.x = size.width - r.position.x - r.size.x + theme_cache.panel_style->get_margin(SIDE_LEFT) - theme_cache.panel_style->get_margin(SIDE_RIGHT);
+ }
- if (rtl) {
- r.position.x = size.width - r.position.x - r.size.x + theme_cache.panel_style->get_margin(SIDE_LEFT) - theme_cache.panel_style->get_margin(SIDE_RIGHT);
+ if (items[i].custom_bg.a > 0.001f) {
+ draw_rect(r, items[i].custom_bg);
+ }
+
+ Ref style;
+ bool is_hovered = (hovered == i);
+ bool is_selected = items[i].selected;
+ bool is_disabled = items[i].disabled;
+ bool is_focused = has_focus();
+
+ if (is_disabled) {
+ if (is_hovered) {
+ style = theme_cache.disabled_hovered_style;
+ } else {
+ style = theme_cache.disabled_style;
}
-
- if (should_draw_selected_bg) {
- draw_style_box(sbsel, r);
- }
- if (should_draw_hovered_selected_bg) {
- if (has_focus(true)) {
- draw_style_box(theme_cache.hovered_selected_focus_style, r);
+ } else {
+ if (is_hovered && is_selected) {
+ if (is_focused) {
+ style = theme_cache.hovered_selected_focus_style;
} else {
- draw_style_box(theme_cache.hovered_selected_style, r);
+ style = theme_cache.hovered_selected_style;
}
+ } else if (is_hovered) {
+ style = theme_cache.hovered_style;
+ } else if (is_selected) {
+ style = sbsel;
}
- if (should_draw_hovered_bg) {
- draw_style_box(theme_cache.hovered_style, r);
- }
- if (should_draw_custom_bg) {
- draw_rect(r, items[i].custom_bg);
- }
+ }
+
+ if (style.is_valid()) {
+ draw_style_box(style, r);
}
Vector2 text_ofs;
@@ -1641,20 +1651,24 @@ void ItemList::_notification(int p_what) {
Color txt_modulate;
if (items[i].custom_fg != Color()) {
txt_modulate = items[i].custom_fg;
- } else if (items[i].selected && hovered == i) {
- txt_modulate = theme_cache.font_hovered_selected_color;
- } else if (items[i].selected) {
- txt_modulate = theme_cache.font_selected_color;
- } else if (hovered == i) {
+ } else if (is_disabled) {
+ if (is_hovered) {
+ txt_modulate = theme_cache.font_disabled_hovered_color;
+ } else {
+ txt_modulate = theme_cache.font_disabled_color;
+ }
+ } else if (is_selected) {
+ if (is_hovered) {
+ txt_modulate = theme_cache.font_hovered_selected_color;
+ } else {
+ txt_modulate = theme_cache.font_selected_color;
+ }
+ } else if (is_hovered) {
txt_modulate = theme_cache.font_hovered_color;
} else {
txt_modulate = theme_cache.font_color;
}
- if (items[i].disabled) {
- txt_modulate.a *= 0.5;
- }
-
if (icon_mode == ICON_MODE_TOP && max_text_lines > 0) {
text_ofs.y += MAX(theme_cache.v_separation, 0) / 2;
text_ofs.x += MAX(theme_cache.h_separation, 0) / 2;
@@ -2485,6 +2499,8 @@ void ItemList::_bind_methods() {
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, ItemList, font_selected_color);
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_CONSTANT, ItemList, font_outline_size, "outline_size");
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, ItemList, font_outline_color);
+ BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, ItemList, font_disabled_color);
+ BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, ItemList, font_disabled_hovered_color);
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, ItemList, scroll_hint);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, ItemList, scroll_hint_color);
@@ -2497,6 +2513,8 @@ void ItemList::_bind_methods() {
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ItemList, selected_focus_style, "selected_focus");
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ItemList, cursor_style, "cursor_unfocused");
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ItemList, cursor_focus_style, "cursor");
+ BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ItemList, disabled_style, "disabled");
+ BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_STYLEBOX, ItemList, disabled_hovered_style, "disabled_hovered");
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, ItemList, guide_color);
Item defaults(true);
diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h
index 7890148dd6..d210135a7a 100644
--- a/scene/gui/item_list.h
+++ b/scene/gui/item_list.h
@@ -175,6 +175,8 @@ protected:
Color font_selected_color;
int font_outline_size = 0;
Color font_outline_color;
+ Color font_disabled_color;
+ Color font_disabled_hovered_color;
int line_separation = 0;
int icon_margin = 0;
@@ -185,6 +187,8 @@ protected:
Ref selected_focus_style;
Ref cursor_style;
Ref cursor_focus_style;
+ Ref disabled_style;
+ Ref disabled_hovered_style;
Color guide_color;
Ref scroll_hint;
diff --git a/scene/theme/default_theme.cpp b/scene/theme/default_theme.cpp
index 3de32c443a..c0b1b0bcdb 100644
--- a/scene/theme/default_theme.cpp
+++ b/scene/theme/default_theme.cpp
@@ -970,14 +970,18 @@ void fill_default_theme(Ref &theme, const Ref &default_font, const
theme->set_color("font_hovered_color", "ItemList", control_font_hover_color);
theme->set_color("font_hovered_selected_color", "ItemList", control_font_pressed_color);
theme->set_color("font_selected_color", "ItemList", control_font_pressed_color);
+ theme->set_color("font_disabled_color", "ItemList", control_font_disabled_color);
+ theme->set_color("font_disabled_hovered_color", "ItemList", control_font_disabled_color);
theme->set_color("font_outline_color", "ItemList", Color(0, 0, 0));
theme->set_color("guide_color", "ItemList", Color(0.7, 0.7, 0.7, 0.25));
theme->set_color("scroll_hint_color", "ItemList", Color(0, 0, 0));
- theme->set_stylebox("hovered", "ItemList", make_flat_stylebox(Color(1, 1, 1, 0.07)));
+ theme->set_stylebox("hovered", "ItemList", make_flat_stylebox(style_hover_color));
theme->set_stylebox("hovered_selected", "ItemList", make_flat_stylebox(style_hover_selected_color));
theme->set_stylebox("hovered_selected_focus", "ItemList", make_flat_stylebox(style_hover_selected_color));
theme->set_stylebox("selected", "ItemList", make_flat_stylebox(style_selected_color));
theme->set_stylebox("selected_focus", "ItemList", make_flat_stylebox(style_selected_color));
+ theme->set_stylebox("disabled", "ItemList", make_flat_stylebox(style_disabled_color));
+ theme->set_stylebox("disabled_hovered", "ItemList", make_flat_stylebox(style_hover_color));
theme->set_stylebox("cursor", "ItemList", focus);
theme->set_stylebox("cursor_unfocused", "ItemList", focus);
theme->set_icon("scroll_hint", "ItemList", icons["scroll_hint_vertical"]);