Home » Community » U++ community news and announcements » DarkTheme function parameters changed
|
|
|
|
|
|
|
|
| Re: DarkTheme function parameters changed [message #60812 is a reply to message #60810] |
Sat, 14 September 2024 22:32   |
Tom1
Messages: 1319 Registered: March 2007
|
Ultimate Contributor |
|
|
Hi Mirek,
Very, very nice! After tuning for a good while, I ended up with 0.24, 0.7, 0.16 ... but then I looked at the old code and there was within a comment 0.21, 0.72, 0.07 for physiologically correct values. I guess they are even better with this new algorithm.
Now that DarkTheme() 'color inversion' works so great, maybe a slight tuning of default TheIDE text colors (along the lines laid out in material.io Dark theme documentation) is in place. I'm thinking about:
1. replacing any saturated (default) text colors with non-saturated pastel colors
2. checking the text contrast with those colors on both light and dark background
This might offer more balanced light/dark theme experience (... maybe).
Best regards,
Tom
|
|
|
|
|
|
| Re: DarkTheme function parameters changed [message #60814 is a reply to message #60812] |
Sun, 15 September 2024 10:10   |
 |
mirek
Messages: 14291 Registered: November 2005
|
Ultimate Member |
|
|
Tom1 wrote on Sat, 14 September 2024 22:32Hi Mirek,
Very, very nice! After tuning for a good while, I ended up with 0.24, 0.7, 0.16 ... but then I looked at the old code and there was within a comment 0.21, 0.72, 0.07 for physiologically correct values. I guess they are even better with this new algorithm.
Well.. The whole purpose is that with previous algorithm, LtRed becomes pink, Blue becomes white. Which is true here as well, with "physiologically correct" values. (The reason is simple - LtBlue is still dark color and we do not have enough range to make it light).
So it is all about compromise - after all, what matters is that colored texts remain readable while retaining reasonable color information. Warning text still needs to be red (and preferably not pink).
Mirek
|
|
|
|
| Re: DarkTheme function parameters changed [message #60819 is a reply to message #60814] |
Mon, 16 September 2024 13:01   |
Tom1
Messages: 1319 Registered: March 2007
|
Ultimate Contributor |
|
|
Hi Mirek,
These two functions can be useful tools when working with colors, so please feel free to merge them in Color.h / Color.cpp if you like:
// Formula from https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
double RelativeLuminance(Color color) {
auto comp = [&] (double c){
c /= 255;
return (c <= 0.03928) ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4);
};
return comp(color.GetR()) * 0.2126 + comp(color.GetG()) * 0.7152 + comp(color.GetB()) * 0.0722;
}
// Formula from https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
double ContrastRatio(Color c1, Color c2) {
double rl1 = RelativeLuminance(c1);
double rl2 = RelativeLuminance(c2);
return (max(rl1, rl2) + 0.05) / (min(rl1, rl2) + 0.05);
}
Best regards,
Tom
|
|
|
|
|
|
|
|
| Re: DarkTheme function parameters changed [message #60826 is a reply to message #60824] |
Tue, 17 September 2024 20:31   |
Tom1
Messages: 1319 Registered: March 2007
|
Ultimate Contributor |
|
|
mirek wrote on Tue, 17 September 2024 18:00Tom1 wrote on Sat, 14 September 2024 22:32Now that DarkTheme() 'color inversion' works so great, maybe a slight tuning of default TheIDE text colors (along the lines laid out in material.io Dark theme documentation) is in place. I'm thinking about:
Default scheme should always be "host". However, I can add alternative dark theme, if you supply one. It is quite easy, check
CtrlLib/Ch.cpp:716
Mirek
I was actually just thinking about TheIDE accent colors for code editing and other views... just to adjust the dark variants to view nicely on dark backgrounds. But yes, this involves dark theme tuning as well to get contrast optimized.
I remember working on Win32 emulated dark theme colors. The trick was (and I think still is) that many definitions come from platform and mostly only colors need to be adjusted for the dark theme. I recall that the color changes had to be written in-line within ChHostSkin(). If I just create a function called e.g. ChMyCustomSkin(), similar to e.g. ChDarkSkin(), I will not get platform shapes/styles for widgets, but something else instead. Therefore, some reorganization would be helpful:
It would be nice to have theme loading clearly split to two parts:
1. Load system colors (custom or platform) and store with "SColor*_Write();" functions like before.
2. Load shapes/styles from host like in ChHostSkin() (or load custom shapes/styles), and combine with preloaded SColor*() colors for a complete theme.
Also live theme changes would be nice... We have talked about this before and at that time you warned about a potential problem that arises with some controls caching colors internally. Still, it would be an interesting improvement. (I can even imagine a generic Theme(Color)EditorDialog after live theme changes feature has been introduced...)
Best regards,
Tom
|
|
|
|
|
|
| Re: DarkTheme function parameters changed [message #60841 is a reply to message #60830] |
Wed, 18 September 2024 21:11   |
Tom1
Messages: 1319 Registered: March 2007
|
Ultimate Contributor |
|
|
mirek wrote on Wed, 18 September 2024 00:45Tom1 wrote on Tue, 17 September 2024 20:31
It would be nice to have theme loading clearly split to two parts:
1. Load system colors (custom or platform) and store with "SColor*_Write();" functions like before.
2. Load shapes/styles from host like in ChHostSkin() (or load custom shapes/styles), and combine with preloaded SColor*() colors for a complete theme.
You cannot load just shapes. All 3 hosts we use paint the whole widget (think images of widgets).
Mirek
>
OK, I see. So, basically we're stuck with the colors given by host, right? I mean for buttons, scroll bars and more...
Is it also true that if full control of colors is desired, the widgets need to be created internally like ChClassicSkin() and ChStdSkin() do?
BR, Tom
|
|
|
|
| Re: DarkTheme function parameters changed [message #60843 is a reply to message #60841] |
Wed, 18 September 2024 21:59   |
 |
mirek
Messages: 14291 Registered: November 2005
|
Ultimate Member |
|
|
Tom1 wrote on Wed, 18 September 2024 21:11mirek wrote on Wed, 18 September 2024 00:45Tom1 wrote on Tue, 17 September 2024 20:31
It would be nice to have theme loading clearly split to two parts:
1. Load system colors (custom or platform) and store with "SColor*_Write();" functions like before.
2. Load shapes/styles from host like in ChHostSkin() (or load custom shapes/styles), and combine with preloaded SColor*() colors for a complete theme.
You cannot load just shapes. All 3 hosts we use paint the whole widget (think images of widgets).
Mirek
>
OK, I see. So, basically we're stuck with the colors given by host, right? I mean for buttons, scroll bars and more...
No, we can choose any colors we wish - but we need to draw our widgets too... but if you have checked to code reference I sent, it is doing exactly that there...
DarkTheme in windows is currently sort of hack - we apply DarkTheme on light theme widgets (because that is what API we currently use is returning).
Mirek
|
|
|
|
|
|
| Re: DarkTheme function parameters changed [message #60895 is a reply to message #60845] |
Sun, 06 October 2024 14:46   |
Lance
Messages: 656 Registered: March 2007
|
Contributor |
|
|
Thanks to work of both of Mirek and Tom1, Dark Theme now works very naturally on gnome.
Here is a small feature request that may improve user experience on gnome or possible x11 as a whole. But if it's too complicated or unworthy, just ignore it.
On more recent gnome (or at least ubuntu version of gnome), we can quickly switch between darkstyle and normal style using the dropdown menu:

Native applications respond to the changes immediately while, for theide, we have to restart it after theme changes. This makes theide and upp appliations stand out in a negative way.
I was told dconf command tool can monitor the changes. Indeed
$dconf watch /org/gnome/desktop/interface/color-scheme
will report the changes. Or underneath, gio, can be used somehow to access the settings or possibly even subscribe to certain changes, which I don't know how.
If upp can listen to the event and request all Ctrl to Refresh (hierachically) themselves, and all SColorXXX returns a reference (to a static variable who has application-long life time which will by updated by Upp at theme-changes), a upp application can behave more similar to a native gnome/x11 application.
However, all user programs alos need to change accordingly to use Color& instead of Color to store SColorXXXs that they use in their own chameleon style. But this won't break their programs catastrophically even if they don't: any part that they call SColorXXX on the site will be reflectly after first Refresh, while the part they stored a copy of SColorXXX, in, for example, a Chameleon style, will only be corrected after a restart.
More can be involved than just color, eg, icon,etc. But it could be a simple , albeit tedious, work for Mirek.
|
|
|
|
|
|
| Re: DarkTheme function parameters changed [message #60898 is a reply to message #60895] |
Sun, 06 October 2024 21:37   |
 |
mirek
Messages: 14291 Registered: November 2005
|
Ultimate Member |
|
|
Lance wrote on Sun, 06 October 2024 14:46
If upp can listen to the event and request all Ctrl to Refresh (hierachically) themselves, and all SColorXXX returns a reference (to a static variable who has application-long life time which will by updated by Upp at theme-changes), a upp application can behave more similar to a native gnome/x11 application.
However, all user programs alos need to change accordingly to use Color& instead of Color to store SColorXXXs that they use in their own chameleon style. But this won't break their programs catastrophically even if they don't: any part that they call SColorXXX on the site will be reflectly after first Refresh, while the part they stored a copy of SColorXXX, in, for example, a Chameleon style, will only be corrected after a restart.
That is not enough, look at this:
CtrlLib/ArrayCtrl.h:686
ArrayCtrl& EvenRowColor(Color paper = Blend(SColorMark, SColorPaper, 220), Color ink = SColorText);
[Updated on: Sun, 06 October 2024 21:38] Report message to a moderator
|
|
|
|
|
|
|
|
| Re: DarkTheme function parameters changed [message #60901 is a reply to message #60898] |
Sun, 06 October 2024 22:52   |
Lance
Messages: 656 Registered: March 2007
|
Contributor |
|
|
mirek wrote on Sun, 06 October 2024 15:37That is not enough, look at this:
CtrlLib/ArrayCtrl.h:686
ArrayCtrl& EvenRowColor(Color paper = Blend(SColorMark, SColorPaper, 220), Color ink = SColorText);
Please educate me if I am wrong.
What are SColorMark, SColorPaper, SColorText? Are they some Color variable in ArrayCtrl's Chameleon Style?
When a user code called
Something like this happen (conceptually)
push ink = SColorText;
push paper = Blend(SColorMark, SColorPaper, 220)
push this
call ArrayCtrl::EvenRowColor
If SColorText, SColorMark, SColorPaper are all refreshed after the theme change, EvenColor should receive correct color parameters.
So if instead of store a copy of SColorxxx(), let it store a reference/pointer of SColorxxx() instead. And all SColorXXX() should return Color& instead of Color.
Will this be adequate?
|
|
|
|
| Re: DarkTheme function parameters changed [message #60902 is a reply to message #60901] |
Mon, 07 October 2024 00:26   |
 |
mirek
Messages: 14291 Registered: November 2005
|
Ultimate Member |
|
|
Lance wrote on Sun, 06 October 2024 22:52mirek wrote on Sun, 06 October 2024 15:37That is not enough, look at this:
CtrlLib/ArrayCtrl.h:686
ArrayCtrl& EvenRowColor(Color paper = Blend(SColorMark, SColorPaper, 220), Color ink = SColorText);
Please educate me if I am wrong.
What are SColorMark, SColorPaper, SColorText? Are they some Color variable in ArrayCtrl's Chameleon Style?
When a user code called
Something like this happen (conceptually)
push ink = SColorText;
push paper = Blend(SColorMark, SColorPaper, 220)
push this
call ArrayCtrl::EvenRowColor
If SColorText, SColorMark, SColorPaper are all refreshed after the theme change, EvenColor should receive correct color parameters.
So if instead of store a copy of SColorxxx(), let it store a reference/pointer of SColorxxx() instead. And all SColorXXX() should return Color& instead of Color.
Will this be adequate?
It could easily be a reference, but it does not solve the problem, unless you add somewhat complicate mechanism where the "Blend" part is somehow encoded. I mean, you can make SColorMark work, SColorPaper work, but what is actually stored is some other color, a mix of those two.
It is too clumsy and 'undefined' IMO for the rapid development.
Mirek
|
|
|
|
|
|
| Re: DarkTheme function parameters changed [message #60907 is a reply to message #60904] |
Mon, 07 October 2024 08:51   |
Tom1
Messages: 1319 Registered: March 2007
|
Ultimate Contributor |
|
|
Hi,
Sorry to interfere here, but I would not mind having both theme dependent SColors and "SkinChanged" virtual method called on Ctrls when system theme changes. When the theme changes, everything obviously needs to be Refresh()ed, which could be the default behavior of "SkinChanged". But that is not sufficient, as in some cases content is cached in pre-rendered images which are not aware of the changed theme. Therefore, "SkinChanged" is needed to re-render everything followed by Refresh().
Is there a way to run a test on this? Maybe a branch for testing the idea?
Best regards,
Tom
|
|
|
|
| Re: DarkTheme function parameters changed [message #60908 is a reply to message #60907] |
Mon, 07 October 2024 09:40   |
 |
mirek
Messages: 14291 Registered: November 2005
|
Ultimate Member |
|
|
Tom1 wrote on Mon, 07 October 2024 08:51Hi,
Sorry to interfere here, but I would not mind having both theme dependent SColors and "SkinChanged" virtual method called on Ctrls when system theme changes. When the theme changes, everything obviously needs to be Refresh()ed, which could be the default behavior of "SkinChanged". But that is not sufficient, as in some cases content is cached in pre-rendered images which are not aware of the changed theme. Therefore, "SkinChanged" is needed to re-render everything followed by Refresh().
Is there a way to run a test on this? Maybe a branch for testing the idea?
Best regards,
Tom
Not yet. After 2024 release, I can add the changes to the master - however for forseeable future, we will need "allow theme changes" flag/function call.
|
|
|
|
| Re: DarkTheme function parameters changed [message #60909 is a reply to message #60904] |
Mon, 07 October 2024 09:43   |
 |
mirek
Messages: 14291 Registered: November 2005
|
Ultimate Member |
|
|
Lance wrote on Mon, 07 October 2024 01:59Do you mean that we can have SColorPaper,SColorMark theme-sensitive, but there is no guarantee Blend(SColorPaper, SColorMark, 220) will make any sense in all possible themes we may throw at it?
I mean that Blend(SColorPaper, SColorMark, 220) has to be evaluated at some point. From developer perspective, the most logical point is when he calls Blend. It this was supposed to work without SkinChanged, we would need to do something like changing all colors stored in widgets to functions. I do not think that is a good idea...
Mirek
[Updated on: Mon, 07 October 2024 09:44] Report message to a moderator
|
|
|
|
| Re: DarkTheme function parameters changed [message #60910 is a reply to message #60908] |
Mon, 07 October 2024 10:36   |
Tom1
Messages: 1319 Registered: March 2007
|
Ultimate Contributor |
|
|
mirek wrote on Mon, 07 October 2024 10:40Not yet. After 2024 release, I can add the changes to the master - however for forseeable future, we will need "allow theme changes" flag/function call.
Thanks! Looking forward to both of these events!
Best regards,
Tom
|
|
|
|
| Re: DarkTheme function parameters changed [message #60913 is a reply to message #60909] |
Mon, 07 October 2024 13:57   |
Lance
Messages: 656 Registered: March 2007
|
Contributor |
|
|
mirek wrote on Mon, 07 October 2024 03:43
I mean that Blend(SColorPaper, SColorMark, 220) has to be evaluated at some point. From developer perspective, the most logical point is when he calls Blend. It this was supposed to work without SkinChanged, we would need to do something like changing all colors stored in widgets to functions. I do not think that is a good idea...
Mirek
//header
struct SysColors
{
Color paper;
Color ink;
Color mark;
Color highlight;
...
void RefreshColors();
...
static SysColors scs;
private:
SysColors(){ RefreshColors(); }
};
Color& SColorPaper = SysColors::scs.paper;
Color& SColorMark = SysColors::scs.mark;
//cpp
SysColors SysColors::scs;
Then
Blend(SColorPaper, SColorMark, 220)
will be evaluated everytime with refreshed System Colors.
It will involve a lot of tedious work of changing copied color values to references to variables of program life time. Other than that, it should not present unnecessary work on upp users.
[Updated on: Mon, 07 October 2024 14:12] Report message to a moderator
|
|
|
|
|
|
|
|
| Re: DarkTheme function parameters changed [message #60916 is a reply to message #60913] |
Mon, 07 October 2024 14:48   |
 |
mirek
Messages: 14291 Registered: November 2005
|
Ultimate Member |
|
|
Lance wrote on Mon, 07 October 2024 13:57mirek wrote on Mon, 07 October 2024 03:43
I mean that Blend(SColorPaper, SColorMark, 220) has to be evaluated at some point. From developer perspective, the most logical point is when he calls Blend. It this was supposed to work without SkinChanged, we would need to do something like changing all colors stored in widgets to functions. I do not think that is a good idea...
Mirek
//header
struct SysColors
{
Color paper;
Color ink;
Color mark;
Color highlight;
...
void RefreshColors();
...
static SysColors scs;
private:
SysColors(){ RefreshColors(); }
};
Color& SColorPaper = SysColors::scs.paper;
Color& SColorMark = SysColors::scs.mark;
//cpp
SysColors SysColors::scs;
Then
Blend(SColorPaper, SColorMark, 220)
will be evaluated everytime with refreshed System Colors.
No.
ArrayCtrl ctrl;
ctrl.EvenRowColor();
it gets evaulate once, at this point. If SystemColors change, it is still evaluated for the old values. Changing values to references does not really help, you would at least need to call EvenRowColor again.
And pls note that this is just one example. What about e.g.
ctrl.Add(AttrText("Hello there!").Ink(IsDarkTheme() ? Blend(White(), LtBlue()) : Blue());
[Updated on: Mon, 07 October 2024 14:50] Report message to a moderator
|
|
|
|
| Re: DarkTheme function parameters changed [message #60917 is a reply to message #60916] |
Mon, 07 October 2024 16:49   |
Lance
Messages: 656 Registered: March 2007
|
Contributor |
|
|
I see the challenge now.
We need something like theme-dependent color.
With regard to Blend(), would it ever need more than 2 colors?
I have a hackish solution.
class DynColor{
struct _combo{
Color c;
char f[4];
};
operator Color()const{
switch(f[3] & 3){
case 0: // the 64 bits are a Color*
return * reinterpret_cast<const Color*>(this);
case 1: // a normal color hold at data.c
return c;
case 2: // Blend, with f[0], f[1] the index
// of System colors, hopefully
// we don't have more than 256 of them
// , and f[2] hold the third paramenter of Blend
return Blend(GetSysColorFromIndex(f[0],
GetSysColorFromIndex(f[1]),
f[2]);
case 3: // let's handle the
//ctrl.Add(AttrText("Hello there!").Ink(IsDarkTheme() ? Blend(White(), LtBlue()) : Blue());
// case here
// theme dependant blend
return IsDarkTheme() ?
Blend( treat_c as byte[4], and store blend information there) :
Blend(GetSysColorFromIndex(f[0],
GetSysColorFromIndex(f[1]),
f[2]);
}
}
private:
combo data;
};
Just a prototype for conception. We need to consider endianness at least.
Now, we can
ctrl.Add(AttrText("Hello there!").Ink(ConstructDynColor(DarkBlender{...}, NormalBlender{...}));
Yes I am aware this requires changes to AttrText code. I can imagine it's quite involving.
Also this will require everywhere that requires dynamic color to use 64-bit color, a double in storage space.
[Updated on: Mon, 07 October 2024 17:31] Report message to a moderator
|
|
|
|
|
|
|
|
| Re: DarkTheme function parameters changed [message #60930 is a reply to message #60919] |
Wed, 09 October 2024 23:39   |
Lance
Messages: 656 Registered: March 2007
|
Contributor |
|
|
Maybe we can do dynamic color within the current Color. I don't know the full picture, but here are some thoughts:
1. upto 254 System colors are store in a c array that is indexable with a integer i (0<=i<=254); These are, of course, SColorPaper, SColorInk, SBlack, SWhite, etc.
2. End user(programmer) are deprived of alpha value of 255. With alpha=255
a. if r=g=b=255, that's the Null Color;
b. If g=b=255, r<255, r is the color index of a system color;
c. if b<=254, the Final Color = Blend(ColorFromIndex(r), ColorFromIndex(g), b);
3. If a programmer's Color choice conflicts with dynamic color ones, a warning will be logged but a color close enough will be silently supplied instead.
4. Color are finalized on the site. So AttrTxt, etc, only calculate the final Color before it actually renders text.
5. UPP supports light theme(normal theme), dark theme out of box, free of charge. If a programmer wants his/her program sticks to light theme, sticks to dark theme, stick to host theme (between dark and non-dark, any non-dark host theme will be interpreted to light theme by upp, before further themes are developed, if ever). Remove the chamalion Style * style;(a further 8 byte reduction on x64 platforms) from Ctrl definition, but add a GetChStyle()const virtual function, which will return light theme, dark theme, or host-dependant theme according to programmers' choice. If anyone want to Style a Ctrl, he/she should override GetChStyel() to return pointers to his/her own full set of theme values. Don't use, don't pay.
5. Icon will remain to be an issue.
|
|
|
|
|
|
Goto Forum:
Current Time: Mon May 04 17:53:49 GMT+2 2026
Total time taken to generate the page: 0.01142 seconds
|