Merge pull request #111169 from YeldhamDev/tab_icon_modulation

Add icon color theme items for `TabBar` and `TabContainer`
This commit is contained in:
Thaddeus Crews 2025-10-03 12:00:58 -05:00
commit eecb957610
No known key found for this signature in database
GPG key ID: 8C6E5FEB5FC03CCC
8 changed files with 81 additions and 10 deletions

View file

@ -388,6 +388,18 @@
<theme_item name="font_unselected_color" data_type="color" type="Color" default="Color(0.7, 0.7, 0.7, 1)"> <theme_item name="font_unselected_color" data_type="color" type="Color" default="Color(0.7, 0.7, 0.7, 1)">
Font color of the other, unselected tabs. Font color of the other, unselected tabs.
</theme_item> </theme_item>
<theme_item name="icon_disabled_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)">
Icon color of disabled tabs.
</theme_item>
<theme_item name="icon_hovered_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)">
Icon color of the currently hovered tab. Does not apply to the selected tab.
</theme_item>
<theme_item name="icon_selected_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)">
Icon color of the currently selected tab.
</theme_item>
<theme_item name="icon_unselected_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)">
Icon color of the other, unselected tabs.
</theme_item>
<theme_item name="h_separation" data_type="constant" type="int" default="4"> <theme_item name="h_separation" data_type="constant" type="int" default="4">
The horizontal separation between the elements inside tabs. The horizontal separation between the elements inside tabs.
</theme_item> </theme_item>

View file

@ -305,7 +305,7 @@
Font color of disabled tabs. Font color of disabled tabs.
</theme_item> </theme_item>
<theme_item name="font_hovered_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)"> <theme_item name="font_hovered_color" data_type="color" type="Color" default="Color(0.95, 0.95, 0.95, 1)">
Font color of the currently hovered tab. Font color of the currently hovered tab. Does not apply to the selected tab.
</theme_item> </theme_item>
<theme_item name="font_outline_color" data_type="color" type="Color" default="Color(0, 0, 0, 1)"> <theme_item name="font_outline_color" data_type="color" type="Color" default="Color(0, 0, 0, 1)">
The tint of text outline of the tab name. The tint of text outline of the tab name.
@ -316,6 +316,18 @@
<theme_item name="font_unselected_color" data_type="color" type="Color" default="Color(0.7, 0.7, 0.7, 1)"> <theme_item name="font_unselected_color" data_type="color" type="Color" default="Color(0.7, 0.7, 0.7, 1)">
Font color of the other, unselected tabs. Font color of the other, unselected tabs.
</theme_item> </theme_item>
<theme_item name="icon_disabled_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)">
Icon color of disabled tabs.
</theme_item>
<theme_item name="icon_hovered_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)">
Icon color of the currently hovered tab. Does not apply to the selected tab.
</theme_item>
<theme_item name="icon_selected_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)">
Icon color of the currently selected tab.
</theme_item>
<theme_item name="icon_unselected_color" data_type="color" type="Color" default="Color(1, 1, 1, 1)">
Icon color of the other, unselected tabs.
</theme_item>
<theme_item name="icon_max_width" data_type="constant" type="int" default="0"> <theme_item name="icon_max_width" data_type="constant" type="int" default="0">
The maximum allowed width of the tab's icon. This limit is applied on top of the default size of the icon, but before the value set with [method TabBar.set_tab_icon_max_width]. The height is adjusted according to the icon's ratio. The maximum allowed width of the tab's icon. This limit is applied on top of the default size of the icon, but before the value set with [method TabBar.set_tab_icon_max_width]. The height is adjusted according to the icon's ratio.
</theme_item> </theme_item>

View file

@ -1172,6 +1172,14 @@ void EditorThemeManager::_populate_standard_styles(const Ref<EditorTheme> &p_the
p_theme->set_color("drop_mark_color", "TabContainer", tab_highlight); p_theme->set_color("drop_mark_color", "TabContainer", tab_highlight);
p_theme->set_color("drop_mark_color", "TabBar", tab_highlight); p_theme->set_color("drop_mark_color", "TabBar", tab_highlight);
Color icon_color = Color(1, 1, 1);
p_theme->set_color("icon_selected_color", "TabContainer", icon_color);
p_theme->set_color("icon_hovered_color", "TabContainer", icon_color);
p_theme->set_color("icon_unselected_color", "TabContainer", icon_color);
p_theme->set_color("icon_selected_color", "TabBar", icon_color);
p_theme->set_color("icon_hovered_color", "TabBar", icon_color);
p_theme->set_color("icon_unselected_color", "TabBar", icon_color);
p_theme->set_icon("menu", "TabContainer", p_theme->get_icon(SNAME("GuiTabMenu"), EditorStringName(EditorIcons))); p_theme->set_icon("menu", "TabContainer", p_theme->get_icon(SNAME("GuiTabMenu"), EditorStringName(EditorIcons)));
p_theme->set_icon("menu_highlight", "TabContainer", p_theme->get_icon(SNAME("GuiTabMenuHl"), EditorStringName(EditorIcons))); p_theme->set_icon("menu_highlight", "TabContainer", p_theme->get_icon(SNAME("GuiTabMenuHl"), EditorStringName(EditorIcons)));
p_theme->set_icon("close", "TabBar", p_theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons))); p_theme->set_icon("close", "TabBar", p_theme->get_icon(SNAME("GuiClose"), EditorStringName(EditorIcons)));

View file

@ -522,20 +522,24 @@ void TabBar::_notification(int p_what) {
if (i != current) { if (i != current) {
Ref<StyleBox> sb; Ref<StyleBox> sb;
Color col; Color fnt_col;
Color icn_col;
if (tabs[i].disabled) { if (tabs[i].disabled) {
sb = theme_cache.tab_disabled_style; sb = theme_cache.tab_disabled_style;
col = theme_cache.font_disabled_color; fnt_col = theme_cache.font_disabled_color;
icn_col = theme_cache.icon_disabled_color;
} else if (i == hover) { } else if (i == hover) {
sb = theme_cache.tab_hovered_style; sb = theme_cache.tab_hovered_style;
col = theme_cache.font_hovered_color; fnt_col = theme_cache.font_hovered_color;
icn_col = theme_cache.icon_hovered_color;
} else { } else {
sb = theme_cache.tab_unselected_style; sb = theme_cache.tab_unselected_style;
col = theme_cache.font_unselected_color; fnt_col = theme_cache.font_unselected_color;
icn_col = theme_cache.icon_unselected_color;
} }
_draw_tab(sb, col, i, rtl ? (size.width - tabs[i].ofs_cache - tabs[i].size_cache) : tabs[i].ofs_cache, false); _draw_tab(sb, fnt_col, icn_col, i, rtl ? (size.width - tabs[i].ofs_cache - tabs[i].size_cache) : tabs[i].ofs_cache, false);
} }
} }
@ -543,7 +547,7 @@ void TabBar::_notification(int p_what) {
if (current >= offset && current <= max_drawn_tab && !tabs[current].hidden) { if (current >= offset && current <= max_drawn_tab && !tabs[current].hidden) {
Ref<StyleBox> sb = tabs[current].disabled ? theme_cache.tab_disabled_style : theme_cache.tab_selected_style; Ref<StyleBox> sb = tabs[current].disabled ? theme_cache.tab_disabled_style : theme_cache.tab_selected_style;
_draw_tab(sb, theme_cache.font_selected_color, current, rtl ? (size.width - tabs[current].ofs_cache - tabs[current].size_cache) : tabs[current].ofs_cache, has_focus(true)); _draw_tab(sb, theme_cache.font_selected_color, theme_cache.icon_selected_color, current, rtl ? (size.width - tabs[current].ofs_cache - tabs[current].size_cache) : tabs[current].ofs_cache, has_focus(true));
} }
if (buttons_visible) { if (buttons_visible) {
@ -625,7 +629,7 @@ void TabBar::_draw_tab_drop(RID p_canvas_item) {
theme_cache.drop_mark_icon->draw(p_canvas_item, Point2(x - theme_cache.drop_mark_icon->get_width() / 2, (size.height - theme_cache.drop_mark_icon->get_height()) / 2), theme_cache.drop_mark_color); theme_cache.drop_mark_icon->draw(p_canvas_item, Point2(x - theme_cache.drop_mark_icon->get_width() / 2, (size.height - theme_cache.drop_mark_icon->get_height()) / 2), theme_cache.drop_mark_color);
} }
void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_index, float p_x, bool p_focus) { void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, const Color &p_font_color, const Color &p_icon_color, int p_index, float p_x, bool p_focus) {
RID ci = get_canvas_item(); RID ci = get_canvas_item();
bool rtl = is_layout_rtl(); bool rtl = is_layout_rtl();
@ -651,7 +655,7 @@ void TabBar::_draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_in
if (icon.is_valid()) { if (icon.is_valid()) {
const Size2 icon_size = _get_tab_icon_size(p_index); const Size2 icon_size = _get_tab_icon_size(p_index);
const Point2 icon_pos = Point2i(rtl ? p_x - icon_size.width : p_x, p_tab_style->get_margin(SIDE_TOP) + ((sb_rect.size.y - sb_ms.y) - icon_size.height) / 2); const Point2 icon_pos = Point2i(rtl ? p_x - icon_size.width : p_x, p_tab_style->get_margin(SIDE_TOP) + ((sb_rect.size.y - sb_ms.y) - icon_size.height) / 2);
icon->draw_rect(ci, Rect2(icon_pos, icon_size)); icon->draw_rect(ci, Rect2(icon_pos, icon_size), false, p_icon_color);
p_x = rtl ? p_x - icon_size.width - theme_cache.h_separation : p_x + icon_size.width + theme_cache.h_separation; p_x = rtl ? p_x - icon_size.width - theme_cache.h_separation : p_x + icon_size.width + theme_cache.h_separation;
} }
@ -2081,6 +2085,11 @@ void TabBar::_bind_methods() {
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabBar, font_disabled_color); BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabBar, font_disabled_color);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabBar, font_outline_color); BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabBar, font_outline_color);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabBar, icon_selected_color);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabBar, icon_hovered_color);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabBar, icon_unselected_color);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabBar, icon_disabled_color);
BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, TabBar, font); BIND_THEME_ITEM(Theme::DATA_TYPE_FONT, TabBar, font);
BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, TabBar, font_size); BIND_THEME_ITEM(Theme::DATA_TYPE_FONT_SIZE, TabBar, font_size);
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TabBar, outline_size); BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TabBar, outline_size);

View file

@ -156,6 +156,11 @@ private:
Color font_disabled_color; Color font_disabled_color;
Color font_outline_color; Color font_outline_color;
Color icon_selected_color;
Color icon_hovered_color;
Color icon_unselected_color;
Color icon_disabled_color;
Ref<Texture2D> close_icon; Ref<Texture2D> close_icon;
Ref<StyleBox> button_pressed_style; Ref<StyleBox> button_pressed_style;
Ref<StyleBox> button_hl_style; Ref<StyleBox> button_hl_style;
@ -172,7 +177,7 @@ private:
void _on_mouse_exited(); void _on_mouse_exited();
void _shape(int p_tab); void _shape(int p_tab);
void _draw_tab(Ref<StyleBox> &p_tab_style, Color &p_font_color, int p_index, float p_x, bool p_focus); void _draw_tab(Ref<StyleBox> &p_tab_style, const Color &p_font_color, const Color &p_icon_color, int p_index, float p_x, bool p_focus);
void _accessibility_action_scroll_into_view(const Variant &p_data, int p_index); void _accessibility_action_scroll_into_view(const Variant &p_data, int p_index);
void _accessibility_action_focus(const Variant &p_data, int p_index); void _accessibility_action_focus(const Variant &p_data, int p_index);

View file

@ -277,6 +277,11 @@ void TabContainer::_on_theme_changed() {
tab_bar->add_theme_color_override(SNAME("font_disabled_color"), theme_cache.font_disabled_color); tab_bar->add_theme_color_override(SNAME("font_disabled_color"), theme_cache.font_disabled_color);
tab_bar->add_theme_color_override(SNAME("font_outline_color"), theme_cache.font_outline_color); tab_bar->add_theme_color_override(SNAME("font_outline_color"), theme_cache.font_outline_color);
tab_bar->add_theme_color_override(SNAME("icon_selected_color"), theme_cache.icon_selected_color);
tab_bar->add_theme_color_override(SNAME("icon_hovered_color"), theme_cache.icon_hovered_color);
tab_bar->add_theme_color_override(SNAME("icon_unselected_color"), theme_cache.icon_unselected_color);
tab_bar->add_theme_color_override(SNAME("icon_disabled_color"), theme_cache.icon_disabled_color);
tab_bar->add_theme_font_override(SceneStringName(font), theme_cache.tab_font); tab_bar->add_theme_font_override(SceneStringName(font), theme_cache.tab_font);
tab_bar->add_theme_font_size_override(SceneStringName(font_size), theme_cache.tab_font_size); tab_bar->add_theme_font_size_override(SceneStringName(font_size), theme_cache.tab_font_size);
@ -1166,6 +1171,11 @@ void TabContainer::_bind_methods() {
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabContainer, font_disabled_color); BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabContainer, font_disabled_color);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabContainer, font_outline_color); BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabContainer, font_outline_color);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabContainer, icon_selected_color);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabContainer, icon_hovered_color);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabContainer, icon_unselected_color);
BIND_THEME_ITEM(Theme::DATA_TYPE_COLOR, TabContainer, icon_disabled_color);
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_FONT, TabContainer, tab_font, "font"); BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_FONT, TabContainer, tab_font, "font");
BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_FONT_SIZE, TabContainer, tab_font_size, "font_size"); BIND_THEME_ITEM_CUSTOM(Theme::DATA_TYPE_FONT_SIZE, TabContainer, tab_font_size, "font_size");
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TabContainer, outline_size); BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, TabContainer, outline_size);

View file

@ -93,6 +93,11 @@ private:
Color font_disabled_color; Color font_disabled_color;
Color font_outline_color; Color font_outline_color;
Color icon_selected_color;
Color icon_hovered_color;
Color icon_unselected_color;
Color icon_disabled_color;
Ref<Font> tab_font; Ref<Font> tab_font;
int tab_font_size; int tab_font_size;
} theme_cache; } theme_cache;

View file

@ -993,6 +993,11 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_outline_color", "TabContainer", Color(0, 0, 0)); theme->set_color("font_outline_color", "TabContainer", Color(0, 0, 0));
theme->set_color("drop_mark_color", "TabContainer", Color(1, 1, 1)); theme->set_color("drop_mark_color", "TabContainer", Color(1, 1, 1));
theme->set_color("icon_selected_color", "TabContainer", Color(1, 1, 1, 1));
theme->set_color("icon_hovered_color", "TabContainer", Color(1, 1, 1, 1));
theme->set_color("icon_unselected_color", "TabContainer", Color(1, 1, 1, 1));
theme->set_color("icon_disabled_color", "TabContainer", Color(1, 1, 1, 1));
theme->set_constant("side_margin", "TabContainer", Math::round(8 * scale)); theme->set_constant("side_margin", "TabContainer", Math::round(8 * scale));
theme->set_constant("icon_separation", "TabContainer", Math::round(4 * scale)); theme->set_constant("icon_separation", "TabContainer", Math::round(4 * scale));
theme->set_constant("icon_max_width", "TabContainer", 0); theme->set_constant("icon_max_width", "TabContainer", 0);
@ -1025,6 +1030,11 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
theme->set_color("font_outline_color", "TabBar", Color(0, 0, 0)); theme->set_color("font_outline_color", "TabBar", Color(0, 0, 0));
theme->set_color("drop_mark_color", "TabBar", Color(1, 1, 1)); theme->set_color("drop_mark_color", "TabBar", Color(1, 1, 1));
theme->set_color("icon_selected_color", "TabBar", Color(1, 1, 1, 1));
theme->set_color("icon_hovered_color", "TabBar", Color(1, 1, 1, 1));
theme->set_color("icon_unselected_color", "TabBar", Color(1, 1, 1, 1));
theme->set_color("icon_disabled_color", "TabBar", Color(1, 1, 1, 1));
theme->set_constant("h_separation", "TabBar", Math::round(4 * scale)); theme->set_constant("h_separation", "TabBar", Math::round(4 * scale));
theme->set_constant("icon_max_width", "TabBar", 0); theme->set_constant("icon_max_width", "TabBar", 0);
theme->set_constant("outline_size", "TabBar", 0); theme->set_constant("outline_size", "TabBar", 0);