emilk / emilk/egui

Impossible to set disabled text color.

Open
#2,848 2 comments 2 reactions 0 assignees View on GitHub
bug
Dominant language
Rust
Stars
30.6k
Forks
2.1k
Avg merge
1d 9h
Merged PRs (30d)
72

Description

**Describe the bug**

This is a follow-up to my [discussion](https://github.com/emilk/egui/discussions/2842).

First things first: it's non-intuitive how the disabled styling works. For example, the following code:

```
ui.visuals_mut().widgets.noninteractive.weak_bg_fill = egui::Color32::from_rgb(255, 255, 255);
ui.add_enabled_ui(enabled, |ui| {ui.add_sized(egui::Vec2::new(100.0, 50.0), btn);
```

produces the following image:
![egui_1](https://user-images.githubusercontent.com/6390092/228305633-c01f9750-c745-4095-89ee-e15eeea3d557.png)

Despite the fact that the noninteractive state color is set explicitly to white, it's rendered gray. In the source code, I see that the final color is calculated as a mix between `noninteractive` and `inactive` states. Indeed, setting the `inactive` weak color fixes the problem:

```
ui.visuals_mut().widgets.noninteractive.weak_bg_fill = egui::Color32::from_rgb(255, 255, 255);
ui.visuals_mut().widgets.inactive.weak_bg_fill = egui::Color32::from_rgb(255, 255, 255);
ui.add_enabled_ui(enabled, |ui| {ui.add_sized(egui::Vec2::new(100.0, 50.0), btn);
```
![egui_2](https://user-images.githubusercontent.com/6390092/228306253-df5ac0e1-c282-43e7-ae18-b8b09c68b180.png)

But there's no way to set the color of the disabled text. For example, in the images above the text color is set to (0, 255, 0). But it is clearly not _true_ green.

In the source code, the disabled text color is set like this:

```
pub fn weak_text_color(&self) -> Color32 {
self.gray_out(self.text_color())
}

pub fn gray_out(&self, color: Color32) -> Color32 {
crate::ecolor::tint_color_towards(color, self.fade_out_to_color())
}

pub fn fade_out_to_color(&self) -> Color32 {
self.widgets.noninteractive.weak_bg_fill
}

/// Cheap and ugly.
/// Made for graying out disabled `Ui`s.
pub fn tint_color_towards(color: Color32, target: Color32) -> Color32 {
let [mut r, mut g, mut b, mut a] = color.to_array();

if a == 0 {
r /= 2;
g /= 2;
b /= 2;
} else if a < 170 {
// Cheapish and looks ok.
// Works for e.g. grid stripes.
let div = (2 * 255 / a as i32) as u8;
r = r / 2 + target.r() / div;
g = g / 2 + target.g() / div;
b = b / 2 + target.b() / div;
a /= 2;
} else {
r = r / 2 + target.r() / 2;
g = g / 2 + target.g() / 2;
b = b / 2 + target.b() / 2;
}
Color32::from_rgba_premultiplied(r, g, b, a)
}
```

So there's simply no way to do it.

There's probably a reason why disabled colors are done like this, but honestly, it's far from flexible and actually very frustrating. Why not simply keep a dedicated color variable for this? If I'd need mixed color, I'd do it myself, why the lib forces it?

Contributor guide

Open the contributing guide

Research direction

Start with the mentioned `weak_text_color`, `gray_out`, and `fade_out_to_color` functions, then trace how disabled widgets derive their text color from the visuals state. Done means disabled text can use an explicitly configurable color without the forced mix, while preserving the existing disabled styling behavior where appropriate.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
design, frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.