Skip to content

Add support for custom font colors in the TabBar #106263

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

lodetrick
Copy link
Contributor

@lodetrick lodetrick commented May 11, 2025

Partially Addresses: godotengine/godot-proposals#9161
Related: #88709, #106164

The inspiration for this PR was #106164 and the desire to set a custom color for the Output and Debugger tabs now that they are within a TabBar, but there is a desire to do such, as evidenced by the previous proposal.

Currently it is impossible to set colors individually for tabs in a TabBar. This PR adds support to set custom overrides for the selected, unselected, hovered, and disabled colors on a per tab basis.

TabBar with Rainbow-Colored Tabs

@lodetrick lodetrick requested review from a team as code owners May 11, 2025 02:30
@lodetrick lodetrick force-pushed the tabbar-individual-colors branch from 26397e2 to cb79183 Compare May 11, 2025 03:09
@AThousandShips AThousandShips added this to the 4.x milestone May 11, 2025
@lodetrick
Copy link
Contributor Author

lodetrick commented May 11, 2025

Admittedly this is lot of API for a relatively simple change. I'm curious what others think about using the set_font_color_override_all() and set_font_color_override(State p_state) convention instead, perhaps using the Button.DRAW_PRESSED enum or just making a new enum that doesn't have a PRESSED_HOVER option for clarity (because the TabBar does not support pressed and hover styles at the same time). The current method names might be a bit long but I also think that they accurately convey the use of the method.

@lodetrick
Copy link
Contributor Author

lodetrick commented May 12, 2025

I reduced the size of the API from eight to the three functions seen below:

extends TabContainer

func _ready():
    var color = get_tab_bar().get_font_color_override(BaseButton.DRAW_DISABLED, 3)
    get_tab_bar().set_font_color_override(BaseButton.DRAW_PRESSED, 0, Color.DEEP_PINK)
    get_tab_bar().set_font_color_override_all(2, Color.YELLOW)

This should hopefully make it easier to use, and behind the scenes it is neater, using an array of Colors instead of individual variables. Feedback is welcome on the specific enum used.

Another option would be to have a TabBar::DrawMode enum with the same values but without the DRAW_PRESSED_HOVER value. I do worry that this would be too repetitive though.

@lodetrick lodetrick force-pushed the tabbar-individual-colors branch 3 times, most recently from d1d04b9 to 4c302b0 Compare May 14, 2025 17:30
@lodetrick lodetrick force-pushed the tabbar-individual-colors branch from 4c302b0 to 26ea808 Compare May 18, 2025 00:56
@lodetrick
Copy link
Contributor Author

I updated to use a TabBar::DrawMode enum. I also swapped the order of the arguments, so that the tab index is always first.

extends TabContainer

func _ready():
    var color = get_tab_bar().get_font_color_override(0, TabBar.DRAW_DISABLED)
    get_tab_bar().set_font_color_override(1, TabBar.DRAW_PRESSED, Color.DEEP_PINK)
    get_tab_bar().set_font_color_override_all(2, Color.YELLOW)

@KoBeWi
Copy link
Member

KoBeWi commented May 18, 2025

While I somewhat like the new API, for the purpose of coloring bottom panel you only need DRAW_NORMAL. Currently the buttons display the default pressed and hover colors.

Also, since the user will not have access to the tabs directly, it does not even need to be exposed. If you want to set color of a dock's tab, it can be exposed as a property of EditorDock.

Docks aside, the proposal you linked does not mention tab colors, only italics text.

@lodetrick
Copy link
Contributor Author

I can hide these so they are just for internal use for now. I can't gauge community interest in this specific feature, its creation was motivated by compatibility for the bottom panel.

@@ -521,13 +521,13 @@ void TabBar::_notification(int p_what) {

if (tabs[i].disabled) {
sb = theme_cache.tab_disabled_style;
col = theme_cache.font_disabled_color;
col = tabs[i].font_color_overrides[DrawMode::DRAW_DISABLED].a > 0 ? tabs[i].font_color_overrides[DrawMode::DRAW_DISABLED] : theme_cache.font_disabled_color;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be replaced by a method, like _select_color(tabs[i].font_color_overrides[DrawMode::DRAW_DISABLED], theme_cache.font_disabled_color). More readable and less repetitive.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to make that a macro instead, as the logic is just one line? Or would an inline function make more sense.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Methods are better than macros. You can make a static function in cpp file, we use them sometimes.

Copy link
Member

@KoBeWi KoBeWi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is primarily made for #106164, however there is some extra stuff that likely won't be needed. Though if it's internal we can easily remove it I guess. Overall looks ok.

@lodetrick lodetrick force-pushed the tabbar-individual-colors branch from fbb9801 to 59a4e4c Compare May 18, 2025 18:25
@lodetrick
Copy link
Contributor Author

Could you confirm that the static function has the right qualifiers? Copied below:

static inline Color _select_color(const Color &p_override_color, const Color &p_default_color) {
	return p_override_color.a > 0 ? p_override_color : p_default_color;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants